diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-12-20 19:53:05 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-12-20 19:53:05 +0000 |
commit | 0b57cec536236d46e3dba9bd041533462f33dbb7 (patch) | |
tree | 56229dbdbbf76d18580f72f789003db17246c8d9 /contrib/llvm/lib/Target/Mips | |
parent | 718ef55ec7785aae63f98f8ca05dc07ed399c16d (diff) | |
download | src-0b57cec536236d46e3dba9bd041533462f33dbb7.tar.gz src-0b57cec536236d46e3dba9bd041533462f33dbb7.zip |
Move all sources from the llvm project into contrib/llvm-project.
This uses the new layout of the upstream repository, which was recently
migrated to GitHub, and converted into a "monorepo". That is, most of
the earlier separate sub-projects with their own branches and tags were
consolidated into one top-level directory, and are now branched and
tagged together.
Updating the vendor area to match this layout is next.
Notes
Notes:
svn path=/head/; revision=355940
Diffstat (limited to 'contrib/llvm/lib/Target/Mips')
132 files changed, 0 insertions, 80633 deletions
diff --git a/contrib/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/contrib/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp deleted file mode 100644 index 989cba13efe8..000000000000 --- a/contrib/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ /dev/null @@ -1,8530 +0,0 @@ -//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "MCTargetDesc/MipsABIFlagsSection.h" -#include "MCTargetDesc/MipsABIInfo.h" -#include "MCTargetDesc/MipsBaseInfo.h" -#include "MCTargetDesc/MipsMCExpr.h" -#include "MCTargetDesc/MipsMCTargetDesc.h" -#include "MipsTargetStreamer.h" -#include "TargetInfo/MipsTargetInfo.h" -#include "llvm/ADT/APFloat.h" -#include "llvm/ADT/STLExtras.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/MCParser/MCAsmLexer.h" -#include "llvm/MC/MCParser/MCAsmParser.h" -#include "llvm/MC/MCParser/MCAsmParserExtension.h" -#include "llvm/MC/MCParser/MCAsmParserUtils.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/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 MipsAssemblerOptions *Opts) { - ATReg = Opts->getATRegIndex(); - Reorder = Opts->isReorder(); - Macro = Opts->isMacro(); - Features = Opts->getFeatures(); - } - - unsigned getATRegIndex() const { return ATReg; } - bool setATRegIndex(unsigned Reg) { - if (Reg > 31) - return false; - - ATReg = Reg; - return true; - } - - bool isReorder() const { return Reorder; } - void setReorder() { Reorder = true; } - void setNoReorder() { Reorder = false; } - - bool isMacro() const { return Macro; } - void setMacro() { Macro = true; } - void setNoMacro() { Macro = false; } - - const FeatureBitset &getFeatures() const { return Features; } - void setFeatures(const FeatureBitset &Features_) { Features = Features_; } - - // Set of features that are either architecture features or referenced - // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6). - // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]). - // The reason we need this mask is explained in the selectArch function. - // FIXME: Ideally we would like TableGen to generate this information. - static const FeatureBitset AllArchRelatedMask; - -private: - unsigned ATReg = 1; - bool Reorder = true; - bool Macro = true; - FeatureBitset Features; -}; - -} // end anonymous namespace - -const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = { - Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3, - Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4, - Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5, - Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2, - Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6, - Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3, - Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips, - Mips::FeatureCnMipsP, Mips::FeatureFP64Bit, Mips::FeatureGP64Bit, - Mips::FeatureNaN2008 -}; - -namespace { - -class MipsAsmParser : public MCTargetAsmParser { - MipsTargetStreamer &getTargetStreamer() { - MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer(); - return static_cast<MipsTargetStreamer &>(TS); - } - - MipsABIInfo ABI; - SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions; - MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a - // nullptr, which indicates that no function is currently - // selected. This usually happens after an '.end func' - // directive. - bool IsLittleEndian; - bool IsPicEnabled; - bool IsCpRestoreSet; - int CpRestoreOffset; - unsigned GPReg; - unsigned CpSaveLocation; - /// 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, - OperandVector &Operands, MCStreamer &Out, - uint64_t &ErrorInfo, - bool MatchingInlineAsm) override; - - /// Parse a register as used in CFI directives - bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; - - bool parseParenSuffix(StringRef Name, OperandVector &Operands); - - bool parseBracketSuffix(StringRef Name, OperandVector &Operands); - - bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID); - - bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, - SMLoc NameLoc, OperandVector &Operands) override; - - bool ParseDirective(AsmToken DirectiveID) override; - - OperandMatchResultTy parseMemOperand(OperandVector &Operands); - OperandMatchResultTy - 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 parseRegisterList(OperandVector &Operands); - - bool searchSymbolAlias(OperandVector &Operands); - - bool parseOperand(OperandVector &, StringRef Mnemonic); - - enum MacroExpanderResultTy { - MER_NotAMacro, - MER_Success, - MER_Fail, - }; - - // Expands assembly pseudo instructions. - MacroExpanderResultTy tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, - MCStreamer &Out, - const MCSubtargetInfo *STI); - - bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI); - - bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg, - bool Is32BitImm, bool IsAddress, SMLoc IDLoc, - MCStreamer &Out, const MCSubtargetInfo *STI); - - 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); - - 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); - - 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); - - bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI); - - bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI); - - bool expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI); - - bool expandCondBranches(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI); - - bool expandDivRem(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI, const bool IsMips64, - const bool Signed); - - bool expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU, SMLoc IDLoc, - MCStreamer &Out, const MCSubtargetInfo *STI); - - bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI); - - bool expandUsh(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI); - - bool expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI); - - bool expandSge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI); - - bool expandSgeImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI); - - bool expandSgtImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI); - - 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); - - bool expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI, bool IsLoad); - - bool expandStoreDM1Macro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI); - - bool expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI); - - bool expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI); - - bool expandMXTRAlias(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI); - - bool expandSaaAddr(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI); - - bool reportParseError(Twine ErrorMsg); - bool reportParseError(SMLoc Loc, Twine ErrorMsg); - - bool parseMemOffset(const MCExpr *&Res, bool isParenExpr); - - bool isEvaluated(const MCExpr *Expr); - bool parseSetMips0Directive(); - bool parseSetArchDirective(); - bool parseSetFeature(uint64_t Feature); - bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup. - bool parseDirectiveCpLoad(SMLoc Loc); - bool parseDirectiveCpLocal(SMLoc Loc); - bool parseDirectiveCpRestore(SMLoc Loc); - bool parseDirectiveCPSetup(); - bool parseDirectiveCPReturn(); - bool parseDirectiveNaN(); - bool parseDirectiveSet(); - bool parseDirectiveOption(); - bool parseInsnDirective(); - bool parseRSectionDirective(StringRef Section); - bool parseSSectionDirective(StringRef Section, unsigned Type); - - bool parseSetAtDirective(); - bool parseSetNoAtDirective(); - bool parseSetMacroDirective(); - bool parseSetNoMacroDirective(); - bool parseSetMsaDirective(); - bool parseSetNoMsaDirective(); - bool parseSetNoDspDirective(); - bool parseSetReorderDirective(); - bool parseSetNoReorderDirective(); - bool parseSetMips16Directive(); - bool parseSetNoMips16Directive(); - bool parseSetFpDirective(); - bool parseSetOddSPRegDirective(); - bool parseSetNoOddSPRegDirective(); - bool parseSetPopDirective(); - bool parseSetPushDirective(); - bool parseSetSoftFloatDirective(); - bool parseSetHardFloatDirective(); - bool parseSetMtDirective(); - bool parseSetNoMtDirective(); - bool parseSetNoCRCDirective(); - bool parseSetNoVirtDirective(); - bool parseSetNoGINVDirective(); - - bool parseSetAssignment(); - - bool parseDirectiveGpWord(); - bool parseDirectiveGpDWord(); - bool parseDirectiveDtpRelWord(); - bool parseDirectiveDtpRelDWord(); - bool parseDirectiveTpRelWord(); - bool parseDirectiveTpRelDWord(); - bool parseDirectiveModule(); - bool parseDirectiveModuleFP(); - bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI, - StringRef Directive); - - bool parseInternalDirectiveReallowModule(); - - bool eatComma(StringRef ErrorStr); - - int matchCPURegisterName(StringRef Symbol); - - int matchHWRegsRegisterName(StringRef Symbol); - - int matchFPURegisterName(StringRef Name); - - int matchFCCRegisterName(StringRef Name); - - int matchACRegisterName(StringRef Name); - - int matchMSA128RegisterName(StringRef Name); - - int matchMSA128CtrlRegisterName(StringRef Name); - - unsigned getReg(int RC, 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); - - // Helper function that checks if the value of a vector index is within the - // boundaries of accepted values for each RegisterKind - // Example: INSERT.B $w0[n], $1 => 16 > n >= 0 - bool validateMSAIndex(int Val, int RegKind); - - // Selects a new architecture by updating the FeatureBits with the necessary - // info including implied dependencies. - // Internally, it clears all the feature bits related to *any* architecture - // and selects the new one using the ToggleFeature functionality of the - // MCSubtargetInfo object that handles implied dependencies. The reason we - // clear all the arch related bits manually is because ToggleFeature only - // clears the features that imply the feature being cleared and not the - // features implied by the feature being cleared. This is easier to see - // with an example: - // -------------------------------------------------- - // | Feature | Implies | - // | -------------------------------------------------| - // | FeatureMips1 | None | - // | FeatureMips2 | FeatureMips1 | - // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 | - // | FeatureMips4 | FeatureMips3 | - // | ... | | - // -------------------------------------------------- - // - // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 | - // FeatureMipsGP64 | FeatureMips1) - // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4). - void selectArch(StringRef ArchFeature) { - MCSubtargetInfo &STI = copySTI(); - FeatureBitset FeatureBits = STI.getFeatureBits(); - FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask; - STI.setFeatureBits(FeatureBits); - setAvailableFeatures( - ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature))); - AssemblerOptions.back()->setFeatures(STI.getFeatureBits()); - } - - void setFeatureBits(uint64_t Feature, StringRef FeatureString) { - if (!(getSTI().getFeatureBits()[Feature])) { - MCSubtargetInfo &STI = copySTI(); - setAvailableFeatures( - ComputeAvailableFeatures(STI.ToggleFeature(FeatureString))); - AssemblerOptions.back()->setFeatures(STI.getFeatureBits()); - } - } - - void clearFeatureBits(uint64_t Feature, StringRef FeatureString) { - if (getSTI().getFeatureBits()[Feature]) { - MCSubtargetInfo &STI = copySTI(); - setAvailableFeatures( - ComputeAvailableFeatures(STI.ToggleFeature(FeatureString))); - AssemblerOptions.back()->setFeatures(STI.getFeatureBits()); - } - } - - void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) { - setFeatureBits(Feature, FeatureString); - AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits()); - } - - void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) { - clearFeatureBits(Feature, FeatureString); - AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits()); - } - -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 - }; - - MipsAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser, - const MCInstrInfo &MII, const MCTargetOptions &Options) - : MCTargetAsmParser(Options, sti, MII), - 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())); - - // Remember the initial assembler options. The user can not modify these. - AssemblerOptions.push_back( - llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits())); - - // Create an assembler options environment for the user to modify. - AssemblerOptions.push_back( - llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits())); - - getTargetStreamer().updateABIInfo(*this); - - if (!isABI_O32() && !useOddSPReg() != 0) - report_fatal_error("-mno-odd-spreg requires the O32 ABI"); - - CurrentFn = nullptr; - - IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent(); - - IsCpRestoreSet = false; - CpRestoreOffset = -1; - GPReg = ABI.GetGlobalPtr(); - - 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); - } - - /// True if all of $fcc0 - $fcc7 exist for the current ISA. - bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); } - - 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(); } - bool isABI_O32() const { return ABI.IsO32(); } - bool isABI_FPXX() const { - return getSTI().getFeatureBits()[Mips::FeatureFPXX]; - } - - bool useOddSPReg() const { - return !(getSTI().getFeatureBits()[Mips::FeatureNoOddSPReg]); - } - - 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]; - } - - 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]); - } - - bool hasCnMipsP() const { - return (getSTI().getFeatureBits()[Mips::FeatureCnMipsP]); - } - - bool inPicMode() { - return IsPicEnabled; - } - - bool inMips16Mode() const { - return getSTI().getFeatureBits()[Mips::FeatureMips16]; - } - - bool useTraps() const { - return getSTI().getFeatureBits()[Mips::FeatureUseTCCInDIV]; - } - - 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); - - 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); - } - } -}; - -/// MipsOperand - Instances of this class represent a parsed Mips machine -/// instruction. -class MipsOperand : public MCParsedAsmOperand { -public: - /// Broad categories of register classes - /// The exact class is finalized by the render method. - enum RegKind { - RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit()) - RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and - /// isFP64bit()) - RegKind_FCC = 4, /// FCC - RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which) - RegKind_MSACtrl = 16, /// MSA control registers - RegKind_COP2 = 32, /// COP2 - RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on - /// context). - RegKind_CCR = 128, /// CCR - RegKind_HWRegs = 256, /// HWRegs - RegKind_COP3 = 512, /// COP3 - RegKind_COP0 = 1024, /// COP0 - /// Potentially any (e.g. $1) - RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 | - RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC | - RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0 - }; - -private: - enum KindTy { - k_Immediate, /// An immediate (possibly involving symbol references) - k_Memory, /// Base + Offset Memory Address - k_RegisterIndex, /// A register index in one or more RegKind. - k_Token, /// A simple token - k_RegList, /// A physical register list - } 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; - - struct Token { - const char *Data; - unsigned Length; - }; - - 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; - }; - - struct ImmOp { - const MCExpr *Val; - }; - - struct MemOp { - MipsOperand *Base; - const MCExpr *Off; - }; - - struct RegListOp { - SmallVector<unsigned, 10> *List; - }; - - union { - struct Token Tok; - struct RegIdxOp RegIdx; - struct ImmOp Imm; - struct MemOp Mem; - struct RegListOp RegList; - }; - - SMLoc StartLoc, EndLoc; - - /// Internal constructor for register kinds - static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, StringRef Str, - RegKind RegKind, - const MCRegisterInfo *RegInfo, - SMLoc S, SMLoc E, - MipsAsmParser &Parser) { - auto Op = llvm::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; - } - -public: - /// Coerce the register to GPR32 and return the real register for the current - /// target. - unsigned getGPR32Reg() const { - assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!"); - AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc); - unsigned ClassID = Mips::GPR32RegClassID; - return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); - } - - /// Coerce the register to GPR32 and return the real register for the current - /// target. - unsigned getGPRMM16Reg() const { - assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!"); - unsigned ClassID = Mips::GPR32RegClassID; - return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); - } - - /// Coerce the register to GPR64 and return the real register for the current - /// target. - unsigned getGPR64Reg() const { - assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!"); - unsigned ClassID = Mips::GPR64RegClassID; - return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); - } - -private: - /// Coerce the register to AFGR64 and return the real register for the current - /// target. - unsigned getAFGR64Reg() const { - assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!"); - if (RegIdx.Index % 2 != 0) - AsmParser.Warning(StartLoc, "Float register should be even."); - return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID) - .getRegister(RegIdx.Index / 2); - } - - /// Coerce the register to FGR64 and return the real register for the current - /// target. - unsigned getFGR64Reg() const { - assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!"); - return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID) - .getRegister(RegIdx.Index); - } - - /// Coerce the register to FGR32 and return the real register for the current - /// target. - unsigned getFGR32Reg() const { - assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!"); - return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID) - .getRegister(RegIdx.Index); - } - - /// Coerce the register to FCC and return the real register for the current - /// target. - unsigned getFCCReg() const { - assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!"); - return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID) - .getRegister(RegIdx.Index); - } - - /// Coerce the register to MSA128 and return the real register for the current - /// target. - unsigned getMSA128Reg() const { - assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!"); - // It doesn't matter which of the MSA128[BHWD] classes we use. They are all - // identical - unsigned ClassID = Mips::MSA128BRegClassID; - return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); - } - - /// Coerce the register to MSACtrl and return the real register for the - /// current target. - unsigned getMSACtrlReg() const { - assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!"); - unsigned ClassID = Mips::MSACtrlRegClassID; - return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); - } - - /// Coerce the register to COP0 and return the real register for the - /// current target. - unsigned getCOP0Reg() const { - assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!"); - unsigned ClassID = Mips::COP0RegClassID; - return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); - } - - /// Coerce the register to COP2 and return the real register for the - /// current target. - unsigned getCOP2Reg() const { - assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!"); - unsigned ClassID = Mips::COP2RegClassID; - return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); - } - - /// Coerce the register to COP3 and return the real register for the - /// current target. - unsigned getCOP3Reg() const { - assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!"); - unsigned ClassID = Mips::COP3RegClassID; - return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); - } - - /// Coerce the register to ACC64DSP and return the real register for the - /// current target. - unsigned getACC64DSPReg() const { - assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!"); - unsigned ClassID = Mips::ACC64DSPRegClassID; - return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); - } - - /// Coerce the register to HI32DSP and return the real register for the - /// current target. - unsigned getHI32DSPReg() const { - assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!"); - unsigned ClassID = Mips::HI32DSPRegClassID; - return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); - } - - /// Coerce the register to LO32DSP and return the real register for the - /// current target. - unsigned getLO32DSPReg() const { - assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!"); - unsigned ClassID = Mips::LO32DSPRegClassID; - return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); - } - - /// Coerce the register to CCR and return the real register for the - /// current target. - unsigned getCCRReg() const { - assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!"); - unsigned ClassID = Mips::CCRRegClassID; - return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); - } - - /// Coerce the register to HWRegs and return the real register for the - /// current target. - unsigned getHWRegsReg() const { - assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!"); - unsigned ClassID = Mips::HWRegsRegClassID; - return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); - } - -public: - void addExpr(MCInst &Inst, const MCExpr *Expr) const { - // Add as immediate when possible. Null MCExpr = 0. - if (!Expr) - Inst.addOperand(MCOperand::createImm(0)); - else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr)) - Inst.addOperand(MCOperand::createImm(CE->getValue())); - else - Inst.addOperand(MCOperand::createExpr(Expr)); - } - - void addRegOperands(MCInst &Inst, unsigned N) const { - llvm_unreachable("Use a custom parser instead"); - } - - /// 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())); - } - - void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::createReg(getGPRMM16Reg())); - } - - void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::createReg(getGPRMM16Reg())); - } - - void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - 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 - void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::createReg(getGPR64Reg())); - } - - void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::createReg(getAFGR64Reg())); - } - - void 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())); - } - - void addFGR32AsmRegOperands(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. - // 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"); - } - - void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::createReg(getFCCReg())); - } - - void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::createReg(getMSA128Reg())); - } - - void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::createReg(getMSACtrlReg())); - } - - void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::createReg(getCOP0Reg())); - } - - void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::createReg(getCOP2Reg())); - } - - void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::createReg(getCOP3Reg())); - } - - void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::createReg(getACC64DSPReg())); - } - - void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::createReg(getHI32DSPReg())); - } - - void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::createReg(getLO32DSPReg())); - } - - void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::createReg(getCCRReg())); - } - - void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::createReg(getHWRegsReg())); - } - - template <unsigned Bits, int Offset = 0, int AdjustOffset = 0> - 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 += Offset; - Imm += AdjustOffset; - Inst.addOperand(MCOperand::createImm(Imm)); - } - - void addImmOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - const MCExpr *Expr = getImm(); - addExpr(Inst, Expr); - } - - void addMemOperands(MCInst &Inst, unsigned N) const { - assert(N == 2 && "Invalid number of operands!"); - - Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit() - ? getMemBase()->getGPR64Reg() - : getMemBase()->getGPR32Reg())); - - const MCExpr *Expr = getMemOff(); - addExpr(Inst, Expr); - } - - void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const { - assert(N == 2 && "Invalid number of operands!"); - - Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg())); - - const MCExpr *Expr = getMemOff(); - addExpr(Inst, Expr); - } - - void addRegListOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "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, accept - // $0/$zero here so that MCK_ZERO works correctly. - return isGPRAsmReg() && RegIdx.Index == 0; - } - - 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); - } - - 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 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()); - } - - 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()); - } - - 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; - - int Size = RegList.List->size(); - if (Size < 2 || Size > 5) - return false; - - unsigned R0 = RegList.List->front(); - unsigned R1 = RegList.List->back(); - if (!((R0 == Mips::S0 && R1 == Mips::RA) || - (R0 == Mips::S0_64 && R1 == Mips::RA_64))) - return false; - - int PrevReg = *RegList.List->begin(); - for (int i = 1; i < Size - 1; i++) { - int Reg = (*(RegList.List))[i]; - if ( Reg != PrevReg + 1) - return false; - PrevReg = Reg; - } - - 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; } - - StringRef getToken() const { - assert(Kind == k_Token && "Invalid access!"); - return StringRef(Tok.Data, Tok.Length); - } - - 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. - if (Kind == k_RegisterIndex && RegIdx.Index == 0 && - RegIdx.Kind & RegKind_GPR) - return getGPR32Reg(); // FIXME: GPR64 too - - llvm_unreachable("Invalid access!"); - return 0; - } - - const MCExpr *getImm() const { - assert((Kind == k_Immediate) && "Invalid access!"); - return Imm.Val; - } - - int64_t getConstantImm() const { - const MCExpr *Val = getImm(); - int64_t Value = 0; - (void)Val->evaluateAsAbsolute(Value); - return Value; - } - - MipsOperand *getMemBase() const { - assert((Kind == k_Memory) && "Invalid access!"); - return Mem.Base; - } - - const MCExpr *getMemOff() const { - assert((Kind == k_Memory) && "Invalid access!"); - return Mem.Off; - } - - int64_t getConstantMemOff() const { - return static_cast<const MCConstantExpr *>(getMemOff())->getValue(); - } - - const SmallVectorImpl<unsigned> &getRegList() const { - assert((Kind == k_RegList) && "Invalid access!"); - return *(RegList.List); - } - - static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S, - MipsAsmParser &Parser) { - auto Op = llvm::make_unique<MipsOperand>(k_Token, Parser); - Op->Tok.Data = Str.data(); - Op->Tok.Length = Str.size(); - Op->StartLoc = S; - Op->EndLoc = S; - return Op; - } - - /// 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); - } - - /// 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); - } - - /// 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); - } - - /// 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, - SMLoc S, SMLoc E, MipsAsmParser &Parser) { - return CreateReg(Index, Str, 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); - } - - /// 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); - } - - /// 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); - } - - /// 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); - } - - static std::unique_ptr<MipsOperand> - CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) { - auto Op = llvm::make_unique<MipsOperand>(k_Immediate, Parser); - Op->Imm.Val = Val; - Op->StartLoc = S; - Op->EndLoc = E; - return Op; - } - - 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); - Op->Mem.Base = Base.release(); - Op->Mem.Off = Off; - Op->StartLoc = S; - Op->EndLoc = E; - return Op; - } - - static std::unique_ptr<MipsOperand> - CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc, - MipsAsmParser &Parser) { - assert(Regs.size() > 0 && "Empty list not allowed"); - - auto Op = llvm::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; - } - - 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)) - return false; - return (RegIdx.Index == 0 || - (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; - 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; - } - - /// getStartLoc - Get the location of the first token of this operand. - SMLoc getStartLoc() const override { return StartLoc; } - /// getEndLoc - Get the location of the last token of this operand. - SMLoc getEndLoc() const override { return EndLoc; } - - void print(raw_ostream &OS) const override { - switch (Kind) { - case k_Immediate: - OS << "Imm<"; - OS << *Imm.Val; - OS << ">"; - break; - case k_Memory: - OS << "Mem<"; - Mem.Base->print(OS); - OS << ", "; - OS << *Mem.Off; - OS << ">"; - break; - case k_RegisterIndex: - OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ", " - << StringRef(RegIdx.Tok.Data, RegIdx.Tok.Length) << ">"; - break; - case k_Token: - OS << getToken(); - break; - case k_RegList: - OS << "RegList< "; - for (auto Reg : (*RegList.List)) - 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; - } - } - } -}; // class MipsOperand - -} // end anonymous 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: - 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; - } -} - -static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) { - if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) { - return &SRExpr->getSymbol(); - } - - if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) { - const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS()); - const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS()); - - if (LHSSym) - return LHSSym; - - if (RHSSym) - return RHSSym; - - return nullptr; - } - - if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr)) - return getSingleMCSymbol(UExpr->getSubExpr()); - - return nullptr; -} - -static unsigned countMCSymbolRefExpr(const MCExpr *Expr) { - if (isa<MCSymbolRefExpr>(Expr)) - return 1; - - if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) - return countMCSymbolRefExpr(BExpr->getLHS()) + - countMCSymbolRefExpr(BExpr->getRHS()); - - if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr)) - return countMCSymbolRefExpr(UExpr->getSubExpr()); - - return 0; -} - -bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, - MCStreamer &Out, - const MCSubtargetInfo *STI) { - MipsTargetStreamer &TOut = getTargetStreamer(); - const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode()); - bool ExpandedJalSym = false; - - Inst.setLoc(IDLoc); - - if (MCID.isBranch() || MCID.isCall()) { - const unsigned Opcode = Inst.getOpcode(); - MCOperand Offset; - - switch (Opcode) { - default: - break; - case Mips::BBIT0: - case Mips::BBIT032: - case Mips::BBIT1: - case Mips::BBIT132: - assert(hasCnMips() && "instruction only valid for octeon cpus"); - LLVM_FALLTHROUGH; - - case Mips::BEQ: - case Mips::BNE: - case Mips::BEQ_MM: - case Mips::BNE_MM: - assert(MCID.getNumOperands() == 3 && "unexpected number of operands"); - Offset = Inst.getOperand(2); - if (!Offset.isImm()) - break; // We'll deal with this situation later on when applying fixups. - if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm())) - return Error(IDLoc, "branch target out of range"); - if (OffsetToAlignment(Offset.getImm(), - 1LL << (inMicroMipsMode() ? 1 : 2))) - return Error(IDLoc, "branch to misaligned address"); - break; - case Mips::BGEZ: - case Mips::BGTZ: - case Mips::BLEZ: - case Mips::BLTZ: - case Mips::BGEZAL: - case Mips::BLTZAL: - case Mips::BC1F: - case Mips::BC1T: - case Mips::BGEZ_MM: - case Mips::BGTZ_MM: - case Mips::BLEZ_MM: - case Mips::BLTZ_MM: - case Mips::BGEZAL_MM: - case Mips::BLTZAL_MM: - case Mips::BC1F_MM: - case Mips::BC1T_MM: - 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()) - break; // We'll deal with this situation later on when applying fixups. - if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm())) - return Error(IDLoc, "branch target out of range"); - if (OffsetToAlignment(Offset.getImm(), - 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: - case Mips::BNEZC16_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 (!isInt<8>(Offset.getImm())) - return Error(IDLoc, "branch target out of range"); - if (OffsetToAlignment(Offset.getImm(), 2LL)) - return Error(IDLoc, "branch to misaligned address"); - break; - } - } - - // SSNOP is deprecated on MIPS32r6/MIPS64r6 - // We still accept it but it is a normal nop. - if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) { - std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6"; - Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a " - "nop instruction"); - } - - if (hasCnMips()) { - const unsigned Opcode = Inst.getOpcode(); - MCOperand Opnd; - int Imm; - - switch (Opcode) { - default: - break; - - case Mips::BBIT0: - case Mips::BBIT032: - case Mips::BBIT1: - case Mips::BBIT132: - assert(MCID.getNumOperands() == 3 && "unexpected number of operands"); - // The offset is handled above - Opnd = Inst.getOperand(1); - if (!Opnd.isImm()) - return Error(IDLoc, "expected immediate operand kind"); - Imm = Opnd.getImm(); - if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 || - Opcode == Mips::BBIT1 ? 63 : 31)) - return Error(IDLoc, "immediate operand value out of range"); - if (Imm > 31) { - Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032 - : Mips::BBIT132); - Inst.getOperand(1).setImm(Imm - 32); - } - break; - - case Mips::SEQi: - case Mips::SNEi: - assert(MCID.getNumOperands() == 3 && "unexpected number of operands"); - Opnd = Inst.getOperand(2); - if (!Opnd.isImm()) - return Error(IDLoc, "expected immediate operand kind"); - Imm = Opnd.getImm(); - if (!isInt<10>(Imm)) - return Error(IDLoc, "immediate operand value out of range"); - break; - } - } - - // 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) && - inPicMode()) { - warnIfNoMacro(IDLoc); - - const MCExpr *JalExpr = Inst.getOperand(0).getExpr(); - - // We can do this expansion if there's only 1 symbol in the argument - // expression. - if (countMCSymbolRefExpr(JalExpr) > 1) - 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. - 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 (isABI_O32()) { - // If it's a local symbol and the O32 ABI is being used, we expand to: - // lw $25, 0($gp) - // R_(MICRO)MIPS_GOT16 label - // 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, GPReg, - MCOperand::createExpr(Got16RelocExpr), IDLoc, STI); - TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9, - MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI); - } 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()); - - TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, - GPReg, MCOperand::createExpr(GotDispRelocExpr), IDLoc, - STI); - } - } 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()); - - TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, GPReg, - MCOperand::createExpr(Call16RelocExpr), IDLoc, STI); - } - - MCInst JalrInst; - if (IsCpRestoreSet && inMicroMipsMode()) - JalrInst.setOpcode(Mips::JALRS_MM); - else - JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR); - 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); - } - - Inst = JalrInst; - ExpandedJalSym = true; - } - - bool IsPCRelativeLoad = (MCID.TSFlags & MipsII::IsPCRelativeLoad) != 0; - if ((MCID.mayLoad() || MCID.mayStore()) && !IsPCRelativeLoad) { - // 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++) { - const MCOperandInfo &OpInfo = MCID.OpInfo[i]; - if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) || - (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) { - MCOperand &Op = Inst.getOperand(i); - if (Op.isImm()) { - int64_t MemOffset = Op.getImm(); - if (MemOffset < -32768 || MemOffset > 32767) { - // Offset can't exceed 16bit value. - expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad()); - return getParser().hasPendingError(); - } - } else if (Op.isExpr()) { - const MCExpr *Expr = Op.getExpr(); - if (Expr->getKind() == MCExpr::SymbolRef) { - const MCSymbolRefExpr *SR = - static_cast<const MCSymbolRefExpr *>(Expr); - if (SR->getKind() == MCSymbolRefExpr::VK_None) { - // Expand symbol. - expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad()); - return getParser().hasPendingError(); - } - } else if (!isEvaluated(Expr)) { - expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad()); - return getParser().hasPendingError(); - } - } - } - } // for - } // if load/store - - if (inMicroMipsMode()) { - if (MCID.mayLoad() && Inst.getOpcode() != Mips::LWP_MM) { - // Try to create 16-bit GP relative load instruction. - for (unsigned i = 0; i < MCID.getNumOperands(); i++) { - const MCOperandInfo &OpInfo = MCID.OpInfo[i]; - if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) || - (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) { - MCOperand &Op = Inst.getOperand(i); - if (Op.isImm()) { - int MemOffset = Op.getImm(); - MCOperand &DstReg = Inst.getOperand(0); - MCOperand &BaseReg = Inst.getOperand(1); - if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) && - getContext().getRegisterInfo()->getRegClass( - Mips::GPRMM16RegClassID).contains(DstReg.getReg()) && - (BaseReg.getReg() == Mips::GP || - BaseReg.getReg() == Mips::GP_64)) { - - TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset, - IDLoc, STI); - return false; - } - } - } - } // for - } // if load - - // TODO: Handle this with the AsmOperandClass.PredicateMethod. - - MCOperand Opnd; - int Imm; - - switch (Inst.getOpcode()) { - default: - break; - case Mips::ADDIUSP_MM: - Opnd = Inst.getOperand(0); - if (!Opnd.isImm()) - return Error(IDLoc, "expected immediate operand kind"); - Imm = Opnd.getImm(); - if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) || - Imm % 4 != 0) - return Error(IDLoc, "immediate operand value out of range"); - break; - case Mips::SLL16_MM: - case Mips::SRL16_MM: - Opnd = Inst.getOperand(2); - if (!Opnd.isImm()) - return Error(IDLoc, "expected immediate operand kind"); - Imm = Opnd.getImm(); - if (Imm < 1 || Imm > 8) - return Error(IDLoc, "immediate operand value out of range"); - break; - case Mips::LI16_MM: - Opnd = Inst.getOperand(1); - if (!Opnd.isImm()) - return Error(IDLoc, "expected immediate operand kind"); - Imm = Opnd.getImm(); - if (Imm < -1 || Imm > 126) - return Error(IDLoc, "immediate operand value out of range"); - break; - case Mips::ADDIUR2_MM: - Opnd = Inst.getOperand(2); - if (!Opnd.isImm()) - return Error(IDLoc, "expected immediate operand kind"); - Imm = Opnd.getImm(); - if (!(Imm == 1 || Imm == -1 || - ((Imm % 4 == 0) && Imm < 28 && Imm > 0))) - return Error(IDLoc, "immediate operand value out of range"); - break; - case Mips::ANDI16_MM: - Opnd = Inst.getOperand(2); - if (!Opnd.isImm()) - return Error(IDLoc, "expected immediate operand kind"); - Imm = Opnd.getImm(); - if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 || - Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 || - Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535)) - return Error(IDLoc, "immediate operand value out of range"); - break; - case Mips::LBU16_MM: - Opnd = Inst.getOperand(2); - if (!Opnd.isImm()) - return Error(IDLoc, "expected immediate operand kind"); - Imm = Opnd.getImm(); - if (Imm < -1 || Imm > 14) - return Error(IDLoc, "immediate operand value out of range"); - break; - case Mips::SB16_MM: - case Mips::SB16_MMR6: - Opnd = Inst.getOperand(2); - if (!Opnd.isImm()) - return Error(IDLoc, "expected immediate operand kind"); - Imm = Opnd.getImm(); - if (Imm < 0 || Imm > 15) - return Error(IDLoc, "immediate operand value out of range"); - break; - case Mips::LHU16_MM: - case Mips::SH16_MM: - case Mips::SH16_MMR6: - Opnd = Inst.getOperand(2); - if (!Opnd.isImm()) - return Error(IDLoc, "expected immediate operand kind"); - Imm = Opnd.getImm(); - if (Imm < 0 || Imm > 30 || (Imm % 2 != 0)) - return Error(IDLoc, "immediate operand value out of range"); - break; - case Mips::LW16_MM: - case Mips::SW16_MM: - case Mips::SW16_MMR6: - Opnd = Inst.getOperand(2); - if (!Opnd.isImm()) - return Error(IDLoc, "expected immediate operand kind"); - Imm = Opnd.getImm(); - if (Imm < 0 || Imm > 60 || (Imm % 4 != 0)) - return Error(IDLoc, "immediate operand value out of range"); - break; - case Mips::ADDIUPC_MM: - Opnd = Inst.getOperand(1); - if (!Opnd.isImm()) - return Error(IDLoc, "expected immediate operand kind"); - 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); - switch (ExpandResult) { - case MER_NotAMacro: - Out.EmitInstruction(Inst, *STI); - break; - case MER_Success: - break; - case MER_Fail: - 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 ((Inst.getOpcode() == Mips::JalOneReg || - Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) && - isPicAndNotNxxAbi()) { - if (IsCpRestoreSet) { - // We need a NOP between the JALR and the LW: - // 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); - - // Load the $gp from the stack. - TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI); - } else - Warning(IDLoc, "no .cprestore used in PIC mode"); - } - - return false; -} - -MipsAsmParser::MacroExpanderResultTy -MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI) { - switch (Inst.getOpcode()) { - default: - return MER_NotAMacro; - case Mips::LoadImm32: - return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success; - case Mips::LoadImm64: - return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success; - case Mips::LoadAddrImm32: - case Mips::LoadAddrImm64: - assert(Inst.getOperand(0).isReg() && "expected register operand kind"); - assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) && - "expected immediate operand kind"); - - return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister, - Inst.getOperand(1), - Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc, - Out, STI) - ? MER_Fail - : MER_Success; - case Mips::LoadAddrReg32: - case Mips::LoadAddrReg64: - assert(Inst.getOperand(0).isReg() && "expected register operand kind"); - assert(Inst.getOperand(1).isReg() && "expected register operand kind"); - assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) && - "expected immediate operand kind"); - - return expandLoadAddress(Inst.getOperand(0).getReg(), - Inst.getOperand(1).getReg(), Inst.getOperand(2), - Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc, - Out, STI) - ? MER_Fail - : MER_Success; - case Mips::B_MM_Pseudo: - case Mips::B_MMR6_Pseudo: - return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail - : MER_Success; - case Mips::SWM_MM: - case Mips::LWM_MM: - return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail - : MER_Success; - case Mips::JalOneReg: - case Mips::JalTwoReg: - return expandJalWithRegs(Inst, IDLoc, Out, STI) ? 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; - case Mips::BLT: - case Mips::BLE: - case Mips::BGE: - case Mips::BGT: - case Mips::BLTU: - case Mips::BLEU: - case Mips::BGEU: - case Mips::BGTU: - case Mips::BLTL: - case Mips::BLEL: - case Mips::BGEL: - case Mips::BGTL: - case Mips::BLTUL: - case Mips::BLEUL: - case Mips::BGEUL: - case Mips::BGTUL: - case Mips::BLTImmMacro: - case Mips::BLEImmMacro: - case Mips::BGEImmMacro: - case Mips::BGTImmMacro: - case Mips::BLTUImmMacro: - case Mips::BLEUImmMacro: - case Mips::BGEUImmMacro: - case Mips::BGTUImmMacro: - case Mips::BLTLImmMacro: - case Mips::BLELImmMacro: - case Mips::BGELImmMacro: - case Mips::BGTLImmMacro: - case Mips::BLTULImmMacro: - case Mips::BLEULImmMacro: - case Mips::BGEULImmMacro: - case Mips::BGTULImmMacro: - return expandCondBranches(Inst, IDLoc, Out, STI) ? 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; - case Mips::DSDivMacro: - case Mips::DSDivIMacro: - case Mips::DSRemMacro: - case Mips::DSRemIMacro: - return expandDivRem(Inst, IDLoc, Out, STI, 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; - 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; - case Mips::Ulh: - return expandUlh(Inst, true, IDLoc, Out, STI) ? 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; - case Mips::Ulw: - case Mips::Usw: - return expandUxw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; - case Mips::NORImm: - case Mips::NORImm64: - return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; - case Mips::SGE: - case Mips::SGEU: - return expandSge(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; - case Mips::SGEImm: - case Mips::SGEUImm: - case Mips::SGEImm64: - case Mips::SGEUImm64: - return expandSgeImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; - case Mips::SGTImm: - case Mips::SGTUImm: - case Mips::SGTImm64: - case Mips::SGTUImm64: - return expandSgtImm(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: - 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 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: - 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 MER_NotAMacro; - case Mips::ROL: - case Mips::ROR: - return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; - case Mips::ROLImm: - case Mips::RORImm: - return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; - case Mips::DROL: - case Mips::DROR: - return expandDRotation(Inst, IDLoc, Out, STI) ? 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::SDC1_M1: - return expandStoreDM1Macro(Inst, IDLoc, Out, STI) - ? 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; - case Mips::SaaAddr: - case Mips::SaadAddr: - return expandSaaAddr(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; - } -} - -bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, - MCStreamer &Out, - const MCSubtargetInfo *STI) { - MipsTargetStreamer &TOut = getTargetStreamer(); - - // Create a JALR instruction which is going to replace the pseudo-JAL. - MCInst JalrInst; - JalrInst.setLoc(IDLoc); - const MCOperand FirstRegOp = Inst.getOperand(0); - const unsigned Opcode = Inst.getOpcode(); - - if (Opcode == Mips::JalOneReg) { - // jal $rs => jalr $rs - if (IsCpRestoreSet && inMicroMipsMode()) { - JalrInst.setOpcode(Mips::JALRS16_MM); - JalrInst.addOperand(FirstRegOp); - } else if (inMicroMipsMode()) { - JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM); - JalrInst.addOperand(FirstRegOp); - } else { - JalrInst.setOpcode(Mips::JALR); - JalrInst.addOperand(MCOperand::createReg(Mips::RA)); - JalrInst.addOperand(FirstRegOp); - } - } else if (Opcode == Mips::JalTwoReg) { - // jal $rd, $rs => jalr $rd, $rs - if (IsCpRestoreSet && inMicroMipsMode()) - JalrInst.setOpcode(Mips::JALRS_MM); - else - JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR); - JalrInst.addOperand(FirstRegOp); - const MCOperand SecondRegOp = Inst.getOperand(1); - JalrInst.addOperand(SecondRegOp); - } - Out.EmitInstruction(JalrInst, *STI); - - // 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); - - return false; -} - -/// Can the value be represented by a unsigned N-bit value and a shift left? -template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) { - unsigned BitNum = findFirstSet(x); - - return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum); -} - -/// Load (or add) an immediate into a register. -/// -/// @param ImmValue The immediate to load. -/// @param DstReg The register that will hold the immediate. -/// @param SrcReg A register to add to the immediate or Mips::NoRegister -/// for a simple initialization. -/// @param Is32BitImm Is ImmValue 32-bit or 64-bit? -/// @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. -bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg, - unsigned SrcReg, bool Is32BitImm, - bool IsAddress, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI) { - MipsTargetStreamer &TOut = getTargetStreamer(); - - if (!Is32BitImm && !isGP64bit()) { - Error(IDLoc, "instruction requires a 64-bit architecture"); - return true; - } - - if (Is32BitImm) { - if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) { - // Sign extend up to 64-bit so that the predicates match the hardware - // behaviour. In particular, isInt<16>(0xffff8000) and similar should be - // true. - ImmValue = SignExtend64<32>(ImmValue); - } else { - Error(IDLoc, "instruction requires a 32-bit immediate"); - return true; - } - } - - unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg(); - unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu; - - bool UseSrcReg = false; - if (SrcReg != Mips::NoRegister) - UseSrcReg = true; - - unsigned TmpReg = DstReg; - if (UseSrcReg && - getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) { - // At this point we need AT to perform the expansions and we exit if it is - // not available. - unsigned ATReg = getATReg(IDLoc); - if (!ATReg) - return true; - TmpReg = ATReg; - } - - if (isInt<16>(ImmValue)) { - if (!UseSrcReg) - SrcReg = ZeroReg; - - // This doesn't quite follow the usual ABI expectations for N32 but matches - // 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); - return false; - } - - TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI); - return false; - } - - if (isUInt<16>(ImmValue)) { - unsigned TmpReg = DstReg; - if (SrcReg == DstReg) { - TmpReg = getATReg(IDLoc); - if (!TmpReg) - return true; - } - - TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI); - if (UseSrcReg) - TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI); - return false; - } - - if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) { - warnIfNoMacro(IDLoc); - - 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); - if (UseSrcReg) - TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI); - 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); - if (Bits15To0) - TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI); - if (UseSrcReg) - TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI); - return false; - } - - TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI); - if (Bits15To0) - TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI); - if (UseSrcReg) - TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI); - return false; - } - - if (isShiftedUIntAtAnyPosition<16>(ImmValue)) { - if (Is32BitImm) { - Error(IDLoc, "instruction requires a 32-bit immediate"); - return true; - } - - // Traditionally, these immediates are shifted as little as possible and as - // such we align the most significant bit to bit 15 of our temporary. - unsigned FirstSet = findFirstSet((uint64_t)ImmValue); - 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); - - if (UseSrcReg) - TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI); - - return false; - } - - warnIfNoMacro(IDLoc); - - // The remaining case is packed with a sequence of dsll and ori with zeros - // being omitted and any neighbouring dsll's being coalesced. - // The highest 32-bit's are equivalent to a 32-bit immediate load. - - // 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)) - return false; - - // Shift and accumulate into the register. If a 16-bit chunk is zero, then - // skip it and defer the shift to the next chunk. - unsigned ShiftCarriedForwards = 16; - for (int BitNum = 16; BitNum >= 0; BitNum -= 16) { - 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); - ShiftCarriedForwards = 0; - } - - ShiftCarriedForwards += 16; - } - ShiftCarriedForwards -= 16; - - // Finish any remaining shifts left by trailing zeros. - if (ShiftCarriedForwards) - TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI); - - if (UseSrcReg) - TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI); - - return false; -} - -bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc, - MCStreamer &Out, const MCSubtargetInfo *STI) { - 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)) - return true; - - return false; -} - -bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg, - const MCOperand &Offset, - bool Is32BitAddress, SMLoc IDLoc, - MCStreamer &Out, - const MCSubtargetInfo *STI) { - // 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. - // We currently can't do this because we depend on the equality - // operator and N64 can end up with a GPR32/GPR64 mismatch. - 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()) { - 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; - } - - return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true, - IDLoc, Out, STI); -} - -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; - 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, GPReg, 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, GPReg, 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, GPReg, 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, GPReg, 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); - - return false; - } - - const MipsMCExpr *HiExpr = - MipsMCExpr::create(MipsMCExpr::MEK_HI, SymExpr, getContext()); - const MipsMCExpr *LoExpr = - MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext()); - - // 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); - - if (canUseATReg() && UseSrcReg && RdRegIsRsReg) { - unsigned ATReg = getATReg(IDLoc); - - // If $rs is the same as $rd: - // (d)la $rd, sym($rd) => lui $at, %highest(sym) - // daddiu $at, $at, %higher(sym) - // dsll $at, $at, 16 - // daddiu $at, $at, %hi(sym) - // 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); - - return false; - } else if (canUseATReg() && !RdRegIsRsReg && DstReg != getATReg(IDLoc)) { - 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) || - (canUseATReg() && DstReg == getATReg(IDLoc))) { - // 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); - - 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; - } - } - - // And now, the 32-bit symbol address expansion: - // If $rs is the same as $rd: - // (d)la $rd, sym($rd) => lui $at, %hi(sym) - // ori $at, $at, %lo(sym) - // addu $rd, $at, $rd - // Otherwise, if the $rs is different from $rd or if $rs isn't specified: - // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym) - // ori $rd, $rd, %lo(sym) - // (addu $rd, $rd, $rs) - 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.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI); - TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), - IDLoc, STI); - - if (UseSrcReg) - TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI); - 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, GPReg, MCOperand::createExpr(GotExpr), - IDLoc, STI); - } else { //isABI_N64() - TOut.emitRRX(Mips::LD, ATReg, GPReg, 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); - - 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(); - - assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 && - "unexpected number of operands"); - - MCOperand Offset = Inst.getOperand(0); - if (Offset.isExpr()) { - Inst.clear(); - Inst.setOpcode(Mips::BEQ_MM); - Inst.addOperand(MCOperand::createReg(Mips::ZERO)); - Inst.addOperand(MCOperand::createReg(Mips::ZERO)); - Inst.addOperand(MCOperand::createExpr(Offset.getExpr())); - } else { - assert(Offset.isImm() && "expected immediate operand kind"); - if (isInt<11>(Offset.getImm())) { - // If offset fits into 11 bits then this instruction becomes microMIPS - // 16-bit unconditional branch instruction. - if (inMicroMipsMode()) - Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM); - } else { - if (!isInt<17>(Offset.getImm())) - return Error(IDLoc, "branch target out of range"); - if (OffsetToAlignment(Offset.getImm(), 1LL << 1)) - return Error(IDLoc, "branch to misaligned address"); - Inst.clear(); - Inst.setOpcode(Mips::BEQ_MM); - Inst.addOperand(MCOperand::createReg(Mips::ZERO)); - Inst.addOperand(MCOperand::createReg(Mips::ZERO)); - Inst.addOperand(MCOperand::createImm(Offset.getImm())); - } - } - Out.EmitInstruction(Inst, *STI); - - // 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); - - return false; -} - -bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI) { - MipsTargetStreamer &TOut = getTargetStreamer(); - const MCOperand &DstRegOp = Inst.getOperand(0); - assert(DstRegOp.isReg() && "expected register operand kind"); - - const MCOperand &ImmOp = Inst.getOperand(1); - 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; - - unsigned OpCode = 0; - switch(Inst.getOpcode()) { - case Mips::BneImm: - OpCode = Mips::BNE; - break; - 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 { - warnIfNoMacro(IDLoc); - - unsigned ATReg = getATReg(IDLoc); - if (!ATReg) - return true; - - if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true, - IDLoc, Out, STI)) - 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); - } - 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; - - 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) - 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); - return; - } - - assert(OffsetOp.isExpr() && "expected expression operand kind"); - if (inPicMode()) { - // FIXME: - // a) Fix lw/sw $reg, symbol($reg) instruction expanding. - // b) If expression includes offset (sym + number), do not - // encode the offset into a relocation. Take it in account - // in the last load/store instruction. - // c) Check that immediates of R_MIPS_GOT16/R_MIPS_LO16 relocations - // do not exceed 16-bit. - // d) Use R_MIPS_GOT_PAGE/R_MIPS_GOT_OFST relocations instead - // of R_MIPS_GOT_DISP in appropriate cases to reduce number - // of GOT entries. - expandLoadAddress(TmpReg, Mips::NoRegister, OffsetOp, !ABI.ArePtrs64bit(), - IDLoc, Out, STI); - TOut.emitRRI(Inst.getOpcode(), DstReg, TmpReg, 0, IDLoc, STI); - } else { - 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) { - 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."); - - if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 && - Inst.getOperand(OpNum - 1).getImm() >= 0 && - (Inst.getOperand(OpNum - 2).getReg() == Mips::SP || - Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) && - (Inst.getOperand(OpNum - 3).getReg() == Mips::RA || - Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) { - // It can be implemented as SWM16 or LWM16 instruction. - if (inMicroMipsMode() && hasMips32r6()) - NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6; - else - NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM; - } - - Inst.setOpcode(NewOpcode); - Out.EmitInstruction(Inst, *STI); - return false; -} - -bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc, - MCStreamer &Out, - const MCSubtargetInfo *STI) { - MipsTargetStreamer &TOut = getTargetStreamer(); - bool EmittedNoMacroWarning = false; - unsigned PseudoOpcode = Inst.getOpcode(); - unsigned SrcReg = Inst.getOperand(0).getReg(); - const MCOperand &TrgOp = Inst.getOperand(1); - const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr(); - - unsigned ZeroSrcOpcode, ZeroTrgOpcode; - bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality; - - unsigned TrgReg; - if (TrgOp.isReg()) - TrgReg = TrgOp.getReg(); - else if (TrgOp.isImm()) { - warnIfNoMacro(IDLoc); - EmittedNoMacroWarning = true; - - TrgReg = getATReg(IDLoc); - if (!TrgReg) - return true; - - switch(PseudoOpcode) { - default: - llvm_unreachable("unknown opcode for branch pseudo-instruction"); - case Mips::BLTImmMacro: - PseudoOpcode = Mips::BLT; - break; - case Mips::BLEImmMacro: - PseudoOpcode = Mips::BLE; - break; - case Mips::BGEImmMacro: - PseudoOpcode = Mips::BGE; - break; - case Mips::BGTImmMacro: - PseudoOpcode = Mips::BGT; - break; - case Mips::BLTUImmMacro: - PseudoOpcode = Mips::BLTU; - break; - case Mips::BLEUImmMacro: - PseudoOpcode = Mips::BLEU; - break; - case Mips::BGEUImmMacro: - PseudoOpcode = Mips::BGEU; - break; - case Mips::BGTUImmMacro: - PseudoOpcode = Mips::BGTU; - break; - case Mips::BLTLImmMacro: - PseudoOpcode = Mips::BLTL; - break; - case Mips::BLELImmMacro: - PseudoOpcode = Mips::BLEL; - break; - case Mips::BGELImmMacro: - PseudoOpcode = Mips::BGEL; - break; - case Mips::BGTLImmMacro: - PseudoOpcode = Mips::BGTL; - break; - case Mips::BLTULImmMacro: - PseudoOpcode = Mips::BLTUL; - break; - case Mips::BLEULImmMacro: - PseudoOpcode = Mips::BLEUL; - break; - case Mips::BGEULImmMacro: - PseudoOpcode = Mips::BGEUL; - break; - case Mips::BGTULImmMacro: - PseudoOpcode = Mips::BGTUL; - break; - } - - if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(), - false, IDLoc, Out, STI)) - return true; - } - - switch (PseudoOpcode) { - case Mips::BLT: - case Mips::BLTU: - case Mips::BLTL: - case Mips::BLTUL: - AcceptsEquality = false; - ReverseOrderSLT = false; - IsUnsigned = - ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL)); - IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL)); - ZeroSrcOpcode = Mips::BGTZ; - ZeroTrgOpcode = Mips::BLTZ; - break; - case Mips::BLE: - case Mips::BLEU: - case Mips::BLEL: - case Mips::BLEUL: - AcceptsEquality = true; - ReverseOrderSLT = true; - IsUnsigned = - ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL)); - IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL)); - ZeroSrcOpcode = Mips::BGEZ; - ZeroTrgOpcode = Mips::BLEZ; - break; - case Mips::BGE: - case Mips::BGEU: - case Mips::BGEL: - case Mips::BGEUL: - AcceptsEquality = true; - ReverseOrderSLT = false; - IsUnsigned = - ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL)); - IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL)); - ZeroSrcOpcode = Mips::BLEZ; - ZeroTrgOpcode = Mips::BGEZ; - break; - case Mips::BGT: - case Mips::BGTU: - case Mips::BGTL: - case Mips::BGTUL: - AcceptsEquality = false; - ReverseOrderSLT = true; - IsUnsigned = - ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL)); - IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL)); - ZeroSrcOpcode = Mips::BLTZ; - ZeroTrgOpcode = Mips::BGTZ; - break; - default: - llvm_unreachable("unknown opcode for branch pseudo-instruction"); - } - - bool IsTrgRegZero = (TrgReg == Mips::ZERO); - bool IsSrcRegZero = (SrcReg == Mips::ZERO); - if (IsSrcRegZero && IsTrgRegZero) { - // FIXME: All of these Opcode-specific if's are needed for compatibility - // 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); - return false; - } - if (PseudoOpcode == Mips::BLE) { - TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), - IDLoc, STI); - Warning(IDLoc, "branch is always taken"); - return false; - } - if (PseudoOpcode == Mips::BGE) { - TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), - IDLoc, STI); - Warning(IDLoc, "branch is always taken"); - return false; - } - if (PseudoOpcode == Mips::BGT) { - TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), - IDLoc, STI); - return false; - } - if (PseudoOpcode == Mips::BGTU) { - TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO, - MCOperand::createExpr(OffsetExpr), IDLoc, STI); - 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); - Warning(IDLoc, "branch is always taken"); - return false; - } - // If both registers are $0 and the pseudo-branch does not accept - // equality, it will never be taken, so we don't have to emit anything. - return false; - } - if (IsSrcRegZero || IsTrgRegZero) { - if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) || - (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) { - // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or - // if the $rt is $0 and the pseudo-branch is BLTU (x < 0), - // the pseudo-branch will never be taken, so we don't emit anything. - // This only applies to unsigned pseudo-branches. - return false; - } - if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) || - (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) { - // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or - // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0), - // 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); - Warning(IDLoc, "branch is always taken"); - return false; - } - if (IsUnsigned) { - // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or - // if the $rt is $0 and the pseudo-branch is BGTU (x > 0), - // the pseudo-branch will be taken only when the non-zero register is - // different from 0, so we emit a BNEZ. - // - // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or - // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0), - // the pseudo-branch will be taken only when the non-zero register is - // equal to 0, so we emit a BEQZ. - // - // 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); - 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); - return false; - } - - // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the - // expansions. If it is not available, we return. - unsigned ATRegNum = getATReg(IDLoc); - if (!ATRegNum) - return true; - - if (!EmittedNoMacroWarning) - warnIfNoMacro(IDLoc); - - // SLT fits well with 2 of our 4 pseudo-branches: - // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and - // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs". - // If the result of the SLT is 1, we branch, and if it's 0, we don't. - // 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. - // 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 - // opposites. - // - // 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); - 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(); - - 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); - 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(); - - 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 (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; - } 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); - 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); - 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; - - if (UseTraps) { - TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI); - } else { - // Branch to the li instruction. - BrTarget = Context.createTempSymbol(); - LabelOp = MCOperand::createExpr(MCSymbolRefExpr::create(BrTarget, Context)); - TOut.emitRRX(Mips::BNE, RtReg, ZeroReg, LabelOp, IDLoc, STI); - } - - TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI); - - if (!UseTraps) - TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI); - - if (!Signed) { - if (!UseTraps) - TOut.getStreamer().EmitLabel(BrTarget); - - TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI); - return false; - } - - unsigned ATReg = getATReg(IDLoc); - 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); - - if (IsMips64) { - TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI); - TOut.emitDSLL(ATReg, ATReg, 63, IDLoc, STI); - } else { - TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI); - } - - if (UseTraps) - TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI); - 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); - } - - 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); - - return false; -} - -bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc, - MCStreamer &Out, const MCSubtargetInfo *STI) { - if (hasMips32r6() || hasMips64r6()) { - return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6"); - } - - 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); - - unsigned FirstLbuDstReg = IsLargeOffset ? DstReg : ATReg; - unsigned SecondLbuDstReg = IsLargeOffset ? ATReg : DstReg; - - unsigned LbuSrcReg = IsLargeOffset ? ATReg : SrcReg; - unsigned SllReg = IsLargeOffset ? DstReg : ATReg; - - 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); - - 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"); - } - - 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(); - - 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 ? 1 : (OffsetValue + 1); - int64_t SecondOffset = IsLargeOffset ? 0 : OffsetValue; - if (isLittle()) - std::swap(FirstOffset, SecondOffset); - - 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); - } - - return false; -} - -bool MipsAsmParser::expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI) { - if (hasMips32r6() || hasMips64r6()) { - return Error(IDLoc, "instruction not supported on mips32r6 or mips64r6"); - } - - 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(); - - // 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)) - return true; - } - - if (DoMove) - std::swap(DstReg, TmpReg); - - 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); - - if (DoMove) - TOut.emitRRR(Mips::OR, TmpReg, DstReg, Mips::ZERO, IDLoc, STI); - - return false; -} - -bool MipsAsmParser::expandSge(MCInst &Inst, 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 DstReg = Inst.getOperand(0).getReg(); - unsigned SrcReg = Inst.getOperand(1).getReg(); - unsigned OpReg = Inst.getOperand(2).getReg(); - unsigned OpCode; - - warnIfNoMacro(IDLoc); - - switch (Inst.getOpcode()) { - case Mips::SGE: - OpCode = Mips::SLT; - break; - case Mips::SGEU: - OpCode = Mips::SLTu; - break; - default: - llvm_unreachable("unexpected 'sge' opcode"); - } - - // $SrcReg >= $OpReg is equal to (not ($SrcReg < $OpReg)) - TOut.emitRRR(OpCode, DstReg, SrcReg, OpReg, IDLoc, STI); - TOut.emitRRI(Mips::XORi, DstReg, DstReg, 1, IDLoc, STI); - - return false; -} - -bool MipsAsmParser::expandSgeImm(MCInst &Inst, 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).isImm() && "Invalid instruction operand."); - - unsigned DstReg = Inst.getOperand(0).getReg(); - unsigned SrcReg = Inst.getOperand(1).getReg(); - int64_t ImmValue = Inst.getOperand(2).getImm(); - unsigned OpRegCode, OpImmCode; - - warnIfNoMacro(IDLoc); - - switch (Inst.getOpcode()) { - case Mips::SGEImm: - case Mips::SGEImm64: - OpRegCode = Mips::SLT; - OpImmCode = Mips::SLTi; - break; - case Mips::SGEUImm: - case Mips::SGEUImm64: - OpRegCode = Mips::SLTu; - OpImmCode = Mips::SLTiu; - break; - default: - llvm_unreachable("unexpected 'sge' opcode with immediate"); - } - - // $SrcReg >= Imm is equal to (not ($SrcReg < Imm)) - if (isInt<16>(ImmValue)) { - // Use immediate version of STL. - TOut.emitRRI(OpImmCode, DstReg, SrcReg, ImmValue, IDLoc, STI); - TOut.emitRRI(Mips::XORi, DstReg, DstReg, 1, IDLoc, STI); - } else { - unsigned ImmReg = DstReg; - if (DstReg == SrcReg) { - unsigned ATReg = getATReg(Inst.getLoc()); - if (!ATReg) - return true; - ImmReg = ATReg; - } - - if (loadImmediate(ImmValue, ImmReg, Mips::NoRegister, isInt<32>(ImmValue), - false, IDLoc, Out, STI)) - return true; - - TOut.emitRRR(OpRegCode, DstReg, SrcReg, ImmReg, IDLoc, STI); - TOut.emitRRI(Mips::XORi, DstReg, DstReg, 1, IDLoc, STI); - } - - return false; -} - -bool MipsAsmParser::expandSgtImm(MCInst &Inst, 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).isImm() && "Invalid instruction operand."); - - unsigned DstReg = Inst.getOperand(0).getReg(); - unsigned SrcReg = Inst.getOperand(1).getReg(); - unsigned ImmReg = DstReg; - int64_t ImmValue = Inst.getOperand(2).getImm(); - unsigned OpCode; - - warnIfNoMacro(IDLoc); - - switch (Inst.getOpcode()) { - case Mips::SGTImm: - case Mips::SGTImm64: - OpCode = Mips::SLT; - break; - case Mips::SGTUImm: - case Mips::SGTUImm64: - OpCode = Mips::SLTu; - break; - default: - llvm_unreachable("unexpected 'sgt' opcode with immediate"); - } - - if (DstReg == SrcReg) { - unsigned ATReg = getATReg(Inst.getLoc()); - if (!ATReg) - return true; - ImmReg = ATReg; - } - - if (loadImmediate(ImmValue, ImmReg, Mips::NoRegister, isInt<32>(ImmValue), - false, IDLoc, Out, STI)) - return true; - - // $SrcReg > $ImmReg is equal to $ImmReg < $SrcReg - TOut.emitRRR(OpCode, DstReg, ImmReg, SrcReg, IDLoc, STI); - - return false; -} - -bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, 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).isImm() && "Invalid instruction operand."); - - unsigned ATReg = Mips::NoRegister; - unsigned FinalDstReg = Mips::NoRegister; - unsigned DstReg = Inst.getOperand(0).getReg(); - unsigned SrcReg = Inst.getOperand(1).getReg(); - int64_t ImmValue = Inst.getOperand(2).getImm(); - - bool Is32Bit = isInt<32>(ImmValue) || (!isGP64bit() && isUInt<32>(ImmValue)); - - unsigned FinalOpcode = Inst.getOpcode(); - - if (DstReg == SrcReg) { - ATReg = getATReg(Inst.getLoc()); - if (!ATReg) - return true; - FinalDstReg = DstReg; - DstReg = ATReg; - } - - if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, - Inst.getLoc(), Out, STI)) { - switch (FinalOpcode) { - default: - llvm_unreachable("unimplemented expansion"); - case Mips::ADDi: - FinalOpcode = Mips::ADD; - break; - case Mips::ADDiu: - FinalOpcode = Mips::ADDu; - break; - case Mips::ANDi: - FinalOpcode = Mips::AND; - break; - case Mips::NORImm: - FinalOpcode = Mips::NOR; - break; - case Mips::ORi: - FinalOpcode = Mips::OR; - break; - case Mips::SLTi: - FinalOpcode = Mips::SLT; - break; - case Mips::SLTiu: - FinalOpcode = Mips::SLTu; - break; - 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); - else - TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI); - return false; - } - return true; -} - -bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI) { - MipsTargetStreamer &TOut = getTargetStreamer(); - unsigned ATReg = Mips::NoRegister; - unsigned DReg = Inst.getOperand(0).getReg(); - unsigned SReg = Inst.getOperand(1).getReg(); - unsigned TReg = Inst.getOperand(2).getReg(); - unsigned TmpReg = DReg; - - unsigned FirstShift = Mips::NOP; - unsigned SecondShift = Mips::NOP; - - if (hasMips32r2()) { - if (DReg == SReg) { - TmpReg = getATReg(Inst.getLoc()); - if (!TmpReg) - return true; - } - - 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); - return false; - } - - if (Inst.getOpcode() == Mips::ROR) { - TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI); - return false; - } - - return true; - } - - if (hasMips32()) { - switch (Inst.getOpcode()) { - default: - llvm_unreachable("unexpected instruction opcode"); - case Mips::ROL: - FirstShift = Mips::SRLV; - SecondShift = Mips::SLLV; - break; - case Mips::ROR: - FirstShift = Mips::SLLV; - SecondShift = Mips::SRLV; - break; - } - - ATReg = getATReg(Inst.getLoc()); - 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); - - return false; - } - - return true; -} - -bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc, - MCStreamer &Out, - const MCSubtargetInfo *STI) { - MipsTargetStreamer &TOut = getTargetStreamer(); - unsigned ATReg = Mips::NoRegister; - unsigned DReg = Inst.getOperand(0).getReg(); - unsigned SReg = Inst.getOperand(1).getReg(); - int64_t ImmValue = Inst.getOperand(2).getImm(); - - unsigned FirstShift = Mips::NOP; - 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); - return false; - } - - if (Inst.getOpcode() == Mips::RORImm) { - TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI); - return false; - } - - return true; - } - - if (hasMips32()) { - if (ImmValue == 0) { - TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI); - return false; - } - - switch (Inst.getOpcode()) { - default: - llvm_unreachable("unexpected instruction opcode"); - case Mips::ROLImm: - FirstShift = Mips::SLL; - SecondShift = Mips::SRL; - break; - case Mips::RORImm: - FirstShift = Mips::SRL; - SecondShift = Mips::SLL; - break; - } - - ATReg = getATReg(Inst.getLoc()); - 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); - - return false; - } - - return true; -} - -bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI) { - MipsTargetStreamer &TOut = getTargetStreamer(); - unsigned ATReg = Mips::NoRegister; - unsigned DReg = Inst.getOperand(0).getReg(); - unsigned SReg = Inst.getOperand(1).getReg(); - unsigned TReg = Inst.getOperand(2).getReg(); - unsigned TmpReg = DReg; - - unsigned FirstShift = Mips::NOP; - unsigned SecondShift = Mips::NOP; - - if (hasMips64r2()) { - if (TmpReg == SReg) { - TmpReg = getATReg(Inst.getLoc()); - if (!TmpReg) - return true; - } - - 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); - return false; - } - - if (Inst.getOpcode() == Mips::DROR) { - TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI); - return false; - } - - return true; - } - - if (hasMips64()) { - switch (Inst.getOpcode()) { - default: - llvm_unreachable("unexpected instruction opcode"); - case Mips::DROL: - FirstShift = Mips::DSRLV; - SecondShift = Mips::DSLLV; - break; - case Mips::DROR: - FirstShift = Mips::DSLLV; - SecondShift = Mips::DSRLV; - break; - } - - ATReg = getATReg(Inst.getLoc()); - 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); - - return false; - } - - return true; -} - -bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc, - MCStreamer &Out, - const MCSubtargetInfo *STI) { - MipsTargetStreamer &TOut = getTargetStreamer(); - unsigned ATReg = Mips::NoRegister; - unsigned DReg = Inst.getOperand(0).getReg(); - unsigned SReg = Inst.getOperand(1).getReg(); - int64_t ImmValue = Inst.getOperand(2).getImm() % 64; - - unsigned FirstShift = Mips::NOP; - unsigned SecondShift = Mips::NOP; - - MCInst TmpInst; - - if (hasMips64r2()) { - unsigned FinalOpcode = Mips::NOP; - if (ImmValue == 0) - FinalOpcode = Mips::DROTR; - else if (ImmValue % 32 == 0) - FinalOpcode = Mips::DROTR32; - else if ((ImmValue >= 1) && (ImmValue <= 32)) { - if (Inst.getOpcode() == Mips::DROLImm) - FinalOpcode = Mips::DROTR32; - else - FinalOpcode = Mips::DROTR; - } else if (ImmValue >= 33) { - if (Inst.getOpcode() == Mips::DROLImm) - FinalOpcode = Mips::DROTR; - else - FinalOpcode = Mips::DROTR32; - } - - uint64_t ShiftValue = ImmValue % 32; - if (Inst.getOpcode() == Mips::DROLImm) - ShiftValue = (32 - ImmValue % 32) % 32; - - TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI); - - return false; - } - - if (hasMips64()) { - if (ImmValue == 0) { - TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI); - return false; - } - - switch (Inst.getOpcode()) { - default: - llvm_unreachable("unexpected instruction opcode"); - case Mips::DROLImm: - if ((ImmValue >= 1) && (ImmValue <= 31)) { - FirstShift = Mips::DSLL; - SecondShift = Mips::DSRL32; - } - if (ImmValue == 32) { - FirstShift = Mips::DSLL32; - SecondShift = Mips::DSRL32; - } - if ((ImmValue >= 33) && (ImmValue <= 63)) { - FirstShift = Mips::DSLL32; - SecondShift = Mips::DSRL; - } - break; - case Mips::DRORImm: - if ((ImmValue >= 1) && (ImmValue <= 31)) { - FirstShift = Mips::DSRL; - SecondShift = Mips::DSLL32; - } - if (ImmValue == 32) { - FirstShift = Mips::DSRL32; - SecondShift = Mips::DSLL32; - } - if ((ImmValue >= 33) && (ImmValue <= 63)) { - FirstShift = Mips::DSRL32; - SecondShift = Mips::DSLL; - } - break; - } - - ATReg = getATReg(Inst.getLoc()); - 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); - - return false; - } - - 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); - else - TOut.emitEmptyDelaySlot(false, IDLoc, STI); - TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI); - - return false; -} - -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; -} - -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); - } - - 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; -} - - -// Expand 's.d $<reg> offset($reg2)' to 'swc1 $<reg+1>, offset($reg2); -// swc1 $<reg>, offset+4($reg2)' -// or if little endian to 'swc1 $<reg>, offset($reg2); -// swc1 $<reg+1>, offset+4($reg2)' -// for Mips1. -bool MipsAsmParser::expandStoreDM1Macro(MCInst &Inst, SMLoc IDLoc, - MCStreamer &Out, - const MCSubtargetInfo *STI) { - if (!isABI_O32()) - return true; - - warnIfNoMacro(IDLoc); - - MipsTargetStreamer &TOut = getTargetStreamer(); - unsigned Opcode = Mips::SWC1; - 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 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; - - if (!IsLittleEndian) - std::swap(FirstReg, SecondReg); - - TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI); - TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI); - - return false; -} - -bool MipsAsmParser::expandSeq(MCInst &Inst, 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 DstReg = Inst.getOperand(0).getReg(); - unsigned SrcReg = Inst.getOperand(1).getReg(); - unsigned OpReg = Inst.getOperand(2).getReg(); - - warnIfNoMacro(IDLoc); - - if (SrcReg != Mips::ZERO && OpReg != Mips::ZERO) { - TOut.emitRRR(Mips::XOR, DstReg, SrcReg, OpReg, IDLoc, STI); - TOut.emitRRI(Mips::SLTiu, DstReg, DstReg, 1, IDLoc, STI); - return false; - } - - unsigned Reg = SrcReg == Mips::ZERO ? OpReg : SrcReg; - TOut.emitRRI(Mips::SLTiu, DstReg, Reg, 1, IDLoc, STI); - return false; -} - -bool MipsAsmParser::expandSeqI(MCInst &Inst, 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).isImm() && "Invalid instruction operand."); - - unsigned DstReg = Inst.getOperand(0).getReg(); - unsigned SrcReg = Inst.getOperand(1).getReg(); - int64_t Imm = Inst.getOperand(2).getImm(); - - warnIfNoMacro(IDLoc); - - if (Imm == 0) { - TOut.emitRRI(Mips::SLTiu, DstReg, SrcReg, 1, IDLoc, STI); - return false; - } - - if (SrcReg == Mips::ZERO) { - Warning(IDLoc, "comparison is always false"); - TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu, - DstReg, SrcReg, SrcReg, IDLoc, STI); - return false; - } - - unsigned Opc; - 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, DstReg, SrcReg, ATReg, IDLoc, STI); - TOut.emitRRI(Mips::SLTiu, DstReg, DstReg, 1, IDLoc, STI); - return false; - } - - TOut.emitRRI(Opc, DstReg, SrcReg, Imm, IDLoc, STI); - TOut.emitRRI(Mips::SLTiu, DstReg, DstReg, 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; -} - -bool MipsAsmParser::expandSaaAddr(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI) { - assert(Inst.getNumOperands() == 3 && "expected three operands"); - assert(Inst.getOperand(0).isReg() && "expected register operand kind"); - assert(Inst.getOperand(1).isReg() && "expected register operand kind"); - - warnIfNoMacro(IDLoc); - - MipsTargetStreamer &TOut = getTargetStreamer(); - unsigned Opcode = Inst.getOpcode() == Mips::SaaAddr ? Mips::SAA : Mips::SAAD; - unsigned RtReg = Inst.getOperand(0).getReg(); - unsigned BaseReg = Inst.getOperand(1).getReg(); - const MCOperand &BaseOp = Inst.getOperand(2); - - if (BaseOp.isImm()) { - int64_t ImmValue = BaseOp.getImm(); - if (ImmValue == 0) { - TOut.emitRR(Opcode, RtReg, BaseReg, IDLoc, STI); - return false; - } - } - - unsigned ATReg = getATReg(IDLoc); - if (!ATReg) - return true; - - if (expandLoadAddress(ATReg, BaseReg, BaseOp, !isGP64bit(), IDLoc, Out, STI)) - return true; - - TOut.emitRR(Opcode, RtReg, ATReg, 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; - } -} - -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; - - return Match_Success; - -} - -static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands, - uint64_t ErrorInfo) { - if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) { - SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc(); - if (ErrorLoc == SMLoc()) - return Loc; - return ErrorLoc; - } - return Loc; -} - -bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, - OperandVector &Operands, - MCStreamer &Out, - uint64_t &ErrorInfo, - bool MatchingInlineAsm) { - MCInst Inst; - unsigned MatchResult = - MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm); - - switch (MatchResult) { - case Match_Success: - if (processInstruction(Inst, IDLoc, Out, STI)) - return true; - return false; - case Match_MissingFeature: - Error(IDLoc, "instruction requires a CPU feature not currently enabled"); - return true; - case Match_InvalidOperand: { - SMLoc ErrorLoc = IDLoc; - if (ErrorInfo != ~0ULL) { - if (ErrorInfo >= Operands.size()) - return Error(IDLoc, "too few operands for instruction"); - - ErrorLoc = Operands[ErrorInfo]->getStartLoc(); - if (ErrorLoc == SMLoc()) - ErrorLoc = IDLoc; - } - - 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: - return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), - "expected 1-bit unsigned immediate"); - case Match_UImm2_0: - return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), - "expected 2-bit unsigned immediate"); - case Match_UImm2_1: - return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), - "expected immediate in range 1 .. 4"); - case Match_UImm3_0: - return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), - "expected 3-bit unsigned immediate"); - 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"); - case Match_UImm5_32: - return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), - "expected immediate in range 32 .. 63"); - case Match_UImm5_33: - return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), - "expected immediate in range 33 .. 64"); - case Match_UImm5_0_Report_UImm6: - // This is used on UImm5 operands that have a corresponding UImm5_32 - // operand to avoid confusing the user. - return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), - "expected 6-bit unsigned immediate"); - 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: - 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!"); -} - -void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) { - if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex) - Warning(Loc, "used $at (currently $" + Twine(RegIndex) + - ") without \".set noat\""); -} - -void MipsAsmParser::warnIfNoMacro(SMLoc Loc) { - if (!AssemblerOptions.back()->isMacro()) - 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) { - getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg, - Range, SMFixIt(Range, FixMsg), - ShowColors); -} - -int MipsAsmParser::matchCPURegisterName(StringRef Name) { - int CC; - - CC = StringSwitch<unsigned>(Name) - .Case("zero", 0) - .Cases("at", "AT", 1) - .Case("a0", 4) - .Case("a1", 5) - .Case("a2", 6) - .Case("a3", 7) - .Case("v0", 2) - .Case("v1", 3) - .Case("s0", 16) - .Case("s1", 17) - .Case("s2", 18) - .Case("s3", 19) - .Case("s4", 20) - .Case("s5", 21) - .Case("s6", 22) - .Case("s7", 23) - .Case("k0", 26) - .Case("k1", 27) - .Case("gp", 28) - .Case("sp", 29) - .Case("fp", 30) - .Case("s8", 30) - .Case("ra", 31) - .Case("t0", 8) - .Case("t1", 9) - .Case("t2", 10) - .Case("t3", 11) - .Case("t4", 12) - .Case("t5", 13) - .Case("t6", 14) - .Case("t7", 15) - .Case("t8", 24) - .Case("t9", 25) - .Default(-1); - - if (!(isABI_N32() || isABI_N64())) - return CC; - - if (12 <= CC && CC <= 15) { - // Name is one of t4-t7 - AsmToken RegTok = getLexer().peekTok(); - SMRange RegRange = RegTok.getLocRange(); - - StringRef FixedName = StringSwitch<StringRef>(Name) - .Case("t4", "t0") - .Case("t5", "t1") - .Case("t6", "t2") - .Case("t7", "t3") - .Default(""); - assert(FixedName != "" && "Register name is not one of t4-t7."); - - printWarningWithFixIt("register names $t4-$t7 are only available in O32.", - "Did you mean $" + FixedName + "?", RegRange); - } - - // Although SGI documentation just cuts out t0-t3 for n32/n64, - // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7 - // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7. - if (8 <= CC && CC <= 11) - CC += 4; - - if (CC == -1) - CC = StringSwitch<unsigned>(Name) - .Case("a4", 8) - .Case("a5", 9) - .Case("a6", 10) - .Case("a7", 11) - .Case("kt0", 26) - .Case("kt1", 27) - .Default(-1); - - return CC; -} - -int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) { - int CC; - - CC = StringSwitch<unsigned>(Name) - .Case("hwr_cpunum", 0) - .Case("hwr_synci_step", 1) - .Case("hwr_cc", 2) - .Case("hwr_ccres", 3) - .Case("hwr_ulr", 29) - .Default(-1); - - return CC; -} - -int MipsAsmParser::matchFPURegisterName(StringRef Name) { - if (Name[0] == 'f') { - StringRef NumString = Name.substr(1); - unsigned IntVal; - if (NumString.getAsInteger(10, IntVal)) - return -1; // This is not an integer. - if (IntVal > 31) // Maximum index for fpu register. - return -1; - return IntVal; - } - return -1; -} - -int MipsAsmParser::matchFCCRegisterName(StringRef Name) { - if (Name.startswith("fcc")) { - StringRef NumString = Name.substr(3); - unsigned IntVal; - if (NumString.getAsInteger(10, IntVal)) - return -1; // This is not an integer. - if (IntVal > 7) // There are only 8 fcc registers. - return -1; - return IntVal; - } - return -1; -} - -int MipsAsmParser::matchACRegisterName(StringRef Name) { - if (Name.startswith("ac")) { - StringRef NumString = Name.substr(2); - unsigned IntVal; - if (NumString.getAsInteger(10, IntVal)) - return -1; // This is not an integer. - if (IntVal > 3) // There are only 3 acc registers. - return -1; - return IntVal; - } - return -1; -} - -int MipsAsmParser::matchMSA128RegisterName(StringRef Name) { - unsigned IntVal; - - if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal)) - return -1; - - if (IntVal > 31) - return -1; - - return IntVal; -} - -int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) { - int CC; - - CC = StringSwitch<unsigned>(Name) - .Case("msair", 0) - .Case("msacsr", 1) - .Case("msaaccess", 2) - .Case("msasave", 3) - .Case("msamodify", 4) - .Case("msarequest", 5) - .Case("msamap", 6) - .Case("msaunmap", 7) - .Default(-1); - - return CC; -} - -bool MipsAsmParser::canUseATReg() { - return AssemblerOptions.back()->getATRegIndex() != 0; -} - -unsigned MipsAsmParser::getATReg(SMLoc Loc) { - unsigned ATIndex = AssemblerOptions.back()->getATRegIndex(); - if (ATIndex == 0) { - reportParseError(Loc, - "pseudo-instruction requires $at, which is not available"); - return 0; - } - unsigned AT = getReg( - (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex); - return AT; -} - -unsigned MipsAsmParser::getReg(int RC, int RegNo) { - return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo); -} - -bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { - MCAsmParser &Parser = getParser(); - LLVM_DEBUG(dbgs() << "parseOperand\n"); - - // Check if the current operand has a custom associated parser, if so, try to - // custom parse the operand, or fallback to the general approach. - OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic); - if (ResTy == MatchOperand_Success) - return false; - // If there wasn't a custom match, try the generic matcher below. Otherwise, - // there was a match, but an error occurred, in which case, just return that - // the operand parsing failed. - if (ResTy == MatchOperand_ParseFail) - return true; - - LLVM_DEBUG(dbgs() << ".. Generic Parser\n"); - - switch (getLexer().getKind()) { - case AsmToken::Dollar: { - // Parse the register. - SMLoc S = Parser.getTok().getLoc(); - - // Almost all registers have been parsed by custom parsers. There is only - // one exception to this. $zero (and it's alias $0) will reach this point - // for div, divu, and similar instructions because it is not an operand - // to the instruction definition but an explicit register. Special case - // this situation for now. - if (parseAnyRegister(Operands) != MatchOperand_NoMatch) - return false; - - // Maybe it is a symbol reference. - StringRef Identifier; - if (Parser.parseIdentifier(Identifier)) - return true; - - SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); - MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier); - // Otherwise create a symbol reference. - const MCExpr *Res = - MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); - - Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this)); - return false; - } - default: { - LLVM_DEBUG(dbgs() << ".. generic integer expression\n"); - - const MCExpr *Expr; - SMLoc S = Parser.getTok().getLoc(); // Start location of the operand. - if (getParser().parseExpression(Expr)) - return true; - - SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); - - Operands.push_back(MipsOperand::CreateImm(Expr, S, E, *this)); - return false; - } - } // switch(getLexer().getKind()) - return true; -} - -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::Unary: - return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr()); - case MCExpr::Target: - return true; - } - return false; -} - -bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, - SMLoc &EndLoc) { - SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands; - OperandMatchResultTy ResTy = parseAnyRegister(Operands); - if (ResTy == MatchOperand_Success) { - assert(Operands.size() == 1); - MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front()); - StartLoc = Operand.getStartLoc(); - EndLoc = Operand.getEndLoc(); - - // AFAIK, we only support numeric registers and named GPR's in CFI - // directives. - // Don't worry about eating tokens before failing. Using an unrecognised - // register is a parse error. - if (Operand.isGPRAsmReg()) { - // Resolve to GPR32 or GPR64 appropriately. - RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg(); - } - - return (RegNo == (unsigned)-1); - } - - assert(Operands.size() == 0); - return (RegNo == (unsigned)-1); -} - -bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) { - SMLoc S; - - if (isParenExpr) - return getParser().parseParenExprOfDepth(0, Res, S); - return getParser().parseExpression(Res); -} - -OperandMatchResultTy -MipsAsmParser::parseMemOperand(OperandVector &Operands) { - MCAsmParser &Parser = getParser(); - LLVM_DEBUG(dbgs() << "parseMemOperand\n"); - const MCExpr *IdVal = nullptr; - SMLoc S; - bool isParenExpr = false; - OperandMatchResultTy Res = MatchOperand_NoMatch; - // First operand is the offset. - S = Parser.getTok().getLoc(); - - if (getLexer().getKind() == AsmToken::LParen) { - Parser.Lex(); - isParenExpr = true; - } - - if (getLexer().getKind() != AsmToken::Dollar) { - if (parseMemOffset(IdVal, isParenExpr)) - return MatchOperand_ParseFail; - - const AsmToken &Tok = Parser.getTok(); // Get the next token. - if (Tok.isNot(AsmToken::LParen)) { - MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]); - if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") { - SMLoc E = - SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); - Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this)); - return MatchOperand_Success; - } - if (Tok.is(AsmToken::EndOfStatement)) { - SMLoc E = - SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); - - // 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); - 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()); - } - - Parser.Lex(); // Eat the '(' token. - } - - Res = parseAnyRegister(Operands); - if (Res != MatchOperand_Success) - return Res; - - if (Parser.getTok().isNot(AsmToken::RParen)) { - Error(Parser.getTok().getLoc(), "')' expected"); - return MatchOperand_ParseFail; - } - - SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); - - Parser.Lex(); // Eat the ')' token. - - if (!IdVal) - IdVal = MCConstantExpr::create(0, getContext()); - - // Replace the register operand with the memory operand. - std::unique_ptr<MipsOperand> op( - static_cast<MipsOperand *>(Operands.back().release())); - // Remove the register from the operands. - // "op" will be managed by k_Memory. - Operands.pop_back(); - // Add the memory operand. - if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) { - int64_t Imm; - if (IdVal->evaluateAsAbsolute(Imm)) - IdVal = MCConstantExpr::create(Imm, getContext()); - else if (BE->getLHS()->getKind() != MCExpr::SymbolRef) - IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(), - getContext()); - } - - Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this)); - return MatchOperand_Success; -} - -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 (Expr->getKind() == MCExpr::SymbolRef) { - const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr); - StringRef DefSymbol = Ref->getSymbol().getName(); - if (DefSymbol.startswith("$")) { - OperandMatchResultTy ResTy = - matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S); - if (ResTy == MatchOperand_Success) { - Parser.Lex(); - return true; - } - if (ResTy == MatchOperand_ParseFail) - llvm_unreachable("Should never ParseFail"); - } - } - } 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; - } - } - } - - return false; -} - -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)); - return MatchOperand_Success; - } - - Index = matchHWRegsRegisterName(Identifier); - if (Index != -1) { - Operands.push_back(MipsOperand::createHWRegsReg( - Index, Identifier, 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)); - return MatchOperand_Success; - } - - Index = matchFCCRegisterName(Identifier); - if (Index != -1) { - Operands.push_back(MipsOperand::createFCCReg( - Index, Identifier, 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)); - return MatchOperand_Success; - } - - Index = matchMSA128RegisterName(Identifier); - if (Index != -1) { - Operands.push_back(MipsOperand::createMSA128Reg( - Index, Identifier, 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)); - return MatchOperand_Success; - } - - return MatchOperand_NoMatch; -} - -OperandMatchResultTy -MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, - const AsmToken &Token, SMLoc S) { - if (Token.is(AsmToken::Identifier)) { - LLVM_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"); - } - Operands.push_back(MipsOperand::createNumericReg( - RegNum, Token.getString(), getContext().getRegisterInfo(), S, - Token.getLoc(), *this)); - return MatchOperand_Success; - } - - LLVM_DEBUG(dbgs() << Token.getKind() << "\n"); - - return MatchOperand_NoMatch; -} - -OperandMatchResultTy -MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) { - auto Token = getLexer().peekTok(false); - return matchAnyRegisterWithoutDollar(Operands, Token, S); -} - -OperandMatchResultTy -MipsAsmParser::parseAnyRegister(OperandVector &Operands) { - MCAsmParser &Parser = getParser(); - LLVM_DEBUG(dbgs() << "parseAnyRegister\n"); - - auto Token = Parser.getTok(); - - SMLoc S = Token.getLoc(); - - if (Token.isNot(AsmToken::Dollar)) { - LLVM_DEBUG(dbgs() << ".. !$ -> try sym aliasing\n"); - if (Token.is(AsmToken::Identifier)) { - if (searchSymbolAlias(Operands)) - return MatchOperand_Success; - } - LLVM_DEBUG(dbgs() << ".. !symalias -> NoMatch\n"); - return MatchOperand_NoMatch; - } - LLVM_DEBUG(dbgs() << ".. $\n"); - - OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S); - if (ResTy == MatchOperand_Success) { - Parser.Lex(); // $ - Parser.Lex(); // identifier - } - return ResTy; -} - -OperandMatchResultTy -MipsAsmParser::parseJumpTarget(OperandVector &Operands) { - MCAsmParser &Parser = getParser(); - LLVM_DEBUG(dbgs() << "parseJumpTarget\n"); - - SMLoc S = getLexer().getLoc(); - - // Registers are a valid target and have priority over symbols. - OperandMatchResultTy 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 - return MatchOperand_ParseFail; - } - Operands.push_back( - MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this)); - return MatchOperand_Success; -} - -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. - 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; - int64_t Val = MCE->getValue(); - SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); - Operands.push_back(MipsOperand::CreateImm( - MCConstantExpr::create(0 - Val, getContext()), S, E, *this)); - return MatchOperand_Success; -} - -OperandMatchResultTy -MipsAsmParser::parseRegisterList(OperandVector &Operands) { - MCAsmParser &Parser = getParser(); - SmallVector<unsigned, 10> Regs; - unsigned RegNo; - unsigned PrevReg = Mips::NoRegister; - bool RegRange = false; - SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands; - - if (Parser.getTok().isNot(AsmToken::Dollar)) - return MatchOperand_ParseFail; - - SMLoc S = Parser.getTok().getLoc(); - while (parseAnyRegister(TmpOperands) == MatchOperand_Success) { - SMLoc E = getLexer().getLoc(); - MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back()); - RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg(); - if (RegRange) { - // Remove last register operand because registers from register range - // should be inserted first. - if ((isGP64bit() && RegNo == Mips::RA_64) || - (!isGP64bit() && RegNo == Mips::RA)) { - Regs.push_back(RegNo); - } else { - unsigned TmpReg = PrevReg + 1; - while (TmpReg <= RegNo) { - if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) || - (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) && - isGP64bit())) { - Error(E, "invalid register operand"); - return MatchOperand_ParseFail; - } - - PrevReg = TmpReg; - Regs.push_back(TmpReg++); - } - } - - RegRange = false; - } else { - if ((PrevReg == Mips::NoRegister) && - ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) || - (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) { - Error(E, "$16 or $31 expected"); - return MatchOperand_ParseFail; - } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA || - (RegNo >= Mips::S0 && RegNo <= Mips::S7)) && - !isGP64bit()) || - ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 || - (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) && - isGP64bit()))) { - Error(E, "invalid register operand"); - return MatchOperand_ParseFail; - } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) && - ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) || - (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 && - isGP64bit()))) { - Error(E, "consecutive register numbers expected"); - return MatchOperand_ParseFail; - } - - Regs.push_back(RegNo); - } - - if (Parser.getTok().is(AsmToken::Minus)) - RegRange = true; - - if (!Parser.getTok().isNot(AsmToken::Minus) && - !Parser.getTok().isNot(AsmToken::Comma)) { - Error(E, "',' or '-' expected"); - return MatchOperand_ParseFail; - } - - Lex(); // Consume comma or minus - if (Parser.getTok().isNot(AsmToken::Dollar)) - break; - - PrevReg = RegNo; - } - - SMLoc E = Parser.getTok().getLoc(); - Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this)); - parseMemOperand(Operands); - return MatchOperand_Success; -} - -/// Sometimes (i.e. load/stores) the operand may be followed immediately by -/// either this. -/// ::= '(', register, ')' -/// handle it before we iterate so we don't get tripped up by the lack of -/// a comma. -bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) { - MCAsmParser &Parser = getParser(); - if (getLexer().is(AsmToken::LParen)) { - Operands.push_back( - MipsOperand::CreateToken("(", getLexer().getLoc(), *this)); - Parser.Lex(); - if (parseOperand(Operands, Name)) { - SMLoc Loc = getLexer().getLoc(); - return Error(Loc, "unexpected token in argument list"); - } - if (Parser.getTok().isNot(AsmToken::RParen)) { - SMLoc Loc = getLexer().getLoc(); - return Error(Loc, "unexpected token, expected ')'"); - } - Operands.push_back( - MipsOperand::CreateToken(")", getLexer().getLoc(), *this)); - Parser.Lex(); - } - return false; -} - -/// Sometimes (i.e. in MSA) the operand may be followed immediately by -/// either one of these. -/// ::= '[', register, ']' -/// ::= '[', integer, ']' -/// handle it before we iterate so we don't get tripped up by the lack of -/// a comma. -bool MipsAsmParser::parseBracketSuffix(StringRef Name, - OperandVector &Operands) { - MCAsmParser &Parser = getParser(); - if (getLexer().is(AsmToken::LBrac)) { - Operands.push_back( - MipsOperand::CreateToken("[", getLexer().getLoc(), *this)); - Parser.Lex(); - if (parseOperand(Operands, Name)) { - SMLoc Loc = getLexer().getLoc(); - return Error(Loc, "unexpected token in argument list"); - } - if (Parser.getTok().isNot(AsmToken::RBrac)) { - SMLoc Loc = getLexer().getLoc(); - return Error(Loc, "unexpected token, expected ']'"); - } - Operands.push_back( - MipsOperand::CreateToken("]", getLexer().getLoc(), *this)); - Parser.Lex(); - } - return false; -} - -static std::string MipsMnemonicSpellCheck(StringRef S, const FeatureBitset &FBS, - unsigned VariantID = 0); - -bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, - SMLoc NameLoc, OperandVector &Operands) { - MCAsmParser &Parser = getParser(); - LLVM_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)) { - FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits()); - std::string Suggestion = MipsMnemonicSpellCheck(Name, FBS); - return Error(NameLoc, "unknown instruction" + Suggestion); - } - // First operand in MCInst is instruction mnemonic. - Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this)); - - // Read the remaining operands. - if (getLexer().isNot(AsmToken::EndOfStatement)) { - // Read the first operand. - if (parseOperand(Operands, Name)) { - SMLoc Loc = getLexer().getLoc(); - return Error(Loc, "unexpected token in argument list"); - } - if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands)) - return true; - // AFAIK, parenthesis suffixes are never on the first operand - - while (getLexer().is(AsmToken::Comma)) { - Parser.Lex(); // Eat the comma. - // Parse and remember the operand. - if (parseOperand(Operands, Name)) { - SMLoc Loc = getLexer().getLoc(); - return Error(Loc, "unexpected token in argument list"); - } - // Parse bracket and parenthesis suffixes before we iterate - if (getLexer().is(AsmToken::LBrac)) { - if (parseBracketSuffix(Name, Operands)) - return true; - } else if (getLexer().is(AsmToken::LParen) && - parseParenSuffix(Name, Operands)) - return true; - } - } - if (getLexer().isNot(AsmToken::EndOfStatement)) { - SMLoc Loc = getLexer().getLoc(); - 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) { - SMLoc Loc = getLexer().getLoc(); - return Error(Loc, ErrorMsg); -} - -bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) { - return Error(Loc, ErrorMsg); -} - -bool MipsAsmParser::parseSetNoAtDirective() { - MCAsmParser &Parser = getParser(); - // Line should look like: ".set noat". - - // Set the $at register to $0. - AssemblerOptions.back()->setATRegIndex(0); - - Parser.Lex(); // Eat "noat". - - // 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; - } - - getTargetStreamer().emitDirectiveSetNoAt(); - Parser.Lex(); // Consume the EndOfStatement. - return false; -} - -bool MipsAsmParser::parseSetAtDirective() { - // Line can be: ".set at", which sets $at to $1 - // or ".set at=$reg", which sets $at to $reg. - MCAsmParser &Parser = getParser(); - Parser.Lex(); // Eat "at". - - if (getLexer().is(AsmToken::EndOfStatement)) { - // No register was specified, so we set $at to $1. - AssemblerOptions.back()->setATRegIndex(1); - - getTargetStreamer().emitDirectiveSetAt(); - Parser.Lex(); // Consume the EndOfStatement. - return false; - } - - if (getLexer().isNot(AsmToken::Equal)) { - reportParseError("unexpected token, expected equals sign"); - return false; - } - Parser.Lex(); // Eat "=". - - if (getLexer().isNot(AsmToken::Dollar)) { - if (getLexer().is(AsmToken::EndOfStatement)) { - reportParseError("no register specified"); - return false; - } else { - reportParseError("unexpected token, expected dollar sign '$'"); - return false; - } - } - Parser.Lex(); // Eat "$". - - // Find out what "reg" is. - unsigned AtRegNo; - const AsmToken &Reg = Parser.getTok(); - if (Reg.is(AsmToken::Identifier)) { - AtRegNo = matchCPURegisterName(Reg.getIdentifier()); - } else if (Reg.is(AsmToken::Integer)) { - AtRegNo = Reg.getIntVal(); - } else { - reportParseError("unexpected token, expected identifier or integer"); - return false; - } - - // Check if $reg is a valid register. If it is, set $at to $reg. - if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) { - reportParseError("invalid register"); - return false; - } - Parser.Lex(); // Eat "reg". - - // 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; - } - - getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo); - - Parser.Lex(); // Consume the EndOfStatement. - return false; -} - -bool MipsAsmParser::parseSetReorderDirective() { - MCAsmParser &Parser = getParser(); - Parser.Lex(); - // 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; - } - AssemblerOptions.back()->setReorder(); - getTargetStreamer().emitDirectiveSetReorder(); - Parser.Lex(); // Consume the EndOfStatement. - return false; -} - -bool MipsAsmParser::parseSetNoReorderDirective() { - MCAsmParser &Parser = getParser(); - Parser.Lex(); - // 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; - } - AssemblerOptions.back()->setNoReorder(); - getTargetStreamer().emitDirectiveSetNoReorder(); - Parser.Lex(); // Consume the EndOfStatement. - return false; -} - -bool MipsAsmParser::parseSetMacroDirective() { - MCAsmParser &Parser = getParser(); - Parser.Lex(); - // 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; - } - AssemblerOptions.back()->setMacro(); - getTargetStreamer().emitDirectiveSetMacro(); - Parser.Lex(); // Consume the EndOfStatement. - return false; -} - -bool MipsAsmParser::parseSetNoMacroDirective() { - MCAsmParser &Parser = getParser(); - Parser.Lex(); - // 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; - } - if (AssemblerOptions.back()->isReorder()) { - reportParseError("`noreorder' must be set before `nomacro'"); - return false; - } - AssemblerOptions.back()->setNoMacro(); - getTargetStreamer().emitDirectiveSetNoMacro(); - Parser.Lex(); // Consume the EndOfStatement. - return false; -} - -bool MipsAsmParser::parseSetMsaDirective() { - MCAsmParser &Parser = getParser(); - Parser.Lex(); - - // If this is not the end of the statement, report an error. - if (getLexer().isNot(AsmToken::EndOfStatement)) - return reportParseError("unexpected token, expected end of statement"); - - setFeatureBits(Mips::FeatureMSA, "msa"); - getTargetStreamer().emitDirectiveSetMsa(); - return false; -} - -bool MipsAsmParser::parseSetNoMsaDirective() { - MCAsmParser &Parser = getParser(); - Parser.Lex(); - - // If this is not the end of the statement, report an error. - if (getLexer().isNot(AsmToken::EndOfStatement)) - return reportParseError("unexpected token, expected end of statement"); - - clearFeatureBits(Mips::FeatureMSA, "msa"); - getTargetStreamer().emitDirectiveSetNoMsa(); - return false; -} - -bool MipsAsmParser::parseSetNoDspDirective() { - MCAsmParser &Parser = getParser(); - Parser.Lex(); // Eat "nodsp". - - // 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::FeatureDSP, "dsp"); - getTargetStreamer().emitDirectiveSetNoDsp(); - return false; -} - -bool MipsAsmParser::parseSetMips16Directive() { - MCAsmParser &Parser = getParser(); - Parser.Lex(); // Eat "mips16". - - // 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::FeatureMips16, "mips16"); - getTargetStreamer().emitDirectiveSetMips16(); - Parser.Lex(); // Consume the EndOfStatement. - return false; -} - -bool MipsAsmParser::parseSetNoMips16Directive() { - MCAsmParser &Parser = getParser(); - Parser.Lex(); // Eat "nomips16". - - // 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::FeatureMips16, "mips16"); - getTargetStreamer().emitDirectiveSetNoMips16(); - Parser.Lex(); // Consume the EndOfStatement. - return false; -} - -bool MipsAsmParser::parseSetFpDirective() { - MCAsmParser &Parser = getParser(); - MipsABIFlagsSection::FpABIKind FpAbiVal; - // Line can be: .set fp=32 - // .set fp=xx - // .set fp=64 - Parser.Lex(); // Eat fp token - AsmToken Tok = Parser.getTok(); - if (Tok.isNot(AsmToken::Equal)) { - reportParseError("unexpected token, expected equals sign '='"); - return false; - } - Parser.Lex(); // Eat '=' token. - Tok = Parser.getTok(); - - if (!parseFpABIValue(FpAbiVal, ".set")) - return false; - - if (getLexer().isNot(AsmToken::EndOfStatement)) { - reportParseError("unexpected token, expected end of statement"); - return false; - } - getTargetStreamer().emitDirectiveSetFp(FpAbiVal); - Parser.Lex(); // Consume the EndOfStatement. - return false; -} - -bool MipsAsmParser::parseSetOddSPRegDirective() { - MCAsmParser &Parser = getParser(); - - Parser.Lex(); // Eat "oddspreg". - if (getLexer().isNot(AsmToken::EndOfStatement)) { - reportParseError("unexpected token, expected end of statement"); - return false; - } - - clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg"); - getTargetStreamer().emitDirectiveSetOddSPReg(); - return false; -} - -bool MipsAsmParser::parseSetNoOddSPRegDirective() { - MCAsmParser &Parser = getParser(); - - Parser.Lex(); // Eat "nooddspreg". - if (getLexer().isNot(AsmToken::EndOfStatement)) { - reportParseError("unexpected token, expected end of statement"); - return false; - } - - setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg"); - getTargetStreamer().emitDirectiveSetNoOddSPReg(); - 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(); - - Parser.Lex(); - if (getLexer().isNot(AsmToken::EndOfStatement)) - return reportParseError("unexpected token, expected end of statement"); - - // Always keep an element on the options "stack" to prevent the user - // from changing the initial options. This is how we remember them. - if (AssemblerOptions.size() == 2) - return reportParseError(Loc, ".set pop with no .set push"); - - MCSubtargetInfo &STI = copySTI(); - AssemblerOptions.pop_back(); - setAvailableFeatures( - ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures())); - STI.setFeatureBits(AssemblerOptions.back()->getFeatures()); - - getTargetStreamer().emitDirectiveSetPop(); - return false; -} - -bool MipsAsmParser::parseSetPushDirective() { - MCAsmParser &Parser = getParser(); - Parser.Lex(); - if (getLexer().isNot(AsmToken::EndOfStatement)) - return reportParseError("unexpected token, expected end of statement"); - - // Create a copy of the current assembler options environment and push it. - AssemblerOptions.push_back( - llvm::make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get())); - - getTargetStreamer().emitDirectiveSetPush(); - return false; -} - -bool MipsAsmParser::parseSetSoftFloatDirective() { - MCAsmParser &Parser = getParser(); - Parser.Lex(); - if (getLexer().isNot(AsmToken::EndOfStatement)) - return reportParseError("unexpected token, expected end of statement"); - - setFeatureBits(Mips::FeatureSoftFloat, "soft-float"); - getTargetStreamer().emitDirectiveSetSoftFloat(); - return false; -} - -bool MipsAsmParser::parseSetHardFloatDirective() { - MCAsmParser &Parser = getParser(); - Parser.Lex(); - if (getLexer().isNot(AsmToken::EndOfStatement)) - return reportParseError("unexpected token, expected end of statement"); - - clearFeatureBits(Mips::FeatureSoftFloat, "soft-float"); - getTargetStreamer().emitDirectiveSetHardFloat(); - return false; -} - -bool MipsAsmParser::parseSetAssignment() { - StringRef Name; - MCAsmParser &Parser = getParser(); - - if (Parser.parseIdentifier(Name)) - return 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); - return false; - } - - MCSymbol *Sym; - const MCExpr *Value; - if (MCParserUtils::parseAssignmentExpression(Name, /* allow_redef */ true, - Parser, Sym, Value)) - return true; - Sym->setVariableValue(Value); - - return false; -} - -bool MipsAsmParser::parseSetMips0Directive() { - MCAsmParser &Parser = getParser(); - Parser.Lex(); - if (getLexer().isNot(AsmToken::EndOfStatement)) - return reportParseError("unexpected token, expected end of statement"); - - // Reset assembler options to their initial values. - MCSubtargetInfo &STI = copySTI(); - setAvailableFeatures( - ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures())); - STI.setFeatureBits(AssemblerOptions.front()->getFeatures()); - AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures()); - - getTargetStreamer().emitDirectiveSetMips0(); - return false; -} - -bool MipsAsmParser::parseSetArchDirective() { - MCAsmParser &Parser = getParser(); - Parser.Lex(); - if (getLexer().isNot(AsmToken::Equal)) - return reportParseError("unexpected token, expected equals sign"); - - Parser.Lex(); - StringRef Arch = getParser().parseStringToEndOfStatement().trim(); - if (Arch.empty()) - return reportParseError("expected arch identifier"); - - StringRef ArchFeatureName = - StringSwitch<StringRef>(Arch) - .Case("mips1", "mips1") - .Case("mips2", "mips2") - .Case("mips3", "mips3") - .Case("mips4", "mips4") - .Case("mips5", "mips5") - .Case("mips32", "mips32") - .Case("mips32r2", "mips32r2") - .Case("mips32r3", "mips32r3") - .Case("mips32r5", "mips32r5") - .Case("mips32r6", "mips32r6") - .Case("mips64", "mips64") - .Case("mips64r2", "mips64r2") - .Case("mips64r3", "mips64r3") - .Case("mips64r5", "mips64r5") - .Case("mips64r6", "mips64r6") - .Case("octeon", "cnmips") - .Case("octeon+", "cnmipsp") - .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; -} - -bool MipsAsmParser::parseSetFeature(uint64_t Feature) { - MCAsmParser &Parser = getParser(); - Parser.Lex(); - if (getLexer().isNot(AsmToken::EndOfStatement)) - return reportParseError("unexpected token, expected end of statement"); - - switch (Feature) { - default: - llvm_unreachable("Unimplemented feature"); - case Mips::FeatureDSP: - 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: - selectArch("mips1"); - getTargetStreamer().emitDirectiveSetMips1(); - break; - case Mips::FeatureMips2: - selectArch("mips2"); - getTargetStreamer().emitDirectiveSetMips2(); - break; - case Mips::FeatureMips3: - selectArch("mips3"); - getTargetStreamer().emitDirectiveSetMips3(); - break; - case Mips::FeatureMips4: - selectArch("mips4"); - getTargetStreamer().emitDirectiveSetMips4(); - break; - case Mips::FeatureMips5: - selectArch("mips5"); - getTargetStreamer().emitDirectiveSetMips5(); - break; - case Mips::FeatureMips32: - selectArch("mips32"); - getTargetStreamer().emitDirectiveSetMips32(); - break; - case Mips::FeatureMips32r2: - selectArch("mips32r2"); - getTargetStreamer().emitDirectiveSetMips32R2(); - break; - case Mips::FeatureMips32r3: - selectArch("mips32r3"); - getTargetStreamer().emitDirectiveSetMips32R3(); - break; - case Mips::FeatureMips32r5: - selectArch("mips32r5"); - getTargetStreamer().emitDirectiveSetMips32R5(); - break; - case Mips::FeatureMips32r6: - selectArch("mips32r6"); - getTargetStreamer().emitDirectiveSetMips32R6(); - break; - case Mips::FeatureMips64: - selectArch("mips64"); - getTargetStreamer().emitDirectiveSetMips64(); - break; - case Mips::FeatureMips64r2: - selectArch("mips64r2"); - getTargetStreamer().emitDirectiveSetMips64R2(); - break; - case Mips::FeatureMips64r3: - selectArch("mips64r3"); - getTargetStreamer().emitDirectiveSetMips64R3(); - break; - case Mips::FeatureMips64r5: - selectArch("mips64r5"); - getTargetStreamer().emitDirectiveSetMips64R5(); - break; - case Mips::FeatureMips64r6: - 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; -} - -bool MipsAsmParser::eatComma(StringRef ErrorStr) { - MCAsmParser &Parser = getParser(); - if (getLexer().isNot(AsmToken::Comma)) { - SMLoc Loc = getLexer().getLoc(); - return Error(Loc, ErrorStr); - } - - Parser.Lex(); // Eat the comma. - return true; -} - -// Used to determine if .cpload, .cprestore, and .cpsetup have any effect. -// In this class, it is only used for .cprestore. -// FIXME: Only keep track of IsPicEnabled in one place, instead of in both -// MipsTargetELFStreamer and MipsAsmParser. -bool MipsAsmParser::isPicAndNotNxxAbi() { - return inPicMode() && !(isABI_N32() || isABI_N64()); -} - -bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) { - if (AssemblerOptions.back()->isReorder()) - Warning(Loc, ".cpload should be inside a noreorder section"); - - if (inMips16Mode()) { - reportParseError(".cpload is not supported in Mips16 mode"); - return false; - } - - SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg; - OperandMatchResultTy ResTy = parseAnyRegister(Reg); - if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) { - reportParseError("expected register containing function address"); - return false; - } - - MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]); - if (!RegOpnd.isGPRAsmReg()) { - reportParseError(RegOpnd.getStartLoc(), "invalid register"); - return false; - } - - // 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; - } - - getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg()); - return false; -} - -bool MipsAsmParser::parseDirectiveCpLocal(SMLoc Loc) { - if (!isABI_N32() && !isABI_N64()) { - reportParseError(".cplocal is allowed only in N32 or N64 mode"); - return false; - } - - SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg; - OperandMatchResultTy ResTy = parseAnyRegister(Reg); - if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) { - reportParseError("expected register containing global pointer"); - return false; - } - - MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]); - if (!RegOpnd.isGPRAsmReg()) { - reportParseError(RegOpnd.getStartLoc(), "invalid register"); - return false; - } - - // 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; - } - getParser().Lex(); // Consume the EndOfStatement. - - unsigned NewReg = RegOpnd.getGPR32Reg(); - if (IsPicEnabled) - GPReg = NewReg; - - getTargetStreamer().emitDirectiveCpLocal(NewReg); - return false; -} - -bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) { - MCAsmParser &Parser = getParser(); - - // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it - // is used in non-PIC mode. - - if (inMips16Mode()) { - reportParseError(".cprestore is not supported in Mips16 mode"); - return false; - } - - // Get the stack offset value. - const MCExpr *StackOffset; - int64_t StackOffsetVal; - if (Parser.parseExpression(StackOffset)) { - reportParseError("expected stack offset value"); - return false; - } - - if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) { - reportParseError("stack offset is not an absolute expression"); - return false; - } - - if (StackOffsetVal < 0) { - Warning(Loc, ".cprestore with negative stack offset has no effect"); - IsCpRestoreSet = false; - } else { - IsCpRestoreSet = true; - CpRestoreOffset = StackOffsetVal; - } - - // 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; - } - - if (!getTargetStreamer().emitDirectiveCpRestore( - CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI)) - return true; - Parser.Lex(); // Consume the EndOfStatement. - return false; -} - -bool MipsAsmParser::parseDirectiveCPSetup() { - MCAsmParser &Parser = getParser(); - unsigned FuncReg; - unsigned Save; - bool SaveIsReg = true; - - SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg; - OperandMatchResultTy ResTy = parseAnyRegister(TmpReg); - if (ResTy == MatchOperand_NoMatch) { - reportParseError("expected register containing function address"); - return false; - } - - MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]); - if (!FuncRegOpnd.isGPRAsmReg()) { - reportParseError(FuncRegOpnd.getStartLoc(), "invalid register"); - return false; - } - - FuncReg = FuncRegOpnd.getGPR32Reg(); - TmpReg.clear(); - - if (!eatComma("unexpected token, expected comma")) - return true; - - ResTy = parseAnyRegister(TmpReg); - if (ResTy == MatchOperand_NoMatch) { - const MCExpr *OffsetExpr; - int64_t OffsetVal; - SMLoc ExprLoc = getLexer().getLoc(); - - if (Parser.parseExpression(OffsetExpr) || - !OffsetExpr->evaluateAsAbsolute(OffsetVal)) { - reportParseError(ExprLoc, "expected save register or stack offset"); - return false; - } - - Save = OffsetVal; - SaveIsReg = false; - } else { - MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]); - if (!SaveOpnd.isGPRAsmReg()) { - reportParseError(SaveOpnd.getStartLoc(), "invalid register"); - return false; - } - Save = SaveOpnd.getGPR32Reg(); - } - - if (!eatComma("unexpected token, expected comma")) - return true; - - const MCExpr *Expr; - if (Parser.parseExpression(Expr)) { - reportParseError("expected expression"); - return false; - } - - if (Expr->getKind() != MCExpr::SymbolRef) { - reportParseError("expected symbol"); - return false; - } - const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr); - - CpSaveLocation = Save; - CpSaveLocationIsRegister = SaveIsReg; - - getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(), - SaveIsReg); - return false; -} - -bool MipsAsmParser::parseDirectiveCPReturn() { - getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation, - CpSaveLocationIsRegister); - return false; -} - -bool MipsAsmParser::parseDirectiveNaN() { - MCAsmParser &Parser = getParser(); - if (getLexer().isNot(AsmToken::EndOfStatement)) { - const AsmToken &Tok = Parser.getTok(); - - if (Tok.getString() == "2008") { - Parser.Lex(); - getTargetStreamer().emitDirectiveNaN2008(); - return false; - } else if (Tok.getString() == "legacy") { - Parser.Lex(); - getTargetStreamer().emitDirectiveNaNLegacy(); - return false; - } - } - // If we don't recognize the option passed to the .nan - // directive (e.g. no option or unknown option), emit an error. - reportParseError("invalid option in .nan directive"); - return false; -} - -bool MipsAsmParser::parseDirectiveSet() { - const AsmToken &Tok = getParser().getTok(); - StringRef IdVal = Tok.getString(); - SMLoc Loc = Tok.getLoc(); - - if (IdVal == "noat") - return parseSetNoAtDirective(); - if (IdVal == "at") - return parseSetAtDirective(); - if (IdVal == "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") - return parseSetFpDirective(); - if (IdVal == "oddspreg") - return parseSetOddSPRegDirective(); - if (IdVal == "nooddspreg") - return parseSetNoOddSPRegDirective(); - if (IdVal == "pop") - return parseSetPopDirective(); - if (IdVal == "push") - return parseSetPushDirective(); - if (IdVal == "reorder") - return parseSetReorderDirective(); - if (IdVal == "noreorder") - return parseSetNoReorderDirective(); - if (IdVal == "macro") - return parseSetMacroDirective(); - if (IdVal == "nomacro") - return parseSetNoMacroDirective(); - if (IdVal == "mips16") - return parseSetMips16Directive(); - if (IdVal == "nomips16") - return parseSetNoMips16Directive(); - if (IdVal == "nomicromips") { - clearFeatureBits(Mips::FeatureMicroMips, "micromips"); - getTargetStreamer().emitDirectiveSetNoMicroMips(); - getParser().eatToEndOfStatement(); - return false; - } - if (IdVal == "micromips") { - if (hasMips64r6()) { - Error(Loc, ".set micromips directive is not supported with MIPS64R6"); - return false; - } - return parseSetFeature(Mips::FeatureMicroMips); - } - if (IdVal == "mips0") - return parseSetMips0Directive(); - if (IdVal == "mips1") - return parseSetFeature(Mips::FeatureMips1); - if (IdVal == "mips2") - return parseSetFeature(Mips::FeatureMips2); - if (IdVal == "mips3") - return parseSetFeature(Mips::FeatureMips3); - if (IdVal == "mips4") - return parseSetFeature(Mips::FeatureMips4); - if (IdVal == "mips5") - return parseSetFeature(Mips::FeatureMips5); - if (IdVal == "mips32") - return parseSetFeature(Mips::FeatureMips32); - if (IdVal == "mips32r2") - return parseSetFeature(Mips::FeatureMips32r2); - if (IdVal == "mips32r3") - return parseSetFeature(Mips::FeatureMips32r3); - if (IdVal == "mips32r5") - return parseSetFeature(Mips::FeatureMips32r5); - if (IdVal == "mips32r6") - return parseSetFeature(Mips::FeatureMips32r6); - if (IdVal == "mips64") - return parseSetFeature(Mips::FeatureMips64); - if (IdVal == "mips64r2") - return parseSetFeature(Mips::FeatureMips64r2); - if (IdVal == "mips64r3") - return parseSetFeature(Mips::FeatureMips64r3); - if (IdVal == "mips64r5") - return parseSetFeature(Mips::FeatureMips64r5); - if (IdVal == "mips64r6") { - if (inMicroMipsMode()) { - Error(Loc, "MIPS64R6 is not supported with microMIPS"); - return false; - } - return parseSetFeature(Mips::FeatureMips64r6); - } - if (IdVal == "dsp") - return parseSetFeature(Mips::FeatureDSP); - if (IdVal == "dspr2") - return parseSetFeature(Mips::FeatureDSPR2); - if (IdVal == "nodsp") - return parseSetNoDspDirective(); - if (IdVal == "msa") - return parseSetMsaDirective(); - if (IdVal == "nomsa") - return parseSetNoMsaDirective(); - if (IdVal == "mt") - return parseSetMtDirective(); - if (IdVal == "nomt") - return parseSetNoMtDirective(); - if (IdVal == "softfloat") - return parseSetSoftFloatDirective(); - if (IdVal == "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(); -} - -/// parseDirectiveGpWord -/// ::= .gpword local_sym -bool MipsAsmParser::parseDirectiveGpWord() { - MCAsmParser &Parser = getParser(); - const MCExpr *Value; - // EmitGPRel32Value requires an expression, so we are using base class - // method to evaluate the expression. - if (getParser().parseExpression(Value)) - return true; - getParser().getStreamer().EmitGPRel32Value(Value); - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return Error(getLexer().getLoc(), - "unexpected token, expected end of statement"); - Parser.Lex(); // Eat EndOfStatement token. - return false; -} - -/// parseDirectiveGpDWord -/// ::= .gpdword local_sym -bool MipsAsmParser::parseDirectiveGpDWord() { - MCAsmParser &Parser = getParser(); - const MCExpr *Value; - // EmitGPRel64Value requires an expression, so we are using base class - // method to evaluate the expression. - if (getParser().parseExpression(Value)) - return true; - 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(), - "unexpected token, expected end of statement"); - Parser.Lex(); // Eat EndOfStatement token. - return false; -} - -bool MipsAsmParser::parseDirectiveOption() { - MCAsmParser &Parser = getParser(); - // Get the option token. - 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"); - } - - StringRef Option = Tok.getIdentifier(); - - if (Option == "pic0") { - // MipsAsmParser needs to know if the current PIC mode changes. - IsPicEnabled = false; - - getTargetStreamer().emitDirectiveOptionPic0(); - Parser.Lex(); - if (Parser.getTok().isNot(AsmToken::EndOfStatement)) { - return Error(Parser.getTok().getLoc(), - "unexpected token, expected end of statement"); - } - return false; - } - - if (Option == "pic2") { - // MipsAsmParser needs to know if the current PIC mode changes. - IsPicEnabled = true; - - getTargetStreamer().emitDirectiveOptionPic2(); - Parser.Lex(); - if (Parser.getTok().isNot(AsmToken::EndOfStatement)) { - return Error(Parser.getTok().getLoc(), - "unexpected token, expected end of statement"); - } - return false; - } - - // Unknown option. - Warning(Parser.getTok().getLoc(), - "unknown option, expected 'pic0' or 'pic2'"); - Parser.eatToEndOfStatement(); - return false; -} - -/// parseInsnDirective -/// ::= .insn -bool MipsAsmParser::parseInsnDirective() { - // 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; - } - - // The actual label marking happens in - // MipsELFStreamer::createPendingLabelRelocs(). - getTargetStreamer().emitDirectiveInsn(); - - getParser().Lex(); // Eat EndOfStatement token. - 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(); - SMLoc L = Lexer.getLoc(); - - if (!getTargetStreamer().isModuleDirectiveAllowed()) { - // TODO : get a better message. - reportParseError(".module directive must appear before any code"); - return false; - } - - StringRef Option; - if (Parser.parseIdentifier(Option)) { - reportParseError("expected .module option identifier"); - return false; - } - - if (Option == "oddspreg") { - clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg"); - - // Synchronize the abiflags information with the FeatureBits information we - // changed above. - getTargetStreamer().updateABIInfo(*this); - - // If printing assembly, use the recently updated abiflags information. - // If generating ELF, don't do anything (the .MIPS.abiflags section gets - // emitted at the end). - getTargetStreamer().emitDirectiveModuleOddSPReg(); - - // 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 == "nooddspreg") { - if (!isABI_O32()) { - return Error(L, "'.module nooddspreg' requires the O32 ABI"); - } - - setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg"); - - // Synchronize the abiflags information with the FeatureBits information we - // changed above. - getTargetStreamer().updateABIInfo(*this); - - // If printing assembly, use the recently updated abiflags information. - // If generating ELF, don't do anything (the .MIPS.abiflags section gets - // emitted at the end). - getTargetStreamer().emitDirectiveModuleOddSPReg(); - - // 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 == "fp") { - return parseDirectiveModuleFP(); - } else if (Option == "softfloat") { - setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float"); - - // 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().emitDirectiveModuleSoftFloat(); - - // 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 == "hardfloat") { - clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float"); - - // 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().emitDirectiveModuleHardFloat(); - - // 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 == "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."); - } -} - -/// parseDirectiveModuleFP -/// ::= =32 -/// ::= =xx -/// ::= =64 -bool MipsAsmParser::parseDirectiveModuleFP() { - MCAsmParser &Parser = getParser(); - MCAsmLexer &Lexer = getLexer(); - - if (Lexer.isNot(AsmToken::Equal)) { - reportParseError("unexpected token, expected equals sign '='"); - return false; - } - Parser.Lex(); // Eat '=' token. - - MipsABIFlagsSection::FpABIKind FpABI; - if (!parseFpABIValue(FpABI, ".module")) - return false; - - if (getLexer().isNot(AsmToken::EndOfStatement)) { - reportParseError("unexpected token, expected end of statement"); - return false; - } - - // Synchronize the abiflags information with the FeatureBits information we - // changed above. - getTargetStreamer().updateABIInfo(*this); - - // If printing assembly, use the recently updated abiflags information. - // If generating ELF, don't do anything (the .MIPS.abiflags section gets - // emitted at the end). - getTargetStreamer().emitDirectiveModuleFP(); - - Parser.Lex(); // Consume the EndOfStatement. - return false; -} - -bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI, - StringRef Directive) { - MCAsmParser &Parser = getParser(); - MCAsmLexer &Lexer = getLexer(); - bool ModuleLevelOptions = Directive == ".module"; - - if (Lexer.is(AsmToken::Identifier)) { - StringRef Value = Parser.getTok().getString(); - Parser.Lex(); - - if (Value != "xx") { - reportParseError("unsupported value, expected 'xx', '32' or '64'"); - return false; - } - - if (!isABI_O32()) { - reportParseError("'" + Directive + " fp=xx' requires the O32 ABI"); - return false; - } - - FpABI = MipsABIFlagsSection::FpABIKind::XX; - if (ModuleLevelOptions) { - setModuleFeatureBits(Mips::FeatureFPXX, "fpxx"); - clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64"); - } else { - setFeatureBits(Mips::FeatureFPXX, "fpxx"); - clearFeatureBits(Mips::FeatureFP64Bit, "fp64"); - } - return true; - } - - if (Lexer.is(AsmToken::Integer)) { - unsigned Value = Parser.getTok().getIntVal(); - Parser.Lex(); - - if (Value != 32 && Value != 64) { - reportParseError("unsupported value, expected 'xx', '32' or '64'"); - return false; - } - - if (Value == 32) { - if (!isABI_O32()) { - reportParseError("'" + Directive + " fp=32' requires the O32 ABI"); - return false; - } - - FpABI = MipsABIFlagsSection::FpABIKind::S32; - if (ModuleLevelOptions) { - clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx"); - clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64"); - } else { - clearFeatureBits(Mips::FeatureFPXX, "fpxx"); - clearFeatureBits(Mips::FeatureFP64Bit, "fp64"); - } - } else { - FpABI = MipsABIFlagsSection::FpABIKind::S64; - if (ModuleLevelOptions) { - clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx"); - setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64"); - } else { - clearFeatureBits(Mips::FeatureFPXX, "fpxx"); - setFeatureBits(Mips::FeatureFP64Bit, "fp64"); - } - } - - return true; - } - - return false; -} - -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()); - return false; - } - if (IDVal == ".cplocal") { - parseDirectiveCpLocal(DirectiveID.getLoc()); - return false; - } - if (IDVal == ".ent") { - StringRef SymbolName; - - if (Parser.parseIdentifier(SymbolName)) { - reportParseError("expected identifier after .ent"); - return false; - } - - // There's an undocumented extension that allows an integer to - // follow the name of the procedure which AFAICS is ignored by GAS. - // Example: .ent foo,2 - if (getLexer().isNot(AsmToken::EndOfStatement)) { - if (getLexer().isNot(AsmToken::Comma)) { - // Even though we accept this undocumented extension for compatibility - // reasons, the additional integer argument does not actually change - // the behaviour of the '.ent' directive, so we would like to discourage - // its use. We do this by not referring to the extended version in - // error messages which are not directly related to its use. - reportParseError("unexpected token, expected end of statement"); - return false; - } - Parser.Lex(); // Eat the comma. - const MCExpr *DummyNumber; - int64_t DummyNumberVal; - // If the user was explicitly trying to use the extended version, - // we still give helpful extension-related error messages. - if (Parser.parseExpression(DummyNumber)) { - reportParseError("expected number after comma"); - return false; - } - if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) { - reportParseError("expected an absolute expression after comma"); - return false; - } - } - - // 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; - } - - MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName); - - getTargetStreamer().emitDirectiveEnt(*Sym); - CurrentFn = Sym; - IsCpRestoreSet = false; - return false; - } - - if (IDVal == ".end") { - StringRef SymbolName; - - if (Parser.parseIdentifier(SymbolName)) { - reportParseError("expected identifier after .end"); - return false; - } - - if (getLexer().isNot(AsmToken::EndOfStatement)) { - reportParseError("unexpected token, expected end of statement"); - return false; - } - - if (CurrentFn == nullptr) { - reportParseError(".end used without .ent"); - return false; - } - - if ((SymbolName != CurrentFn->getName())) { - reportParseError(".end symbol does not match .ent symbol"); - return false; - } - - getTargetStreamer().emitDirectiveEnd(SymbolName); - CurrentFn = nullptr; - IsCpRestoreSet = false; - return false; - } - - if (IDVal == ".frame") { - // .frame $stack_reg, frame_size_in_bytes, $return_reg - SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg; - OperandMatchResultTy ResTy = parseAnyRegister(TmpReg); - if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) { - reportParseError("expected stack register"); - return false; - } - - MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]); - if (!StackRegOpnd.isGPRAsmReg()) { - reportParseError(StackRegOpnd.getStartLoc(), - "expected general purpose register"); - return false; - } - unsigned StackReg = StackRegOpnd.getGPR32Reg(); - - if (Parser.getTok().is(AsmToken::Comma)) - Parser.Lex(); - else { - reportParseError("unexpected token, expected comma"); - return false; - } - - // Parse the frame size. - const MCExpr *FrameSize; - int64_t FrameSizeVal; - - if (Parser.parseExpression(FrameSize)) { - reportParseError("expected frame size value"); - return false; - } - - if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) { - reportParseError("frame size not an absolute expression"); - return false; - } - - if (Parser.getTok().is(AsmToken::Comma)) - Parser.Lex(); - else { - reportParseError("unexpected token, expected comma"); - return false; - } - - // Parse the return register. - TmpReg.clear(); - ResTy = parseAnyRegister(TmpReg); - if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) { - reportParseError("expected return register"); - return false; - } - - MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]); - if (!ReturnRegOpnd.isGPRAsmReg()) { - reportParseError(ReturnRegOpnd.getStartLoc(), - "expected general purpose register"); - return false; - } - - // 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; - } - - getTargetStreamer().emitFrame(StackReg, FrameSizeVal, - ReturnRegOpnd.getGPR32Reg()); - IsCpRestoreSet = false; - return false; - } - - if (IDVal == ".set") { - parseDirectiveSet(); - return false; - } - - if (IDVal == ".mask" || IDVal == ".fmask") { - // .mask bitmask, frame_offset - // bitmask: One bit for each register used. - // frame_offset: Offset from Canonical Frame Address ($sp on entry) where - // first register is expected to be saved. - // Examples: - // .mask 0x80000000, -4 - // .fmask 0x80000000, -4 - // - - // Parse the bitmask - const MCExpr *BitMask; - int64_t BitMaskVal; - - if (Parser.parseExpression(BitMask)) { - reportParseError("expected bitmask value"); - return false; - } - - if (!BitMask->evaluateAsAbsolute(BitMaskVal)) { - reportParseError("bitmask not an absolute expression"); - return false; - } - - if (Parser.getTok().is(AsmToken::Comma)) - Parser.Lex(); - else { - reportParseError("unexpected token, expected comma"); - return false; - } - - // Parse the frame_offset - const MCExpr *FrameOffset; - int64_t FrameOffsetVal; - - if (Parser.parseExpression(FrameOffset)) { - reportParseError("expected frame offset value"); - return false; - } - - if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) { - reportParseError("frame offset not an absolute expression"); - return false; - } - - // 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; - } - - if (IDVal == ".mask") - getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal); - else - getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal); - return false; - } - - if (IDVal == ".nan") - return parseDirectiveNaN(); - - if (IDVal == ".gpword") { - parseDirectiveGpWord(); - return false; - } - - if (IDVal == ".gpdword") { - parseDirectiveGpDWord(); - return false; - } - - if (IDVal == ".dtprelword") { - parseDirectiveDtpRelWord(); - return false; - } - - if (IDVal == ".dtpreldword") { - parseDirectiveDtpRelDWord(); - return false; - } - - if (IDVal == ".tprelword") { - parseDirectiveTpRelWord(); - return false; - } - - if (IDVal == ".tpreldword") { - parseDirectiveTpRelDWord(); - return false; - } - - if (IDVal == ".option") { - parseDirectiveOption(); - return false; - } - - if (IDVal == ".abicalls") { - getTargetStreamer().emitDirectiveAbiCalls(); - if (Parser.getTok().isNot(AsmToken::EndOfStatement)) { - Error(Parser.getTok().getLoc(), - "unexpected token, expected end of statement"); - } - 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; - } - - return true; -} - -bool MipsAsmParser::parseInternalDirectiveReallowModule() { - // 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; - } - - getTargetStreamer().reallowModuleDirective(); - - getParser().Lex(); // Eat EndOfStatement token. - return false; -} - -extern "C" void LLVMInitializeMipsAsmParser() { - RegisterMCAsmParser<MipsAsmParser> X(getTheMipsTarget()); - RegisterMCAsmParser<MipsAsmParser> Y(getTheMipselTarget()); - RegisterMCAsmParser<MipsAsmParser> A(getTheMips64Target()); - RegisterMCAsmParser<MipsAsmParser> B(getTheMips64elTarget()); -} - -#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/contrib/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp b/contrib/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp deleted file mode 100644 index 9fdf4e390e10..000000000000 --- a/contrib/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp +++ /dev/null @@ -1,2621 +0,0 @@ -//===- MipsDisassembler.cpp - Disassembler for Mips -----------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file is part of the Mips Disassembler. -// -//===----------------------------------------------------------------------===// - -#include "MCTargetDesc/MipsMCTargetDesc.h" -#include "Mips.h" -#include "TargetInfo/MipsTargetInfo.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCDisassembler/MCDisassembler.h" -#include "llvm/MC/MCFixedLenDisassembler.h" -#include "llvm/MC/MCInst.h" -#include "llvm/MC/MCRegisterInfo.h" -#include "llvm/MC/MCSubtargetInfo.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/TargetRegistry.h" -#include "llvm/Support/raw_ostream.h" -#include <cassert> -#include <cstdint> - -using namespace llvm; - -#define DEBUG_TYPE "mips-disassembler" - -using DecodeStatus = MCDisassembler::DecodeStatus; - -namespace { - -class MipsDisassembler : public MCDisassembler { - bool IsMicroMips; - bool IsBigEndian; - -public: - MipsDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx, bool IsBigEndian) - : MCDisassembler(STI, Ctx), - IsMicroMips(STI.getFeatureBits()[Mips::FeatureMicroMips]), - IsBigEndian(IsBigEndian) {} - - bool hasMips2() const { return STI.getFeatureBits()[Mips::FeatureMips2]; } - bool hasMips3() const { return STI.getFeatureBits()[Mips::FeatureMips3]; } - bool hasMips32() const { return STI.getFeatureBits()[Mips::FeatureMips32]; } - - bool hasMips32r6() const { - return STI.getFeatureBits()[Mips::FeatureMips32r6]; - } - - bool isFP64() const { return STI.getFeatureBits()[Mips::FeatureFP64Bit]; } - - bool isGP64() const { return STI.getFeatureBits()[Mips::FeatureGP64Bit]; } - - bool isPTR64() const { return STI.getFeatureBits()[Mips::FeaturePTR64Bit]; } - - bool hasCnMips() const { return STI.getFeatureBits()[Mips::FeatureCnMips]; } - - bool hasCnMipsP() const { return STI.getFeatureBits()[Mips::FeatureCnMipsP]; } - - bool hasCOP3() const { - // Only present in MIPS-I and MIPS-II - return !hasMips32() && !hasMips3(); - } - - DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size, - ArrayRef<uint8_t> Bytes, uint64_t Address, - raw_ostream &VStream, - raw_ostream &CStream) const override; -}; - -} // end anonymous namespace - -// Forward declare these because the autogenerated code will reference them. -// Definitions are further down. -static DecodeStatus DecodeGPR64RegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeCPU16RegsRegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeGPRMM16RegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeGPRMM16ZeroRegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeGPRMM16MovePRegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeGPR32RegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodePtrRegisterClass(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeDSPRRegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeFGR64RegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeFGR32RegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeCCRRegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeFCCRegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeFGRCCRegisterClass(MCInst &Inst, unsigned RegNo, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeHWRegsRegisterClass(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeAFGR64RegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeACC64DSPRegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeHI32DSPRegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeLO32DSPRegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeMSA128BRegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeMSA128HRegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeMSA128WRegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeMSA128DRegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeMSACtrlRegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeCOP0RegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeCOP2RegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeBranchTarget(MCInst &Inst, - unsigned Offset, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeBranchTarget1SImm16(MCInst &Inst, - unsigned Offset, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeJumpTarget(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeBranchTarget21(MCInst &Inst, - unsigned Offset, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeBranchTarget21MM(MCInst &Inst, - unsigned Offset, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeBranchTarget26(MCInst &Inst, - unsigned Offset, - uint64_t Address, - const void *Decoder); - -// DecodeBranchTarget7MM - Decode microMIPS branch offset, which is -// shifted left by 1 bit. -static DecodeStatus DecodeBranchTarget7MM(MCInst &Inst, - unsigned Offset, - uint64_t Address, - const void *Decoder); - -// DecodeBranchTarget10MM - Decode microMIPS branch offset, which is -// shifted left by 1 bit. -static DecodeStatus DecodeBranchTarget10MM(MCInst &Inst, - unsigned Offset, - uint64_t Address, - const void *Decoder); - -// DecodeBranchTargetMM - Decode microMIPS branch offset, which is -// shifted left by 1 bit. -static DecodeStatus DecodeBranchTargetMM(MCInst &Inst, - unsigned Offset, - uint64_t Address, - const void *Decoder); - -// DecodeBranchTarget26MM - Decode microMIPS branch offset, which is -// shifted left by 1 bit. -static DecodeStatus DecodeBranchTarget26MM(MCInst &Inst, - unsigned Offset, - uint64_t Address, - const void *Decoder); - -// DecodeJumpTargetMM - Decode microMIPS jump target, which is -// shifted left by 1 bit. -static DecodeStatus DecodeJumpTargetMM(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeMem(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeMemEVA(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeLoadByte15(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeCacheOp(MCInst &Inst, unsigned Insn, uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeCacheeOp_CacheOpR6(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeCacheOpMM(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodePrefeOpMM(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeSyncI(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeSyncI_MM(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeSynciR6(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeMSA128Mem(MCInst &Inst, unsigned Insn, - uint64_t Address, const void *Decoder); - -static DecodeStatus DecodeMemMMImm4(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeMemMMSPImm5Lsl2(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeMemMMGPImm7Lsl2(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeMemMMReglistImm4Lsl2(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeMemMMImm9(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeMemMMImm12(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeMemMMImm16(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeFMem(MCInst &Inst, unsigned Insn, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeFMemMMR2(MCInst &Inst, unsigned Insn, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeFMem2(MCInst &Inst, unsigned Insn, uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeFMem3(MCInst &Inst, unsigned Insn, uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeFMemCop2R6(MCInst &Inst, unsigned Insn, - uint64_t Address, const void *Decoder); - -static DecodeStatus DecodeFMemCop2MMR6(MCInst &Inst, unsigned Insn, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeSpecial3LlSc(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeAddiur2Simm7(MCInst &Inst, - unsigned Value, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeLi16Imm(MCInst &Inst, - unsigned Value, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodePOOL16BEncodedField(MCInst &Inst, - unsigned Value, - uint64_t Address, - const void *Decoder); - -template <unsigned Bits, int Offset, int Scale> -static DecodeStatus DecodeUImmWithOffsetAndScale(MCInst &Inst, unsigned Value, - uint64_t Address, - const void *Decoder); - -template <unsigned Bits, int Offset> -static DecodeStatus DecodeUImmWithOffset(MCInst &Inst, unsigned Value, - uint64_t Address, - const void *Decoder) { - return DecodeUImmWithOffsetAndScale<Bits, Offset, 1>(Inst, Value, Address, - Decoder); -} - -template <unsigned Bits, int Offset = 0, int ScaleBy = 1> -static DecodeStatus DecodeSImmWithOffsetAndScale(MCInst &Inst, unsigned Value, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeInsSize(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeSimm19Lsl2(MCInst &Inst, unsigned Insn, - uint64_t Address, const void *Decoder); - -static DecodeStatus DecodeSimm18Lsl3(MCInst &Inst, unsigned Insn, - uint64_t Address, const void *Decoder); - -static DecodeStatus DecodeSimm9SP(MCInst &Inst, unsigned Insn, - uint64_t Address, const void *Decoder); - -static DecodeStatus DecodeANDI16Imm(MCInst &Inst, unsigned Insn, - uint64_t Address, const void *Decoder); - -static DecodeStatus DecodeSimm23Lsl2(MCInst &Inst, unsigned Insn, - uint64_t Address, const void *Decoder); - -/// INSVE_[BHWD] have an implicit operand that the generated decoder doesn't -/// handle. -template <typename InsnType> -static DecodeStatus DecodeINSVE_DF(MCInst &MI, InsnType insn, uint64_t Address, - const void *Decoder); - -template <typename InsnType> -static DecodeStatus DecodeDAHIDATIMMR6(MCInst &MI, InsnType insn, uint64_t Address, - const void *Decoder); - -template <typename InsnType> -static DecodeStatus DecodeDAHIDATI(MCInst &MI, InsnType insn, uint64_t Address, - const void *Decoder); - -template <typename InsnType> -static DecodeStatus DecodeDAHIDATIMMR6(MCInst &MI, InsnType insn, uint64_t Address, - const void *Decoder); - -template <typename InsnType> -static DecodeStatus DecodeDAHIDATI(MCInst &MI, InsnType insn, uint64_t Address, - const void *Decoder); - -template <typename InsnType> -static DecodeStatus -DecodeAddiGroupBranch(MCInst &MI, InsnType insn, uint64_t Address, - const void *Decoder); - -template <typename InsnType> -static DecodeStatus -DecodePOP35GroupBranchMMR6(MCInst &MI, InsnType insn, uint64_t Address, - const void *Decoder); - -template <typename InsnType> -static DecodeStatus -DecodeDaddiGroupBranch(MCInst &MI, InsnType insn, uint64_t Address, - const void *Decoder); - -template <typename InsnType> -static DecodeStatus -DecodePOP37GroupBranchMMR6(MCInst &MI, InsnType insn, uint64_t Address, - const void *Decoder); - -template <typename InsnType> -static DecodeStatus -DecodePOP65GroupBranchMMR6(MCInst &MI, InsnType insn, uint64_t Address, - const void *Decoder); - -template <typename InsnType> -static DecodeStatus -DecodePOP75GroupBranchMMR6(MCInst &MI, InsnType insn, uint64_t Address, - const void *Decoder); - -template <typename InsnType> -static DecodeStatus -DecodeBlezlGroupBranch(MCInst &MI, InsnType insn, uint64_t Address, - const void *Decoder); - -template <typename InsnType> -static DecodeStatus -DecodeBgtzlGroupBranch(MCInst &MI, InsnType insn, uint64_t Address, - const void *Decoder); - -template <typename InsnType> -static DecodeStatus -DecodeBgtzGroupBranch(MCInst &MI, InsnType insn, uint64_t Address, - const void *Decoder); - -template <typename InsnType> -static DecodeStatus -DecodeBlezGroupBranch(MCInst &MI, InsnType insn, uint64_t Address, - const void *Decoder); - -template <typename InsnType> -static DecodeStatus -DecodeBgtzGroupBranchMMR6(MCInst &MI, InsnType insn, uint64_t Address, - const void *Decoder); - -template <typename InsnType> -static DecodeStatus -DecodeBlezGroupBranchMMR6(MCInst &MI, InsnType insn, uint64_t Address, - const void *Decoder); - -template <typename InsnType> -static DecodeStatus DecodeDINS(MCInst &MI, InsnType Insn, uint64_t Address, - const void *Decoder); - -template <typename InsnType> -static DecodeStatus DecodeDEXT(MCInst &MI, InsnType Insn, uint64_t Address, - const void *Decoder); - -template <typename InsnType> -static DecodeStatus DecodeCRC(MCInst &MI, InsnType Insn, uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeRegListOperand(MCInst &Inst, unsigned Insn, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeRegListOperand16(MCInst &Inst, unsigned Insn, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeMovePRegPair(MCInst &Inst, unsigned RegPair, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeMovePOperands(MCInst &Inst, unsigned Insn, - uint64_t Address, const void *Decoder); - -static MCDisassembler *createMipsDisassembler( - const Target &T, - const MCSubtargetInfo &STI, - MCContext &Ctx) { - return new MipsDisassembler(STI, Ctx, true); -} - -static MCDisassembler *createMipselDisassembler( - const Target &T, - const MCSubtargetInfo &STI, - MCContext &Ctx) { - return new MipsDisassembler(STI, Ctx, false); -} - -extern "C" void LLVMInitializeMipsDisassembler() { - // Register the disassembler. - TargetRegistry::RegisterMCDisassembler(getTheMipsTarget(), - createMipsDisassembler); - TargetRegistry::RegisterMCDisassembler(getTheMipselTarget(), - createMipselDisassembler); - TargetRegistry::RegisterMCDisassembler(getTheMips64Target(), - createMipsDisassembler); - TargetRegistry::RegisterMCDisassembler(getTheMips64elTarget(), - createMipselDisassembler); -} - -#include "MipsGenDisassemblerTables.inc" - -static unsigned getReg(const void *D, unsigned RC, unsigned RegNo) { - const MipsDisassembler *Dis = static_cast<const MipsDisassembler*>(D); - const MCRegisterInfo *RegInfo = Dis->getContext().getRegisterInfo(); - return *(RegInfo->getRegClass(RC).begin() + RegNo); -} - -template <typename InsnType> -static DecodeStatus DecodeINSVE_DF(MCInst &MI, InsnType insn, uint64_t Address, - const void *Decoder) { - using DecodeFN = DecodeStatus (*)(MCInst &, unsigned, uint64_t, const void *); - - // The size of the n field depends on the element size - // The register class also depends on this. - InsnType tmp = fieldFromInstruction(insn, 17, 5); - unsigned NSize = 0; - DecodeFN RegDecoder = nullptr; - if ((tmp & 0x18) == 0x00) { // INSVE_B - NSize = 4; - RegDecoder = DecodeMSA128BRegisterClass; - } else if ((tmp & 0x1c) == 0x10) { // INSVE_H - NSize = 3; - RegDecoder = DecodeMSA128HRegisterClass; - } else if ((tmp & 0x1e) == 0x18) { // INSVE_W - NSize = 2; - RegDecoder = DecodeMSA128WRegisterClass; - } else if ((tmp & 0x1f) == 0x1c) { // INSVE_D - NSize = 1; - RegDecoder = DecodeMSA128DRegisterClass; - } else - llvm_unreachable("Invalid encoding"); - - assert(NSize != 0 && RegDecoder != nullptr); - - // $wd - tmp = fieldFromInstruction(insn, 6, 5); - if (RegDecoder(MI, tmp, Address, Decoder) == MCDisassembler::Fail) - return MCDisassembler::Fail; - // $wd_in - if (RegDecoder(MI, tmp, Address, Decoder) == MCDisassembler::Fail) - return MCDisassembler::Fail; - // $n - tmp = fieldFromInstruction(insn, 16, NSize); - MI.addOperand(MCOperand::createImm(tmp)); - // $ws - tmp = fieldFromInstruction(insn, 11, 5); - if (RegDecoder(MI, tmp, Address, Decoder) == MCDisassembler::Fail) - return MCDisassembler::Fail; - // $n2 - MI.addOperand(MCOperand::createImm(0)); - - return MCDisassembler::Success; -} - -template <typename InsnType> -static DecodeStatus DecodeDAHIDATIMMR6(MCInst &MI, InsnType insn, uint64_t Address, - const void *Decoder) { - InsnType Rs = fieldFromInstruction(insn, 16, 5); - InsnType Imm = fieldFromInstruction(insn, 0, 16); - MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR64RegClassID, - Rs))); - MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR64RegClassID, - Rs))); - MI.addOperand(MCOperand::createImm(Imm)); - - return MCDisassembler::Success; -} - -template <typename InsnType> -static DecodeStatus DecodeDAHIDATI(MCInst &MI, InsnType insn, uint64_t Address, - const void *Decoder) { - InsnType Rs = fieldFromInstruction(insn, 21, 5); - InsnType Imm = fieldFromInstruction(insn, 0, 16); - MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR64RegClassID, - Rs))); - MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR64RegClassID, - Rs))); - MI.addOperand(MCOperand::createImm(Imm)); - - return MCDisassembler::Success; -} - -template <typename InsnType> -static DecodeStatus DecodeAddiGroupBranch(MCInst &MI, InsnType insn, - uint64_t Address, - const void *Decoder) { - // If we are called then we can assume that MIPS32r6/MIPS64r6 is enabled - // (otherwise we would have matched the ADDI instruction from the earlier - // ISA's instead). - // - // We have: - // 0b001000 sssss ttttt iiiiiiiiiiiiiiii - // BOVC if rs >= rt - // BEQZALC if rs == 0 && rt != 0 - // BEQC if rs < rt && rs != 0 - - InsnType Rs = fieldFromInstruction(insn, 21, 5); - InsnType Rt = fieldFromInstruction(insn, 16, 5); - int64_t Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 4 + 4; - bool HasRs = false; - - if (Rs >= Rt) { - MI.setOpcode(Mips::BOVC); - HasRs = true; - } else if (Rs != 0 && Rs < Rt) { - MI.setOpcode(Mips::BEQC); - HasRs = true; - } else - MI.setOpcode(Mips::BEQZALC); - - if (HasRs) - MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, - Rs))); - - MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, - Rt))); - MI.addOperand(MCOperand::createImm(Imm)); - - return MCDisassembler::Success; -} - -template <typename InsnType> -static DecodeStatus DecodePOP35GroupBranchMMR6(MCInst &MI, InsnType insn, - uint64_t Address, - const void *Decoder) { - InsnType Rt = fieldFromInstruction(insn, 21, 5); - InsnType Rs = fieldFromInstruction(insn, 16, 5); - int64_t Imm = 0; - - if (Rs >= Rt) { - MI.setOpcode(Mips::BOVC_MMR6); - MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, - Rt))); - MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, - Rs))); - Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 2 + 4; - } else if (Rs != 0 && Rs < Rt) { - MI.setOpcode(Mips::BEQC_MMR6); - MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, - Rs))); - MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, - Rt))); - Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 4 + 4; - } else { - MI.setOpcode(Mips::BEQZALC_MMR6); - MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, - Rt))); - Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 2 + 4; - } - - MI.addOperand(MCOperand::createImm(Imm)); - - return MCDisassembler::Success; -} - -template <typename InsnType> -static DecodeStatus DecodeDaddiGroupBranch(MCInst &MI, InsnType insn, - uint64_t Address, - const void *Decoder) { - // If we are called then we can assume that MIPS32r6/MIPS64r6 is enabled - // (otherwise we would have matched the ADDI instruction from the earlier - // ISA's instead). - // - // We have: - // 0b011000 sssss ttttt iiiiiiiiiiiiiiii - // BNVC if rs >= rt - // BNEZALC if rs == 0 && rt != 0 - // BNEC if rs < rt && rs != 0 - - InsnType Rs = fieldFromInstruction(insn, 21, 5); - InsnType Rt = fieldFromInstruction(insn, 16, 5); - int64_t Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 4 + 4; - bool HasRs = false; - - if (Rs >= Rt) { - MI.setOpcode(Mips::BNVC); - HasRs = true; - } else if (Rs != 0 && Rs < Rt) { - MI.setOpcode(Mips::BNEC); - HasRs = true; - } else - MI.setOpcode(Mips::BNEZALC); - - if (HasRs) - MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, - Rs))); - - MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, - Rt))); - MI.addOperand(MCOperand::createImm(Imm)); - - return MCDisassembler::Success; -} - -template <typename InsnType> -static DecodeStatus DecodePOP37GroupBranchMMR6(MCInst &MI, InsnType insn, - uint64_t Address, - const void *Decoder) { - InsnType Rt = fieldFromInstruction(insn, 21, 5); - InsnType Rs = fieldFromInstruction(insn, 16, 5); - int64_t Imm = 0; - - if (Rs >= Rt) { - MI.setOpcode(Mips::BNVC_MMR6); - MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, - Rt))); - MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, - Rs))); - Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 2 + 4; - } else if (Rs != 0 && Rs < Rt) { - MI.setOpcode(Mips::BNEC_MMR6); - MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, - Rs))); - MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, - Rt))); - Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 4 + 4; - } else { - MI.setOpcode(Mips::BNEZALC_MMR6); - MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, - Rt))); - Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 2 + 4; - } - - MI.addOperand(MCOperand::createImm(Imm)); - - return MCDisassembler::Success; -} - -template <typename InsnType> -static DecodeStatus DecodePOP65GroupBranchMMR6(MCInst &MI, InsnType insn, - uint64_t Address, - const void *Decoder) { - // We have: - // 0b110101 ttttt sssss iiiiiiiiiiiiiiii - // Invalid if rt == 0 - // BGTZC_MMR6 if rs == 0 && rt != 0 - // BLTZC_MMR6 if rs == rt && rt != 0 - // BLTC_MMR6 if rs != rt && rs != 0 && rt != 0 - - InsnType Rt = fieldFromInstruction(insn, 21, 5); - InsnType Rs = fieldFromInstruction(insn, 16, 5); - int64_t Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 4 + 4; - bool HasRs = false; - - if (Rt == 0) - return MCDisassembler::Fail; - else if (Rs == 0) - MI.setOpcode(Mips::BGTZC_MMR6); - else if (Rs == Rt) - MI.setOpcode(Mips::BLTZC_MMR6); - else { - MI.setOpcode(Mips::BLTC_MMR6); - HasRs = true; - } - - if (HasRs) - MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, - Rs))); - - MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, - Rt))); - - MI.addOperand(MCOperand::createImm(Imm)); - - return MCDisassembler::Success; -} - -template <typename InsnType> -static DecodeStatus DecodePOP75GroupBranchMMR6(MCInst &MI, InsnType insn, - uint64_t Address, - const void *Decoder) { - // We have: - // 0b111101 ttttt sssss iiiiiiiiiiiiiiii - // Invalid if rt == 0 - // BLEZC_MMR6 if rs == 0 && rt != 0 - // BGEZC_MMR6 if rs == rt && rt != 0 - // BGEC_MMR6 if rs != rt && rs != 0 && rt != 0 - - InsnType Rt = fieldFromInstruction(insn, 21, 5); - InsnType Rs = fieldFromInstruction(insn, 16, 5); - int64_t Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 4 + 4; - bool HasRs = false; - - if (Rt == 0) - return MCDisassembler::Fail; - else if (Rs == 0) - MI.setOpcode(Mips::BLEZC_MMR6); - else if (Rs == Rt) - MI.setOpcode(Mips::BGEZC_MMR6); - else { - HasRs = true; - MI.setOpcode(Mips::BGEC_MMR6); - } - - if (HasRs) - MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, - Rs))); - - MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, - Rt))); - - MI.addOperand(MCOperand::createImm(Imm)); - - return MCDisassembler::Success; -} - -template <typename InsnType> -static DecodeStatus DecodeBlezlGroupBranch(MCInst &MI, InsnType insn, - uint64_t Address, - const void *Decoder) { - // If we are called then we can assume that MIPS32r6/MIPS64r6 is enabled - // (otherwise we would have matched the BLEZL instruction from the earlier - // ISA's instead). - // - // We have: - // 0b010110 sssss ttttt iiiiiiiiiiiiiiii - // Invalid if rs == 0 - // BLEZC if rs == 0 && rt != 0 - // BGEZC if rs == rt && rt != 0 - // BGEC if rs != rt && rs != 0 && rt != 0 - - InsnType Rs = fieldFromInstruction(insn, 21, 5); - InsnType Rt = fieldFromInstruction(insn, 16, 5); - int64_t Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 4 + 4; - bool HasRs = false; - - if (Rt == 0) - return MCDisassembler::Fail; - else if (Rs == 0) - MI.setOpcode(Mips::BLEZC); - else if (Rs == Rt) - MI.setOpcode(Mips::BGEZC); - else { - HasRs = true; - MI.setOpcode(Mips::BGEC); - } - - if (HasRs) - MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, - Rs))); - - MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, - Rt))); - - MI.addOperand(MCOperand::createImm(Imm)); - - return MCDisassembler::Success; -} - -template <typename InsnType> -static DecodeStatus DecodeBgtzlGroupBranch(MCInst &MI, InsnType insn, - uint64_t Address, - const void *Decoder) { - // If we are called then we can assume that MIPS32r6/MIPS64r6 is enabled - // (otherwise we would have matched the BGTZL instruction from the earlier - // ISA's instead). - // - // We have: - // 0b010111 sssss ttttt iiiiiiiiiiiiiiii - // Invalid if rs == 0 - // BGTZC if rs == 0 && rt != 0 - // BLTZC if rs == rt && rt != 0 - // BLTC if rs != rt && rs != 0 && rt != 0 - - bool HasRs = false; - - InsnType Rs = fieldFromInstruction(insn, 21, 5); - InsnType Rt = fieldFromInstruction(insn, 16, 5); - int64_t Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 4 + 4; - - if (Rt == 0) - return MCDisassembler::Fail; - else if (Rs == 0) - MI.setOpcode(Mips::BGTZC); - else if (Rs == Rt) - MI.setOpcode(Mips::BLTZC); - else { - MI.setOpcode(Mips::BLTC); - HasRs = true; - } - - if (HasRs) - MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, - Rs))); - - MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, - Rt))); - - MI.addOperand(MCOperand::createImm(Imm)); - - return MCDisassembler::Success; -} - -template <typename InsnType> -static DecodeStatus DecodeBgtzGroupBranch(MCInst &MI, InsnType insn, - uint64_t Address, - const void *Decoder) { - // If we are called then we can assume that MIPS32r6/MIPS64r6 is enabled - // (otherwise we would have matched the BGTZ instruction from the earlier - // ISA's instead). - // - // We have: - // 0b000111 sssss ttttt iiiiiiiiiiiiiiii - // BGTZ if rt == 0 - // BGTZALC if rs == 0 && rt != 0 - // BLTZALC if rs != 0 && rs == rt - // BLTUC if rs != 0 && rs != rt - - InsnType Rs = fieldFromInstruction(insn, 21, 5); - InsnType Rt = fieldFromInstruction(insn, 16, 5); - int64_t Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 4 + 4; - bool HasRs = false; - bool HasRt = false; - - if (Rt == 0) { - MI.setOpcode(Mips::BGTZ); - HasRs = true; - } else if (Rs == 0) { - MI.setOpcode(Mips::BGTZALC); - HasRt = true; - } else if (Rs == Rt) { - MI.setOpcode(Mips::BLTZALC); - HasRs = true; - } else { - MI.setOpcode(Mips::BLTUC); - HasRs = true; - HasRt = true; - } - - if (HasRs) - MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, - Rs))); - - if (HasRt) - MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, - Rt))); - - MI.addOperand(MCOperand::createImm(Imm)); - - return MCDisassembler::Success; -} - -template <typename InsnType> -static DecodeStatus DecodeBlezGroupBranch(MCInst &MI, InsnType insn, - uint64_t Address, - const void *Decoder) { - // If we are called then we can assume that MIPS32r6/MIPS64r6 is enabled - // (otherwise we would have matched the BLEZL instruction from the earlier - // ISA's instead). - // - // We have: - // 0b000110 sssss ttttt iiiiiiiiiiiiiiii - // Invalid if rs == 0 - // BLEZALC if rs == 0 && rt != 0 - // BGEZALC if rs == rt && rt != 0 - // BGEUC if rs != rt && rs != 0 && rt != 0 - - InsnType Rs = fieldFromInstruction(insn, 21, 5); - InsnType Rt = fieldFromInstruction(insn, 16, 5); - int64_t Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 4 + 4; - bool HasRs = false; - - if (Rt == 0) - return MCDisassembler::Fail; - else if (Rs == 0) - MI.setOpcode(Mips::BLEZALC); - else if (Rs == Rt) - MI.setOpcode(Mips::BGEZALC); - else { - HasRs = true; - MI.setOpcode(Mips::BGEUC); - } - - if (HasRs) - MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, - Rs))); - MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, - Rt))); - - MI.addOperand(MCOperand::createImm(Imm)); - - return MCDisassembler::Success; -} - -// Override the generated disassembler to produce DEXT all the time. This is -// for feature / behaviour parity with binutils. -template <typename InsnType> -static DecodeStatus DecodeDEXT(MCInst &MI, InsnType Insn, uint64_t Address, - const void *Decoder) { - unsigned Msbd = fieldFromInstruction(Insn, 11, 5); - unsigned Lsb = fieldFromInstruction(Insn, 6, 5); - unsigned Size = 0; - unsigned Pos = 0; - - switch (MI.getOpcode()) { - case Mips::DEXT: - Pos = Lsb; - Size = Msbd + 1; - break; - case Mips::DEXTM: - Pos = Lsb; - Size = Msbd + 1 + 32; - break; - case Mips::DEXTU: - Pos = Lsb + 32; - Size = Msbd + 1; - break; - default: - llvm_unreachable("Unknown DEXT instruction!"); - } - - MI.setOpcode(Mips::DEXT); - - InsnType Rs = fieldFromInstruction(Insn, 21, 5); - InsnType Rt = fieldFromInstruction(Insn, 16, 5); - - MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR64RegClassID, Rt))); - MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR64RegClassID, Rs))); - MI.addOperand(MCOperand::createImm(Pos)); - MI.addOperand(MCOperand::createImm(Size)); - - return MCDisassembler::Success; -} - -// Override the generated disassembler to produce DINS all the time. This is -// for feature / behaviour parity with binutils. -template <typename InsnType> -static DecodeStatus DecodeDINS(MCInst &MI, InsnType Insn, uint64_t Address, - const void *Decoder) { - unsigned Msbd = fieldFromInstruction(Insn, 11, 5); - unsigned Lsb = fieldFromInstruction(Insn, 6, 5); - unsigned Size = 0; - unsigned Pos = 0; - - switch (MI.getOpcode()) { - case Mips::DINS: - Pos = Lsb; - Size = Msbd + 1 - Pos; - break; - case Mips::DINSM: - Pos = Lsb; - Size = Msbd + 33 - Pos; - break; - case Mips::DINSU: - Pos = Lsb + 32; - // mbsd = pos + size - 33 - // mbsd - pos + 33 = size - Size = Msbd + 33 - Pos; - break; - default: - llvm_unreachable("Unknown DINS instruction!"); - } - - InsnType Rs = fieldFromInstruction(Insn, 21, 5); - InsnType Rt = fieldFromInstruction(Insn, 16, 5); - - MI.setOpcode(Mips::DINS); - MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR64RegClassID, Rt))); - MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR64RegClassID, Rs))); - MI.addOperand(MCOperand::createImm(Pos)); - MI.addOperand(MCOperand::createImm(Size)); - - return MCDisassembler::Success; -} - -// Auto-generated decoder wouldn't add the third operand for CRC32*. -template <typename InsnType> -static DecodeStatus DecodeCRC(MCInst &MI, InsnType Insn, uint64_t Address, - const void *Decoder) { - InsnType Rs = fieldFromInstruction(Insn, 21, 5); - InsnType Rt = fieldFromInstruction(Insn, 16, 5); - MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, - Rt))); - MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, - Rs))); - MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, - Rt))); - return MCDisassembler::Success; -} - -/// Read two bytes from the ArrayRef and return 16 bit halfword sorted -/// according to the given endianness. -static DecodeStatus readInstruction16(ArrayRef<uint8_t> Bytes, uint64_t Address, - uint64_t &Size, uint32_t &Insn, - bool IsBigEndian) { - // We want to read exactly 2 Bytes of data. - if (Bytes.size() < 2) { - Size = 0; - return MCDisassembler::Fail; - } - - if (IsBigEndian) { - Insn = (Bytes[0] << 8) | Bytes[1]; - } else { - Insn = (Bytes[1] << 8) | Bytes[0]; - } - - return MCDisassembler::Success; -} - -/// Read four bytes from the ArrayRef and return 32 bit word sorted -/// according to the given endianness. -static DecodeStatus readInstruction32(ArrayRef<uint8_t> Bytes, uint64_t Address, - uint64_t &Size, uint32_t &Insn, - bool IsBigEndian, bool IsMicroMips) { - // We want to read exactly 4 Bytes of data. - if (Bytes.size() < 4) { - Size = 0; - return MCDisassembler::Fail; - } - - // High 16 bits of a 32-bit microMIPS instruction (where the opcode is) - // always precede the low 16 bits in the instruction stream (that is, they - // are placed at lower addresses in the instruction stream). - // - // microMIPS byte ordering: - // Big-endian: 0 | 1 | 2 | 3 - // Little-endian: 1 | 0 | 3 | 2 - - if (IsBigEndian) { - // Encoded as a big-endian 32-bit word in the stream. - Insn = - (Bytes[3] << 0) | (Bytes[2] << 8) | (Bytes[1] << 16) | (Bytes[0] << 24); - } else { - if (IsMicroMips) { - Insn = (Bytes[2] << 0) | (Bytes[3] << 8) | (Bytes[0] << 16) | - (Bytes[1] << 24); - } else { - Insn = (Bytes[0] << 0) | (Bytes[1] << 8) | (Bytes[2] << 16) | - (Bytes[3] << 24); - } - } - - return MCDisassembler::Success; -} - -DecodeStatus MipsDisassembler::getInstruction(MCInst &Instr, uint64_t &Size, - ArrayRef<uint8_t> Bytes, - uint64_t Address, - raw_ostream &VStream, - raw_ostream &CStream) const { - uint32_t Insn; - DecodeStatus Result; - Size = 0; - - if (IsMicroMips) { - Result = readInstruction16(Bytes, Address, Size, Insn, IsBigEndian); - if (Result == MCDisassembler::Fail) - return MCDisassembler::Fail; - - if (hasMips32r6()) { - LLVM_DEBUG( - dbgs() << "Trying MicroMipsR616 table (16-bit instructions):\n"); - // Calling the auto-generated decoder function for microMIPS32R6 - // 16-bit instructions. - Result = decodeInstruction(DecoderTableMicroMipsR616, Instr, Insn, - Address, this, STI); - if (Result != MCDisassembler::Fail) { - Size = 2; - return Result; - } - } - - LLVM_DEBUG(dbgs() << "Trying MicroMips16 table (16-bit instructions):\n"); - // Calling the auto-generated decoder function for microMIPS 16-bit - // instructions. - Result = decodeInstruction(DecoderTableMicroMips16, Instr, Insn, Address, - this, STI); - if (Result != MCDisassembler::Fail) { - Size = 2; - return Result; - } - - Result = readInstruction32(Bytes, Address, Size, Insn, IsBigEndian, true); - if (Result == MCDisassembler::Fail) - return MCDisassembler::Fail; - - if (hasMips32r6()) { - LLVM_DEBUG( - dbgs() << "Trying MicroMips32r632 table (32-bit instructions):\n"); - // Calling the auto-generated decoder function. - Result = decodeInstruction(DecoderTableMicroMipsR632, Instr, Insn, Address, - this, STI); - if (Result != MCDisassembler::Fail) { - Size = 4; - return Result; - } - } - - LLVM_DEBUG(dbgs() << "Trying MicroMips32 table (32-bit instructions):\n"); - // Calling the auto-generated decoder function. - Result = decodeInstruction(DecoderTableMicroMips32, Instr, Insn, Address, - this, STI); - if (Result != MCDisassembler::Fail) { - Size = 4; - return Result; - } - - if (isFP64()) { - LLVM_DEBUG(dbgs() << "Trying MicroMipsFP64 table (32-bit opcodes):\n"); - Result = decodeInstruction(DecoderTableMicroMipsFP6432, Instr, Insn, - Address, this, STI); - if (Result != MCDisassembler::Fail) { - Size = 4; - return Result; - } - } - - // This is an invalid instruction. Claim that the Size is 2 bytes. Since - // microMIPS instructions have a minimum alignment of 2, the next 2 bytes - // could form a valid instruction. The two bytes we rejected as an - // instruction could have actually beeen an inline constant pool that is - // unconditionally branched over. - Size = 2; - return MCDisassembler::Fail; - } - - // Attempt to read the instruction so that we can attempt to decode it. If - // the buffer is not 4 bytes long, let the higher level logic figure out - // what to do with a size of zero and MCDisassembler::Fail. - Result = readInstruction32(Bytes, Address, Size, Insn, IsBigEndian, false); - if (Result == MCDisassembler::Fail) - return MCDisassembler::Fail; - - // The only instruction size for standard encoded MIPS. - Size = 4; - - if (hasCOP3()) { - LLVM_DEBUG(dbgs() << "Trying COP3_ table (32-bit opcodes):\n"); - Result = - decodeInstruction(DecoderTableCOP3_32, Instr, Insn, Address, this, STI); - if (Result != MCDisassembler::Fail) - return Result; - } - - if (hasMips32r6() && isGP64()) { - LLVM_DEBUG( - dbgs() << "Trying Mips32r6_64r6 (GPR64) table (32-bit opcodes):\n"); - Result = decodeInstruction(DecoderTableMips32r6_64r6_GP6432, Instr, Insn, - Address, this, STI); - if (Result != MCDisassembler::Fail) - return Result; - } - - if (hasMips32r6() && isPTR64()) { - LLVM_DEBUG( - dbgs() << "Trying Mips32r6_64r6 (PTR64) table (32-bit opcodes):\n"); - Result = decodeInstruction(DecoderTableMips32r6_64r6_PTR6432, Instr, Insn, - Address, this, STI); - if (Result != MCDisassembler::Fail) - return Result; - } - - if (hasMips32r6()) { - LLVM_DEBUG(dbgs() << "Trying Mips32r6_64r6 table (32-bit opcodes):\n"); - Result = decodeInstruction(DecoderTableMips32r6_64r632, Instr, Insn, - Address, this, STI); - if (Result != MCDisassembler::Fail) - return Result; - } - - if (hasMips2() && isPTR64()) { - LLVM_DEBUG( - dbgs() << "Trying Mips32r6_64r6 (PTR64) table (32-bit opcodes):\n"); - Result = decodeInstruction(DecoderTableMips32_64_PTR6432, Instr, Insn, - Address, this, STI); - if (Result != MCDisassembler::Fail) - return Result; - } - - if (hasCnMips()) { - LLVM_DEBUG(dbgs() << "Trying CnMips table (32-bit opcodes):\n"); - Result = decodeInstruction(DecoderTableCnMips32, Instr, Insn, - Address, this, STI); - if (Result != MCDisassembler::Fail) - return Result; - } - - if (hasCnMipsP()) { - LLVM_DEBUG(dbgs() << "Trying CnMipsP table (32-bit opcodes):\n"); - Result = decodeInstruction(DecoderTableCnMipsP32, Instr, Insn, - Address, this, STI); - if (Result != MCDisassembler::Fail) - return Result; - } - - if (isGP64()) { - LLVM_DEBUG(dbgs() << "Trying Mips64 (GPR64) table (32-bit opcodes):\n"); - Result = decodeInstruction(DecoderTableMips6432, Instr, Insn, - Address, this, STI); - if (Result != MCDisassembler::Fail) - return Result; - } - - if (isFP64()) { - LLVM_DEBUG( - dbgs() << "Trying MipsFP64 (64 bit FPU) table (32-bit opcodes):\n"); - Result = decodeInstruction(DecoderTableMipsFP6432, Instr, Insn, - Address, this, STI); - if (Result != MCDisassembler::Fail) - return Result; - } - - LLVM_DEBUG(dbgs() << "Trying Mips table (32-bit opcodes):\n"); - // Calling the auto-generated decoder function. - Result = - decodeInstruction(DecoderTableMips32, Instr, Insn, Address, this, STI); - if (Result != MCDisassembler::Fail) - return Result; - - return MCDisassembler::Fail; -} - -static DecodeStatus DecodeCPU16RegsRegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder) { - return MCDisassembler::Fail; -} - -static DecodeStatus DecodeGPR64RegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder) { - if (RegNo > 31) - return MCDisassembler::Fail; - - unsigned Reg = getReg(Decoder, Mips::GPR64RegClassID, RegNo); - Inst.addOperand(MCOperand::createReg(Reg)); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeGPRMM16RegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder) { - if (RegNo > 7) - return MCDisassembler::Fail; - unsigned Reg = getReg(Decoder, Mips::GPRMM16RegClassID, RegNo); - Inst.addOperand(MCOperand::createReg(Reg)); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeGPRMM16ZeroRegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder) { - if (RegNo > 7) - return MCDisassembler::Fail; - unsigned Reg = getReg(Decoder, Mips::GPRMM16ZeroRegClassID, RegNo); - Inst.addOperand(MCOperand::createReg(Reg)); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeGPRMM16MovePRegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder) { - if (RegNo > 7) - return MCDisassembler::Fail; - unsigned Reg = getReg(Decoder, Mips::GPRMM16MovePRegClassID, RegNo); - Inst.addOperand(MCOperand::createReg(Reg)); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeGPR32RegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder) { - if (RegNo > 31) - return MCDisassembler::Fail; - unsigned Reg = getReg(Decoder, Mips::GPR32RegClassID, RegNo); - Inst.addOperand(MCOperand::createReg(Reg)); - return MCDisassembler::Success; -} - -static DecodeStatus DecodePtrRegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder) { - if (static_cast<const MipsDisassembler *>(Decoder)->isGP64()) - return DecodeGPR64RegisterClass(Inst, RegNo, Address, Decoder); - - return DecodeGPR32RegisterClass(Inst, RegNo, Address, Decoder); -} - -static DecodeStatus DecodeDSPRRegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder) { - return DecodeGPR32RegisterClass(Inst, RegNo, Address, Decoder); -} - -static DecodeStatus DecodeFGR64RegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder) { - if (RegNo > 31) - return MCDisassembler::Fail; - - unsigned Reg = getReg(Decoder, Mips::FGR64RegClassID, RegNo); - Inst.addOperand(MCOperand::createReg(Reg)); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeFGR32RegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder) { - if (RegNo > 31) - return MCDisassembler::Fail; - - unsigned Reg = getReg(Decoder, Mips::FGR32RegClassID, RegNo); - Inst.addOperand(MCOperand::createReg(Reg)); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeCCRRegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder) { - if (RegNo > 31) - return MCDisassembler::Fail; - unsigned Reg = getReg(Decoder, Mips::CCRRegClassID, RegNo); - Inst.addOperand(MCOperand::createReg(Reg)); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeFCCRegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder) { - if (RegNo > 7) - return MCDisassembler::Fail; - unsigned Reg = getReg(Decoder, Mips::FCCRegClassID, RegNo); - Inst.addOperand(MCOperand::createReg(Reg)); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeFGRCCRegisterClass(MCInst &Inst, unsigned RegNo, - uint64_t Address, - const void *Decoder) { - if (RegNo > 31) - return MCDisassembler::Fail; - - unsigned Reg = getReg(Decoder, Mips::FGRCCRegClassID, RegNo); - Inst.addOperand(MCOperand::createReg(Reg)); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeMem(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder) { - int Offset = SignExtend32<16>(Insn & 0xffff); - unsigned Reg = fieldFromInstruction(Insn, 16, 5); - unsigned Base = fieldFromInstruction(Insn, 21, 5); - - Reg = getReg(Decoder, Mips::GPR32RegClassID, Reg); - Base = getReg(Decoder, Mips::GPR32RegClassID, Base); - - if (Inst.getOpcode() == Mips::SC || - Inst.getOpcode() == Mips::SCD) - Inst.addOperand(MCOperand::createReg(Reg)); - - Inst.addOperand(MCOperand::createReg(Reg)); - Inst.addOperand(MCOperand::createReg(Base)); - Inst.addOperand(MCOperand::createImm(Offset)); - - return MCDisassembler::Success; -} - -static DecodeStatus DecodeMemEVA(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder) { - int Offset = SignExtend32<9>(Insn >> 7); - unsigned Reg = fieldFromInstruction(Insn, 16, 5); - unsigned Base = fieldFromInstruction(Insn, 21, 5); - - Reg = getReg(Decoder, Mips::GPR32RegClassID, Reg); - Base = getReg(Decoder, Mips::GPR32RegClassID, Base); - - if (Inst.getOpcode() == Mips::SCE) - Inst.addOperand(MCOperand::createReg(Reg)); - - Inst.addOperand(MCOperand::createReg(Reg)); - Inst.addOperand(MCOperand::createReg(Base)); - Inst.addOperand(MCOperand::createImm(Offset)); - - return MCDisassembler::Success; -} - -static DecodeStatus DecodeLoadByte15(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder) { - int Offset = SignExtend32<16>(Insn & 0xffff); - unsigned Base = fieldFromInstruction(Insn, 16, 5); - unsigned Reg = fieldFromInstruction(Insn, 21, 5); - - Base = getReg(Decoder, Mips::GPR32RegClassID, Base); - Reg = getReg(Decoder, Mips::GPR32RegClassID, Reg); - - Inst.addOperand(MCOperand::createReg(Reg)); - Inst.addOperand(MCOperand::createReg(Base)); - Inst.addOperand(MCOperand::createImm(Offset)); - - return MCDisassembler::Success; -} - -static DecodeStatus DecodeCacheOp(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder) { - int Offset = SignExtend32<16>(Insn & 0xffff); - unsigned Hint = fieldFromInstruction(Insn, 16, 5); - unsigned Base = fieldFromInstruction(Insn, 21, 5); - - Base = getReg(Decoder, Mips::GPR32RegClassID, Base); - - Inst.addOperand(MCOperand::createReg(Base)); - Inst.addOperand(MCOperand::createImm(Offset)); - Inst.addOperand(MCOperand::createImm(Hint)); - - return MCDisassembler::Success; -} - -static DecodeStatus DecodeCacheOpMM(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder) { - int Offset = SignExtend32<12>(Insn & 0xfff); - unsigned Base = fieldFromInstruction(Insn, 16, 5); - unsigned Hint = fieldFromInstruction(Insn, 21, 5); - - Base = getReg(Decoder, Mips::GPR32RegClassID, Base); - - Inst.addOperand(MCOperand::createReg(Base)); - Inst.addOperand(MCOperand::createImm(Offset)); - Inst.addOperand(MCOperand::createImm(Hint)); - - return MCDisassembler::Success; -} - -static DecodeStatus DecodePrefeOpMM(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder) { - int Offset = SignExtend32<9>(Insn & 0x1ff); - unsigned Base = fieldFromInstruction(Insn, 16, 5); - unsigned Hint = fieldFromInstruction(Insn, 21, 5); - - Base = getReg(Decoder, Mips::GPR32RegClassID, Base); - - Inst.addOperand(MCOperand::createReg(Base)); - Inst.addOperand(MCOperand::createImm(Offset)); - Inst.addOperand(MCOperand::createImm(Hint)); - - return MCDisassembler::Success; -} - -static DecodeStatus DecodeCacheeOp_CacheOpR6(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder) { - int Offset = SignExtend32<9>(Insn >> 7); - unsigned Hint = fieldFromInstruction(Insn, 16, 5); - unsigned Base = fieldFromInstruction(Insn, 21, 5); - - Base = getReg(Decoder, Mips::GPR32RegClassID, Base); - - Inst.addOperand(MCOperand::createReg(Base)); - Inst.addOperand(MCOperand::createImm(Offset)); - Inst.addOperand(MCOperand::createImm(Hint)); - - return MCDisassembler::Success; -} - -static DecodeStatus DecodeSyncI(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder) { - int Offset = SignExtend32<16>(Insn & 0xffff); - unsigned Base = fieldFromInstruction(Insn, 21, 5); - - Base = getReg(Decoder, Mips::GPR32RegClassID, Base); - - Inst.addOperand(MCOperand::createReg(Base)); - Inst.addOperand(MCOperand::createImm(Offset)); - - return MCDisassembler::Success; -} - -static DecodeStatus DecodeSyncI_MM(MCInst &Inst, unsigned Insn, - uint64_t Address, const void *Decoder) { - int Offset = SignExtend32<16>(Insn & 0xffff); - unsigned Base = fieldFromInstruction(Insn, 16, 5); - - Base = getReg(Decoder, Mips::GPR32RegClassID, Base); - - Inst.addOperand(MCOperand::createReg(Base)); - Inst.addOperand(MCOperand::createImm(Offset)); - - return MCDisassembler::Success; -} - -static DecodeStatus DecodeSynciR6(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder) { - int Immediate = SignExtend32<16>(Insn & 0xffff); - unsigned Base = fieldFromInstruction(Insn, 16, 5); - - Base = getReg(Decoder, Mips::GPR32RegClassID, Base); - - Inst.addOperand(MCOperand::createReg(Base)); - Inst.addOperand(MCOperand::createImm(Immediate)); - - return MCDisassembler::Success; -} - -static DecodeStatus DecodeMSA128Mem(MCInst &Inst, unsigned Insn, - uint64_t Address, const void *Decoder) { - int Offset = SignExtend32<10>(fieldFromInstruction(Insn, 16, 10)); - unsigned Reg = fieldFromInstruction(Insn, 6, 5); - unsigned Base = fieldFromInstruction(Insn, 11, 5); - - Reg = getReg(Decoder, Mips::MSA128BRegClassID, Reg); - Base = getReg(Decoder, Mips::GPR32RegClassID, Base); - - Inst.addOperand(MCOperand::createReg(Reg)); - Inst.addOperand(MCOperand::createReg(Base)); - - // The immediate field of an LD/ST instruction is scaled which means it must - // be multiplied (when decoding) by the size (in bytes) of the instructions' - // data format. - // .b - 1 byte - // .h - 2 bytes - // .w - 4 bytes - // .d - 8 bytes - switch(Inst.getOpcode()) - { - default: - assert(false && "Unexpected instruction"); - return MCDisassembler::Fail; - break; - case Mips::LD_B: - case Mips::ST_B: - Inst.addOperand(MCOperand::createImm(Offset)); - break; - case Mips::LD_H: - case Mips::ST_H: - Inst.addOperand(MCOperand::createImm(Offset * 2)); - break; - case Mips::LD_W: - case Mips::ST_W: - Inst.addOperand(MCOperand::createImm(Offset * 4)); - break; - case Mips::LD_D: - case Mips::ST_D: - Inst.addOperand(MCOperand::createImm(Offset * 8)); - break; - } - - return MCDisassembler::Success; -} - -static DecodeStatus DecodeMemMMImm4(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder) { - unsigned Offset = Insn & 0xf; - unsigned Reg = fieldFromInstruction(Insn, 7, 3); - unsigned Base = fieldFromInstruction(Insn, 4, 3); - - switch (Inst.getOpcode()) { - case Mips::LBU16_MM: - case Mips::LHU16_MM: - case Mips::LW16_MM: - if (DecodeGPRMM16RegisterClass(Inst, Reg, Address, Decoder) - == MCDisassembler::Fail) - return MCDisassembler::Fail; - break; - case Mips::SB16_MM: - case Mips::SB16_MMR6: - case Mips::SH16_MM: - case Mips::SH16_MMR6: - case Mips::SW16_MM: - case Mips::SW16_MMR6: - if (DecodeGPRMM16ZeroRegisterClass(Inst, Reg, Address, Decoder) - == MCDisassembler::Fail) - return MCDisassembler::Fail; - break; - } - - if (DecodeGPRMM16RegisterClass(Inst, Base, Address, Decoder) - == MCDisassembler::Fail) - return MCDisassembler::Fail; - - switch (Inst.getOpcode()) { - case Mips::LBU16_MM: - if (Offset == 0xf) - Inst.addOperand(MCOperand::createImm(-1)); - else - Inst.addOperand(MCOperand::createImm(Offset)); - break; - case Mips::SB16_MM: - case Mips::SB16_MMR6: - Inst.addOperand(MCOperand::createImm(Offset)); - break; - case Mips::LHU16_MM: - case Mips::SH16_MM: - case Mips::SH16_MMR6: - Inst.addOperand(MCOperand::createImm(Offset << 1)); - break; - case Mips::LW16_MM: - case Mips::SW16_MM: - case Mips::SW16_MMR6: - Inst.addOperand(MCOperand::createImm(Offset << 2)); - break; - } - - return MCDisassembler::Success; -} - -static DecodeStatus DecodeMemMMSPImm5Lsl2(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder) { - unsigned Offset = Insn & 0x1F; - unsigned Reg = fieldFromInstruction(Insn, 5, 5); - - Reg = getReg(Decoder, Mips::GPR32RegClassID, Reg); - - Inst.addOperand(MCOperand::createReg(Reg)); - Inst.addOperand(MCOperand::createReg(Mips::SP)); - Inst.addOperand(MCOperand::createImm(Offset << 2)); - - return MCDisassembler::Success; -} - -static DecodeStatus DecodeMemMMGPImm7Lsl2(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder) { - unsigned Offset = Insn & 0x7F; - unsigned Reg = fieldFromInstruction(Insn, 7, 3); - - Reg = getReg(Decoder, Mips::GPR32RegClassID, Reg); - - Inst.addOperand(MCOperand::createReg(Reg)); - Inst.addOperand(MCOperand::createReg(Mips::GP)); - Inst.addOperand(MCOperand::createImm(Offset << 2)); - - return MCDisassembler::Success; -} - -static DecodeStatus DecodeMemMMReglistImm4Lsl2(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder) { - int Offset; - switch (Inst.getOpcode()) { - case Mips::LWM16_MMR6: - case Mips::SWM16_MMR6: - Offset = fieldFromInstruction(Insn, 4, 4); - break; - default: - Offset = SignExtend32<4>(Insn & 0xf); - break; - } - - if (DecodeRegListOperand16(Inst, Insn, Address, Decoder) - == MCDisassembler::Fail) - return MCDisassembler::Fail; - - Inst.addOperand(MCOperand::createReg(Mips::SP)); - Inst.addOperand(MCOperand::createImm(Offset << 2)); - - return MCDisassembler::Success; -} - -static DecodeStatus DecodeMemMMImm9(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder) { - int Offset = SignExtend32<9>(Insn & 0x1ff); - unsigned Reg = fieldFromInstruction(Insn, 21, 5); - unsigned Base = fieldFromInstruction(Insn, 16, 5); - - Reg = getReg(Decoder, Mips::GPR32RegClassID, Reg); - Base = getReg(Decoder, Mips::GPR32RegClassID, Base); - - if (Inst.getOpcode() == Mips::SCE_MM || Inst.getOpcode() == Mips::SC_MMR6) - Inst.addOperand(MCOperand::createReg(Reg)); - - Inst.addOperand(MCOperand::createReg(Reg)); - Inst.addOperand(MCOperand::createReg(Base)); - Inst.addOperand(MCOperand::createImm(Offset)); - - return MCDisassembler::Success; -} - -static DecodeStatus DecodeMemMMImm12(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder) { - int Offset = SignExtend32<12>(Insn & 0x0fff); - unsigned Reg = fieldFromInstruction(Insn, 21, 5); - unsigned Base = fieldFromInstruction(Insn, 16, 5); - - Reg = getReg(Decoder, Mips::GPR32RegClassID, Reg); - Base = getReg(Decoder, Mips::GPR32RegClassID, Base); - - switch (Inst.getOpcode()) { - case Mips::SWM32_MM: - case Mips::LWM32_MM: - if (DecodeRegListOperand(Inst, Insn, Address, Decoder) - == MCDisassembler::Fail) - return MCDisassembler::Fail; - Inst.addOperand(MCOperand::createReg(Base)); - Inst.addOperand(MCOperand::createImm(Offset)); - break; - case Mips::SC_MM: - Inst.addOperand(MCOperand::createReg(Reg)); - LLVM_FALLTHROUGH; - default: - Inst.addOperand(MCOperand::createReg(Reg)); - if (Inst.getOpcode() == Mips::LWP_MM || Inst.getOpcode() == Mips::SWP_MM) - Inst.addOperand(MCOperand::createReg(Reg+1)); - - Inst.addOperand(MCOperand::createReg(Base)); - Inst.addOperand(MCOperand::createImm(Offset)); - } - - return MCDisassembler::Success; -} - -static DecodeStatus DecodeMemMMImm16(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder) { - int Offset = SignExtend32<16>(Insn & 0xffff); - unsigned Reg = fieldFromInstruction(Insn, 21, 5); - unsigned Base = fieldFromInstruction(Insn, 16, 5); - - Reg = getReg(Decoder, Mips::GPR32RegClassID, Reg); - Base = getReg(Decoder, Mips::GPR32RegClassID, Base); - - Inst.addOperand(MCOperand::createReg(Reg)); - Inst.addOperand(MCOperand::createReg(Base)); - Inst.addOperand(MCOperand::createImm(Offset)); - - return MCDisassembler::Success; -} - -static DecodeStatus DecodeFMem(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder) { - int Offset = SignExtend32<16>(Insn & 0xffff); - unsigned Reg = fieldFromInstruction(Insn, 16, 5); - unsigned Base = fieldFromInstruction(Insn, 21, 5); - - Reg = getReg(Decoder, Mips::FGR64RegClassID, Reg); - Base = getReg(Decoder, Mips::GPR32RegClassID, Base); - - Inst.addOperand(MCOperand::createReg(Reg)); - Inst.addOperand(MCOperand::createReg(Base)); - Inst.addOperand(MCOperand::createImm(Offset)); - - return MCDisassembler::Success; -} - -static DecodeStatus DecodeFMemMMR2(MCInst &Inst, unsigned Insn, - uint64_t Address, const void *Decoder) { - // This function is the same as DecodeFMem but with the Reg and Base fields - // swapped according to microMIPS spec. - int Offset = SignExtend32<16>(Insn & 0xffff); - unsigned Base = fieldFromInstruction(Insn, 16, 5); - unsigned Reg = fieldFromInstruction(Insn, 21, 5); - - Reg = getReg(Decoder, Mips::FGR64RegClassID, Reg); - Base = getReg(Decoder, Mips::GPR32RegClassID, Base); - - Inst.addOperand(MCOperand::createReg(Reg)); - Inst.addOperand(MCOperand::createReg(Base)); - Inst.addOperand(MCOperand::createImm(Offset)); - - return MCDisassembler::Success; -} - -static DecodeStatus DecodeFMem2(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder) { - int Offset = SignExtend32<16>(Insn & 0xffff); - unsigned Reg = fieldFromInstruction(Insn, 16, 5); - unsigned Base = fieldFromInstruction(Insn, 21, 5); - - Reg = getReg(Decoder, Mips::COP2RegClassID, Reg); - Base = getReg(Decoder, Mips::GPR32RegClassID, Base); - - Inst.addOperand(MCOperand::createReg(Reg)); - Inst.addOperand(MCOperand::createReg(Base)); - Inst.addOperand(MCOperand::createImm(Offset)); - - return MCDisassembler::Success; -} - -static DecodeStatus DecodeFMem3(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder) { - int Offset = SignExtend32<16>(Insn & 0xffff); - unsigned Reg = fieldFromInstruction(Insn, 16, 5); - unsigned Base = fieldFromInstruction(Insn, 21, 5); - - Reg = getReg(Decoder, Mips::COP3RegClassID, Reg); - Base = getReg(Decoder, Mips::GPR32RegClassID, Base); - - Inst.addOperand(MCOperand::createReg(Reg)); - Inst.addOperand(MCOperand::createReg(Base)); - Inst.addOperand(MCOperand::createImm(Offset)); - - return MCDisassembler::Success; -} - -static DecodeStatus DecodeFMemCop2R6(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder) { - int Offset = SignExtend32<11>(Insn & 0x07ff); - unsigned Reg = fieldFromInstruction(Insn, 16, 5); - unsigned Base = fieldFromInstruction(Insn, 11, 5); - - Reg = getReg(Decoder, Mips::COP2RegClassID, Reg); - Base = getReg(Decoder, Mips::GPR32RegClassID, Base); - - Inst.addOperand(MCOperand::createReg(Reg)); - Inst.addOperand(MCOperand::createReg(Base)); - Inst.addOperand(MCOperand::createImm(Offset)); - - return MCDisassembler::Success; -} - -static DecodeStatus DecodeFMemCop2MMR6(MCInst &Inst, unsigned Insn, - uint64_t Address, const void *Decoder) { - int Offset = SignExtend32<11>(Insn & 0x07ff); - unsigned Reg = fieldFromInstruction(Insn, 21, 5); - unsigned Base = fieldFromInstruction(Insn, 16, 5); - - Reg = getReg(Decoder, Mips::COP2RegClassID, Reg); - Base = getReg(Decoder, Mips::GPR32RegClassID, Base); - - Inst.addOperand(MCOperand::createReg(Reg)); - Inst.addOperand(MCOperand::createReg(Base)); - Inst.addOperand(MCOperand::createImm(Offset)); - - return MCDisassembler::Success; -} - -static DecodeStatus DecodeSpecial3LlSc(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder) { - int64_t Offset = SignExtend64<9>((Insn >> 7) & 0x1ff); - unsigned Rt = fieldFromInstruction(Insn, 16, 5); - unsigned Base = fieldFromInstruction(Insn, 21, 5); - - Rt = getReg(Decoder, Mips::GPR32RegClassID, Rt); - Base = getReg(Decoder, Mips::GPR32RegClassID, Base); - - if(Inst.getOpcode() == Mips::SC_R6 || Inst.getOpcode() == Mips::SCD_R6){ - Inst.addOperand(MCOperand::createReg(Rt)); - } - - Inst.addOperand(MCOperand::createReg(Rt)); - Inst.addOperand(MCOperand::createReg(Base)); - Inst.addOperand(MCOperand::createImm(Offset)); - - return MCDisassembler::Success; -} - -static DecodeStatus DecodeHWRegsRegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder) { - // Currently only hardware register 29 is supported. - if (RegNo != 29) - return MCDisassembler::Fail; - Inst.addOperand(MCOperand::createReg(Mips::HWR29)); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeAFGR64RegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder) { - if (RegNo > 30 || RegNo %2) - return MCDisassembler::Fail; - - unsigned Reg = getReg(Decoder, Mips::AFGR64RegClassID, RegNo /2); - Inst.addOperand(MCOperand::createReg(Reg)); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeACC64DSPRegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder) { - if (RegNo >= 4) - return MCDisassembler::Fail; - - unsigned Reg = getReg(Decoder, Mips::ACC64DSPRegClassID, RegNo); - Inst.addOperand(MCOperand::createReg(Reg)); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeHI32DSPRegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder) { - if (RegNo >= 4) - return MCDisassembler::Fail; - - unsigned Reg = getReg(Decoder, Mips::HI32DSPRegClassID, RegNo); - Inst.addOperand(MCOperand::createReg(Reg)); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeLO32DSPRegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder) { - if (RegNo >= 4) - return MCDisassembler::Fail; - - unsigned Reg = getReg(Decoder, Mips::LO32DSPRegClassID, RegNo); - Inst.addOperand(MCOperand::createReg(Reg)); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeMSA128BRegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder) { - if (RegNo > 31) - return MCDisassembler::Fail; - - unsigned Reg = getReg(Decoder, Mips::MSA128BRegClassID, RegNo); - Inst.addOperand(MCOperand::createReg(Reg)); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeMSA128HRegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder) { - if (RegNo > 31) - return MCDisassembler::Fail; - - unsigned Reg = getReg(Decoder, Mips::MSA128HRegClassID, RegNo); - Inst.addOperand(MCOperand::createReg(Reg)); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeMSA128WRegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder) { - if (RegNo > 31) - return MCDisassembler::Fail; - - unsigned Reg = getReg(Decoder, Mips::MSA128WRegClassID, RegNo); - Inst.addOperand(MCOperand::createReg(Reg)); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeMSA128DRegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder) { - if (RegNo > 31) - return MCDisassembler::Fail; - - unsigned Reg = getReg(Decoder, Mips::MSA128DRegClassID, RegNo); - Inst.addOperand(MCOperand::createReg(Reg)); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeMSACtrlRegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder) { - if (RegNo > 7) - return MCDisassembler::Fail; - - unsigned Reg = getReg(Decoder, Mips::MSACtrlRegClassID, RegNo); - Inst.addOperand(MCOperand::createReg(Reg)); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeCOP0RegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder) { - if (RegNo > 31) - return MCDisassembler::Fail; - - unsigned Reg = getReg(Decoder, Mips::COP0RegClassID, RegNo); - Inst.addOperand(MCOperand::createReg(Reg)); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeCOP2RegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder) { - if (RegNo > 31) - return MCDisassembler::Fail; - - unsigned Reg = getReg(Decoder, Mips::COP2RegClassID, RegNo); - Inst.addOperand(MCOperand::createReg(Reg)); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeBranchTarget(MCInst &Inst, - unsigned Offset, - uint64_t Address, - const void *Decoder) { - int32_t BranchOffset = (SignExtend32<16>(Offset) * 4) + 4; - Inst.addOperand(MCOperand::createImm(BranchOffset)); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeBranchTarget1SImm16(MCInst &Inst, - unsigned Offset, - uint64_t Address, - const void *Decoder) { - int32_t BranchOffset = (SignExtend32<16>(Offset) * 2); - Inst.addOperand(MCOperand::createImm(BranchOffset)); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeJumpTarget(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder) { - unsigned JumpOffset = fieldFromInstruction(Insn, 0, 26) << 2; - Inst.addOperand(MCOperand::createImm(JumpOffset)); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeBranchTarget21(MCInst &Inst, - unsigned Offset, - uint64_t Address, - const void *Decoder) { - int32_t BranchOffset = SignExtend32<21>(Offset) * 4 + 4; - - Inst.addOperand(MCOperand::createImm(BranchOffset)); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeBranchTarget21MM(MCInst &Inst, - unsigned Offset, - uint64_t Address, - const void *Decoder) { - int32_t BranchOffset = SignExtend32<21>(Offset) * 4 + 4; - - Inst.addOperand(MCOperand::createImm(BranchOffset)); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeBranchTarget26(MCInst &Inst, - unsigned Offset, - uint64_t Address, - const void *Decoder) { - int32_t BranchOffset = SignExtend32<26>(Offset) * 4 + 4; - - Inst.addOperand(MCOperand::createImm(BranchOffset)); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeBranchTarget7MM(MCInst &Inst, - unsigned Offset, - uint64_t Address, - const void *Decoder) { - int32_t BranchOffset = SignExtend32<8>(Offset << 1); - Inst.addOperand(MCOperand::createImm(BranchOffset)); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeBranchTarget10MM(MCInst &Inst, - unsigned Offset, - uint64_t Address, - const void *Decoder) { - int32_t BranchOffset = SignExtend32<11>(Offset << 1); - Inst.addOperand(MCOperand::createImm(BranchOffset)); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeBranchTargetMM(MCInst &Inst, - unsigned Offset, - uint64_t Address, - const void *Decoder) { - int32_t BranchOffset = SignExtend32<16>(Offset) * 2 + 4; - Inst.addOperand(MCOperand::createImm(BranchOffset)); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeBranchTarget26MM(MCInst &Inst, - unsigned Offset, - uint64_t Address, - const void *Decoder) { - int32_t BranchOffset = SignExtend32<27>(Offset << 1); - - Inst.addOperand(MCOperand::createImm(BranchOffset)); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeJumpTargetMM(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder) { - unsigned JumpOffset = fieldFromInstruction(Insn, 0, 26) << 1; - Inst.addOperand(MCOperand::createImm(JumpOffset)); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeAddiur2Simm7(MCInst &Inst, - unsigned Value, - uint64_t Address, - const void *Decoder) { - if (Value == 0) - Inst.addOperand(MCOperand::createImm(1)); - else if (Value == 0x7) - Inst.addOperand(MCOperand::createImm(-1)); - else - Inst.addOperand(MCOperand::createImm(Value << 2)); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeLi16Imm(MCInst &Inst, - unsigned Value, - uint64_t Address, - const void *Decoder) { - if (Value == 0x7F) - Inst.addOperand(MCOperand::createImm(-1)); - else - Inst.addOperand(MCOperand::createImm(Value)); - return MCDisassembler::Success; -} - -static DecodeStatus DecodePOOL16BEncodedField(MCInst &Inst, - unsigned Value, - uint64_t Address, - const void *Decoder) { - Inst.addOperand(MCOperand::createImm(Value == 0x0 ? 8 : Value)); - return MCDisassembler::Success; -} - -template <unsigned Bits, int Offset, int Scale> -static DecodeStatus DecodeUImmWithOffsetAndScale(MCInst &Inst, unsigned Value, - uint64_t Address, - const void *Decoder) { - Value &= ((1 << Bits) - 1); - Value *= Scale; - Inst.addOperand(MCOperand::createImm(Value + Offset)); - return MCDisassembler::Success; -} - -template <unsigned Bits, int Offset, int ScaleBy> -static DecodeStatus DecodeSImmWithOffsetAndScale(MCInst &Inst, unsigned Value, - uint64_t Address, - const void *Decoder) { - int32_t Imm = SignExtend32<Bits>(Value) * ScaleBy; - Inst.addOperand(MCOperand::createImm(Imm + Offset)); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeInsSize(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder) { - // First we need to grab the pos(lsb) from MCInst. - // This function only handles the 32 bit variants of ins, as dins - // variants are handled differently. - int Pos = Inst.getOperand(2).getImm(); - int Size = (int) Insn - Pos + 1; - Inst.addOperand(MCOperand::createImm(SignExtend32<16>(Size))); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeSimm19Lsl2(MCInst &Inst, unsigned Insn, - uint64_t Address, const void *Decoder) { - Inst.addOperand(MCOperand::createImm(SignExtend32<19>(Insn) * 4)); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeSimm18Lsl3(MCInst &Inst, unsigned Insn, - uint64_t Address, const void *Decoder) { - Inst.addOperand(MCOperand::createImm(SignExtend32<18>(Insn) * 8)); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeSimm9SP(MCInst &Inst, unsigned Insn, - uint64_t Address, const void *Decoder) { - int32_t DecodedValue; - switch (Insn) { - case 0: DecodedValue = 256; break; - case 1: DecodedValue = 257; break; - case 510: DecodedValue = -258; break; - case 511: DecodedValue = -257; break; - default: DecodedValue = SignExtend32<9>(Insn); break; - } - Inst.addOperand(MCOperand::createImm(DecodedValue * 4)); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeANDI16Imm(MCInst &Inst, unsigned Insn, - uint64_t Address, const void *Decoder) { - // Insn must be >= 0, since it is unsigned that condition is always true. - assert(Insn < 16); - int32_t DecodedValues[] = {128, 1, 2, 3, 4, 7, 8, 15, 16, 31, 32, 63, 64, - 255, 32768, 65535}; - Inst.addOperand(MCOperand::createImm(DecodedValues[Insn])); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeRegListOperand(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder) { - unsigned Regs[] = {Mips::S0, Mips::S1, Mips::S2, Mips::S3, Mips::S4, Mips::S5, - Mips::S6, Mips::S7, Mips::FP}; - unsigned RegNum; - - unsigned RegLst = fieldFromInstruction(Insn, 21, 5); - - // Empty register lists are not allowed. - if (RegLst == 0) - return MCDisassembler::Fail; - - RegNum = RegLst & 0xf; - - // RegLst values 10-15, and 26-31 are reserved. - if (RegNum > 9) - return MCDisassembler::Fail; - - for (unsigned i = 0; i < RegNum; i++) - Inst.addOperand(MCOperand::createReg(Regs[i])); - - if (RegLst & 0x10) - Inst.addOperand(MCOperand::createReg(Mips::RA)); - - return MCDisassembler::Success; -} - -static DecodeStatus DecodeRegListOperand16(MCInst &Inst, unsigned Insn, - uint64_t Address, - const void *Decoder) { - unsigned Regs[] = {Mips::S0, Mips::S1, Mips::S2, Mips::S3}; - unsigned RegLst; - switch(Inst.getOpcode()) { - default: - RegLst = fieldFromInstruction(Insn, 4, 2); - break; - case Mips::LWM16_MMR6: - case Mips::SWM16_MMR6: - RegLst = fieldFromInstruction(Insn, 8, 2); - break; - } - unsigned RegNum = RegLst & 0x3; - - for (unsigned i = 0; i <= RegNum; i++) - Inst.addOperand(MCOperand::createReg(Regs[i])); - - Inst.addOperand(MCOperand::createReg(Mips::RA)); - - return MCDisassembler::Success; -} - -static DecodeStatus DecodeMovePOperands(MCInst &Inst, unsigned Insn, - uint64_t Address, - const void *Decoder) { - unsigned RegPair = fieldFromInstruction(Insn, 7, 3); - if (DecodeMovePRegPair(Inst, RegPair, Address, Decoder) == - MCDisassembler::Fail) - return MCDisassembler::Fail; - - unsigned RegRs; - if (static_cast<const MipsDisassembler*>(Decoder)->hasMips32r6()) - RegRs = fieldFromInstruction(Insn, 0, 2) | - (fieldFromInstruction(Insn, 3, 1) << 2); - else - RegRs = fieldFromInstruction(Insn, 1, 3); - if (DecodeGPRMM16MovePRegisterClass(Inst, RegRs, Address, Decoder) == - MCDisassembler::Fail) - return MCDisassembler::Fail; - - unsigned RegRt = fieldFromInstruction(Insn, 4, 3); - if (DecodeGPRMM16MovePRegisterClass(Inst, RegRt, Address, Decoder) == - MCDisassembler::Fail) - return MCDisassembler::Fail; - - return MCDisassembler::Success; -} - -static DecodeStatus DecodeMovePRegPair(MCInst &Inst, unsigned RegPair, - uint64_t Address, const void *Decoder) { - switch (RegPair) { - default: - return MCDisassembler::Fail; - case 0: - Inst.addOperand(MCOperand::createReg(Mips::A1)); - Inst.addOperand(MCOperand::createReg(Mips::A2)); - break; - case 1: - Inst.addOperand(MCOperand::createReg(Mips::A1)); - Inst.addOperand(MCOperand::createReg(Mips::A3)); - break; - case 2: - Inst.addOperand(MCOperand::createReg(Mips::A2)); - Inst.addOperand(MCOperand::createReg(Mips::A3)); - break; - case 3: - Inst.addOperand(MCOperand::createReg(Mips::A0)); - Inst.addOperand(MCOperand::createReg(Mips::S5)); - break; - case 4: - Inst.addOperand(MCOperand::createReg(Mips::A0)); - Inst.addOperand(MCOperand::createReg(Mips::S6)); - break; - case 5: - Inst.addOperand(MCOperand::createReg(Mips::A0)); - Inst.addOperand(MCOperand::createReg(Mips::A1)); - break; - case 6: - Inst.addOperand(MCOperand::createReg(Mips::A0)); - Inst.addOperand(MCOperand::createReg(Mips::A2)); - break; - case 7: - Inst.addOperand(MCOperand::createReg(Mips::A0)); - Inst.addOperand(MCOperand::createReg(Mips::A3)); - break; - } - - return MCDisassembler::Success; -} - -static DecodeStatus DecodeSimm23Lsl2(MCInst &Inst, unsigned Insn, - uint64_t Address, const void *Decoder) { - Inst.addOperand(MCOperand::createImm(SignExtend32<25>(Insn << 2))); - return MCDisassembler::Success; -} - -template <typename InsnType> -static DecodeStatus DecodeBgtzGroupBranchMMR6(MCInst &MI, InsnType insn, - uint64_t Address, - const void *Decoder) { - // We have: - // 0b000111 ttttt sssss iiiiiiiiiiiiiiii - // Invalid if rt == 0 - // BGTZALC_MMR6 if rs == 0 && rt != 0 - // BLTZALC_MMR6 if rs != 0 && rs == rt - // BLTUC_MMR6 if rs != 0 && rs != rt - - InsnType Rt = fieldFromInstruction(insn, 21, 5); - InsnType Rs = fieldFromInstruction(insn, 16, 5); - InsnType Imm = 0; - bool HasRs = false; - bool HasRt = false; - - if (Rt == 0) - return MCDisassembler::Fail; - else if (Rs == 0) { - MI.setOpcode(Mips::BGTZALC_MMR6); - HasRt = true; - Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 2 + 4; - } - else if (Rs == Rt) { - MI.setOpcode(Mips::BLTZALC_MMR6); - HasRs = true; - Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 2 + 4; - } - else { - MI.setOpcode(Mips::BLTUC_MMR6); - HasRs = true; - HasRt = true; - Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 4 + 4; - } - - if (HasRs) - MI.addOperand( - MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, Rs))); - - if (HasRt) - MI.addOperand( - MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, Rt))); - - MI.addOperand(MCOperand::createImm(Imm)); - - return MCDisassembler::Success; -} - -template <typename InsnType> -static DecodeStatus DecodeBlezGroupBranchMMR6(MCInst &MI, InsnType insn, - uint64_t Address, - const void *Decoder) { - // We have: - // 0b000110 ttttt sssss iiiiiiiiiiiiiiii - // Invalid if rt == 0 - // BLEZALC_MMR6 if rs == 0 && rt != 0 - // BGEZALC_MMR6 if rs == rt && rt != 0 - // BGEUC_MMR6 if rs != rt && rs != 0 && rt != 0 - - InsnType Rt = fieldFromInstruction(insn, 21, 5); - InsnType Rs = fieldFromInstruction(insn, 16, 5); - InsnType Imm = 0; - bool HasRs = false; - - if (Rt == 0) - return MCDisassembler::Fail; - else if (Rs == 0) { - MI.setOpcode(Mips::BLEZALC_MMR6); - Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 2 + 4; - } - else if (Rs == Rt) { - MI.setOpcode(Mips::BGEZALC_MMR6); - Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 2 + 4; - } - else { - HasRs = true; - MI.setOpcode(Mips::BGEUC_MMR6); - Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 4 + 4; - } - - if (HasRs) - MI.addOperand( - MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, Rs))); - MI.addOperand( - MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, Rt))); - - MI.addOperand(MCOperand::createImm(Imm)); - - return MCDisassembler::Success; -} diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.cpp b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.cpp deleted file mode 100644 index fca1149453c9..000000000000 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.cpp +++ /dev/null @@ -1,74 +0,0 @@ -//===- MipsABIFlagsSection.cpp - Mips ELF ABI Flags Section ---------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "MCTargetDesc/MipsABIFlagsSection.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/MC/MCStreamer.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MipsABIFlags.h" - -using namespace llvm; - -uint8_t MipsABIFlagsSection::getFpABIValue() { - switch (FpABI) { - case FpABIKind::ANY: - return Mips::Val_GNU_MIPS_ABI_FP_ANY; - case FpABIKind::SOFT: - return Mips::Val_GNU_MIPS_ABI_FP_SOFT; - case FpABIKind::XX: - return Mips::Val_GNU_MIPS_ABI_FP_XX; - case FpABIKind::S32: - return Mips::Val_GNU_MIPS_ABI_FP_DOUBLE; - case FpABIKind::S64: - if (Is32BitABI) - return OddSPReg ? Mips::Val_GNU_MIPS_ABI_FP_64 - : Mips::Val_GNU_MIPS_ABI_FP_64A; - return Mips::Val_GNU_MIPS_ABI_FP_DOUBLE; - } - - llvm_unreachable("unexpected fp abi value"); -} - -StringRef MipsABIFlagsSection::getFpABIString(FpABIKind Value) { - switch (Value) { - case FpABIKind::XX: - return "xx"; - case FpABIKind::S32: - return "32"; - case FpABIKind::S64: - return "64"; - default: - llvm_unreachable("unsupported fp abi value"); - } -} - -uint8_t MipsABIFlagsSection::getCPR1SizeValue() { - if (FpABI == FpABIKind::XX) - return (uint8_t)Mips::AFL_REG_32; - return (uint8_t)CPR1Size; -} - -namespace llvm { - -MCStreamer &operator<<(MCStreamer &OS, MipsABIFlagsSection &ABIFlagsSection) { - // Write out a Elf_Internal_ABIFlags_v0 struct - OS.EmitIntValue(ABIFlagsSection.getVersionValue(), 2); // version - OS.EmitIntValue(ABIFlagsSection.getISALevelValue(), 1); // isa_level - OS.EmitIntValue(ABIFlagsSection.getISARevisionValue(), 1); // isa_rev - OS.EmitIntValue(ABIFlagsSection.getGPRSizeValue(), 1); // gpr_size - OS.EmitIntValue(ABIFlagsSection.getCPR1SizeValue(), 1); // cpr1_size - OS.EmitIntValue(ABIFlagsSection.getCPR2SizeValue(), 1); // cpr2_size - OS.EmitIntValue(ABIFlagsSection.getFpABIValue(), 1); // fp_abi - OS.EmitIntValue(ABIFlagsSection.getISAExtensionValue(), 4); // isa_ext - OS.EmitIntValue(ABIFlagsSection.getASESetValue(), 4); // ases - OS.EmitIntValue(ABIFlagsSection.getFlags1Value(), 4); // flags1 - OS.EmitIntValue(ABIFlagsSection.getFlags2Value(), 4); // flags2 - return OS; -} - -} // end namespace llvm diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h deleted file mode 100644 index 6091ee24b04d..000000000000 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h +++ /dev/null @@ -1,208 +0,0 @@ -//===- MipsABIFlagsSection.h - Mips ELF ABI Flags Section -------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSABIFLAGSSECTION_H -#define LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSABIFLAGSSECTION_H - -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MipsABIFlags.h" -#include <cstdint> - -namespace llvm { - -class MCStreamer; - -struct MipsABIFlagsSection { - // Internal representation of the fp_abi related values used in .module. - enum class FpABIKind { ANY, XX, S32, S64, SOFT }; - - // Version of flags structure. - uint16_t Version = 0; - // The level of the ISA: 1-5, 32, 64. - uint8_t ISALevel = 0; - // The revision of ISA: 0 for MIPS V and below, 1-n otherwise. - uint8_t ISARevision = 0; - // The size of general purpose registers. - Mips::AFL_REG GPRSize = Mips::AFL_REG_NONE; - // The size of co-processor 1 registers. - Mips::AFL_REG CPR1Size = Mips::AFL_REG_NONE; - // The size of co-processor 2 registers. - Mips::AFL_REG CPR2Size = Mips::AFL_REG_NONE; - // Processor-specific extension. - Mips::AFL_EXT ISAExtension = Mips::AFL_EXT_NONE; - // Mask of ASEs used. - uint32_t ASESet = 0; - - bool OddSPReg = false; - - bool Is32BitABI = false; - -protected: - // The floating-point ABI. - FpABIKind FpABI = FpABIKind::ANY; - -public: - MipsABIFlagsSection() = default; - - uint16_t getVersionValue() { return (uint16_t)Version; } - uint8_t getISALevelValue() { return (uint8_t)ISALevel; } - uint8_t getISARevisionValue() { return (uint8_t)ISARevision; } - uint8_t getGPRSizeValue() { return (uint8_t)GPRSize; } - uint8_t getCPR1SizeValue(); - uint8_t getCPR2SizeValue() { return (uint8_t)CPR2Size; } - uint8_t getFpABIValue(); - uint32_t getISAExtensionValue() { return (uint32_t)ISAExtension; } - uint32_t getASESetValue() { return (uint32_t)ASESet; } - - uint32_t getFlags1Value() { - uint32_t Value = 0; - - if (OddSPReg) - Value |= (uint32_t)Mips::AFL_FLAGS1_ODDSPREG; - - return Value; - } - - uint32_t getFlags2Value() { return 0; } - - FpABIKind getFpABI() { return FpABI; } - void setFpABI(FpABIKind Value, bool IsABI32Bit) { - FpABI = Value; - Is32BitABI = IsABI32Bit; - } - - StringRef getFpABIString(FpABIKind Value); - - template <class PredicateLibrary> - void setISALevelAndRevisionFromPredicates(const PredicateLibrary &P) { - if (P.hasMips64()) { - ISALevel = 64; - if (P.hasMips64r6()) - ISARevision = 6; - else if (P.hasMips64r5()) - ISARevision = 5; - else if (P.hasMips64r3()) - ISARevision = 3; - else if (P.hasMips64r2()) - ISARevision = 2; - else - ISARevision = 1; - } else if (P.hasMips32()) { - ISALevel = 32; - if (P.hasMips32r6()) - ISARevision = 6; - else if (P.hasMips32r5()) - ISARevision = 5; - else if (P.hasMips32r3()) - ISARevision = 3; - else if (P.hasMips32r2()) - ISARevision = 2; - else - ISARevision = 1; - } else { - ISARevision = 0; - if (P.hasMips5()) - ISALevel = 5; - else if (P.hasMips4()) - ISALevel = 4; - else if (P.hasMips3()) - ISALevel = 3; - else if (P.hasMips2()) - ISALevel = 2; - else if (P.hasMips1()) - ISALevel = 1; - else - llvm_unreachable("Unknown ISA level!"); - } - } - - template <class PredicateLibrary> - void setGPRSizeFromPredicates(const PredicateLibrary &P) { - GPRSize = P.isGP64bit() ? Mips::AFL_REG_64 : Mips::AFL_REG_32; - } - - template <class PredicateLibrary> - void setCPR1SizeFromPredicates(const PredicateLibrary &P) { - if (P.useSoftFloat()) - CPR1Size = Mips::AFL_REG_NONE; - else if (P.hasMSA()) - CPR1Size = Mips::AFL_REG_128; - else - CPR1Size = P.isFP64bit() ? Mips::AFL_REG_64 : Mips::AFL_REG_32; - } - - template <class PredicateLibrary> - void setISAExtensionFromPredicates(const PredicateLibrary &P) { - if (P.hasCnMipsP()) - ISAExtension = Mips::AFL_EXT_OCTEONP; - else if (P.hasCnMips()) - ISAExtension = Mips::AFL_EXT_OCTEON; - else - ISAExtension = Mips::AFL_EXT_NONE; - } - - template <class PredicateLibrary> - void setASESetFromPredicates(const PredicateLibrary &P) { - ASESet = 0; - if (P.hasDSP()) - ASESet |= Mips::AFL_ASE_DSP; - if (P.hasDSPR2()) - ASESet |= Mips::AFL_ASE_DSPR2; - if (P.hasMSA()) - ASESet |= Mips::AFL_ASE_MSA; - if (P.inMicroMipsMode()) - ASESet |= Mips::AFL_ASE_MICROMIPS; - if (P.inMips16Mode()) - ASESet |= Mips::AFL_ASE_MIPS16; - if (P.hasMT()) - ASESet |= Mips::AFL_ASE_MT; - if (P.hasCRC()) - ASESet |= Mips::AFL_ASE_CRC; - if (P.hasVirt()) - ASESet |= Mips::AFL_ASE_VIRT; - if (P.hasGINV()) - ASESet |= Mips::AFL_ASE_GINV; - } - - template <class PredicateLibrary> - void setFpAbiFromPredicates(const PredicateLibrary &P) { - Is32BitABI = P.isABI_O32(); - - FpABI = FpABIKind::ANY; - if (P.useSoftFloat()) - FpABI = FpABIKind::SOFT; - else if (P.isABI_N32() || P.isABI_N64()) - FpABI = FpABIKind::S64; - else if (P.isABI_O32()) { - if (P.isABI_FPXX()) - FpABI = FpABIKind::XX; - else if (P.isFP64bit()) - FpABI = FpABIKind::S64; - else - FpABI = FpABIKind::S32; - } - } - - template <class PredicateLibrary> - void setAllFromPredicates(const PredicateLibrary &P) { - setISALevelAndRevisionFromPredicates(P); - setGPRSizeFromPredicates(P); - setCPR1SizeFromPredicates(P); - setISAExtensionFromPredicates(P); - setASESetFromPredicates(P); - setFpAbiFromPredicates(P); - OddSPReg = P.useOddSPReg(); - } -}; - -MCStreamer &operator<<(MCStreamer &OS, MipsABIFlagsSection &ABIFlagsSection); - -} // end namespace llvm - -#endif // LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSABIFLAGSSECTION_H diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp deleted file mode 100644 index bdd190fc17c9..000000000000 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp +++ /dev/null @@ -1,127 +0,0 @@ -//===---- MipsABIInfo.cpp - Information about MIPS ABI's ------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "MipsABIInfo.h" -#include "MipsRegisterInfo.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/StringSwitch.h" -#include "llvm/MC/MCTargetOptions.h" - -using namespace llvm; - -// Note: this option is defined here to be visible from libLLVMMipsAsmParser -// and libLLVMMipsCodeGen -cl::opt<bool> -EmitJalrReloc("mips-jalr-reloc", cl::Hidden, - cl::desc("MIPS: Emit R_{MICRO}MIPS_JALR relocation with jalr"), - cl::init(true)); - -namespace { -static const MCPhysReg O32IntRegs[4] = {Mips::A0, Mips::A1, Mips::A2, Mips::A3}; - -static const MCPhysReg Mips64IntRegs[8] = { - Mips::A0_64, Mips::A1_64, Mips::A2_64, Mips::A3_64, - Mips::T0_64, Mips::T1_64, Mips::T2_64, Mips::T3_64}; -} - -ArrayRef<MCPhysReg> MipsABIInfo::GetByValArgRegs() const { - if (IsO32()) - return makeArrayRef(O32IntRegs); - if (IsN32() || IsN64()) - return makeArrayRef(Mips64IntRegs); - llvm_unreachable("Unhandled ABI"); -} - -ArrayRef<MCPhysReg> MipsABIInfo::GetVarArgRegs() const { - if (IsO32()) - return makeArrayRef(O32IntRegs); - if (IsN32() || IsN64()) - return makeArrayRef(Mips64IntRegs); - llvm_unreachable("Unhandled ABI"); -} - -unsigned MipsABIInfo::GetCalleeAllocdArgSizeInBytes(CallingConv::ID CC) const { - if (IsO32()) - return CC != CallingConv::Fast ? 16 : 0; - if (IsN32() || IsN64()) - return 0; - llvm_unreachable("Unhandled ABI"); -} - -MipsABIInfo MipsABIInfo::computeTargetABI(const Triple &TT, StringRef CPU, - const MCTargetOptions &Options) { - if (Options.getABIName().startswith("o32")) - return MipsABIInfo::O32(); - if (Options.getABIName().startswith("n32")) - return MipsABIInfo::N32(); - if (Options.getABIName().startswith("n64")) - return MipsABIInfo::N64(); - if (TT.getEnvironment() == llvm::Triple::GNUABIN32) - return MipsABIInfo::N32(); - assert(Options.getABIName().empty() && "Unknown ABI option for MIPS"); - - if (TT.isMIPS64()) - return MipsABIInfo::N64(); - return MipsABIInfo::O32(); -} - -unsigned MipsABIInfo::GetStackPtr() const { - return ArePtrs64bit() ? Mips::SP_64 : Mips::SP; -} - -unsigned MipsABIInfo::GetFramePtr() const { - return ArePtrs64bit() ? Mips::FP_64 : Mips::FP; -} - -unsigned MipsABIInfo::GetBasePtr() const { - return ArePtrs64bit() ? Mips::S7_64 : Mips::S7; -} - -unsigned MipsABIInfo::GetGlobalPtr() const { - return ArePtrs64bit() ? Mips::GP_64 : Mips::GP; -} - -unsigned MipsABIInfo::GetNullPtr() const { - return ArePtrs64bit() ? Mips::ZERO_64 : Mips::ZERO; -} - -unsigned MipsABIInfo::GetZeroReg() const { - return AreGprs64bit() ? Mips::ZERO_64 : Mips::ZERO; -} - -unsigned MipsABIInfo::GetPtrAdduOp() const { - return ArePtrs64bit() ? Mips::DADDu : Mips::ADDu; -} - -unsigned MipsABIInfo::GetPtrAddiuOp() const { - return ArePtrs64bit() ? Mips::DADDiu : Mips::ADDiu; -} - -unsigned MipsABIInfo::GetPtrSubuOp() const { - return ArePtrs64bit() ? Mips::DSUBu : Mips::SUBu; -} - -unsigned MipsABIInfo::GetPtrAndOp() const { - return ArePtrs64bit() ? Mips::AND64 : Mips::AND; -} - -unsigned MipsABIInfo::GetGPRMoveOp() const { - return ArePtrs64bit() ? Mips::OR64 : Mips::OR; -} - -unsigned MipsABIInfo::GetEhDataReg(unsigned I) const { - static const unsigned EhDataReg[] = { - Mips::A0, Mips::A1, Mips::A2, Mips::A3 - }; - static const unsigned EhDataReg64[] = { - Mips::A0_64, Mips::A1_64, Mips::A2_64, Mips::A3_64 - }; - - return IsN64() ? EhDataReg64[I] : EhDataReg[I]; -} - diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h deleted file mode 100644 index 534e6573b63c..000000000000 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h +++ /dev/null @@ -1,81 +0,0 @@ -//===---- MipsABIInfo.h - Information about MIPS ABI's --------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSABIINFO_H -#define LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSABIINFO_H - -#include "llvm/ADT/Triple.h" -#include "llvm/IR/CallingConv.h" -#include "llvm/MC/MCRegisterInfo.h" - -namespace llvm { - -template <typename T> class ArrayRef; -class MCTargetOptions; -class StringRef; -class TargetRegisterClass; - -class MipsABIInfo { -public: - enum class ABI { Unknown, O32, N32, N64 }; - -protected: - ABI ThisABI; - -public: - MipsABIInfo(ABI ThisABI) : ThisABI(ThisABI) {} - - static MipsABIInfo Unknown() { return MipsABIInfo(ABI::Unknown); } - static MipsABIInfo O32() { return MipsABIInfo(ABI::O32); } - static MipsABIInfo N32() { return MipsABIInfo(ABI::N32); } - static MipsABIInfo N64() { return MipsABIInfo(ABI::N64); } - static MipsABIInfo computeTargetABI(const Triple &TT, StringRef CPU, - const MCTargetOptions &Options); - - bool IsKnown() const { return ThisABI != ABI::Unknown; } - bool IsO32() const { return ThisABI == ABI::O32; } - bool IsN32() const { return ThisABI == ABI::N32; } - bool IsN64() const { return ThisABI == ABI::N64; } - ABI GetEnumValue() const { return ThisABI; } - - /// The registers to use for byval arguments. - ArrayRef<MCPhysReg> GetByValArgRegs() const; - - /// The registers to use for the variable argument list. - ArrayRef<MCPhysReg> GetVarArgRegs() const; - - /// Obtain the size of the area allocated by the callee for arguments. - /// CallingConv::FastCall affects the value for O32. - unsigned GetCalleeAllocdArgSizeInBytes(CallingConv::ID CC) const; - - /// Ordering of ABI's - /// MipsGenSubtargetInfo.inc will use this to resolve conflicts when given - /// multiple ABI options. - bool operator<(const MipsABIInfo Other) const { - return ThisABI < Other.GetEnumValue(); - } - - unsigned GetStackPtr() const; - unsigned GetFramePtr() const; - unsigned GetBasePtr() const; - unsigned GetGlobalPtr() const; - unsigned GetNullPtr() const; - unsigned GetZeroReg() const; - unsigned GetPtrAdduOp() const; - unsigned GetPtrAddiuOp() const; - unsigned GetPtrSubuOp() const; - unsigned GetPtrAndOp() const; - unsigned GetGPRMoveOp() const; - inline bool ArePtrs64bit() const { return IsN64(); } - inline bool AreGprs64bit() const { return IsN32() || IsN64(); } - - unsigned GetEhDataReg(unsigned I) const; -}; -} - -#endif diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp deleted file mode 100644 index 859f9cbbca07..000000000000 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp +++ /dev/null @@ -1,591 +0,0 @@ -//===-- MipsAsmBackend.cpp - Mips Asm Backend ----------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements the MipsAsmBackend class. -// -//===----------------------------------------------------------------------===// -// - -#include "MCTargetDesc/MipsAsmBackend.h" -#include "MCTargetDesc/MipsABIInfo.h" -#include "MCTargetDesc/MipsFixupKinds.h" -#include "MCTargetDesc/MipsMCExpr.h" -#include "MCTargetDesc/MipsMCTargetDesc.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/MC/MCAsmBackend.h" -#include "llvm/MC/MCAssembler.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCDirectives.h" -#include "llvm/MC/MCELFObjectWriter.h" -#include "llvm/MC/MCFixupKindInfo.h" -#include "llvm/MC/MCObjectWriter.h" -#include "llvm/MC/MCSubtargetInfo.h" -#include "llvm/MC/MCTargetOptions.h" -#include "llvm/MC/MCValue.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/Format.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/raw_ostream.h" - -using namespace llvm; - -// Prepare value for the target space for it -static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, - MCContext &Ctx) { - - unsigned Kind = Fixup.getKind(); - - // Add/subtract and shift - switch (Kind) { - default: - return 0; - case FK_Data_2: - case Mips::fixup_Mips_LO16: - case Mips::fixup_Mips_GPREL16: - case Mips::fixup_Mips_GPOFF_HI: - case Mips::fixup_Mips_GPOFF_LO: - case Mips::fixup_Mips_GOT_PAGE: - case Mips::fixup_Mips_GOT_OFST: - case Mips::fixup_Mips_GOT_DISP: - case Mips::fixup_Mips_GOT_LO16: - case Mips::fixup_Mips_CALL_LO16: - case Mips::fixup_MICROMIPS_GPOFF_HI: - case Mips::fixup_MICROMIPS_GPOFF_LO: - case Mips::fixup_MICROMIPS_LO16: - case Mips::fixup_MICROMIPS_GOT_PAGE: - case Mips::fixup_MICROMIPS_GOT_OFST: - case Mips::fixup_MICROMIPS_GOT_DISP: - case Mips::fixup_MIPS_PCLO16: - Value &= 0xffff; - break; - case FK_DTPRel_4: - case FK_DTPRel_8: - case FK_TPRel_4: - case FK_TPRel_8: - case FK_GPRel_4: - case FK_Data_4: - case FK_Data_8: - case Mips::fixup_Mips_SUB: - case Mips::fixup_MICROMIPS_SUB: - break; - case Mips::fixup_Mips_PC16: - // The displacement is then divided by 4 to give us an 18 bit - // address range. Forcing a signed division because Value can be negative. - Value = (int64_t)Value / 4; - // We now check if Value can be encoded as a 16-bit signed immediate. - if (!isInt<16>(Value)) { - Ctx.reportError(Fixup.getLoc(), "out of range PC16 fixup"); - return 0; - } - break; - case Mips::fixup_MIPS_PC19_S2: - case Mips::fixup_MICROMIPS_PC19_S2: - // Forcing a signed division because Value can be negative. - Value = (int64_t)Value / 4; - // We now check if Value can be encoded as a 19-bit signed immediate. - if (!isInt<19>(Value)) { - Ctx.reportError(Fixup.getLoc(), "out of range PC19 fixup"); - return 0; - } - break; - case Mips::fixup_Mips_26: - // So far we are only using this type for jumps. - // The displacement is then divided by 4 to give us an 28 bit - // address range. - Value >>= 2; - break; - case Mips::fixup_Mips_HI16: - case Mips::fixup_Mips_GOT: - case Mips::fixup_MICROMIPS_GOT16: - case Mips::fixup_Mips_GOT_HI16: - case Mips::fixup_Mips_CALL_HI16: - case Mips::fixup_MICROMIPS_HI16: - case Mips::fixup_MIPS_PCHI16: - // Get the 2nd 16-bits. Also add 1 if bit 15 is 1. - Value = ((Value + 0x8000) >> 16) & 0xffff; - break; - case Mips::fixup_Mips_HIGHER: - case Mips::fixup_MICROMIPS_HIGHER: - // Get the 3rd 16-bits. - Value = ((Value + 0x80008000LL) >> 32) & 0xffff; - break; - case Mips::fixup_Mips_HIGHEST: - case Mips::fixup_MICROMIPS_HIGHEST: - // Get the 4th 16-bits. - Value = ((Value + 0x800080008000LL) >> 48) & 0xffff; - break; - case Mips::fixup_MICROMIPS_26_S1: - Value >>= 1; - break; - case Mips::fixup_MICROMIPS_PC7_S1: - Value -= 4; - // Forcing a signed division because Value can be negative. - Value = (int64_t) Value / 2; - // We now check if Value can be encoded as a 7-bit signed immediate. - if (!isInt<7>(Value)) { - Ctx.reportError(Fixup.getLoc(), "out of range PC7 fixup"); - return 0; - } - break; - case Mips::fixup_MICROMIPS_PC10_S1: - Value -= 2; - // Forcing a signed division because Value can be negative. - Value = (int64_t) Value / 2; - // We now check if Value can be encoded as a 10-bit signed immediate. - if (!isInt<10>(Value)) { - Ctx.reportError(Fixup.getLoc(), "out of range PC10 fixup"); - return 0; - } - break; - case Mips::fixup_MICROMIPS_PC16_S1: - Value -= 4; - // Forcing a signed division because Value can be negative. - Value = (int64_t)Value / 2; - // We now check if Value can be encoded as a 16-bit signed immediate. - if (!isInt<16>(Value)) { - Ctx.reportError(Fixup.getLoc(), "out of range PC16 fixup"); - return 0; - } - break; - case Mips::fixup_MIPS_PC18_S3: - // Forcing a signed division because Value can be negative. - Value = (int64_t)Value / 8; - // We now check if Value can be encoded as a 18-bit signed immediate. - if (!isInt<18>(Value)) { - Ctx.reportError(Fixup.getLoc(), "out of range PC18 fixup"); - return 0; - } - break; - case Mips::fixup_MICROMIPS_PC18_S3: - // Check alignment. - if ((Value & 7)) { - Ctx.reportError(Fixup.getLoc(), "out of range PC18 fixup"); - } - // Forcing a signed division because Value can be negative. - Value = (int64_t)Value / 8; - // We now check if Value can be encoded as a 18-bit signed immediate. - if (!isInt<18>(Value)) { - Ctx.reportError(Fixup.getLoc(), "out of range PC18 fixup"); - return 0; - } - break; - case Mips::fixup_MIPS_PC21_S2: - // Forcing a signed division because Value can be negative. - Value = (int64_t) Value / 4; - // We now check if Value can be encoded as a 21-bit signed immediate. - if (!isInt<21>(Value)) { - Ctx.reportError(Fixup.getLoc(), "out of range PC21 fixup"); - return 0; - } - break; - case Mips::fixup_MIPS_PC26_S2: - // Forcing a signed division because Value can be negative. - Value = (int64_t) Value / 4; - // We now check if Value can be encoded as a 26-bit signed immediate. - if (!isInt<26>(Value)) { - Ctx.reportError(Fixup.getLoc(), "out of range PC26 fixup"); - return 0; - } - break; - case Mips::fixup_MICROMIPS_PC26_S1: - // Forcing a signed division because Value can be negative. - Value = (int64_t)Value / 2; - // We now check if Value can be encoded as a 26-bit signed immediate. - if (!isInt<26>(Value)) { - Ctx.reportFatalError(Fixup.getLoc(), "out of range PC26 fixup"); - return 0; - } - break; - case Mips::fixup_MICROMIPS_PC21_S1: - // Forcing a signed division because Value can be negative. - Value = (int64_t)Value / 2; - // We now check if Value can be encoded as a 21-bit signed immediate. - if (!isInt<21>(Value)) { - Ctx.reportError(Fixup.getLoc(), "out of range PC21 fixup"); - return 0; - } - break; - } - - return Value; -} - -std::unique_ptr<MCObjectTargetWriter> -MipsAsmBackend::createObjectTargetWriter() const { - return createMipsELFObjectWriter(TheTriple, IsN32); -} - -// Little-endian fixup data byte ordering: -// mips32r2: a | b | x | x -// microMIPS: x | x | a | b - -static bool needsMMLEByteOrder(unsigned Kind) { - return Kind != Mips::fixup_MICROMIPS_PC10_S1 && - Kind >= Mips::fixup_MICROMIPS_26_S1 && - Kind < Mips::LastTargetFixupKind; -} - -// Calculate index for microMIPS specific little endian byte order -static unsigned calculateMMLEIndex(unsigned i) { - assert(i <= 3 && "Index out of range!"); - - return (1 - i / 2) * 2 + i % 2; -} - -/// ApplyFixup - Apply the \p Value for given \p Fixup into the provided -/// data fragment, at the offset specified by the fixup and following the -/// fixup kind as appropriate. -void MipsAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, - const MCValue &Target, - MutableArrayRef<char> Data, uint64_t Value, - bool IsResolved, - const MCSubtargetInfo *STI) const { - MCFixupKind Kind = Fixup.getKind(); - MCContext &Ctx = Asm.getContext(); - Value = adjustFixupValue(Fixup, Value, Ctx); - - if (!Value) - return; // Doesn't change encoding. - - // Where do we start in the object - unsigned Offset = Fixup.getOffset(); - // Number of bytes we need to fixup - unsigned NumBytes = (getFixupKindInfo(Kind).TargetSize + 7) / 8; - // Used to point to big endian bytes - unsigned FullSize; - - switch ((unsigned)Kind) { - case FK_Data_2: - case Mips::fixup_Mips_16: - case Mips::fixup_MICROMIPS_PC10_S1: - FullSize = 2; - break; - case FK_Data_8: - case Mips::fixup_Mips_64: - FullSize = 8; - break; - case FK_Data_4: - default: - FullSize = 4; - break; - } - - // Grab current value, if any, from bits. - uint64_t CurVal = 0; - - bool microMipsLEByteOrder = needsMMLEByteOrder((unsigned) Kind); - - for (unsigned i = 0; i != NumBytes; ++i) { - unsigned Idx = Endian == support::little - ? (microMipsLEByteOrder ? calculateMMLEIndex(i) : i) - : (FullSize - 1 - i); - CurVal |= (uint64_t)((uint8_t)Data[Offset + Idx]) << (i*8); - } - - uint64_t Mask = ((uint64_t)(-1) >> - (64 - getFixupKindInfo(Kind).TargetSize)); - CurVal |= Value & Mask; - - // Write out the fixed up bytes back to the code/data bits. - for (unsigned i = 0; i != NumBytes; ++i) { - unsigned Idx = Endian == support::little - ? (microMipsLEByteOrder ? calculateMMLEIndex(i) : i) - : (FullSize - 1 - i); - Data[Offset + Idx] = (uint8_t)((CurVal >> (i*8)) & 0xff); - } -} - -Optional<MCFixupKind> MipsAsmBackend::getFixupKind(StringRef Name) const { - return StringSwitch<Optional<MCFixupKind>>(Name) - .Case("R_MIPS_NONE", FK_NONE) - .Case("R_MIPS_32", FK_Data_4) - .Case("R_MIPS_GOT_PAGE", (MCFixupKind)Mips::fixup_Mips_GOT_PAGE) - .Case("R_MIPS_CALL_HI16", (MCFixupKind)Mips::fixup_Mips_CALL_HI16) - .Case("R_MIPS_CALL_LO16", (MCFixupKind)Mips::fixup_Mips_CALL_LO16) - .Case("R_MIPS_CALL16", (MCFixupKind)Mips::fixup_Mips_CALL16) - .Case("R_MIPS_GOT16", (MCFixupKind)Mips::fixup_Mips_GOT) - .Case("R_MIPS_GOT_PAGE", (MCFixupKind)Mips::fixup_Mips_GOT_PAGE) - .Case("R_MIPS_GOT_OFST", (MCFixupKind)Mips::fixup_Mips_GOT_OFST) - .Case("R_MIPS_GOT_DISP", (MCFixupKind)Mips::fixup_Mips_GOT_DISP) - .Case("R_MIPS_GOT_HI16", (MCFixupKind)Mips::fixup_Mips_GOT_HI16) - .Case("R_MIPS_GOT_LO16", (MCFixupKind)Mips::fixup_Mips_GOT_LO16) - .Case("R_MIPS_TLS_GOTTPREL", (MCFixupKind)Mips::fixup_Mips_GOTTPREL) - .Case("R_MIPS_TLS_DTPREL_HI16", (MCFixupKind)Mips::fixup_Mips_DTPREL_HI) - .Case("R_MIPS_TLS_DTPREL_LO16", (MCFixupKind)Mips::fixup_Mips_DTPREL_LO) - .Case("R_MIPS_TLS_GD", (MCFixupKind)Mips::fixup_Mips_TLSGD) - .Case("R_MIPS_TLS_LDM", (MCFixupKind)Mips::fixup_Mips_TLSLDM) - .Case("R_MIPS_TLS_TPREL_HI16", (MCFixupKind)Mips::fixup_Mips_TPREL_HI) - .Case("R_MIPS_TLS_TPREL_LO16", (MCFixupKind)Mips::fixup_Mips_TPREL_LO) - .Case("R_MICROMIPS_CALL16", (MCFixupKind)Mips::fixup_MICROMIPS_CALL16) - .Case("R_MICROMIPS_GOT_DISP", (MCFixupKind)Mips::fixup_MICROMIPS_GOT_DISP) - .Case("R_MICROMIPS_GOT_PAGE", (MCFixupKind)Mips::fixup_MICROMIPS_GOT_PAGE) - .Case("R_MICROMIPS_GOT_OFST", (MCFixupKind)Mips::fixup_MICROMIPS_GOT_OFST) - .Case("R_MICROMIPS_GOT16", (MCFixupKind)Mips::fixup_MICROMIPS_GOT16) - .Case("R_MICROMIPS_TLS_GOTTPREL", - (MCFixupKind)Mips::fixup_MICROMIPS_GOTTPREL) - .Case("R_MICROMIPS_TLS_DTPREL_HI16", - (MCFixupKind)Mips::fixup_MICROMIPS_TLS_DTPREL_HI16) - .Case("R_MICROMIPS_TLS_DTPREL_LO16", - (MCFixupKind)Mips::fixup_MICROMIPS_TLS_DTPREL_LO16) - .Case("R_MICROMIPS_TLS_GD", (MCFixupKind)Mips::fixup_MICROMIPS_TLS_GD) - .Case("R_MICROMIPS_TLS_LDM", (MCFixupKind)Mips::fixup_MICROMIPS_TLS_LDM) - .Case("R_MICROMIPS_TLS_TPREL_HI16", - (MCFixupKind)Mips::fixup_MICROMIPS_TLS_TPREL_HI16) - .Case("R_MICROMIPS_TLS_TPREL_LO16", - (MCFixupKind)Mips::fixup_MICROMIPS_TLS_TPREL_LO16) - .Case("R_MIPS_JALR", (MCFixupKind)Mips::fixup_Mips_JALR) - .Case("R_MICROMIPS_JALR", (MCFixupKind)Mips::fixup_MICROMIPS_JALR) - .Default(MCAsmBackend::getFixupKind(Name)); -} - -const MCFixupKindInfo &MipsAsmBackend:: -getFixupKindInfo(MCFixupKind Kind) const { - const static MCFixupKindInfo LittleEndianInfos[] = { - // This table *must* be in same the order of fixup_* kinds in - // MipsFixupKinds.h. - // - // name offset bits flags - { "fixup_Mips_16", 0, 16, 0 }, - { "fixup_Mips_32", 0, 32, 0 }, - { "fixup_Mips_REL32", 0, 32, 0 }, - { "fixup_Mips_26", 0, 26, 0 }, - { "fixup_Mips_HI16", 0, 16, 0 }, - { "fixup_Mips_LO16", 0, 16, 0 }, - { "fixup_Mips_GPREL16", 0, 16, 0 }, - { "fixup_Mips_LITERAL", 0, 16, 0 }, - { "fixup_Mips_GOT", 0, 16, 0 }, - { "fixup_Mips_PC16", 0, 16, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_Mips_CALL16", 0, 16, 0 }, - { "fixup_Mips_GPREL32", 0, 32, 0 }, - { "fixup_Mips_SHIFT5", 6, 5, 0 }, - { "fixup_Mips_SHIFT6", 6, 5, 0 }, - { "fixup_Mips_64", 0, 64, 0 }, - { "fixup_Mips_TLSGD", 0, 16, 0 }, - { "fixup_Mips_GOTTPREL", 0, 16, 0 }, - { "fixup_Mips_TPREL_HI", 0, 16, 0 }, - { "fixup_Mips_TPREL_LO", 0, 16, 0 }, - { "fixup_Mips_TLSLDM", 0, 16, 0 }, - { "fixup_Mips_DTPREL_HI", 0, 16, 0 }, - { "fixup_Mips_DTPREL_LO", 0, 16, 0 }, - { "fixup_Mips_Branch_PCRel", 0, 16, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_Mips_GPOFF_HI", 0, 16, 0 }, - { "fixup_MICROMIPS_GPOFF_HI",0, 16, 0 }, - { "fixup_Mips_GPOFF_LO", 0, 16, 0 }, - { "fixup_MICROMIPS_GPOFF_LO",0, 16, 0 }, - { "fixup_Mips_GOT_PAGE", 0, 16, 0 }, - { "fixup_Mips_GOT_OFST", 0, 16, 0 }, - { "fixup_Mips_GOT_DISP", 0, 16, 0 }, - { "fixup_Mips_HIGHER", 0, 16, 0 }, - { "fixup_MICROMIPS_HIGHER", 0, 16, 0 }, - { "fixup_Mips_HIGHEST", 0, 16, 0 }, - { "fixup_MICROMIPS_HIGHEST", 0, 16, 0 }, - { "fixup_Mips_GOT_HI16", 0, 16, 0 }, - { "fixup_Mips_GOT_LO16", 0, 16, 0 }, - { "fixup_Mips_CALL_HI16", 0, 16, 0 }, - { "fixup_Mips_CALL_LO16", 0, 16, 0 }, - { "fixup_Mips_PC18_S3", 0, 18, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_MIPS_PC19_S2", 0, 19, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_MIPS_PC21_S2", 0, 21, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_MIPS_PC26_S2", 0, 26, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_MIPS_PCHI16", 0, 16, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_MIPS_PCLO16", 0, 16, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_MICROMIPS_26_S1", 0, 26, 0 }, - { "fixup_MICROMIPS_HI16", 0, 16, 0 }, - { "fixup_MICROMIPS_LO16", 0, 16, 0 }, - { "fixup_MICROMIPS_GOT16", 0, 16, 0 }, - { "fixup_MICROMIPS_PC7_S1", 0, 7, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_MICROMIPS_PC10_S1", 0, 10, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_MICROMIPS_PC16_S1", 0, 16, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_MICROMIPS_PC26_S1", 0, 26, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_MICROMIPS_PC19_S2", 0, 19, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_MICROMIPS_PC18_S3", 0, 18, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_MICROMIPS_PC21_S1", 0, 21, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_MICROMIPS_CALL16", 0, 16, 0 }, - { "fixup_MICROMIPS_GOT_DISP", 0, 16, 0 }, - { "fixup_MICROMIPS_GOT_PAGE", 0, 16, 0 }, - { "fixup_MICROMIPS_GOT_OFST", 0, 16, 0 }, - { "fixup_MICROMIPS_TLS_GD", 0, 16, 0 }, - { "fixup_MICROMIPS_TLS_LDM", 0, 16, 0 }, - { "fixup_MICROMIPS_TLS_DTPREL_HI16", 0, 16, 0 }, - { "fixup_MICROMIPS_TLS_DTPREL_LO16", 0, 16, 0 }, - { "fixup_MICROMIPS_GOTTPREL", 0, 16, 0 }, - { "fixup_MICROMIPS_TLS_TPREL_HI16", 0, 16, 0 }, - { "fixup_MICROMIPS_TLS_TPREL_LO16", 0, 16, 0 }, - { "fixup_Mips_SUB", 0, 64, 0 }, - { "fixup_MICROMIPS_SUB", 0, 64, 0 }, - { "fixup_Mips_JALR", 0, 32, 0 }, - { "fixup_MICROMIPS_JALR", 0, 32, 0 } - }; - static_assert(array_lengthof(LittleEndianInfos) == Mips::NumTargetFixupKinds, - "Not all MIPS little endian fixup kinds added!"); - - const static MCFixupKindInfo BigEndianInfos[] = { - // This table *must* be in same the order of fixup_* kinds in - // MipsFixupKinds.h. - // - // name offset bits flags - { "fixup_Mips_16", 16, 16, 0 }, - { "fixup_Mips_32", 0, 32, 0 }, - { "fixup_Mips_REL32", 0, 32, 0 }, - { "fixup_Mips_26", 6, 26, 0 }, - { "fixup_Mips_HI16", 16, 16, 0 }, - { "fixup_Mips_LO16", 16, 16, 0 }, - { "fixup_Mips_GPREL16", 16, 16, 0 }, - { "fixup_Mips_LITERAL", 16, 16, 0 }, - { "fixup_Mips_GOT", 16, 16, 0 }, - { "fixup_Mips_PC16", 16, 16, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_Mips_CALL16", 16, 16, 0 }, - { "fixup_Mips_GPREL32", 0, 32, 0 }, - { "fixup_Mips_SHIFT5", 21, 5, 0 }, - { "fixup_Mips_SHIFT6", 21, 5, 0 }, - { "fixup_Mips_64", 0, 64, 0 }, - { "fixup_Mips_TLSGD", 16, 16, 0 }, - { "fixup_Mips_GOTTPREL", 16, 16, 0 }, - { "fixup_Mips_TPREL_HI", 16, 16, 0 }, - { "fixup_Mips_TPREL_LO", 16, 16, 0 }, - { "fixup_Mips_TLSLDM", 16, 16, 0 }, - { "fixup_Mips_DTPREL_HI", 16, 16, 0 }, - { "fixup_Mips_DTPREL_LO", 16, 16, 0 }, - { "fixup_Mips_Branch_PCRel",16, 16, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_Mips_GPOFF_HI", 16, 16, 0 }, - { "fixup_MICROMIPS_GPOFF_HI", 16, 16, 0 }, - { "fixup_Mips_GPOFF_LO", 16, 16, 0 }, - { "fixup_MICROMIPS_GPOFF_LO", 16, 16, 0 }, - { "fixup_Mips_GOT_PAGE", 16, 16, 0 }, - { "fixup_Mips_GOT_OFST", 16, 16, 0 }, - { "fixup_Mips_GOT_DISP", 16, 16, 0 }, - { "fixup_Mips_HIGHER", 16, 16, 0 }, - { "fixup_MICROMIPS_HIGHER", 16, 16, 0 }, - { "fixup_Mips_HIGHEST", 16, 16, 0 }, - { "fixup_MICROMIPS_HIGHEST",16, 16, 0 }, - { "fixup_Mips_GOT_HI16", 16, 16, 0 }, - { "fixup_Mips_GOT_LO16", 16, 16, 0 }, - { "fixup_Mips_CALL_HI16", 16, 16, 0 }, - { "fixup_Mips_CALL_LO16", 16, 16, 0 }, - { "fixup_Mips_PC18_S3", 14, 18, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_MIPS_PC19_S2", 13, 19, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_MIPS_PC21_S2", 11, 21, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_MIPS_PC26_S2", 6, 26, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_MIPS_PCHI16", 16, 16, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_MIPS_PCLO16", 16, 16, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_MICROMIPS_26_S1", 6, 26, 0 }, - { "fixup_MICROMIPS_HI16", 16, 16, 0 }, - { "fixup_MICROMIPS_LO16", 16, 16, 0 }, - { "fixup_MICROMIPS_GOT16", 16, 16, 0 }, - { "fixup_MICROMIPS_PC7_S1", 9, 7, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_MICROMIPS_PC10_S1", 6, 10, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_MICROMIPS_PC16_S1",16, 16, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_MICROMIPS_PC26_S1", 6, 26, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_MICROMIPS_PC19_S2",13, 19, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_MICROMIPS_PC18_S3",14, 18, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_MICROMIPS_PC21_S1",11, 21, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_MICROMIPS_CALL16", 16, 16, 0 }, - { "fixup_MICROMIPS_GOT_DISP", 16, 16, 0 }, - { "fixup_MICROMIPS_GOT_PAGE", 16, 16, 0 }, - { "fixup_MICROMIPS_GOT_OFST", 16, 16, 0 }, - { "fixup_MICROMIPS_TLS_GD", 16, 16, 0 }, - { "fixup_MICROMIPS_TLS_LDM", 16, 16, 0 }, - { "fixup_MICROMIPS_TLS_DTPREL_HI16", 16, 16, 0 }, - { "fixup_MICROMIPS_TLS_DTPREL_LO16", 16, 16, 0 }, - { "fixup_MICROMIPS_GOTTPREL", 16, 16, 0 }, - { "fixup_MICROMIPS_TLS_TPREL_HI16", 16, 16, 0 }, - { "fixup_MICROMIPS_TLS_TPREL_LO16", 16, 16, 0 }, - { "fixup_Mips_SUB", 0, 64, 0 }, - { "fixup_MICROMIPS_SUB", 0, 64, 0 }, - { "fixup_Mips_JALR", 0, 32, 0 }, - { "fixup_MICROMIPS_JALR", 0, 32, 0 } - }; - static_assert(array_lengthof(BigEndianInfos) == Mips::NumTargetFixupKinds, - "Not all MIPS big endian fixup kinds added!"); - - if (Kind < FirstTargetFixupKind) - return MCAsmBackend::getFixupKindInfo(Kind); - - assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && - "Invalid kind!"); - - if (Endian == support::little) - return LittleEndianInfos[Kind - FirstTargetFixupKind]; - return BigEndianInfos[Kind - FirstTargetFixupKind]; -} - -/// WriteNopData - Write an (optimal) nop sequence of Count bytes -/// to the given output. If the target cannot generate such a sequence, -/// it should return an error. -/// -/// \return - True on success. -bool MipsAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count) const { - // Check for a less than instruction size number of bytes - // FIXME: 16 bit instructions are not handled yet here. - // We shouldn't be using a hard coded number for instruction size. - - // If the count is not 4-byte aligned, we must be writing data into the text - // section (otherwise we have unaligned instructions, and thus have far - // bigger problems), so just write zeros instead. - OS.write_zeros(Count); - return true; -} - -bool MipsAsmBackend::shouldForceRelocation(const MCAssembler &Asm, - const MCFixup &Fixup, - const MCValue &Target) { - const unsigned FixupKind = Fixup.getKind(); - switch (FixupKind) { - default: - return false; - // All these relocations require special processing - // at linking time. Delegate this work to a linker. - case Mips::fixup_Mips_CALL_HI16: - case Mips::fixup_Mips_CALL_LO16: - case Mips::fixup_Mips_CALL16: - case Mips::fixup_Mips_GOT: - case Mips::fixup_Mips_GOT_PAGE: - case Mips::fixup_Mips_GOT_OFST: - case Mips::fixup_Mips_GOT_DISP: - case Mips::fixup_Mips_GOT_HI16: - case Mips::fixup_Mips_GOT_LO16: - case Mips::fixup_Mips_GOTTPREL: - case Mips::fixup_Mips_DTPREL_HI: - case Mips::fixup_Mips_DTPREL_LO: - case Mips::fixup_Mips_TLSGD: - case Mips::fixup_Mips_TLSLDM: - case Mips::fixup_Mips_TPREL_HI: - case Mips::fixup_Mips_TPREL_LO: - case Mips::fixup_Mips_JALR: - case Mips::fixup_MICROMIPS_CALL16: - case Mips::fixup_MICROMIPS_GOT_DISP: - case Mips::fixup_MICROMIPS_GOT_PAGE: - case Mips::fixup_MICROMIPS_GOT_OFST: - case Mips::fixup_MICROMIPS_GOT16: - case Mips::fixup_MICROMIPS_GOTTPREL: - case Mips::fixup_MICROMIPS_TLS_DTPREL_HI16: - case Mips::fixup_MICROMIPS_TLS_DTPREL_LO16: - case Mips::fixup_MICROMIPS_TLS_GD: - case Mips::fixup_MICROMIPS_TLS_LDM: - case Mips::fixup_MICROMIPS_TLS_TPREL_HI16: - case Mips::fixup_MICROMIPS_TLS_TPREL_LO16: - case Mips::fixup_MICROMIPS_JALR: - return true; - } -} - -bool MipsAsmBackend::isMicroMips(const MCSymbol *Sym) const { - if (const auto *ElfSym = dyn_cast<const MCSymbolELF>(Sym)) { - if (ElfSym->getOther() & ELF::STO_MIPS_MICROMIPS) - return true; - } - return false; -} - -MCAsmBackend *llvm::createMipsAsmBackend(const Target &T, - const MCSubtargetInfo &STI, - const MCRegisterInfo &MRI, - const MCTargetOptions &Options) { - MipsABIInfo ABI = MipsABIInfo::computeTargetABI(STI.getTargetTriple(), STI.getCPU(), Options); - return new MipsAsmBackend(T, MRI, STI.getTargetTriple(), STI.getCPU(), ABI.IsN32()); -} diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h deleted file mode 100644 index 4d7e36995ae4..000000000000 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h +++ /dev/null @@ -1,98 +0,0 @@ -//===-- MipsAsmBackend.h - Mips Asm Backend ------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the MipsAsmBackend class. -// -//===----------------------------------------------------------------------===// -// - -#ifndef LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSASMBACKEND_H -#define LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSASMBACKEND_H - -#include "MCTargetDesc/MipsFixupKinds.h" -#include "llvm/ADT/Triple.h" -#include "llvm/MC/MCAsmBackend.h" - -namespace llvm { - -class MCAssembler; -struct MCFixupKindInfo; -class MCObjectWriter; -class MCRegisterInfo; -class MCSymbolELF; -class Target; - -class MipsAsmBackend : public MCAsmBackend { - Triple TheTriple; - bool IsN32; - -public: - MipsAsmBackend(const Target &T, const MCRegisterInfo &MRI, const Triple &TT, - StringRef CPU, bool N32) - : MCAsmBackend(TT.isLittleEndian() ? support::little : support::big), - TheTriple(TT), IsN32(N32) {} - - std::unique_ptr<MCObjectTargetWriter> - createObjectTargetWriter() const override; - - void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, - const MCValue &Target, MutableArrayRef<char> Data, - uint64_t Value, bool IsResolved, - const MCSubtargetInfo *STI) const override; - - Optional<MCFixupKind> getFixupKind(StringRef Name) const override; - const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override; - - unsigned getNumFixupKinds() const override { - return Mips::NumTargetFixupKinds; - } - - /// @name Target Relaxation Interfaces - /// @{ - - /// MayNeedRelaxation - Check whether the given instruction may need - /// relaxation. - /// - /// \param Inst - The instruction to test. - bool mayNeedRelaxation(const MCInst &Inst, - const MCSubtargetInfo &STI) const override { - return false; - } - - /// fixupNeedsRelaxation - Target specific predicate for whether a given - /// fixup requires the associated instruction to be relaxed. - bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, - const MCRelaxableFragment *DF, - const MCAsmLayout &Layout) const override { - // FIXME. - llvm_unreachable("RelaxInstruction() unimplemented"); - return false; - } - - /// RelaxInstruction - Relax the instruction in the given fragment - /// to the next wider instruction. - /// - /// \param Inst - The instruction to relax, which may be the same - /// as the output. - /// \param [out] Res On return, the relaxed instruction. - void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI, - MCInst &Res) const override {} - - /// @} - - bool writeNopData(raw_ostream &OS, uint64_t Count) const override; - - bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup, - const MCValue &Target) override; - - bool isMicroMips(const MCSymbol *Sym) const override; -}; // class MipsAsmBackend - -} // namespace - -#endif diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h deleted file mode 100644 index 6d8cb264158f..000000000000 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h +++ /dev/null @@ -1,136 +0,0 @@ -//===-- MipsBaseInfo.h - Top level definitions for MIPS MC ------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains small standalone helper functions and enum definitions for -// the Mips target useful for the compiler back-end and the MC libraries. -// -//===----------------------------------------------------------------------===// -#ifndef LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSBASEINFO_H -#define LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSBASEINFO_H - -#include "MipsFixupKinds.h" -#include "MipsMCTargetDesc.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/Support/DataTypes.h" -#include "llvm/Support/ErrorHandling.h" - -namespace llvm { - -/// MipsII - This namespace holds all of the target specific flags that -/// instruction info tracks. -/// -namespace MipsII { - /// Target Operand Flag enum. - enum TOF { - //===------------------------------------------------------------------===// - // Mips Specific MachineOperand flags. - - MO_NO_FLAG, - - /// MO_GOT - Represents the offset into the global offset table at which - /// the address the relocation entry symbol resides during execution. - MO_GOT, - - /// MO_GOT_CALL - Represents the offset into the global offset table at - /// which the address of a call site relocation entry symbol resides - /// during execution. This is different from the above since this flag - /// can only be present in call instructions. - MO_GOT_CALL, - - /// MO_GPREL - Represents the offset from the current gp value to be used - /// for the relocatable object file being produced. - MO_GPREL, - - /// MO_ABS_HI/LO - Represents the hi or low part of an absolute symbol - /// address. - MO_ABS_HI, - MO_ABS_LO, - - /// MO_TLSGD - Represents the offset into the global offset table at which - // the module ID and TSL block offset reside during execution (General - // Dynamic TLS). - MO_TLSGD, - - /// MO_TLSLDM - Represents the offset into the global offset table at which - // the module ID and TSL block offset reside during execution (Local - // Dynamic TLS). - MO_TLSLDM, - MO_DTPREL_HI, - MO_DTPREL_LO, - - /// MO_GOTTPREL - Represents the offset from the thread pointer (Initial - // Exec TLS). - MO_GOTTPREL, - - /// MO_TPREL_HI/LO - Represents the hi and low part of the offset from - // the thread pointer (Local Exec TLS). - MO_TPREL_HI, - MO_TPREL_LO, - - // N32/64 Flags. - MO_GPOFF_HI, - MO_GPOFF_LO, - MO_GOT_DISP, - MO_GOT_PAGE, - MO_GOT_OFST, - - /// MO_HIGHER/HIGHEST - Represents the highest or higher half word of a - /// 64-bit symbol address. - MO_HIGHER, - MO_HIGHEST, - - /// MO_GOT_HI16/LO16, MO_CALL_HI16/LO16 - Relocations used for large GOTs. - MO_GOT_HI16, - MO_GOT_LO16, - MO_CALL_HI16, - MO_CALL_LO16, - - /// Helper operand used to generate R_MIPS_JALR - MO_JALR - }; - - enum { - //===------------------------------------------------------------------===// - // Instruction encodings. These are the standard/most common forms for - // Mips instructions. - // - - // Pseudo - This represents an instruction that is a pseudo instruction - // or one that has not been implemented yet. It is illegal to code generate - // it, but tolerated for intermediate implementation stages. - Pseudo = 0, - - /// FrmR - This form is for instructions of the format R. - FrmR = 1, - /// FrmI - This form is for instructions of the format I. - FrmI = 2, - /// FrmJ - This form is for instructions of the format J. - FrmJ = 3, - /// FrmFR - This form is for instructions of the format FR. - FrmFR = 4, - /// FrmFI - This form is for instructions of the format FI. - FrmFI = 5, - /// FrmOther - This form is for instructions that have no specific format. - FrmOther = 6, - - FormMask = 15, - /// IsCTI - Instruction is a Control Transfer Instruction. - IsCTI = 1 << 4, - /// HasForbiddenSlot - Instruction has a forbidden slot. - HasForbiddenSlot = 1 << 5, - /// IsPCRelativeLoad - A Load instruction with implicit source register - /// ($pc) with explicit offset and destination register - IsPCRelativeLoad = 1 << 6, - /// HasFCCRegOperand - Instruction uses an $fcc<x> register. - HasFCCRegOperand = 1 << 7 - - }; -} -} - -#endif diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp deleted file mode 100644 index cf7bae98a27f..000000000000 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp +++ /dev/null @@ -1,695 +0,0 @@ -//===-- MipsELFObjectWriter.cpp - Mips ELF Writer -------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "MCTargetDesc/MipsFixupKinds.h" -#include "MCTargetDesc/MipsMCTargetDesc.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/BinaryFormat/ELF.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCELFObjectWriter.h" -#include "llvm/MC/MCFixup.h" -#include "llvm/MC/MCObjectWriter.h" -#include "llvm/MC/MCSymbolELF.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/raw_ostream.h" -#include <algorithm> -#include <cassert> -#include <cstdint> -#include <iterator> -#include <list> -#include <utility> - -#define DEBUG_TYPE "mips-elf-object-writer" - -using namespace llvm; - -namespace { - -/// Holds additional information needed by the relocation ordering algorithm. -struct MipsRelocationEntry { - const ELFRelocationEntry R; ///< The relocation. - bool Matched = false; ///< Is this relocation part of a match. - - MipsRelocationEntry(const ELFRelocationEntry &R) : R(R) {} - - void print(raw_ostream &Out) const { - R.print(Out); - Out << ", Matched=" << Matched; - } -}; - -#ifndef NDEBUG -raw_ostream &operator<<(raw_ostream &OS, const MipsRelocationEntry &RHS) { - RHS.print(OS); - return OS; -} -#endif - -class MipsELFObjectWriter : public MCELFObjectTargetWriter { -public: - MipsELFObjectWriter(uint8_t OSABI, bool HasRelocationAddend, bool Is64); - - ~MipsELFObjectWriter() override = default; - - unsigned getRelocType(MCContext &Ctx, const MCValue &Target, - const MCFixup &Fixup, bool IsPCRel) const override; - bool needsRelocateWithSymbol(const MCSymbol &Sym, - unsigned Type) const override; - void sortRelocs(const MCAssembler &Asm, - std::vector<ELFRelocationEntry> &Relocs) override; -}; - -/// The possible results of the Predicate function used by find_best. -enum FindBestPredicateResult { - FindBest_NoMatch = 0, ///< The current element is not a match. - FindBest_Match, ///< The current element is a match but better ones are - /// possible. - FindBest_PerfectMatch, ///< The current element is an unbeatable match. -}; - -} // end anonymous namespace - -/// Copy elements in the range [First, Last) to d1 when the predicate is true or -/// d2 when the predicate is false. This is essentially both std::copy_if and -/// std::remove_copy_if combined into a single pass. -template <class InputIt, class OutputIt1, class OutputIt2, class UnaryPredicate> -static std::pair<OutputIt1, OutputIt2> copy_if_else(InputIt First, InputIt Last, - OutputIt1 d1, OutputIt2 d2, - UnaryPredicate Predicate) { - for (InputIt I = First; I != Last; ++I) { - if (Predicate(*I)) { - *d1 = *I; - d1++; - } else { - *d2 = *I; - d2++; - } - } - - return std::make_pair(d1, d2); -} - -/// Find the best match in the range [First, Last). -/// -/// An element matches when Predicate(X) returns FindBest_Match or -/// FindBest_PerfectMatch. A value of FindBest_PerfectMatch also terminates -/// the search. BetterThan(A, B) is a comparator that returns true when A is a -/// better match than B. The return value is the position of the best match. -/// -/// This is similar to std::find_if but finds the best of multiple possible -/// matches. -template <class InputIt, class UnaryPredicate, class Comparator> -static InputIt find_best(InputIt First, InputIt Last, UnaryPredicate Predicate, - Comparator BetterThan) { - InputIt Best = Last; - - for (InputIt I = First; I != Last; ++I) { - unsigned Matched = Predicate(*I); - if (Matched != FindBest_NoMatch) { - LLVM_DEBUG(dbgs() << std::distance(First, I) << " is a match ("; - I->print(dbgs()); dbgs() << ")\n"); - if (Best == Last || BetterThan(*I, *Best)) { - LLVM_DEBUG(dbgs() << ".. and it beats the last one\n"); - Best = I; - } - } - if (Matched == FindBest_PerfectMatch) { - LLVM_DEBUG(dbgs() << ".. and it is unbeatable\n"); - break; - } - } - - return Best; -} - -/// Determine the low relocation that matches the given relocation. -/// If the relocation does not need a low relocation then the return value -/// is ELF::R_MIPS_NONE. -/// -/// The relocations that need a matching low part are -/// R_(MIPS|MICROMIPS|MIPS16)_HI16 for all symbols and -/// R_(MIPS|MICROMIPS|MIPS16)_GOT16 for local symbols only. -static unsigned getMatchingLoType(const ELFRelocationEntry &Reloc) { - unsigned Type = Reloc.Type; - if (Type == ELF::R_MIPS_HI16) - return ELF::R_MIPS_LO16; - if (Type == ELF::R_MICROMIPS_HI16) - return ELF::R_MICROMIPS_LO16; - if (Type == ELF::R_MIPS16_HI16) - return ELF::R_MIPS16_LO16; - - if (Reloc.OriginalSymbol && - Reloc.OriginalSymbol->getBinding() != ELF::STB_LOCAL) - return ELF::R_MIPS_NONE; - - if (Type == ELF::R_MIPS_GOT16) - return ELF::R_MIPS_LO16; - if (Type == ELF::R_MICROMIPS_GOT16) - return ELF::R_MICROMIPS_LO16; - if (Type == ELF::R_MIPS16_GOT16) - return ELF::R_MIPS16_LO16; - - return ELF::R_MIPS_NONE; -} - -/// Determine whether a relocation (X) matches the one given in R. -/// -/// A relocation matches if: -/// - It's type matches that of a corresponding low part. This is provided in -/// MatchingType for efficiency. -/// - It's based on the same symbol. -/// - It's offset of greater or equal to that of the one given in R. -/// It should be noted that this rule assumes the programmer does not use -/// offsets that exceed the alignment of the symbol. The carry-bit will be -/// incorrect if this is not true. -/// -/// A matching relocation is unbeatable if: -/// - It is not already involved in a match. -/// - It's offset is exactly that of the one given in R. -static FindBestPredicateResult isMatchingReloc(const MipsRelocationEntry &X, - const ELFRelocationEntry &R, - unsigned MatchingType) { - if (X.R.Type == MatchingType && X.R.OriginalSymbol == R.OriginalSymbol) { - if (!X.Matched && - X.R.OriginalAddend == R.OriginalAddend) - return FindBest_PerfectMatch; - else if (X.R.OriginalAddend >= R.OriginalAddend) - return FindBest_Match; - } - return FindBest_NoMatch; -} - -/// Determine whether Candidate or PreviousBest is the better match. -/// The return value is true if Candidate is the better match. -/// -/// A matching relocation is a better match if: -/// - It has a smaller addend. -/// - It is not already involved in a match. -static bool compareMatchingRelocs(const MipsRelocationEntry &Candidate, - const MipsRelocationEntry &PreviousBest) { - if (Candidate.R.OriginalAddend != PreviousBest.R.OriginalAddend) - return Candidate.R.OriginalAddend < PreviousBest.R.OriginalAddend; - return PreviousBest.Matched && !Candidate.Matched; -} - -#ifndef NDEBUG -/// Print all the relocations. -template <class Container> -static void dumpRelocs(const char *Prefix, const Container &Relocs) { - for (const auto &R : Relocs) - dbgs() << Prefix << R << "\n"; -} -#endif - -MipsELFObjectWriter::MipsELFObjectWriter(uint8_t OSABI, - bool HasRelocationAddend, bool Is64) - : MCELFObjectTargetWriter(Is64, OSABI, ELF::EM_MIPS, HasRelocationAddend) {} - -unsigned MipsELFObjectWriter::getRelocType(MCContext &Ctx, - const MCValue &Target, - const MCFixup &Fixup, - bool IsPCRel) const { - // Determine the type of the relocation. - unsigned Kind = (unsigned)Fixup.getKind(); - - switch (Kind) { - case FK_NONE: - return ELF::R_MIPS_NONE; - case FK_Data_1: - Ctx.reportError(Fixup.getLoc(), - "MIPS does not support one byte relocations"); - return ELF::R_MIPS_NONE; - case Mips::fixup_Mips_16: - case FK_Data_2: - return IsPCRel ? ELF::R_MIPS_PC16 : ELF::R_MIPS_16; - case Mips::fixup_Mips_32: - case FK_Data_4: - return IsPCRel ? ELF::R_MIPS_PC32 : ELF::R_MIPS_32; - } - - if (IsPCRel) { - switch (Kind) { - case FK_Data_8: - Ctx.reportError(Fixup.getLoc(), - "MIPS does not support 64-bit PC-relative relocations"); - return ELF::R_MIPS_NONE; - case Mips::fixup_Mips_Branch_PCRel: - case Mips::fixup_Mips_PC16: - return ELF::R_MIPS_PC16; - case Mips::fixup_MICROMIPS_PC7_S1: - return ELF::R_MICROMIPS_PC7_S1; - case Mips::fixup_MICROMIPS_PC10_S1: - return ELF::R_MICROMIPS_PC10_S1; - case Mips::fixup_MICROMIPS_PC16_S1: - return ELF::R_MICROMIPS_PC16_S1; - case Mips::fixup_MICROMIPS_PC26_S1: - return ELF::R_MICROMIPS_PC26_S1; - case Mips::fixup_MICROMIPS_PC19_S2: - return ELF::R_MICROMIPS_PC19_S2; - case Mips::fixup_MICROMIPS_PC18_S3: - return ELF::R_MICROMIPS_PC18_S3; - case Mips::fixup_MICROMIPS_PC21_S1: - return ELF::R_MICROMIPS_PC21_S1; - case Mips::fixup_MIPS_PC19_S2: - return ELF::R_MIPS_PC19_S2; - case Mips::fixup_MIPS_PC18_S3: - return ELF::R_MIPS_PC18_S3; - case Mips::fixup_MIPS_PC21_S2: - return ELF::R_MIPS_PC21_S2; - case Mips::fixup_MIPS_PC26_S2: - return ELF::R_MIPS_PC26_S2; - case Mips::fixup_MIPS_PCHI16: - return ELF::R_MIPS_PCHI16; - case Mips::fixup_MIPS_PCLO16: - return ELF::R_MIPS_PCLO16; - } - - llvm_unreachable("invalid PC-relative fixup kind!"); - } - - switch (Kind) { - case Mips::fixup_Mips_64: - case FK_Data_8: - return ELF::R_MIPS_64; - case FK_DTPRel_4: - return ELF::R_MIPS_TLS_DTPREL32; - case FK_DTPRel_8: - return ELF::R_MIPS_TLS_DTPREL64; - case FK_TPRel_4: - return ELF::R_MIPS_TLS_TPREL32; - case FK_TPRel_8: - return ELF::R_MIPS_TLS_TPREL64; - case FK_GPRel_4: - if (is64Bit()) { - unsigned Type = (unsigned)ELF::R_MIPS_NONE; - Type = setRType((unsigned)ELF::R_MIPS_GPREL32, Type); - Type = setRType2((unsigned)ELF::R_MIPS_64, Type); - Type = setRType3((unsigned)ELF::R_MIPS_NONE, Type); - return Type; - } - return ELF::R_MIPS_GPREL32; - case Mips::fixup_Mips_GPREL16: - return ELF::R_MIPS_GPREL16; - case Mips::fixup_Mips_26: - return ELF::R_MIPS_26; - case Mips::fixup_Mips_CALL16: - return ELF::R_MIPS_CALL16; - case Mips::fixup_Mips_GOT: - return ELF::R_MIPS_GOT16; - case Mips::fixup_Mips_HI16: - return ELF::R_MIPS_HI16; - case Mips::fixup_Mips_LO16: - return ELF::R_MIPS_LO16; - case Mips::fixup_Mips_TLSGD: - return ELF::R_MIPS_TLS_GD; - case Mips::fixup_Mips_GOTTPREL: - return ELF::R_MIPS_TLS_GOTTPREL; - case Mips::fixup_Mips_TPREL_HI: - return ELF::R_MIPS_TLS_TPREL_HI16; - case Mips::fixup_Mips_TPREL_LO: - return ELF::R_MIPS_TLS_TPREL_LO16; - case Mips::fixup_Mips_TLSLDM: - return ELF::R_MIPS_TLS_LDM; - case Mips::fixup_Mips_DTPREL_HI: - return ELF::R_MIPS_TLS_DTPREL_HI16; - case Mips::fixup_Mips_DTPREL_LO: - return ELF::R_MIPS_TLS_DTPREL_LO16; - case Mips::fixup_Mips_GOT_PAGE: - return ELF::R_MIPS_GOT_PAGE; - case Mips::fixup_Mips_GOT_OFST: - return ELF::R_MIPS_GOT_OFST; - case Mips::fixup_Mips_GOT_DISP: - return ELF::R_MIPS_GOT_DISP; - case Mips::fixup_Mips_GPOFF_HI: { - unsigned Type = (unsigned)ELF::R_MIPS_NONE; - Type = setRType((unsigned)ELF::R_MIPS_GPREL16, Type); - Type = setRType2((unsigned)ELF::R_MIPS_SUB, Type); - Type = setRType3((unsigned)ELF::R_MIPS_HI16, Type); - return Type; - } - case Mips::fixup_MICROMIPS_GPOFF_HI: { - unsigned Type = (unsigned)ELF::R_MIPS_NONE; - Type = setRType((unsigned)ELF::R_MICROMIPS_GPREL16, Type); - Type = setRType2((unsigned)ELF::R_MICROMIPS_SUB, Type); - Type = setRType3((unsigned)ELF::R_MICROMIPS_HI16, Type); - return Type; - } - case Mips::fixup_Mips_GPOFF_LO: { - unsigned Type = (unsigned)ELF::R_MIPS_NONE; - Type = setRType((unsigned)ELF::R_MIPS_GPREL16, Type); - Type = setRType2((unsigned)ELF::R_MIPS_SUB, Type); - Type = setRType3((unsigned)ELF::R_MIPS_LO16, Type); - return Type; - } - case Mips::fixup_MICROMIPS_GPOFF_LO: { - unsigned Type = (unsigned)ELF::R_MIPS_NONE; - Type = setRType((unsigned)ELF::R_MICROMIPS_GPREL16, Type); - Type = setRType2((unsigned)ELF::R_MICROMIPS_SUB, Type); - Type = setRType3((unsigned)ELF::R_MICROMIPS_LO16, Type); - return Type; - } - case Mips::fixup_Mips_HIGHER: - return ELF::R_MIPS_HIGHER; - case Mips::fixup_Mips_HIGHEST: - return ELF::R_MIPS_HIGHEST; - case Mips::fixup_Mips_SUB: - return ELF::R_MIPS_SUB; - case Mips::fixup_Mips_GOT_HI16: - return ELF::R_MIPS_GOT_HI16; - case Mips::fixup_Mips_GOT_LO16: - return ELF::R_MIPS_GOT_LO16; - case Mips::fixup_Mips_CALL_HI16: - return ELF::R_MIPS_CALL_HI16; - case Mips::fixup_Mips_CALL_LO16: - return ELF::R_MIPS_CALL_LO16; - case Mips::fixup_MICROMIPS_26_S1: - return ELF::R_MICROMIPS_26_S1; - case Mips::fixup_MICROMIPS_HI16: - return ELF::R_MICROMIPS_HI16; - case Mips::fixup_MICROMIPS_LO16: - return ELF::R_MICROMIPS_LO16; - case Mips::fixup_MICROMIPS_GOT16: - return ELF::R_MICROMIPS_GOT16; - case Mips::fixup_MICROMIPS_CALL16: - return ELF::R_MICROMIPS_CALL16; - case Mips::fixup_MICROMIPS_GOT_DISP: - return ELF::R_MICROMIPS_GOT_DISP; - case Mips::fixup_MICROMIPS_GOT_PAGE: - return ELF::R_MICROMIPS_GOT_PAGE; - case Mips::fixup_MICROMIPS_GOT_OFST: - return ELF::R_MICROMIPS_GOT_OFST; - case Mips::fixup_MICROMIPS_TLS_GD: - return ELF::R_MICROMIPS_TLS_GD; - case Mips::fixup_MICROMIPS_TLS_LDM: - return ELF::R_MICROMIPS_TLS_LDM; - case Mips::fixup_MICROMIPS_TLS_DTPREL_HI16: - return ELF::R_MICROMIPS_TLS_DTPREL_HI16; - case Mips::fixup_MICROMIPS_TLS_DTPREL_LO16: - return ELF::R_MICROMIPS_TLS_DTPREL_LO16; - case Mips::fixup_MICROMIPS_GOTTPREL: - return ELF::R_MICROMIPS_TLS_GOTTPREL; - case Mips::fixup_MICROMIPS_TLS_TPREL_HI16: - return ELF::R_MICROMIPS_TLS_TPREL_HI16; - case Mips::fixup_MICROMIPS_TLS_TPREL_LO16: - return ELF::R_MICROMIPS_TLS_TPREL_LO16; - case Mips::fixup_MICROMIPS_SUB: - return ELF::R_MICROMIPS_SUB; - case Mips::fixup_MICROMIPS_HIGHER: - return ELF::R_MICROMIPS_HIGHER; - case Mips::fixup_MICROMIPS_HIGHEST: - return ELF::R_MICROMIPS_HIGHEST; - case Mips::fixup_Mips_JALR: - return ELF::R_MIPS_JALR; - case Mips::fixup_MICROMIPS_JALR: - return ELF::R_MICROMIPS_JALR; - } - - llvm_unreachable("invalid fixup kind!"); -} - -/// Sort relocation table entries by offset except where another order is -/// required by the MIPS ABI. -/// -/// MIPS has a few relocations that have an AHL component in the expression used -/// to evaluate them. This AHL component is an addend with the same number of -/// bits as a symbol value but not all of our ABI's are able to supply a -/// sufficiently sized addend in a single relocation. -/// -/// The O32 ABI for example, uses REL relocations which store the addend in the -/// section data. All the relocations with AHL components affect 16-bit fields -/// so the addend for a single relocation is limited to 16-bit. This ABI -/// resolves the limitation by linking relocations (e.g. R_MIPS_HI16 and -/// R_MIPS_LO16) and distributing the addend between the linked relocations. The -/// ABI mandates that such relocations must be next to each other in a -/// particular order (e.g. R_MIPS_HI16 must be immediately followed by a -/// matching R_MIPS_LO16) but the rule is less strict in practice. -/// -/// The de facto standard is lenient in the following ways: -/// - 'Immediately following' does not refer to the next relocation entry but -/// the next matching relocation. -/// - There may be multiple high parts relocations for one low part relocation. -/// - There may be multiple low part relocations for one high part relocation. -/// - The AHL addend in each part does not have to be exactly equal as long as -/// the difference does not affect the carry bit from bit 15 into 16. This is -/// to allow, for example, the use of %lo(foo) and %lo(foo+4) when loading -/// both halves of a long long. -/// -/// See getMatchingLoType() for a description of which high part relocations -/// match which low part relocations. One particular thing to note is that -/// R_MIPS_GOT16 and similar only have AHL addends if they refer to local -/// symbols. -/// -/// It should also be noted that this function is not affected by whether -/// the symbol was kept or rewritten into a section-relative equivalent. We -/// always match using the expressions from the source. -void MipsELFObjectWriter::sortRelocs(const MCAssembler &Asm, - std::vector<ELFRelocationEntry> &Relocs) { - // We do not need to sort the relocation table for RELA relocations which - // N32/N64 uses as the relocation addend contains the value we require, - // rather than it being split across a pair of relocations. - if (hasRelocationAddend()) - return; - - if (Relocs.size() < 2) - return; - - // Sort relocations by the address they are applied to. - llvm::sort(Relocs, - [](const ELFRelocationEntry &A, const ELFRelocationEntry &B) { - return A.Offset < B.Offset; - }); - - std::list<MipsRelocationEntry> Sorted; - std::list<ELFRelocationEntry> Remainder; - - LLVM_DEBUG(dumpRelocs("R: ", Relocs)); - - // Separate the movable relocations (AHL relocations using the high bits) from - // the immobile relocations (everything else). This does not preserve high/low - // matches that already existed in the input. - copy_if_else(Relocs.begin(), Relocs.end(), std::back_inserter(Remainder), - std::back_inserter(Sorted), [](const ELFRelocationEntry &Reloc) { - return getMatchingLoType(Reloc) != ELF::R_MIPS_NONE; - }); - - for (auto &R : Remainder) { - LLVM_DEBUG(dbgs() << "Matching: " << R << "\n"); - - unsigned MatchingType = getMatchingLoType(R); - assert(MatchingType != ELF::R_MIPS_NONE && - "Wrong list for reloc that doesn't need a match"); - - // Find the best matching relocation for the current high part. - // See isMatchingReloc for a description of a matching relocation and - // compareMatchingRelocs for a description of what 'best' means. - auto InsertionPoint = - find_best(Sorted.begin(), Sorted.end(), - [&R, &MatchingType](const MipsRelocationEntry &X) { - return isMatchingReloc(X, R, MatchingType); - }, - compareMatchingRelocs); - - // If we matched then insert the high part in front of the match and mark - // both relocations as being involved in a match. We only mark the high - // part for cosmetic reasons in the debug output. - // - // If we failed to find a match then the high part is orphaned. This is not - // permitted since the relocation cannot be evaluated without knowing the - // carry-in. We can sometimes handle this using a matching low part that is - // already used in a match but we already cover that case in - // isMatchingReloc and compareMatchingRelocs. For the remaining cases we - // should insert the high part at the end of the list. This will cause the - // linker to fail but the alternative is to cause the linker to bind the - // high part to a semi-matching low part and silently calculate the wrong - // value. Unfortunately we have no means to warn the user that we did this - // so leave it up to the linker to complain about it. - if (InsertionPoint != Sorted.end()) - InsertionPoint->Matched = true; - Sorted.insert(InsertionPoint, R)->Matched = true; - } - - LLVM_DEBUG(dumpRelocs("S: ", Sorted)); - - assert(Relocs.size() == Sorted.size() && "Some relocs were not consumed"); - - // Overwrite the original vector with the sorted elements. The caller expects - // them in reverse order. - unsigned CopyTo = 0; - for (const auto &R : reverse(Sorted)) - Relocs[CopyTo++] = R.R; -} - -bool MipsELFObjectWriter::needsRelocateWithSymbol(const MCSymbol &Sym, - unsigned Type) const { - // If it's a compound relocation for N64 then we need the relocation if any - // sub-relocation needs it. - if (!isUInt<8>(Type)) - return needsRelocateWithSymbol(Sym, Type & 0xff) || - needsRelocateWithSymbol(Sym, (Type >> 8) & 0xff) || - needsRelocateWithSymbol(Sym, (Type >> 16) & 0xff); - - switch (Type) { - default: - errs() << Type << "\n"; - llvm_unreachable("Unexpected relocation"); - return true; - - // This relocation doesn't affect the section data. - case ELF::R_MIPS_NONE: - return false; - - // On REL ABI's (e.g. O32), these relocations form pairs. The pairing is done - // by the static linker by matching the symbol and offset. - // We only see one relocation at a time but it's still safe to relocate with - // the section so long as both relocations make the same decision. - // - // Some older linkers may require the symbol for particular cases. Such cases - // are not supported yet but can be added as required. - case ELF::R_MIPS_GOT16: - case ELF::R_MIPS16_GOT16: - case ELF::R_MICROMIPS_GOT16: - case ELF::R_MIPS_HIGHER: - case ELF::R_MIPS_HIGHEST: - case ELF::R_MIPS_HI16: - case ELF::R_MIPS16_HI16: - case ELF::R_MICROMIPS_HI16: - case ELF::R_MIPS_LO16: - case ELF::R_MIPS16_LO16: - case ELF::R_MICROMIPS_LO16: - // FIXME: It should be safe to return false for the STO_MIPS_MICROMIPS but - // we neglect to handle the adjustment to the LSB of the addend that - // it causes in applyFixup() and similar. - if (cast<MCSymbolELF>(Sym).getOther() & ELF::STO_MIPS_MICROMIPS) - return true; - return false; - - case ELF::R_MIPS_GOT_PAGE: - case ELF::R_MICROMIPS_GOT_PAGE: - case ELF::R_MIPS_GOT_OFST: - case ELF::R_MICROMIPS_GOT_OFST: - case ELF::R_MIPS_16: - case ELF::R_MIPS_32: - case ELF::R_MIPS_GPREL32: - if (cast<MCSymbolELF>(Sym).getOther() & ELF::STO_MIPS_MICROMIPS) - return true; - LLVM_FALLTHROUGH; - case ELF::R_MIPS_26: - case ELF::R_MIPS_64: - case ELF::R_MIPS_GPREL16: - case ELF::R_MIPS_PC16: - case ELF::R_MIPS_SUB: - return false; - - // FIXME: Many of these relocations should probably return false but this - // hasn't been confirmed to be safe yet. - case ELF::R_MIPS_REL32: - case ELF::R_MIPS_LITERAL: - case ELF::R_MIPS_CALL16: - case ELF::R_MIPS_SHIFT5: - case ELF::R_MIPS_SHIFT6: - case ELF::R_MIPS_GOT_DISP: - case ELF::R_MIPS_GOT_HI16: - case ELF::R_MIPS_GOT_LO16: - case ELF::R_MIPS_INSERT_A: - case ELF::R_MIPS_INSERT_B: - case ELF::R_MIPS_DELETE: - case ELF::R_MIPS_CALL_HI16: - case ELF::R_MIPS_CALL_LO16: - case ELF::R_MIPS_SCN_DISP: - case ELF::R_MIPS_REL16: - case ELF::R_MIPS_ADD_IMMEDIATE: - case ELF::R_MIPS_PJUMP: - case ELF::R_MIPS_RELGOT: - case ELF::R_MIPS_JALR: - case ELF::R_MIPS_TLS_DTPMOD32: - case ELF::R_MIPS_TLS_DTPREL32: - case ELF::R_MIPS_TLS_DTPMOD64: - case ELF::R_MIPS_TLS_DTPREL64: - case ELF::R_MIPS_TLS_GD: - case ELF::R_MIPS_TLS_LDM: - case ELF::R_MIPS_TLS_DTPREL_HI16: - case ELF::R_MIPS_TLS_DTPREL_LO16: - case ELF::R_MIPS_TLS_GOTTPREL: - case ELF::R_MIPS_TLS_TPREL32: - case ELF::R_MIPS_TLS_TPREL64: - case ELF::R_MIPS_TLS_TPREL_HI16: - case ELF::R_MIPS_TLS_TPREL_LO16: - case ELF::R_MIPS_GLOB_DAT: - case ELF::R_MIPS_PC21_S2: - case ELF::R_MIPS_PC26_S2: - case ELF::R_MIPS_PC18_S3: - case ELF::R_MIPS_PC19_S2: - case ELF::R_MIPS_PCHI16: - case ELF::R_MIPS_PCLO16: - case ELF::R_MIPS_COPY: - case ELF::R_MIPS_JUMP_SLOT: - case ELF::R_MIPS_NUM: - case ELF::R_MIPS_PC32: - case ELF::R_MIPS_EH: - case ELF::R_MICROMIPS_26_S1: - case ELF::R_MICROMIPS_GPREL16: - case ELF::R_MICROMIPS_LITERAL: - case ELF::R_MICROMIPS_PC7_S1: - case ELF::R_MICROMIPS_PC10_S1: - case ELF::R_MICROMIPS_PC16_S1: - case ELF::R_MICROMIPS_CALL16: - case ELF::R_MICROMIPS_GOT_DISP: - case ELF::R_MICROMIPS_GOT_HI16: - case ELF::R_MICROMIPS_GOT_LO16: - case ELF::R_MICROMIPS_SUB: - case ELF::R_MICROMIPS_HIGHER: - case ELF::R_MICROMIPS_HIGHEST: - case ELF::R_MICROMIPS_CALL_HI16: - case ELF::R_MICROMIPS_CALL_LO16: - case ELF::R_MICROMIPS_SCN_DISP: - case ELF::R_MICROMIPS_JALR: - case ELF::R_MICROMIPS_HI0_LO16: - case ELF::R_MICROMIPS_TLS_GD: - case ELF::R_MICROMIPS_TLS_LDM: - case ELF::R_MICROMIPS_TLS_DTPREL_HI16: - case ELF::R_MICROMIPS_TLS_DTPREL_LO16: - case ELF::R_MICROMIPS_TLS_GOTTPREL: - case ELF::R_MICROMIPS_TLS_TPREL_HI16: - case ELF::R_MICROMIPS_TLS_TPREL_LO16: - case ELF::R_MICROMIPS_GPREL7_S2: - case ELF::R_MICROMIPS_PC23_S2: - case ELF::R_MICROMIPS_PC21_S1: - case ELF::R_MICROMIPS_PC26_S1: - case ELF::R_MICROMIPS_PC18_S3: - case ELF::R_MICROMIPS_PC19_S2: - return true; - - // FIXME: Many of these should probably return false but MIPS16 isn't - // supported by the integrated assembler. - case ELF::R_MIPS16_26: - case ELF::R_MIPS16_GPREL: - case ELF::R_MIPS16_CALL16: - case ELF::R_MIPS16_TLS_GD: - case ELF::R_MIPS16_TLS_LDM: - case ELF::R_MIPS16_TLS_DTPREL_HI16: - case ELF::R_MIPS16_TLS_DTPREL_LO16: - case ELF::R_MIPS16_TLS_GOTTPREL: - case ELF::R_MIPS16_TLS_TPREL_HI16: - case ELF::R_MIPS16_TLS_TPREL_LO16: - llvm_unreachable("Unsupported MIPS16 relocation"); - return true; - } -} - -std::unique_ptr<MCObjectTargetWriter> -llvm::createMipsELFObjectWriter(const Triple &TT, bool IsN32) { - uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TT.getOS()); - bool IsN64 = TT.isArch64Bit() && !IsN32; - bool HasRelocationAddend = TT.isArch64Bit(); - return llvm::make_unique<MipsELFObjectWriter>(OSABI, HasRelocationAddend, - IsN64); -} diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp deleted file mode 100644 index 1b83e9445fb5..000000000000 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp +++ /dev/null @@ -1,121 +0,0 @@ -//===-------- MipsELFStreamer.cpp - ELF Object Output ---------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "MipsELFStreamer.h" -#include "MipsOptionRecord.h" -#include "MipsTargetStreamer.h" -#include "llvm/BinaryFormat/ELF.h" -#include "llvm/MC/MCAsmBackend.h" -#include "llvm/MC/MCAssembler.h" -#include "llvm/MC/MCCodeEmitter.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCDwarf.h" -#include "llvm/MC/MCInst.h" -#include "llvm/MC/MCObjectWriter.h" -#include "llvm/MC/MCSymbolELF.h" -#include "llvm/Support/Casting.h" - -using namespace llvm; - -MipsELFStreamer::MipsELFStreamer(MCContext &Context, - std::unique_ptr<MCAsmBackend> MAB, - std::unique_ptr<MCObjectWriter> OW, - std::unique_ptr<MCCodeEmitter> Emitter) - : MCELFStreamer(Context, std::move(MAB), std::move(OW), - std::move(Emitter)) { - RegInfoRecord = new MipsRegInfoRecord(this, Context); - MipsOptionRecords.push_back( - std::unique_ptr<MipsRegInfoRecord>(RegInfoRecord)); -} - -void MipsELFStreamer::EmitInstruction(const MCInst &Inst, - const MCSubtargetInfo &STI) { - MCELFStreamer::EmitInstruction(Inst, STI); - - MCContext &Context = getContext(); - const MCRegisterInfo *MCRegInfo = Context.getRegisterInfo(); - - for (unsigned OpIndex = 0; OpIndex < Inst.getNumOperands(); ++OpIndex) { - const MCOperand &Op = Inst.getOperand(OpIndex); - - if (!Op.isReg()) - continue; - - unsigned Reg = Op.getReg(); - RegInfoRecord->SetPhysRegUsed(Reg, MCRegInfo); - } - - createPendingLabelRelocs(); -} - -void MipsELFStreamer::EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) { - Frame.Begin = getContext().createTempSymbol(); - MCELFStreamer::EmitLabel(Frame.Begin); -} - -MCSymbol *MipsELFStreamer::EmitCFILabel() { - MCSymbol *Label = getContext().createTempSymbol("cfi", true); - MCELFStreamer::EmitLabel(Label); - return Label; -} - -void MipsELFStreamer::EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) { - Frame.End = getContext().createTempSymbol(); - MCELFStreamer::EmitLabel(Frame.End); -} - -void MipsELFStreamer::createPendingLabelRelocs() { - MipsTargetELFStreamer *ELFTargetStreamer = - static_cast<MipsTargetELFStreamer *>(getTargetStreamer()); - - // FIXME: Also mark labels when in MIPS16 mode. - if (ELFTargetStreamer->isMicroMipsEnabled()) { - for (auto *L : Labels) { - auto *Label = cast<MCSymbolELF>(L); - getAssembler().registerSymbol(*Label); - Label->setOther(ELF::STO_MIPS_MICROMIPS); - } - } - - Labels.clear(); -} - -void MipsELFStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc) { - MCELFStreamer::EmitLabel(Symbol); - Labels.push_back(Symbol); -} - -void MipsELFStreamer::SwitchSection(MCSection *Section, - const MCExpr *Subsection) { - MCELFStreamer::SwitchSection(Section, Subsection); - Labels.clear(); -} - -void MipsELFStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, - SMLoc Loc) { - MCELFStreamer::EmitValueImpl(Value, Size, Loc); - Labels.clear(); -} - -void MipsELFStreamer::EmitIntValue(uint64_t Value, unsigned Size) { - MCELFStreamer::EmitIntValue(Value, Size); - Labels.clear(); -} - -void MipsELFStreamer::EmitMipsOptionRecords() { - for (const auto &I : MipsOptionRecords) - I->EmitMipsOptionRecord(); -} - -MCELFStreamer *llvm::createMipsELFStreamer( - MCContext &Context, std::unique_ptr<MCAsmBackend> MAB, - std::unique_ptr<MCObjectWriter> OW, std::unique_ptr<MCCodeEmitter> Emitter, - bool RelaxAll) { - return new MipsELFStreamer(Context, std::move(MAB), std::move(OW), - std::move(Emitter)); -} diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h deleted file mode 100644 index 2febfbc69b6f..000000000000 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h +++ /dev/null @@ -1,82 +0,0 @@ -//===- MipsELFStreamer.h - ELF Object Output --------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This is a custom MCELFStreamer which allows us to insert some hooks before -// emitting data into an actual object file. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSELFSTREAMER_H -#define LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSELFSTREAMER_H - -#include "MipsOptionRecord.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/MC/MCELFStreamer.h" -#include <memory> - -namespace llvm { - -class MCAsmBackend; -class MCCodeEmitter; -class MCContext; -class MCSubtargetInfo; -struct MCDwarfFrameInfo; - -class MipsELFStreamer : public MCELFStreamer { - SmallVector<std::unique_ptr<MipsOptionRecord>, 8> MipsOptionRecords; - MipsRegInfoRecord *RegInfoRecord; - SmallVector<MCSymbol*, 4> Labels; - -public: - MipsELFStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> MAB, - std::unique_ptr<MCObjectWriter> OW, - std::unique_ptr<MCCodeEmitter> Emitter); - - /// Overriding this function allows us to add arbitrary behaviour before the - /// \p Inst is actually emitted. For example, we can inspect the operands and - /// gather sufficient information that allows us to reason about the register - /// usage for the translation unit. - void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override; - - /// Overriding this function allows us to record all labels that should be - /// marked as microMIPS. Based on this data marking is done in - /// EmitInstruction. - void EmitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override; - - /// Overriding this function allows us to dismiss all labels that are - /// candidates for marking as microMIPS when .section directive is processed. - void SwitchSection(MCSection *Section, - const MCExpr *Subsection = nullptr) override; - - /// Overriding these functions allows us to dismiss all labels that are - /// candidates for marking as microMIPS when .word/.long/.4byte etc - /// directives are emitted. - void EmitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) override; - void EmitIntValue(uint64_t Value, unsigned Size) override; - - // Overriding these functions allows us to avoid recording of these labels - // in EmitLabel and later marking them as microMIPS. - void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override; - void EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override; - MCSymbol *EmitCFILabel() override; - - /// Emits all the option records stored up until the point it's called. - void EmitMipsOptionRecords(); - - /// Mark labels as microMIPS, if necessary for the subtarget. - void createPendingLabelRelocs(); -}; - -MCELFStreamer *createMipsELFStreamer(MCContext &Context, - std::unique_ptr<MCAsmBackend> MAB, - std::unique_ptr<MCObjectWriter> OW, - std::unique_ptr<MCCodeEmitter> Emitter, - bool RelaxAll); -} // end namespace llvm - -#endif // LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSELFSTREAMER_H diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h deleted file mode 100644 index b83d822bd8d0..000000000000 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h +++ /dev/null @@ -1,233 +0,0 @@ -//===-- MipsFixupKinds.h - Mips Specific Fixup Entries ----------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSFIXUPKINDS_H -#define LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSFIXUPKINDS_H - -#include "llvm/MC/MCFixup.h" - -namespace llvm { -namespace Mips { - // Although most of the current fixup types reflect a unique relocation - // one can have multiple fixup types for a given relocation and thus need - // to be uniquely named. - // - // This table *must* be in the same order of - // MCFixupKindInfo Infos[Mips::NumTargetFixupKinds] - // in MipsAsmBackend.cpp. - // - enum Fixups { - // Branch fixups resulting in R_MIPS_16. - fixup_Mips_16 = FirstTargetFixupKind, - - // Pure 32 bit data fixup resulting in - R_MIPS_32. - fixup_Mips_32, - - // Full 32 bit data relative data fixup resulting in - R_MIPS_REL32. - fixup_Mips_REL32, - - // Jump 26 bit fixup resulting in - R_MIPS_26. - fixup_Mips_26, - - // Pure upper 16 bit fixup resulting in - R_MIPS_HI16. - fixup_Mips_HI16, - - // Pure lower 16 bit fixup resulting in - R_MIPS_LO16. - fixup_Mips_LO16, - - // 16 bit fixup for GP offest resulting in - R_MIPS_GPREL16. - fixup_Mips_GPREL16, - - // 16 bit literal fixup resulting in - R_MIPS_LITERAL. - fixup_Mips_LITERAL, - - // Symbol fixup resulting in - R_MIPS_GOT16. - fixup_Mips_GOT, - - // PC relative branch fixup resulting in - R_MIPS_PC16. - fixup_Mips_PC16, - - // resulting in - R_MIPS_CALL16. - fixup_Mips_CALL16, - - // resulting in - R_MIPS_GPREL32. - fixup_Mips_GPREL32, - - // resulting in - R_MIPS_SHIFT5. - fixup_Mips_SHIFT5, - - // resulting in - R_MIPS_SHIFT6. - fixup_Mips_SHIFT6, - - // Pure 64 bit data fixup resulting in - R_MIPS_64. - fixup_Mips_64, - - // resulting in - R_MIPS_TLS_GD. - fixup_Mips_TLSGD, - - // resulting in - R_MIPS_TLS_GOTTPREL. - fixup_Mips_GOTTPREL, - - // resulting in - R_MIPS_TLS_TPREL_HI16. - fixup_Mips_TPREL_HI, - - // resulting in - R_MIPS_TLS_TPREL_LO16. - fixup_Mips_TPREL_LO, - - // resulting in - R_MIPS_TLS_LDM. - fixup_Mips_TLSLDM, - - // resulting in - R_MIPS_TLS_DTPREL_HI16. - fixup_Mips_DTPREL_HI, - - // resulting in - R_MIPS_TLS_DTPREL_LO16. - fixup_Mips_DTPREL_LO, - - // PC relative branch fixup resulting in - R_MIPS_PC16 - fixup_Mips_Branch_PCRel, - - // resulting in - R_MIPS_GPREL16/R_MIPS_SUB/R_MIPS_HI16 - // R_MICROMIPS_GPREL16/R_MICROMIPS_SUB/R_MICROMIPS_HI16 - fixup_Mips_GPOFF_HI, - fixup_MICROMIPS_GPOFF_HI, - - // resulting in - R_MIPS_GPREL16/R_MIPS_SUB/R_MIPS_LO16 - // R_MICROMIPS_GPREL16/R_MICROMIPS_SUB/R_MICROMIPS_LO16 - fixup_Mips_GPOFF_LO, - fixup_MICROMIPS_GPOFF_LO, - - // resulting in - R_MIPS_PAGE - fixup_Mips_GOT_PAGE, - - // resulting in - R_MIPS_GOT_OFST - fixup_Mips_GOT_OFST, - - // resulting in - R_MIPS_GOT_DISP - fixup_Mips_GOT_DISP, - - // resulting in - R_MIPS_HIGHER/R_MICROMIPS_HIGHER - fixup_Mips_HIGHER, - fixup_MICROMIPS_HIGHER, - - // resulting in - R_MIPS_HIGHEST/R_MICROMIPS_HIGHEST - fixup_Mips_HIGHEST, - fixup_MICROMIPS_HIGHEST, - - // resulting in - R_MIPS_GOT_HI16 - fixup_Mips_GOT_HI16, - - // resulting in - R_MIPS_GOT_LO16 - fixup_Mips_GOT_LO16, - - // resulting in - R_MIPS_CALL_HI16 - fixup_Mips_CALL_HI16, - - // resulting in - R_MIPS_CALL_LO16 - fixup_Mips_CALL_LO16, - - // resulting in - R_MIPS_PC18_S3 - fixup_MIPS_PC18_S3, - - // resulting in - R_MIPS_PC19_S2 - fixup_MIPS_PC19_S2, - - // resulting in - R_MIPS_PC21_S2 - fixup_MIPS_PC21_S2, - - // resulting in - R_MIPS_PC26_S2 - fixup_MIPS_PC26_S2, - - // resulting in - R_MIPS_PCHI16 - fixup_MIPS_PCHI16, - - // resulting in - R_MIPS_PCLO16 - fixup_MIPS_PCLO16, - - // resulting in - R_MICROMIPS_26_S1 - fixup_MICROMIPS_26_S1, - - // resulting in - R_MICROMIPS_HI16 - fixup_MICROMIPS_HI16, - - // resulting in - R_MICROMIPS_LO16 - fixup_MICROMIPS_LO16, - - // resulting in - R_MICROMIPS_GOT16 - fixup_MICROMIPS_GOT16, - - // resulting in - R_MICROMIPS_PC7_S1 - fixup_MICROMIPS_PC7_S1, - - // resulting in - R_MICROMIPS_PC10_S1 - fixup_MICROMIPS_PC10_S1, - - // resulting in - R_MICROMIPS_PC16_S1 - fixup_MICROMIPS_PC16_S1, - - // resulting in - R_MICROMIPS_PC26_S1 - fixup_MICROMIPS_PC26_S1, - - // resulting in - R_MICROMIPS_PC19_S2 - fixup_MICROMIPS_PC19_S2, - - // resulting in - R_MICROMIPS_PC18_S3 - fixup_MICROMIPS_PC18_S3, - - // resulting in - R_MICROMIPS_PC21_S1 - fixup_MICROMIPS_PC21_S1, - - // resulting in - R_MICROMIPS_CALL16 - fixup_MICROMIPS_CALL16, - - // resulting in - R_MICROMIPS_GOT_DISP - fixup_MICROMIPS_GOT_DISP, - - // resulting in - R_MICROMIPS_GOT_PAGE - fixup_MICROMIPS_GOT_PAGE, - - // resulting in - R_MICROMIPS_GOT_OFST - fixup_MICROMIPS_GOT_OFST, - - // resulting in - R_MICROMIPS_TLS_GD - fixup_MICROMIPS_TLS_GD, - - // resulting in - R_MICROMIPS_TLS_LDM - fixup_MICROMIPS_TLS_LDM, - - // resulting in - R_MICROMIPS_TLS_DTPREL_HI16 - fixup_MICROMIPS_TLS_DTPREL_HI16, - - // resulting in - R_MICROMIPS_TLS_DTPREL_LO16 - fixup_MICROMIPS_TLS_DTPREL_LO16, - - // resulting in - R_MICROMIPS_TLS_GOTTPREL. - fixup_MICROMIPS_GOTTPREL, - - // resulting in - R_MICROMIPS_TLS_TPREL_HI16 - fixup_MICROMIPS_TLS_TPREL_HI16, - - // resulting in - R_MICROMIPS_TLS_TPREL_LO16 - fixup_MICROMIPS_TLS_TPREL_LO16, - - // resulting in - R_MIPS_SUB/R_MICROMIPS_SUB - fixup_Mips_SUB, - fixup_MICROMIPS_SUB, - - // resulting in - R_MIPS_JALR/R_MICROMIPS_JALR - fixup_Mips_JALR, - fixup_MICROMIPS_JALR, - - // Marker - LastTargetFixupKind, - NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind - }; -} // namespace Mips -} // namespace llvm - - -#endif diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.cpp b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.cpp deleted file mode 100644 index fb290a8e3f26..000000000000 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.cpp +++ /dev/null @@ -1,287 +0,0 @@ -//===-- MipsInstPrinter.cpp - Convert Mips MCInst to assembly syntax ------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This class prints an Mips MCInst to a .s file. -// -//===----------------------------------------------------------------------===// - -#include "MipsInstPrinter.h" -#include "MipsInstrInfo.h" -#include "MipsMCExpr.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCInst.h" -#include "llvm/MC/MCInstrInfo.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" -using namespace llvm; - -#define DEBUG_TYPE "asm-printer" - -#define PRINT_ALIAS_INSTR -#include "MipsGenAsmWriter.inc" - -template<unsigned R> -static bool isReg(const MCInst &MI, unsigned OpNo) { - assert(MI.getOperand(OpNo).isReg() && "Register operand expected."); - return MI.getOperand(OpNo).getReg() == R; -} - -const char* Mips::MipsFCCToString(Mips::CondCode CC) { - switch (CC) { - case FCOND_F: - case FCOND_T: return "f"; - case FCOND_UN: - case FCOND_OR: return "un"; - case FCOND_OEQ: - case FCOND_UNE: return "eq"; - case FCOND_UEQ: - case FCOND_ONE: return "ueq"; - case FCOND_OLT: - case FCOND_UGE: return "olt"; - case FCOND_ULT: - case FCOND_OGE: return "ult"; - case FCOND_OLE: - case FCOND_UGT: return "ole"; - case FCOND_ULE: - case FCOND_OGT: return "ule"; - case FCOND_SF: - case FCOND_ST: return "sf"; - case FCOND_NGLE: - case FCOND_GLE: return "ngle"; - case FCOND_SEQ: - case FCOND_SNE: return "seq"; - case FCOND_NGL: - case FCOND_GL: return "ngl"; - case FCOND_LT: - case FCOND_NLT: return "lt"; - case FCOND_NGE: - case FCOND_GE: return "nge"; - case FCOND_LE: - case FCOND_NLE: return "le"; - case FCOND_NGT: - case FCOND_GT: return "ngt"; - } - llvm_unreachable("Impossible condition code!"); -} - -void MipsInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const { - OS << '$' << StringRef(getRegisterName(RegNo)).lower(); -} - -void MipsInstPrinter::printInst(const MCInst *MI, raw_ostream &O, - StringRef Annot, const MCSubtargetInfo &STI) { - switch (MI->getOpcode()) { - default: - break; - case Mips::RDHWR: - case Mips::RDHWR64: - O << "\t.set\tpush\n"; - O << "\t.set\tmips32r2\n"; - break; - case Mips::Save16: - O << "\tsave\t"; - printSaveRestore(MI, O); - O << " # 16 bit inst\n"; - return; - case Mips::SaveX16: - O << "\tsave\t"; - printSaveRestore(MI, O); - O << "\n"; - return; - case Mips::Restore16: - O << "\trestore\t"; - printSaveRestore(MI, O); - O << " # 16 bit inst\n"; - return; - case Mips::RestoreX16: - O << "\trestore\t"; - printSaveRestore(MI, O); - O << "\n"; - return; - } - - // Try to print any aliases first. - if (!printAliasInstr(MI, O) && !printAlias(*MI, O)) - printInstruction(MI, O); - printAnnotation(O, Annot); - - switch (MI->getOpcode()) { - default: - break; - case Mips::RDHWR: - case Mips::RDHWR64: - O << "\n\t.set\tpop"; - } -} - -void MipsInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, - raw_ostream &O) { - const MCOperand &Op = MI->getOperand(OpNo); - if (Op.isReg()) { - printRegName(O, Op.getReg()); - return; - } - - if (Op.isImm()) { - O << formatImm(Op.getImm()); - return; - } - - assert(Op.isExpr() && "unknown operand kind in printOperand"); - Op.getExpr()->print(O, &MAI, true); -} - -template <unsigned Bits, unsigned Offset> -void MipsInstPrinter::printUImm(const MCInst *MI, int opNum, raw_ostream &O) { - const MCOperand &MO = MI->getOperand(opNum); - if (MO.isImm()) { - uint64_t Imm = MO.getImm(); - Imm -= Offset; - Imm &= (1 << Bits) - 1; - Imm += Offset; - O << formatImm(Imm); - return; - } - - printOperand(MI, opNum, O); -} - -void MipsInstPrinter:: -printMemOperand(const MCInst *MI, int opNum, raw_ostream &O) { - // Load/Store memory operands -- imm($reg) - // If PIC target the target is loaded as the - // pattern lw $25,%call16($28) - - // opNum can be invalid if instruction had reglist as operand. - // MemOperand is always last operand of instruction (base + offset). - switch (MI->getOpcode()) { - default: - break; - case Mips::SWM32_MM: - case Mips::LWM32_MM: - case Mips::SWM16_MM: - case Mips::SWM16_MMR6: - case Mips::LWM16_MM: - case Mips::LWM16_MMR6: - opNum = MI->getNumOperands() - 2; - break; - } - - printOperand(MI, opNum+1, O); - O << "("; - printOperand(MI, opNum, O); - O << ")"; -} - -void MipsInstPrinter:: -printMemOperandEA(const MCInst *MI, int opNum, raw_ostream &O) { - // when using stack locations for not load/store instructions - // print the same way as all normal 3 operand instructions. - printOperand(MI, opNum, O); - O << ", "; - printOperand(MI, opNum+1, O); -} - -void MipsInstPrinter:: -printFCCOperand(const MCInst *MI, int opNum, raw_ostream &O) { - const MCOperand& MO = MI->getOperand(opNum); - O << MipsFCCToString((Mips::CondCode)MO.getImm()); -} - -void MipsInstPrinter:: -printSHFMask(const MCInst *MI, int opNum, raw_ostream &O) { - llvm_unreachable("TODO"); -} - -bool MipsInstPrinter::printAlias(const char *Str, const MCInst &MI, - unsigned OpNo, raw_ostream &OS) { - OS << "\t" << Str << "\t"; - printOperand(&MI, OpNo, OS); - return true; -} - -bool MipsInstPrinter::printAlias(const char *Str, const MCInst &MI, - unsigned OpNo0, unsigned OpNo1, - raw_ostream &OS) { - printAlias(Str, MI, OpNo0, OS); - OS << ", "; - printOperand(&MI, OpNo1, OS); - return true; -} - -bool MipsInstPrinter::printAlias(const MCInst &MI, raw_ostream &OS) { - switch (MI.getOpcode()) { - case Mips::BEQ: - case Mips::BEQ_MM: - // beq $zero, $zero, $L2 => b $L2 - // beq $r0, $zero, $L2 => beqz $r0, $L2 - return (isReg<Mips::ZERO>(MI, 0) && isReg<Mips::ZERO>(MI, 1) && - printAlias("b", MI, 2, OS)) || - (isReg<Mips::ZERO>(MI, 1) && printAlias("beqz", MI, 0, 2, OS)); - case Mips::BEQ64: - // beq $r0, $zero, $L2 => beqz $r0, $L2 - return isReg<Mips::ZERO_64>(MI, 1) && printAlias("beqz", MI, 0, 2, OS); - case Mips::BNE: - case Mips::BNE_MM: - // bne $r0, $zero, $L2 => bnez $r0, $L2 - return isReg<Mips::ZERO>(MI, 1) && printAlias("bnez", MI, 0, 2, OS); - case Mips::BNE64: - // bne $r0, $zero, $L2 => bnez $r0, $L2 - return isReg<Mips::ZERO_64>(MI, 1) && printAlias("bnez", MI, 0, 2, OS); - case Mips::BGEZAL: - // bgezal $zero, $L1 => bal $L1 - return isReg<Mips::ZERO>(MI, 0) && printAlias("bal", MI, 1, OS); - case Mips::BC1T: - // bc1t $fcc0, $L1 => bc1t $L1 - return isReg<Mips::FCC0>(MI, 0) && printAlias("bc1t", MI, 1, OS); - case Mips::BC1F: - // bc1f $fcc0, $L1 => bc1f $L1 - return isReg<Mips::FCC0>(MI, 0) && printAlias("bc1f", MI, 1, OS); - case Mips::JALR: - // jalr $ra, $r1 => jalr $r1 - return isReg<Mips::RA>(MI, 0) && printAlias("jalr", MI, 1, OS); - case Mips::JALR64: - // jalr $ra, $r1 => jalr $r1 - return isReg<Mips::RA_64>(MI, 0) && printAlias("jalr", MI, 1, OS); - case Mips::NOR: - case Mips::NOR_MM: - case Mips::NOR_MMR6: - // nor $r0, $r1, $zero => not $r0, $r1 - return isReg<Mips::ZERO>(MI, 2) && printAlias("not", MI, 0, 1, OS); - case Mips::NOR64: - // nor $r0, $r1, $zero => not $r0, $r1 - return isReg<Mips::ZERO_64>(MI, 2) && printAlias("not", MI, 0, 1, OS); - case Mips::OR: - // or $r0, $r1, $zero => move $r0, $r1 - return isReg<Mips::ZERO>(MI, 2) && printAlias("move", MI, 0, 1, OS); - default: return false; - } -} - -void MipsInstPrinter::printSaveRestore(const MCInst *MI, raw_ostream &O) { - for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { - if (i != 0) O << ", "; - if (MI->getOperand(i).isReg()) - printRegName(O, MI->getOperand(i).getReg()); - else - printUImm<16>(MI, i, O); - } -} - -void MipsInstPrinter:: -printRegisterList(const MCInst *MI, int opNum, raw_ostream &O) { - // - 2 because register List is always first operand of instruction and it is - // always followed by memory operand (base + offset). - for (int i = opNum, e = MI->getNumOperands() - 2; i != e; ++i) { - if (i != opNum) - O << ", "; - printRegName(O, MI->getOperand(i).getReg()); - } -} diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.h b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.h deleted file mode 100644 index a34a5c1d6418..000000000000 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.h +++ /dev/null @@ -1,112 +0,0 @@ -//=== MipsInstPrinter.h - Convert Mips MCInst to assembly syntax -*- C++ -*-==// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This class prints a Mips MCInst to a .s file. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSINSTPRINTER_H -#define LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSINSTPRINTER_H -#include "llvm/MC/MCInstPrinter.h" - -namespace llvm { -// These enumeration declarations were originally in MipsInstrInfo.h but -// had to be moved here to avoid circular dependencies between -// LLVMMipsCodeGen and LLVMMipsAsmPrinter. -namespace Mips { -// Mips Branch Codes -enum FPBranchCode { - BRANCH_F, - BRANCH_T, - BRANCH_FL, - BRANCH_TL, - BRANCH_INVALID -}; - -// Mips Condition Codes -enum CondCode { - // To be used with float branch True - FCOND_F, - FCOND_UN, - FCOND_OEQ, - FCOND_UEQ, - FCOND_OLT, - FCOND_ULT, - FCOND_OLE, - FCOND_ULE, - FCOND_SF, - FCOND_NGLE, - FCOND_SEQ, - FCOND_NGL, - FCOND_LT, - FCOND_NGE, - FCOND_LE, - FCOND_NGT, - - // To be used with float branch False - // This conditions have the same mnemonic as the - // above ones, but are used with a branch False; - FCOND_T, - FCOND_OR, - FCOND_UNE, - FCOND_ONE, - FCOND_UGE, - FCOND_OGE, - FCOND_UGT, - FCOND_OGT, - FCOND_ST, - FCOND_GLE, - FCOND_SNE, - FCOND_GL, - FCOND_NLT, - FCOND_GE, - FCOND_NLE, - FCOND_GT -}; - -const char *MipsFCCToString(Mips::CondCode CC); -} // end namespace Mips - -class MipsInstPrinter : public MCInstPrinter { -public: - MipsInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII, - const MCRegisterInfo &MRI) - : MCInstPrinter(MAI, MII, MRI) {} - - // Autogenerated by tblgen. - void printInstruction(const MCInst *MI, raw_ostream &O); - static const char *getRegisterName(unsigned RegNo); - - void printRegName(raw_ostream &OS, unsigned RegNo) const override; - void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot, - const MCSubtargetInfo &STI) override; - - bool printAliasInstr(const MCInst *MI, raw_ostream &OS); - void printCustomAliasOperand(const MCInst *MI, unsigned OpIdx, - unsigned PrintMethodIdx, raw_ostream &O); - -private: - void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O); - template <unsigned Bits, unsigned Offset = 0> - void printUImm(const MCInst *MI, int opNum, raw_ostream &O); - void printMemOperand(const MCInst *MI, int opNum, raw_ostream &O); - void printMemOperandEA(const MCInst *MI, int opNum, raw_ostream &O); - void printFCCOperand(const MCInst *MI, int opNum, raw_ostream &O); - void printSHFMask(const MCInst *MI, int opNum, raw_ostream &O); - - bool printAlias(const char *Str, const MCInst &MI, unsigned OpNo, - raw_ostream &OS); - bool printAlias(const char *Str, const MCInst &MI, unsigned OpNo0, - unsigned OpNo1, raw_ostream &OS); - bool printAlias(const MCInst &MI, raw_ostream &OS); - void printSaveRestore(const MCInst *MI, raw_ostream &O); - void printRegisterList(const MCInst *MI, int opNum, raw_ostream &O); -}; -} // end namespace llvm - -#endif diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp deleted file mode 100644 index ec78158d387d..000000000000 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp +++ /dev/null @@ -1,52 +0,0 @@ -//===-- MipsMCAsmInfo.cpp - Mips Asm Properties ---------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains the declarations of the MipsMCAsmInfo properties. -// -//===----------------------------------------------------------------------===// - -#include "MipsMCAsmInfo.h" -#include "llvm/ADT/Triple.h" - -using namespace llvm; - -void MipsMCAsmInfo::anchor() { } - -MipsMCAsmInfo::MipsMCAsmInfo(const Triple &TheTriple) { - IsLittleEndian = TheTriple.isLittleEndian(); - - if (TheTriple.isMIPS64() && TheTriple.getEnvironment() != Triple::GNUABIN32) - CodePointerSize = CalleeSaveStackSlotSize = 8; - - // FIXME: This condition isn't quite right but it's the best we can do until - // this object can identify the ABI. It will misbehave when using O32 - // on a mips64*-* triple. - if (TheTriple.isMIPS32()) { - PrivateGlobalPrefix = "$"; - PrivateLabelPrefix = "$"; - } - - AlignmentIsInBytes = false; - Data16bitsDirective = "\t.2byte\t"; - Data32bitsDirective = "\t.4byte\t"; - Data64bitsDirective = "\t.8byte\t"; - CommentString = "#"; - ZeroDirective = "\t.space\t"; - GPRel32Directive = "\t.gpword\t"; - GPRel64Directive = "\t.gpdword\t"; - DTPRel32Directive = "\t.dtprelword\t"; - DTPRel64Directive = "\t.dtpreldword\t"; - TPRel32Directive = "\t.tprelword\t"; - TPRel64Directive = "\t.tpreldword\t"; - UseAssignmentForEHBegin = true; - SupportsDebugInformation = true; - ExceptionsType = ExceptionHandling::DwarfCFI; - DwarfRegNumForCFI = true; - HasMipsExpressions = true; - UseIntegratedAssembler = true; -} diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h deleted file mode 100644 index 867f4d223de4..000000000000 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h +++ /dev/null @@ -1,30 +0,0 @@ -//===-- MipsMCAsmInfo.h - Mips Asm Info ------------------------*- C++ -*--===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains the declaration of the MipsMCAsmInfo class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSMCASMINFO_H -#define LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSMCASMINFO_H - -#include "llvm/MC/MCAsmInfoELF.h" - -namespace llvm { -class Triple; - -class MipsMCAsmInfo : public MCAsmInfoELF { - void anchor() override; - -public: - explicit MipsMCAsmInfo(const Triple &TheTriple); -}; - -} // namespace llvm - -#endif diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp deleted file mode 100644 index 759a7fdb32b8..000000000000 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp +++ /dev/null @@ -1,1139 +0,0 @@ -//===-- MipsMCCodeEmitter.cpp - Convert Mips Code to Machine Code ---------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements the MipsMCCodeEmitter class. -// -//===----------------------------------------------------------------------===// - -#include "MipsMCCodeEmitter.h" -#include "MCTargetDesc/MipsFixupKinds.h" -#include "MCTargetDesc/MipsMCExpr.h" -#include "MCTargetDesc/MipsMCTargetDesc.h" -#include "llvm/ADT/APFloat.h" -#include "llvm/ADT/APInt.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCFixup.h" -#include "llvm/MC/MCInst.h" -#include "llvm/MC/MCInstrDesc.h" -#include "llvm/MC/MCInstrInfo.h" -#include "llvm/MC/MCRegisterInfo.h" -#include "llvm/MC/MCSubtargetInfo.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" -#include <cassert> -#include <cstdint> - -using namespace llvm; - -#define DEBUG_TYPE "mccodeemitter" - -#define GET_INSTRMAP_INFO -#include "MipsGenInstrInfo.inc" -#undef GET_INSTRMAP_INFO - -namespace llvm { - -MCCodeEmitter *createMipsMCCodeEmitterEB(const MCInstrInfo &MCII, - const MCRegisterInfo &MRI, - MCContext &Ctx) { - return new MipsMCCodeEmitter(MCII, Ctx, false); -} - -MCCodeEmitter *createMipsMCCodeEmitterEL(const MCInstrInfo &MCII, - const MCRegisterInfo &MRI, - MCContext &Ctx) { - return new MipsMCCodeEmitter(MCII, Ctx, true); -} - -} // end namespace llvm - -// If the D<shift> instruction has a shift amount that is greater -// than 31 (checked in calling routine), lower it to a D<shift>32 instruction -static void LowerLargeShift(MCInst& Inst) { - assert(Inst.getNumOperands() == 3 && "Invalid no. of operands for shift!"); - assert(Inst.getOperand(2).isImm()); - - int64_t Shift = Inst.getOperand(2).getImm(); - if (Shift <= 31) - return; // Do nothing - Shift -= 32; - - // saminus32 - Inst.getOperand(2).setImm(Shift); - - switch (Inst.getOpcode()) { - default: - // Calling function is not synchronized - llvm_unreachable("Unexpected shift instruction"); - case Mips::DSLL: - Inst.setOpcode(Mips::DSLL32); - return; - case Mips::DSRL: - Inst.setOpcode(Mips::DSRL32); - return; - case Mips::DSRA: - Inst.setOpcode(Mips::DSRA32); - return; - case Mips::DROTR: - Inst.setOpcode(Mips::DROTR32); - return; - } -} - -// Fix a bad compact branch encoding for beqc/bnec. -void MipsMCCodeEmitter::LowerCompactBranch(MCInst& Inst) const { - // Encoding may be illegal !(rs < rt), but this situation is - // easily fixed. - unsigned RegOp0 = Inst.getOperand(0).getReg(); - unsigned RegOp1 = Inst.getOperand(1).getReg(); - - unsigned Reg0 = Ctx.getRegisterInfo()->getEncodingValue(RegOp0); - unsigned Reg1 = Ctx.getRegisterInfo()->getEncodingValue(RegOp1); - - if (Inst.getOpcode() == Mips::BNEC || Inst.getOpcode() == Mips::BEQC || - Inst.getOpcode() == Mips::BNEC64 || Inst.getOpcode() == Mips::BEQC64) { - assert(Reg0 != Reg1 && "Instruction has bad operands ($rs == $rt)!"); - if (Reg0 < Reg1) - return; - } else if (Inst.getOpcode() == Mips::BNVC || Inst.getOpcode() == Mips::BOVC) { - if (Reg0 >= Reg1) - return; - } else if (Inst.getOpcode() == Mips::BNVC_MMR6 || - Inst.getOpcode() == Mips::BOVC_MMR6) { - if (Reg1 >= Reg0) - return; - } else - llvm_unreachable("Cannot rewrite unknown branch!"); - - Inst.getOperand(0).setReg(RegOp1); - Inst.getOperand(1).setReg(RegOp0); -} - -bool MipsMCCodeEmitter::isMicroMips(const MCSubtargetInfo &STI) const { - return STI.getFeatureBits()[Mips::FeatureMicroMips]; -} - -bool MipsMCCodeEmitter::isMips32r6(const MCSubtargetInfo &STI) const { - return STI.getFeatureBits()[Mips::FeatureMips32r6]; -} - -void MipsMCCodeEmitter::EmitByte(unsigned char C, raw_ostream &OS) const { - OS << (char)C; -} - -void MipsMCCodeEmitter::EmitInstruction(uint64_t Val, unsigned Size, - const MCSubtargetInfo &STI, - raw_ostream &OS) const { - // Output the instruction encoding in little endian byte order. - // Little-endian byte ordering: - // mips32r2: 4 | 3 | 2 | 1 - // microMIPS: 2 | 1 | 4 | 3 - if (IsLittleEndian && Size == 4 && isMicroMips(STI)) { - EmitInstruction(Val >> 16, 2, STI, OS); - EmitInstruction(Val, 2, STI, OS); - } else { - for (unsigned i = 0; i < Size; ++i) { - unsigned Shift = IsLittleEndian ? i * 8 : (Size - 1 - i) * 8; - EmitByte((Val >> Shift) & 0xff, OS); - } - } -} - -/// encodeInstruction - Emit the instruction. -/// Size the instruction with Desc.getSize(). -void MipsMCCodeEmitter:: -encodeInstruction(const MCInst &MI, raw_ostream &OS, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const -{ - // Non-pseudo instructions that get changed for direct object - // only based on operand values. - // If this list of instructions get much longer we will move - // the check to a function call. Until then, this is more efficient. - MCInst TmpInst = MI; - switch (MI.getOpcode()) { - // If shift amount is >= 32 it the inst needs to be lowered further - case Mips::DSLL: - case Mips::DSRL: - case Mips::DSRA: - case Mips::DROTR: - LowerLargeShift(TmpInst); - break; - // Compact branches, enforce encoding restrictions. - case Mips::BEQC: - case Mips::BNEC: - case Mips::BEQC64: - case Mips::BNEC64: - case Mips::BOVC: - case Mips::BOVC_MMR6: - case Mips::BNVC: - case Mips::BNVC_MMR6: - LowerCompactBranch(TmpInst); - } - - unsigned long N = Fixups.size(); - uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); - - // Check for unimplemented opcodes. - // Unfortunately in MIPS both NOP and SLL will come in with Binary == 0 - // so we have to special check for them. - const unsigned Opcode = TmpInst.getOpcode(); - if ((Opcode != Mips::NOP) && (Opcode != Mips::SLL) && - (Opcode != Mips::SLL_MM) && (Opcode != Mips::SLL_MMR6) && !Binary) - llvm_unreachable("unimplemented opcode in encodeInstruction()"); - - int NewOpcode = -1; - if (isMicroMips(STI)) { - if (isMips32r6(STI)) { - NewOpcode = Mips::MipsR62MicroMipsR6(Opcode, Mips::Arch_micromipsr6); - if (NewOpcode == -1) - NewOpcode = Mips::Std2MicroMipsR6(Opcode, Mips::Arch_micromipsr6); - } - else - NewOpcode = Mips::Std2MicroMips(Opcode, Mips::Arch_micromips); - - // Check whether it is Dsp instruction. - if (NewOpcode == -1) - NewOpcode = Mips::Dsp2MicroMips(Opcode, Mips::Arch_mmdsp); - - if (NewOpcode != -1) { - if (Fixups.size() > N) - Fixups.pop_back(); - - TmpInst.setOpcode (NewOpcode); - Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); - } - - if (((MI.getOpcode() == Mips::MOVEP_MM) || - (MI.getOpcode() == Mips::MOVEP_MMR6))) { - unsigned RegPair = getMovePRegPairOpValue(MI, 0, Fixups, STI); - Binary = (Binary & 0xFFFFFC7F) | (RegPair << 7); - } - } - - const MCInstrDesc &Desc = MCII.get(TmpInst.getOpcode()); - - // Get byte count of instruction - unsigned Size = Desc.getSize(); - if (!Size) - llvm_unreachable("Desc.getSize() returns 0"); - - EmitInstruction(Binary, Size, STI, OS); -} - -/// getBranchTargetOpValue - Return binary encoding of the branch -/// target operand. If the machine operand requires relocation, -/// record the relocation and return zero. -unsigned MipsMCCodeEmitter:: -getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const { - const MCOperand &MO = MI.getOperand(OpNo); - - // If the destination is an immediate, divide by 4. - if (MO.isImm()) return MO.getImm() >> 2; - - assert(MO.isExpr() && - "getBranchTargetOpValue expects only expressions or immediates"); - - const MCExpr *FixupExpression = MCBinaryExpr::createAdd( - MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx); - Fixups.push_back(MCFixup::create(0, FixupExpression, - MCFixupKind(Mips::fixup_Mips_PC16))); - return 0; -} - -/// getBranchTargetOpValue1SImm16 - Return binary encoding of the branch -/// target operand. If the machine operand requires relocation, -/// record the relocation and return zero. -unsigned MipsMCCodeEmitter:: -getBranchTargetOpValue1SImm16(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const { - const MCOperand &MO = MI.getOperand(OpNo); - - // If the destination is an immediate, divide by 2. - if (MO.isImm()) return MO.getImm() >> 1; - - assert(MO.isExpr() && - "getBranchTargetOpValue expects only expressions or immediates"); - - const MCExpr *FixupExpression = MCBinaryExpr::createAdd( - MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx); - Fixups.push_back(MCFixup::create(0, FixupExpression, - MCFixupKind(Mips::fixup_Mips_PC16))); - return 0; -} - -/// getBranchTargetOpValueMMR6 - Return binary encoding of the branch -/// target operand. If the machine operand requires relocation, -/// record the relocation and return zero. -unsigned MipsMCCodeEmitter:: -getBranchTargetOpValueMMR6(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const { - const MCOperand &MO = MI.getOperand(OpNo); - - // If the destination is an immediate, divide by 2. - if (MO.isImm()) - return MO.getImm() >> 1; - - assert(MO.isExpr() && - "getBranchTargetOpValueMMR6 expects only expressions or immediates"); - - const MCExpr *FixupExpression = MCBinaryExpr::createAdd( - MO.getExpr(), MCConstantExpr::create(-2, Ctx), Ctx); - Fixups.push_back(MCFixup::create(0, FixupExpression, - MCFixupKind(Mips::fixup_Mips_PC16))); - return 0; -} - -/// getBranchTargetOpValueLsl2MMR6 - Return binary encoding of the branch -/// target operand. If the machine operand requires relocation, -/// record the relocation and return zero. -unsigned MipsMCCodeEmitter:: -getBranchTargetOpValueLsl2MMR6(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const { - const MCOperand &MO = MI.getOperand(OpNo); - - // If the destination is an immediate, divide by 4. - if (MO.isImm()) - return MO.getImm() >> 2; - - assert(MO.isExpr() && - "getBranchTargetOpValueLsl2MMR6 expects only expressions or immediates"); - - const MCExpr *FixupExpression = MCBinaryExpr::createAdd( - MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx); - Fixups.push_back(MCFixup::create(0, FixupExpression, - MCFixupKind(Mips::fixup_Mips_PC16))); - return 0; -} - -/// getBranchTarget7OpValueMM - Return binary encoding of the microMIPS branch -/// target operand. If the machine operand requires relocation, -/// record the relocation and return zero. -unsigned MipsMCCodeEmitter:: -getBranchTarget7OpValueMM(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const { - const MCOperand &MO = MI.getOperand(OpNo); - - // If the destination is an immediate, divide by 2. - if (MO.isImm()) return MO.getImm() >> 1; - - assert(MO.isExpr() && - "getBranchTargetOpValueMM expects only expressions or immediates"); - - const MCExpr *Expr = MO.getExpr(); - Fixups.push_back(MCFixup::create(0, Expr, - MCFixupKind(Mips::fixup_MICROMIPS_PC7_S1))); - return 0; -} - -/// getBranchTargetOpValueMMPC10 - Return binary encoding of the microMIPS -/// 10-bit branch target operand. If the machine operand requires relocation, -/// record the relocation and return zero. -unsigned MipsMCCodeEmitter:: -getBranchTargetOpValueMMPC10(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const { - const MCOperand &MO = MI.getOperand(OpNo); - - // If the destination is an immediate, divide by 2. - if (MO.isImm()) return MO.getImm() >> 1; - - assert(MO.isExpr() && - "getBranchTargetOpValuePC10 expects only expressions or immediates"); - - const MCExpr *Expr = MO.getExpr(); - Fixups.push_back(MCFixup::create(0, Expr, - MCFixupKind(Mips::fixup_MICROMIPS_PC10_S1))); - return 0; -} - -/// getBranchTargetOpValue - Return binary encoding of the microMIPS branch -/// target operand. If the machine operand requires relocation, -/// record the relocation and return zero. -unsigned MipsMCCodeEmitter:: -getBranchTargetOpValueMM(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const { - const MCOperand &MO = MI.getOperand(OpNo); - - // If the destination is an immediate, divide by 2. - if (MO.isImm()) return MO.getImm() >> 1; - - assert(MO.isExpr() && - "getBranchTargetOpValueMM expects only expressions or immediates"); - - const MCExpr *Expr = MO.getExpr(); - Fixups.push_back(MCFixup::create(0, Expr, - MCFixupKind(Mips:: - fixup_MICROMIPS_PC16_S1))); - return 0; -} - -/// getBranchTarget21OpValue - Return binary encoding of the branch -/// target operand. If the machine operand requires relocation, -/// record the relocation and return zero. -unsigned MipsMCCodeEmitter:: -getBranchTarget21OpValue(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const { - const MCOperand &MO = MI.getOperand(OpNo); - - // If the destination is an immediate, divide by 4. - if (MO.isImm()) return MO.getImm() >> 2; - - assert(MO.isExpr() && - "getBranchTarget21OpValue expects only expressions or immediates"); - - const MCExpr *FixupExpression = MCBinaryExpr::createAdd( - MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx); - Fixups.push_back(MCFixup::create(0, FixupExpression, - MCFixupKind(Mips::fixup_MIPS_PC21_S2))); - return 0; -} - -/// getBranchTarget21OpValueMM - Return binary encoding of the branch -/// target operand for microMIPS. If the machine operand requires -/// relocation, record the relocation and return zero. -unsigned MipsMCCodeEmitter:: -getBranchTarget21OpValueMM(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const { - const MCOperand &MO = MI.getOperand(OpNo); - - // If the destination is an immediate, divide by 4. - if (MO.isImm()) return MO.getImm() >> 2; - - assert(MO.isExpr() && - "getBranchTarget21OpValueMM expects only expressions or immediates"); - - const MCExpr *FixupExpression = MCBinaryExpr::createAdd( - MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx); - Fixups.push_back(MCFixup::create(0, FixupExpression, - MCFixupKind(Mips::fixup_MICROMIPS_PC21_S1))); - return 0; -} - -/// getBranchTarget26OpValue - Return binary encoding of the branch -/// target operand. If the machine operand requires relocation, -/// record the relocation and return zero. -unsigned MipsMCCodeEmitter:: -getBranchTarget26OpValue(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const { - const MCOperand &MO = MI.getOperand(OpNo); - - // If the destination is an immediate, divide by 4. - if (MO.isImm()) return MO.getImm() >> 2; - - assert(MO.isExpr() && - "getBranchTarget26OpValue expects only expressions or immediates"); - - const MCExpr *FixupExpression = MCBinaryExpr::createAdd( - MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx); - Fixups.push_back(MCFixup::create(0, FixupExpression, - MCFixupKind(Mips::fixup_MIPS_PC26_S2))); - return 0; -} - -/// getBranchTarget26OpValueMM - Return binary encoding of the branch -/// target operand. If the machine operand requires relocation, -/// record the relocation and return zero. -unsigned MipsMCCodeEmitter::getBranchTarget26OpValueMM( - const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const { - const MCOperand &MO = MI.getOperand(OpNo); - - // If the destination is an immediate, divide by 2. - if (MO.isImm()) - return MO.getImm() >> 1; - - assert(MO.isExpr() && - "getBranchTarget26OpValueMM expects only expressions or immediates"); - - const MCExpr *FixupExpression = MCBinaryExpr::createAdd( - MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx); - Fixups.push_back(MCFixup::create(0, FixupExpression, - MCFixupKind(Mips::fixup_MICROMIPS_PC26_S1))); - return 0; -} - -/// getJumpOffset16OpValue - Return binary encoding of the jump -/// target operand. If the machine operand requires relocation, -/// record the relocation and return zero. -unsigned MipsMCCodeEmitter:: -getJumpOffset16OpValue(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const { - const MCOperand &MO = MI.getOperand(OpNo); - - if (MO.isImm()) return MO.getImm(); - - assert(MO.isExpr() && - "getJumpOffset16OpValue expects only expressions or an immediate"); - - // TODO: Push fixup. - return 0; -} - -/// getJumpTargetOpValue - Return binary encoding of the jump -/// target operand. If the machine operand requires relocation, -/// record the relocation and return zero. -unsigned MipsMCCodeEmitter:: -getJumpTargetOpValue(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const { - const MCOperand &MO = MI.getOperand(OpNo); - // If the destination is an immediate, divide by 4. - if (MO.isImm()) return MO.getImm()>>2; - - assert(MO.isExpr() && - "getJumpTargetOpValue expects only expressions or an immediate"); - - const MCExpr *Expr = MO.getExpr(); - Fixups.push_back(MCFixup::create(0, Expr, - MCFixupKind(Mips::fixup_Mips_26))); - return 0; -} - -unsigned MipsMCCodeEmitter:: -getJumpTargetOpValueMM(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const { - const MCOperand &MO = MI.getOperand(OpNo); - // If the destination is an immediate, divide by 2. - if (MO.isImm()) return MO.getImm() >> 1; - - assert(MO.isExpr() && - "getJumpTargetOpValueMM expects only expressions or an immediate"); - - const MCExpr *Expr = MO.getExpr(); - Fixups.push_back(MCFixup::create(0, Expr, - MCFixupKind(Mips::fixup_MICROMIPS_26_S1))); - return 0; -} - -unsigned MipsMCCodeEmitter:: -getUImm5Lsl2Encoding(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const { - const MCOperand &MO = MI.getOperand(OpNo); - if (MO.isImm()) { - // The immediate is encoded as 'immediate << 2'. - unsigned Res = getMachineOpValue(MI, MO, Fixups, STI); - assert((Res & 3) == 0); - return Res >> 2; - } - - assert(MO.isExpr() && - "getUImm5Lsl2Encoding expects only expressions or an immediate"); - - return 0; -} - -unsigned MipsMCCodeEmitter:: -getSImm3Lsa2Value(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const { - const MCOperand &MO = MI.getOperand(OpNo); - if (MO.isImm()) { - int Value = MO.getImm(); - return Value >> 2; - } - - return 0; -} - -unsigned MipsMCCodeEmitter:: -getUImm6Lsl2Encoding(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const { - const MCOperand &MO = MI.getOperand(OpNo); - if (MO.isImm()) { - unsigned Value = MO.getImm(); - return Value >> 2; - } - - return 0; -} - -unsigned MipsMCCodeEmitter:: -getSImm9AddiuspValue(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const { - const MCOperand &MO = MI.getOperand(OpNo); - if (MO.isImm()) { - unsigned Binary = (MO.getImm() >> 2) & 0x0000ffff; - return (((Binary & 0x8000) >> 7) | (Binary & 0x00ff)); - } - - return 0; -} - -unsigned MipsMCCodeEmitter:: -getExprOpValue(const MCExpr *Expr, SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const { - int64_t Res; - - if (Expr->evaluateAsAbsolute(Res)) - return Res; - - MCExpr::ExprKind Kind = Expr->getKind(); - if (Kind == MCExpr::Constant) { - return cast<MCConstantExpr>(Expr)->getValue(); - } - - if (Kind == MCExpr::Binary) { - unsigned Res = getExprOpValue(cast<MCBinaryExpr>(Expr)->getLHS(), Fixups, STI); - Res += getExprOpValue(cast<MCBinaryExpr>(Expr)->getRHS(), Fixups, STI); - return Res; - } - - if (Kind == MCExpr::Target) { - const MipsMCExpr *MipsExpr = cast<MipsMCExpr>(Expr); - - Mips::Fixups FixupKind = Mips::Fixups(0); - switch (MipsExpr->getKind()) { - case MipsMCExpr::MEK_None: - case MipsMCExpr::MEK_Special: - llvm_unreachable("Unhandled fixup kind!"); - break; - case MipsMCExpr::MEK_DTPREL: - // MEK_DTPREL is used for marking TLS DIEExpr only - // and contains a regular sub-expression. - return getExprOpValue(MipsExpr->getSubExpr(), Fixups, STI); - case MipsMCExpr::MEK_CALL_HI16: - FixupKind = Mips::fixup_Mips_CALL_HI16; - break; - case MipsMCExpr::MEK_CALL_LO16: - FixupKind = Mips::fixup_Mips_CALL_LO16; - break; - case MipsMCExpr::MEK_DTPREL_HI: - FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_DTPREL_HI16 - : Mips::fixup_Mips_DTPREL_HI; - break; - case MipsMCExpr::MEK_DTPREL_LO: - FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_DTPREL_LO16 - : Mips::fixup_Mips_DTPREL_LO; - break; - case MipsMCExpr::MEK_GOTTPREL: - FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOTTPREL - : Mips::fixup_Mips_GOTTPREL; - break; - case MipsMCExpr::MEK_GOT: - FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT16 - : Mips::fixup_Mips_GOT; - break; - case MipsMCExpr::MEK_GOT_CALL: - FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_CALL16 - : Mips::fixup_Mips_CALL16; - break; - case MipsMCExpr::MEK_GOT_DISP: - FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_DISP - : Mips::fixup_Mips_GOT_DISP; - break; - case MipsMCExpr::MEK_GOT_HI16: - FixupKind = Mips::fixup_Mips_GOT_HI16; - break; - case MipsMCExpr::MEK_GOT_LO16: - FixupKind = Mips::fixup_Mips_GOT_LO16; - break; - case MipsMCExpr::MEK_GOT_PAGE: - FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_PAGE - : Mips::fixup_Mips_GOT_PAGE; - break; - case MipsMCExpr::MEK_GOT_OFST: - FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_OFST - : Mips::fixup_Mips_GOT_OFST; - break; - case MipsMCExpr::MEK_GPREL: - FixupKind = Mips::fixup_Mips_GPREL16; - break; - case MipsMCExpr::MEK_LO: - // Check for %lo(%neg(%gp_rel(X))) - if (MipsExpr->isGpOff()) - FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GPOFF_LO - : Mips::fixup_Mips_GPOFF_LO; - else - FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_LO16 - : Mips::fixup_Mips_LO16; - break; - case MipsMCExpr::MEK_HIGHEST: - FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_HIGHEST - : Mips::fixup_Mips_HIGHEST; - break; - case MipsMCExpr::MEK_HIGHER: - FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_HIGHER - : Mips::fixup_Mips_HIGHER; - break; - case MipsMCExpr::MEK_HI: - // Check for %hi(%neg(%gp_rel(X))) - if (MipsExpr->isGpOff()) - FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GPOFF_HI - : Mips::fixup_Mips_GPOFF_HI; - else - FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_HI16 - : Mips::fixup_Mips_HI16; - break; - case MipsMCExpr::MEK_PCREL_HI16: - FixupKind = Mips::fixup_MIPS_PCHI16; - break; - case MipsMCExpr::MEK_PCREL_LO16: - FixupKind = Mips::fixup_MIPS_PCLO16; - break; - case MipsMCExpr::MEK_TLSGD: - FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_GD - : Mips::fixup_Mips_TLSGD; - break; - case MipsMCExpr::MEK_TLSLDM: - FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_LDM - : Mips::fixup_Mips_TLSLDM; - break; - case MipsMCExpr::MEK_TPREL_HI: - FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_TPREL_HI16 - : Mips::fixup_Mips_TPREL_HI; - break; - case MipsMCExpr::MEK_TPREL_LO: - FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_TPREL_LO16 - : Mips::fixup_Mips_TPREL_LO; - break; - case MipsMCExpr::MEK_NEG: - FixupKind = - isMicroMips(STI) ? Mips::fixup_MICROMIPS_SUB : Mips::fixup_Mips_SUB; - break; - } - Fixups.push_back(MCFixup::create(0, MipsExpr, MCFixupKind(FixupKind))); - return 0; - } - - if (Kind == MCExpr::SymbolRef) { - Mips::Fixups FixupKind = Mips::Fixups(0); - - switch(cast<MCSymbolRefExpr>(Expr)->getKind()) { - default: llvm_unreachable("Unknown fixup kind!"); - break; - case MCSymbolRefExpr::VK_None: - FixupKind = Mips::fixup_Mips_32; // FIXME: This is ok for O32/N32 but not N64. - break; - } // switch - - Fixups.push_back(MCFixup::create(0, Expr, MCFixupKind(FixupKind))); - return 0; - } - return 0; -} - -/// getMachineOpValue - Return binary encoding of operand. If the machine -/// operand requires relocation, record the relocation and return zero. -unsigned MipsMCCodeEmitter:: -getMachineOpValue(const MCInst &MI, const MCOperand &MO, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const { - if (MO.isReg()) { - unsigned Reg = MO.getReg(); - unsigned RegNo = Ctx.getRegisterInfo()->getEncodingValue(Reg); - return RegNo; - } else if (MO.isImm()) { - return static_cast<unsigned>(MO.getImm()); - } else if (MO.isFPImm()) { - return static_cast<unsigned>(APFloat(MO.getFPImm()) - .bitcastToAPInt().getHiBits(32).getLimitedValue()); - } - // MO must be an Expr. - assert(MO.isExpr()); - return getExprOpValue(MO.getExpr(),Fixups, STI); -} - -/// Return binary encoding of memory related operand. -/// If the offset operand requires relocation, record the relocation. -template <unsigned ShiftAmount> -unsigned MipsMCCodeEmitter::getMemEncoding(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const { - // Base register is encoded in bits 20-16, offset is encoded in bits 15-0. - assert(MI.getOperand(OpNo).isReg()); - unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),Fixups, STI) << 16; - unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI); - - // Apply the scale factor if there is one. - OffBits >>= ShiftAmount; - - return (OffBits & 0xFFFF) | RegBits; -} - -unsigned MipsMCCodeEmitter:: -getMemEncodingMMImm4(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const { - // Base register is encoded in bits 6-4, offset is encoded in bits 3-0. - assert(MI.getOperand(OpNo).isReg()); - unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), - Fixups, STI) << 4; - unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), - Fixups, STI); - - return (OffBits & 0xF) | RegBits; -} - -unsigned MipsMCCodeEmitter:: -getMemEncodingMMImm4Lsl1(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const { - // Base register is encoded in bits 6-4, offset is encoded in bits 3-0. - assert(MI.getOperand(OpNo).isReg()); - unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), - Fixups, STI) << 4; - unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), - Fixups, STI) >> 1; - - return (OffBits & 0xF) | RegBits; -} - -unsigned MipsMCCodeEmitter:: -getMemEncodingMMImm4Lsl2(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const { - // Base register is encoded in bits 6-4, offset is encoded in bits 3-0. - assert(MI.getOperand(OpNo).isReg()); - unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), - Fixups, STI) << 4; - unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), - Fixups, STI) >> 2; - - return (OffBits & 0xF) | RegBits; -} - -unsigned MipsMCCodeEmitter:: -getMemEncodingMMSPImm5Lsl2(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const { - // Register is encoded in bits 9-5, offset is encoded in bits 4-0. - assert(MI.getOperand(OpNo).isReg() && - (MI.getOperand(OpNo).getReg() == Mips::SP || - MI.getOperand(OpNo).getReg() == Mips::SP_64) && - "Unexpected base register!"); - unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), - Fixups, STI) >> 2; - - return OffBits & 0x1F; -} - -unsigned MipsMCCodeEmitter:: -getMemEncodingMMGPImm7Lsl2(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const { - // Register is encoded in bits 9-7, offset is encoded in bits 6-0. - assert(MI.getOperand(OpNo).isReg() && - MI.getOperand(OpNo).getReg() == Mips::GP && - "Unexpected base register!"); - - unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), - Fixups, STI) >> 2; - - return OffBits & 0x7F; -} - -unsigned MipsMCCodeEmitter:: -getMemEncodingMMImm9(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const { - // Base register is encoded in bits 20-16, offset is encoded in bits 8-0. - assert(MI.getOperand(OpNo).isReg()); - unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, - STI) << 16; - unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo + 1), Fixups, STI); - - return (OffBits & 0x1FF) | RegBits; -} - -unsigned MipsMCCodeEmitter:: -getMemEncodingMMImm11(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const { - // Base register is encoded in bits 20-16, offset is encoded in bits 10-0. - assert(MI.getOperand(OpNo).isReg()); - unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, - STI) << 16; - unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI); - - return (OffBits & 0x07FF) | RegBits; -} - -unsigned MipsMCCodeEmitter:: -getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const { - // opNum can be invalid if instruction had reglist as operand. - // MemOperand is always last operand of instruction (base + offset). - switch (MI.getOpcode()) { - default: - break; - case Mips::SWM32_MM: - case Mips::LWM32_MM: - OpNo = MI.getNumOperands() - 2; - break; - } - - // Base register is encoded in bits 20-16, offset is encoded in bits 11-0. - assert(MI.getOperand(OpNo).isReg()); - unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI) << 16; - unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI); - - return (OffBits & 0x0FFF) | RegBits; -} - -unsigned MipsMCCodeEmitter:: -getMemEncodingMMImm16(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const { - // Base register is encoded in bits 20-16, offset is encoded in bits 15-0. - assert(MI.getOperand(OpNo).isReg()); - unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, - STI) << 16; - unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI); - - return (OffBits & 0xFFFF) | RegBits; -} - -unsigned MipsMCCodeEmitter:: -getMemEncodingMMImm4sp(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const { - // opNum can be invalid if instruction had reglist as operand - // MemOperand is always last operand of instruction (base + offset) - switch (MI.getOpcode()) { - default: - break; - case Mips::SWM16_MM: - case Mips::SWM16_MMR6: - case Mips::LWM16_MM: - case Mips::LWM16_MMR6: - OpNo = MI.getNumOperands() - 2; - break; - } - - // Offset is encoded in bits 4-0. - assert(MI.getOperand(OpNo).isReg()); - // Base register is always SP - thus it is not encoded. - assert(MI.getOperand(OpNo+1).isImm()); - unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI); - - return ((OffBits >> 2) & 0x0F); -} - -// FIXME: should be called getMSBEncoding -// -unsigned -MipsMCCodeEmitter::getSizeInsEncoding(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const { - assert(MI.getOperand(OpNo-1).isImm()); - assert(MI.getOperand(OpNo).isImm()); - unsigned Position = getMachineOpValue(MI, MI.getOperand(OpNo-1), Fixups, STI); - unsigned Size = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI); - - return Position + Size - 1; -} - -template <unsigned Bits, int Offset> -unsigned -MipsMCCodeEmitter::getUImmWithOffsetEncoding(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const { - assert(MI.getOperand(OpNo).isImm()); - unsigned Value = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI); - Value -= Offset; - return Value; -} - -unsigned -MipsMCCodeEmitter::getSimm19Lsl2Encoding(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const { - const MCOperand &MO = MI.getOperand(OpNo); - if (MO.isImm()) { - // The immediate is encoded as 'immediate << 2'. - unsigned Res = getMachineOpValue(MI, MO, Fixups, STI); - assert((Res & 3) == 0); - return Res >> 2; - } - - assert(MO.isExpr() && - "getSimm19Lsl2Encoding expects only expressions or an immediate"); - - const MCExpr *Expr = MO.getExpr(); - Mips::Fixups FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_PC19_S2 - : Mips::fixup_MIPS_PC19_S2; - Fixups.push_back(MCFixup::create(0, Expr, MCFixupKind(FixupKind))); - return 0; -} - -unsigned -MipsMCCodeEmitter::getSimm18Lsl3Encoding(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const { - const MCOperand &MO = MI.getOperand(OpNo); - if (MO.isImm()) { - // The immediate is encoded as 'immediate << 3'. - unsigned Res = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI); - assert((Res & 7) == 0); - return Res >> 3; - } - - assert(MO.isExpr() && - "getSimm18Lsl2Encoding expects only expressions or an immediate"); - - const MCExpr *Expr = MO.getExpr(); - Mips::Fixups FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_PC18_S3 - : Mips::fixup_MIPS_PC18_S3; - Fixups.push_back(MCFixup::create(0, Expr, MCFixupKind(FixupKind))); - return 0; -} - -unsigned -MipsMCCodeEmitter::getUImm3Mod8Encoding(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const { - assert(MI.getOperand(OpNo).isImm()); - const MCOperand &MO = MI.getOperand(OpNo); - return MO.getImm() % 8; -} - -unsigned -MipsMCCodeEmitter::getUImm4AndValue(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const { - assert(MI.getOperand(OpNo).isImm()); - const MCOperand &MO = MI.getOperand(OpNo); - unsigned Value = MO.getImm(); - switch (Value) { - case 128: return 0x0; - case 1: return 0x1; - case 2: return 0x2; - case 3: return 0x3; - case 4: return 0x4; - case 7: return 0x5; - case 8: return 0x6; - case 15: return 0x7; - case 16: return 0x8; - case 31: return 0x9; - case 32: return 0xa; - case 63: return 0xb; - case 64: return 0xc; - case 255: return 0xd; - case 32768: return 0xe; - case 65535: return 0xf; - } - llvm_unreachable("Unexpected value"); -} - -unsigned -MipsMCCodeEmitter::getRegisterListOpValue(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const { - unsigned res = 0; - - // Register list operand is always first operand of instruction and it is - // placed before memory operand (register + imm). - - for (unsigned I = OpNo, E = MI.getNumOperands() - 2; I < E; ++I) { - unsigned Reg = MI.getOperand(I).getReg(); - unsigned RegNo = Ctx.getRegisterInfo()->getEncodingValue(Reg); - if (RegNo != 31) - res++; - else - res |= 0x10; - } - return res; -} - -unsigned -MipsMCCodeEmitter::getRegisterListOpValue16(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const { - return (MI.getNumOperands() - 4); -} - -unsigned -MipsMCCodeEmitter::getMovePRegPairOpValue(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const { - unsigned res = 0; - - if (MI.getOperand(0).getReg() == Mips::A1 && - MI.getOperand(1).getReg() == Mips::A2) - res = 0; - else if (MI.getOperand(0).getReg() == Mips::A1 && - MI.getOperand(1).getReg() == Mips::A3) - res = 1; - else if (MI.getOperand(0).getReg() == Mips::A2 && - MI.getOperand(1).getReg() == Mips::A3) - res = 2; - else if (MI.getOperand(0).getReg() == Mips::A0 && - MI.getOperand(1).getReg() == Mips::S5) - res = 3; - else if (MI.getOperand(0).getReg() == Mips::A0 && - MI.getOperand(1).getReg() == Mips::S6) - res = 4; - else if (MI.getOperand(0).getReg() == Mips::A0 && - MI.getOperand(1).getReg() == Mips::A1) - res = 5; - else if (MI.getOperand(0).getReg() == Mips::A0 && - MI.getOperand(1).getReg() == Mips::A2) - res = 6; - else if (MI.getOperand(0).getReg() == Mips::A0 && - MI.getOperand(1).getReg() == Mips::A3) - res = 7; - - return res; -} - -unsigned -MipsMCCodeEmitter::getMovePRegSingleOpValue(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const { - assert(((OpNo == 2) || (OpNo == 3)) && - "Unexpected OpNo for movep operand encoding!"); - - MCOperand Op = MI.getOperand(OpNo); - assert(Op.isReg() && "Operand of movep is not a register!"); - switch (Op.getReg()) { - default: - llvm_unreachable("Unknown register for movep!"); - case Mips::ZERO: return 0; - case Mips::S1: return 1; - case Mips::V0: return 2; - case Mips::V1: return 3; - case Mips::S0: return 4; - case Mips::S2: return 5; - case Mips::S3: return 6; - case Mips::S4: return 7; - } -} - -unsigned -MipsMCCodeEmitter::getSimm23Lsl2Encoding(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const { - const MCOperand &MO = MI.getOperand(OpNo); - assert(MO.isImm() && "getSimm23Lsl2Encoding expects only an immediate"); - // The immediate is encoded as 'immediate >> 2'. - unsigned Res = static_cast<unsigned>(MO.getImm()); - assert((Res & 3) == 0); - return Res >> 2; -} - -#include "MipsGenMCCodeEmitter.inc" diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h deleted file mode 100644 index ff6e1d62b05f..000000000000 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h +++ /dev/null @@ -1,275 +0,0 @@ -//===- MipsMCCodeEmitter.h - Convert Mips Code to Machine Code --*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the MipsMCCodeEmitter class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSMCCODEEMITTER_H -#define LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSMCCODEEMITTER_H - -#include "llvm/MC/MCCodeEmitter.h" -#include <cstdint> - -namespace llvm { - -class MCContext; -class MCExpr; -class MCFixup; -class MCInst; -class MCInstrInfo; -class MCOperand; -class MCSubtargetInfo; -class raw_ostream; - -class MipsMCCodeEmitter : public MCCodeEmitter { - const MCInstrInfo &MCII; - MCContext &Ctx; - bool IsLittleEndian; - - bool isMicroMips(const MCSubtargetInfo &STI) const; - bool isMips32r6(const MCSubtargetInfo &STI) const; - -public: - MipsMCCodeEmitter(const MCInstrInfo &mcii, MCContext &Ctx_, bool IsLittle) - : MCII(mcii), Ctx(Ctx_), IsLittleEndian(IsLittle) {} - MipsMCCodeEmitter(const MipsMCCodeEmitter &) = delete; - MipsMCCodeEmitter &operator=(const MipsMCCodeEmitter &) = delete; - ~MipsMCCodeEmitter() override = default; - - void EmitByte(unsigned char C, raw_ostream &OS) const; - - void EmitInstruction(uint64_t Val, unsigned Size, const MCSubtargetInfo &STI, - raw_ostream &OS) const; - - void encodeInstruction(const MCInst &MI, raw_ostream &OS, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const override; - - // getBinaryCodeForInstr - TableGen'erated function for getting the - // binary encoding for an instruction. - uint64_t getBinaryCodeForInstr(const MCInst &MI, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const; - - // getJumpTargetOpValue - Return binary encoding of the jump - // target operand. If the machine operand requires relocation, - // record the relocation and return zero. - unsigned getJumpTargetOpValue(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const; - - // getBranchJumpOpValueMM - Return binary encoding of the microMIPS jump - // target operand. If the machine operand requires relocation, - // record the relocation and return zero. - unsigned getJumpTargetOpValueMM(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const; - - // getUImm5Lsl2Encoding - Return binary encoding of the microMIPS jump - // target operand. - unsigned getUImm5Lsl2Encoding(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const; - - unsigned getSImm3Lsa2Value(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const; - - unsigned getUImm6Lsl2Encoding(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const; - - // getSImm9AddiuspValue - Return binary encoding of the microMIPS addiusp - // instruction immediate operand. - unsigned getSImm9AddiuspValue(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const; - - // getBranchTargetOpValue - Return binary encoding of the branch - // target operand. If the machine operand requires relocation, - // record the relocation and return zero. - unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const; - - // getBranchTargetOpValue1SImm16 - Return binary encoding of the branch - // target operand. If the machine operand requires relocation, - // record the relocation and return zero. - unsigned getBranchTargetOpValue1SImm16(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const; - - // getBranchTargetOpValueMMR6 - Return binary encoding of the branch - // target operand. If the machine operand requires relocation, - // record the relocation and return zero. - unsigned getBranchTargetOpValueMMR6(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const; - - // getBranchTargetOpValueLsl2MMR6 - Return binary encoding of the branch - // target operand. If the machine operand requires relocation, - // record the relocation and return zero. - unsigned getBranchTargetOpValueLsl2MMR6(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const; - - // getBranchTarget7OpValue - Return binary encoding of the microMIPS branch - // target operand. If the machine operand requires relocation, - // record the relocation and return zero. - unsigned getBranchTarget7OpValueMM(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const; - - // getBranchTargetOpValueMMPC10 - Return binary encoding of the microMIPS - // 10-bit branch target operand. If the machine operand requires relocation, - // record the relocation and return zero. - unsigned getBranchTargetOpValueMMPC10(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const; - - // getBranchTargetOpValue - Return binary encoding of the microMIPS branch - // target operand. If the machine operand requires relocation, - // record the relocation and return zero. - unsigned getBranchTargetOpValueMM(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const; - - // getBranchTarget21OpValue - Return binary encoding of the branch - // offset operand. If the machine operand requires relocation, - // record the relocation and return zero. - unsigned getBranchTarget21OpValue(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const; - - // getBranchTarget21OpValueMM - Return binary encoding of the branch - // offset operand for microMIPS. If the machine operand requires - // relocation,record the relocation and return zero. - unsigned getBranchTarget21OpValueMM(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const; - - // getBranchTarget26OpValue - Return binary encoding of the branch - // offset operand. If the machine operand requires relocation, - // record the relocation and return zero. - unsigned getBranchTarget26OpValue(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const; - - // getBranchTarget26OpValueMM - Return binary encoding of the branch - // offset operand. If the machine operand requires relocation, - // record the relocation and return zero. - unsigned getBranchTarget26OpValueMM(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const; - - // getJumpOffset16OpValue - Return binary encoding of the jump - // offset operand. If the machine operand requires relocation, - // record the relocation and return zero. - unsigned getJumpOffset16OpValue(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const; - - // getMachineOpValue - Return binary encoding of operand. If the machin - // operand requires relocation, record the relocation and return zero. - unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const; - - unsigned getMSAMemEncoding(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const; - - template <unsigned ShiftAmount = 0> - unsigned getMemEncoding(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const; - unsigned getMemEncodingMMImm4(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const; - unsigned getMemEncodingMMImm4Lsl1(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const; - unsigned getMemEncodingMMImm4Lsl2(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const; - unsigned getMemEncodingMMSPImm5Lsl2(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const; - unsigned getMemEncodingMMGPImm7Lsl2(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const; - unsigned getMemEncodingMMImm9(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const; - unsigned getMemEncodingMMImm11(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const; - unsigned getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const; - unsigned getMemEncodingMMImm16(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const; - unsigned getMemEncodingMMImm4sp(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const; - unsigned getSizeInsEncoding(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const; - - /// Subtract Offset then encode as a N-bit unsigned integer. - template <unsigned Bits, int Offset> - unsigned getUImmWithOffsetEncoding(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const; - - unsigned getSimm19Lsl2Encoding(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const; - - unsigned getSimm18Lsl3Encoding(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const; - - unsigned getUImm3Mod8Encoding(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const; - unsigned getUImm4AndValue(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const; - - unsigned getMovePRegPairOpValue(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const; - unsigned getMovePRegSingleOpValue(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const; - - unsigned getSimm23Lsl2Encoding(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const; - - unsigned getExprOpValue(const MCExpr *Expr, SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const; - - unsigned getRegisterListOpValue(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const; - - unsigned getRegisterListOpValue16(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const; - -private: - void LowerCompactBranch(MCInst& Inst) const; -}; - -} // end namespace llvm - -#endif // LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSMCCODEEMITTER_H diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp deleted file mode 100644 index 680806c4deb2..000000000000 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp +++ /dev/null @@ -1,302 +0,0 @@ -//===-- MipsMCExpr.cpp - Mips specific MC expression classes --------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "MipsMCExpr.h" -#include "llvm/BinaryFormat/ELF.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCAssembler.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCStreamer.h" -#include "llvm/MC/MCSymbolELF.h" -#include "llvm/MC/MCValue.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/raw_ostream.h" -#include <cstdint> - -using namespace llvm; - -#define DEBUG_TYPE "mipsmcexpr" - -const MipsMCExpr *MipsMCExpr::create(MipsMCExpr::MipsExprKind Kind, - const MCExpr *Expr, MCContext &Ctx) { - return new (Ctx) MipsMCExpr(Kind, Expr); -} - -const MipsMCExpr *MipsMCExpr::createGpOff(MipsMCExpr::MipsExprKind Kind, - const MCExpr *Expr, MCContext &Ctx) { - return create(Kind, create(MEK_NEG, create(MEK_GPREL, Expr, Ctx), Ctx), Ctx); -} - -void MipsMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const { - int64_t AbsVal; - - switch (Kind) { - case MEK_None: - case MEK_Special: - llvm_unreachable("MEK_None and MEK_Special are invalid"); - break; - case MEK_DTPREL: - // MEK_DTPREL is used for marking TLS DIEExpr only - // and contains a regular sub-expression. - getSubExpr()->print(OS, MAI, true); - return; - case MEK_CALL_HI16: - OS << "%call_hi"; - break; - case MEK_CALL_LO16: - OS << "%call_lo"; - break; - case MEK_DTPREL_HI: - OS << "%dtprel_hi"; - break; - case MEK_DTPREL_LO: - OS << "%dtprel_lo"; - break; - case MEK_GOT: - OS << "%got"; - break; - case MEK_GOTTPREL: - OS << "%gottprel"; - break; - case MEK_GOT_CALL: - OS << "%call16"; - break; - case MEK_GOT_DISP: - OS << "%got_disp"; - break; - case MEK_GOT_HI16: - OS << "%got_hi"; - break; - case MEK_GOT_LO16: - OS << "%got_lo"; - break; - case MEK_GOT_PAGE: - OS << "%got_page"; - break; - case MEK_GOT_OFST: - OS << "%got_ofst"; - break; - case MEK_GPREL: - OS << "%gp_rel"; - break; - case MEK_HI: - OS << "%hi"; - break; - case MEK_HIGHER: - OS << "%higher"; - break; - case MEK_HIGHEST: - OS << "%highest"; - break; - case MEK_LO: - OS << "%lo"; - break; - case MEK_NEG: - OS << "%neg"; - break; - case MEK_PCREL_HI16: - OS << "%pcrel_hi"; - break; - case MEK_PCREL_LO16: - OS << "%pcrel_lo"; - break; - case MEK_TLSGD: - OS << "%tlsgd"; - break; - case MEK_TLSLDM: - OS << "%tlsldm"; - break; - case MEK_TPREL_HI: - OS << "%tprel_hi"; - break; - case MEK_TPREL_LO: - OS << "%tprel_lo"; - break; - } - - OS << '('; - if (Expr->evaluateAsAbsolute(AbsVal)) - OS << AbsVal; - else - Expr->print(OS, MAI, true); - OS << ')'; -} - -bool -MipsMCExpr::evaluateAsRelocatableImpl(MCValue &Res, - const MCAsmLayout *Layout, - const MCFixup *Fixup) const { - // Look for the %hi(%neg(%gp_rel(X))) and %lo(%neg(%gp_rel(X))) special cases. - if (isGpOff()) { - const MCExpr *SubExpr = - cast<MipsMCExpr>(cast<MipsMCExpr>(getSubExpr())->getSubExpr()) - ->getSubExpr(); - if (!SubExpr->evaluateAsRelocatable(Res, Layout, Fixup)) - return false; - - Res = MCValue::get(Res.getSymA(), Res.getSymB(), Res.getConstant(), - MEK_Special); - return true; - } - - if (!getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup)) - return false; - - if (Res.getRefKind() != MCSymbolRefExpr::VK_None) - return false; - - // evaluateAsAbsolute() and evaluateAsValue() require that we evaluate the - // %hi/%lo/etc. here. Fixup is a null pointer when either of these is the - // caller. - if (Res.isAbsolute() && Fixup == nullptr) { - int64_t AbsVal = Res.getConstant(); - switch (Kind) { - case MEK_None: - case MEK_Special: - llvm_unreachable("MEK_None and MEK_Special are invalid"); - case MEK_DTPREL: - // MEK_DTPREL is used for marking TLS DIEExpr only - // and contains a regular sub-expression. - return getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup); - case MEK_DTPREL_HI: - case MEK_DTPREL_LO: - case MEK_GOT: - case MEK_GOTTPREL: - case MEK_GOT_CALL: - case MEK_GOT_DISP: - case MEK_GOT_HI16: - case MEK_GOT_LO16: - case MEK_GOT_OFST: - case MEK_GOT_PAGE: - case MEK_GPREL: - case MEK_PCREL_HI16: - case MEK_PCREL_LO16: - case MEK_TLSGD: - case MEK_TLSLDM: - case MEK_TPREL_HI: - case MEK_TPREL_LO: - return false; - case MEK_LO: - case MEK_CALL_LO16: - AbsVal = SignExtend64<16>(AbsVal); - break; - case MEK_CALL_HI16: - case MEK_HI: - AbsVal = SignExtend64<16>((AbsVal + 0x8000) >> 16); - break; - case MEK_HIGHER: - AbsVal = SignExtend64<16>((AbsVal + 0x80008000LL) >> 32); - break; - case MEK_HIGHEST: - AbsVal = SignExtend64<16>((AbsVal + 0x800080008000LL) >> 48); - break; - case MEK_NEG: - AbsVal = -AbsVal; - break; - } - Res = MCValue::get(AbsVal); - return true; - } - - // We want to defer it for relocatable expressions since the constant is - // applied to the whole symbol value. - // - // The value of getKind() that is given to MCValue is only intended to aid - // debugging when inspecting MCValue objects. It shouldn't be relied upon - // for decision making. - Res = MCValue::get(Res.getSymA(), Res.getSymB(), Res.getConstant(), getKind()); - - return true; -} - -void MipsMCExpr::visitUsedExpr(MCStreamer &Streamer) const { - Streamer.visitUsedExpr(*getSubExpr()); -} - -static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) { - switch (Expr->getKind()) { - case MCExpr::Target: - fixELFSymbolsInTLSFixupsImpl(cast<MipsMCExpr>(Expr)->getSubExpr(), Asm); - break; - case MCExpr::Constant: - break; - case MCExpr::Binary: { - const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr); - fixELFSymbolsInTLSFixupsImpl(BE->getLHS(), Asm); - fixELFSymbolsInTLSFixupsImpl(BE->getRHS(), Asm); - break; - } - case MCExpr::SymbolRef: { - // We're known to be under a TLS fixup, so any symbol should be - // modified. There should be only one. - const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr); - cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS); - break; - } - case MCExpr::Unary: - fixELFSymbolsInTLSFixupsImpl(cast<MCUnaryExpr>(Expr)->getSubExpr(), Asm); - break; - } -} - -void MipsMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const { - switch (getKind()) { - case MEK_None: - case MEK_Special: - llvm_unreachable("MEK_None and MEK_Special are invalid"); - break; - case MEK_CALL_HI16: - case MEK_CALL_LO16: - case MEK_GOT: - case MEK_GOT_CALL: - case MEK_GOT_DISP: - case MEK_GOT_HI16: - case MEK_GOT_LO16: - case MEK_GOT_OFST: - case MEK_GOT_PAGE: - case MEK_GPREL: - case MEK_HI: - case MEK_HIGHER: - case MEK_HIGHEST: - case MEK_LO: - case MEK_NEG: - case MEK_PCREL_HI16: - case MEK_PCREL_LO16: - // If we do have nested target-specific expressions, they will be in - // a consecutive chain. - if (const MipsMCExpr *E = dyn_cast<const MipsMCExpr>(getSubExpr())) - E->fixELFSymbolsInTLSFixups(Asm); - break; - case MEK_DTPREL: - case MEK_DTPREL_HI: - case MEK_DTPREL_LO: - case MEK_TLSLDM: - case MEK_TLSGD: - case MEK_GOTTPREL: - case MEK_TPREL_HI: - case MEK_TPREL_LO: - fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm); - break; - } -} - -bool MipsMCExpr::isGpOff(MipsExprKind &Kind) const { - if (getKind() == MEK_HI || getKind() == MEK_LO) { - if (const MipsMCExpr *S1 = dyn_cast<const MipsMCExpr>(getSubExpr())) { - if (const MipsMCExpr *S2 = dyn_cast<const MipsMCExpr>(S1->getSubExpr())) { - if (S1->getKind() == MEK_NEG && S2->getKind() == MEK_GPREL) { - Kind = getKind(); - return true; - } - } - } - } - return false; -} diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.h b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.h deleted file mode 100644 index edc12e87e9b6..000000000000 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.h +++ /dev/null @@ -1,93 +0,0 @@ -//===- MipsMCExpr.h - Mips specific MC expression classes -------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSMCEXPR_H -#define LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSMCEXPR_H - -#include "llvm/MC/MCAsmLayout.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCValue.h" - -namespace llvm { - -class MipsMCExpr : public MCTargetExpr { -public: - enum MipsExprKind { - MEK_None, - MEK_CALL_HI16, - MEK_CALL_LO16, - MEK_DTPREL, - MEK_DTPREL_HI, - MEK_DTPREL_LO, - MEK_GOT, - MEK_GOTTPREL, - MEK_GOT_CALL, - MEK_GOT_DISP, - MEK_GOT_HI16, - MEK_GOT_LO16, - MEK_GOT_OFST, - MEK_GOT_PAGE, - MEK_GPREL, - MEK_HI, - MEK_HIGHER, - MEK_HIGHEST, - MEK_LO, - MEK_NEG, - MEK_PCREL_HI16, - MEK_PCREL_LO16, - MEK_TLSGD, - MEK_TLSLDM, - MEK_TPREL_HI, - MEK_TPREL_LO, - MEK_Special, - }; - -private: - const MipsExprKind Kind; - const MCExpr *Expr; - - explicit MipsMCExpr(MipsExprKind Kind, const MCExpr *Expr) - : Kind(Kind), Expr(Expr) {} - -public: - static const MipsMCExpr *create(MipsExprKind Kind, const MCExpr *Expr, - MCContext &Ctx); - static const MipsMCExpr *createGpOff(MipsExprKind Kind, const MCExpr *Expr, - MCContext &Ctx); - - /// Get the kind of this expression. - MipsExprKind getKind() const { return Kind; } - - /// Get the child of this expression. - const MCExpr *getSubExpr() const { return Expr; } - - void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override; - bool evaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout, - const MCFixup *Fixup) const override; - void visitUsedExpr(MCStreamer &Streamer) const override; - - MCFragment *findAssociatedFragment() const override { - return getSubExpr()->findAssociatedFragment(); - } - - void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const override; - - static bool classof(const MCExpr *E) { - return E->getKind() == MCExpr::Target; - } - - bool isGpOff(MipsExprKind &Kind) const; - bool isGpOff() const { - MipsExprKind Kind; - return isGpOff(Kind); - } -}; - -} // end namespace llvm - -#endif // LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSMCEXPR_H diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCNaCl.h b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCNaCl.h deleted file mode 100644 index ad5aff6552f6..000000000000 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCNaCl.h +++ /dev/null @@ -1,31 +0,0 @@ -//===-- MipsMCNaCl.h - NaCl-related declarations --------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSMCNACL_H -#define LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSMCNACL_H - -#include "llvm/MC/MCELFStreamer.h" - -namespace llvm { - -// Log2 of the NaCl MIPS sandbox's instruction bundle size. -static const unsigned MIPS_NACL_BUNDLE_ALIGN = 4u; - -bool isBasePlusOffsetMemoryAccess(unsigned Opcode, unsigned *AddrIdx, - bool *IsStore = nullptr); -bool baseRegNeedsLoadStoreMask(unsigned Reg); - -// This function creates an MCELFStreamer for Mips NaCl. -MCELFStreamer *createMipsNaClELFStreamer(MCContext &Context, - std::unique_ptr<MCAsmBackend> TAB, - std::unique_ptr<MCObjectWriter> OW, - std::unique_ptr<MCCodeEmitter> Emitter, - bool RelaxAll); -} - -#endif diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp deleted file mode 100644 index ddeec03ba784..000000000000 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp +++ /dev/null @@ -1,208 +0,0 @@ -//===-- MipsMCTargetDesc.cpp - Mips Target Descriptions -------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file provides Mips specific target descriptions. -// -//===----------------------------------------------------------------------===// - -#include "MipsMCTargetDesc.h" -#include "MipsAsmBackend.h" -#include "MipsELFStreamer.h" -#include "MipsInstPrinter.h" -#include "MipsMCAsmInfo.h" -#include "MipsMCNaCl.h" -#include "MipsTargetStreamer.h" -#include "TargetInfo/MipsTargetInfo.h" -#include "llvm/ADT/Triple.h" -#include "llvm/MC/MCCodeEmitter.h" -#include "llvm/MC/MCELFStreamer.h" -#include "llvm/MC/MCInstrAnalysis.h" -#include "llvm/MC/MCInstrInfo.h" -#include "llvm/MC/MCObjectWriter.h" -#include "llvm/MC/MCRegisterInfo.h" -#include "llvm/MC/MCSubtargetInfo.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/MC/MachineLocation.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/FormattedStream.h" -#include "llvm/Support/TargetRegistry.h" - -using namespace llvm; - -#define GET_INSTRINFO_MC_DESC -#include "MipsGenInstrInfo.inc" - -#define GET_SUBTARGETINFO_MC_DESC -#include "MipsGenSubtargetInfo.inc" - -#define GET_REGINFO_MC_DESC -#include "MipsGenRegisterInfo.inc" - -/// Select the Mips CPU for the given triple and cpu name. -/// FIXME: Merge with the copy in MipsSubtarget.cpp -StringRef MIPS_MC::selectMipsCPU(const Triple &TT, StringRef CPU) { - if (CPU.empty() || CPU == "generic") { - if (TT.getSubArch() == llvm::Triple::MipsSubArch_r6) { - if (TT.isMIPS32()) - CPU = "mips32r6"; - else - CPU = "mips64r6"; - } else { - if (TT.isMIPS32()) - CPU = "mips32"; - else - CPU = "mips64"; - } - } - return CPU; -} - -static MCInstrInfo *createMipsMCInstrInfo() { - MCInstrInfo *X = new MCInstrInfo(); - InitMipsMCInstrInfo(X); - return X; -} - -static MCRegisterInfo *createMipsMCRegisterInfo(const Triple &TT) { - MCRegisterInfo *X = new MCRegisterInfo(); - InitMipsMCRegisterInfo(X, Mips::RA); - return X; -} - -static MCSubtargetInfo *createMipsMCSubtargetInfo(const Triple &TT, - StringRef CPU, StringRef FS) { - CPU = MIPS_MC::selectMipsCPU(TT, CPU); - return createMipsMCSubtargetInfoImpl(TT, CPU, FS); -} - -static MCAsmInfo *createMipsMCAsmInfo(const MCRegisterInfo &MRI, - const Triple &TT) { - MCAsmInfo *MAI = new MipsMCAsmInfo(TT); - - unsigned SP = MRI.getDwarfRegNum(Mips::SP, true); - MCCFIInstruction Inst = MCCFIInstruction::createDefCfaRegister(nullptr, SP); - MAI->addInitialFrameState(Inst); - - return MAI; -} - -static MCInstPrinter *createMipsMCInstPrinter(const Triple &T, - unsigned SyntaxVariant, - const MCAsmInfo &MAI, - const MCInstrInfo &MII, - const MCRegisterInfo &MRI) { - return new MipsInstPrinter(MAI, MII, MRI); -} - -static MCStreamer *createMCStreamer(const Triple &T, MCContext &Context, - std::unique_ptr<MCAsmBackend> &&MAB, - std::unique_ptr<MCObjectWriter> &&OW, - std::unique_ptr<MCCodeEmitter> &&Emitter, - bool RelaxAll) { - MCStreamer *S; - if (!T.isOSNaCl()) - S = createMipsELFStreamer(Context, std::move(MAB), std::move(OW), - std::move(Emitter), RelaxAll); - else - S = createMipsNaClELFStreamer(Context, std::move(MAB), std::move(OW), - std::move(Emitter), RelaxAll); - return S; -} - -static MCTargetStreamer *createMipsAsmTargetStreamer(MCStreamer &S, - formatted_raw_ostream &OS, - MCInstPrinter *InstPrint, - bool isVerboseAsm) { - return new MipsTargetAsmStreamer(S, OS); -} - -static MCTargetStreamer *createMipsNullTargetStreamer(MCStreamer &S) { - return new MipsTargetStreamer(S); -} - -static MCTargetStreamer * -createMipsObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) { - return new MipsTargetELFStreamer(S, STI); -} - -namespace { - -class MipsMCInstrAnalysis : public MCInstrAnalysis { -public: - MipsMCInstrAnalysis(const MCInstrInfo *Info) : MCInstrAnalysis(Info) {} - - bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size, - uint64_t &Target) const override { - unsigned NumOps = Inst.getNumOperands(); - if (NumOps == 0) - return false; - switch (Info->get(Inst.getOpcode()).OpInfo[NumOps - 1].OperandType) { - case MCOI::OPERAND_UNKNOWN: - case MCOI::OPERAND_IMMEDIATE: - // jal, bal ... - Target = Inst.getOperand(NumOps - 1).getImm(); - return true; - case MCOI::OPERAND_PCREL: - // b, j, beq ... - Target = Addr + Inst.getOperand(NumOps - 1).getImm(); - return true; - default: - return false; - } - } -}; -} - -static MCInstrAnalysis *createMipsMCInstrAnalysis(const MCInstrInfo *Info) { - return new MipsMCInstrAnalysis(Info); -} - -extern "C" void LLVMInitializeMipsTargetMC() { - for (Target *T : {&getTheMipsTarget(), &getTheMipselTarget(), - &getTheMips64Target(), &getTheMips64elTarget()}) { - // Register the MC asm info. - RegisterMCAsmInfoFn X(*T, createMipsMCAsmInfo); - - // Register the MC instruction info. - TargetRegistry::RegisterMCInstrInfo(*T, createMipsMCInstrInfo); - - // Register the MC register info. - TargetRegistry::RegisterMCRegInfo(*T, createMipsMCRegisterInfo); - - // Register the elf streamer. - TargetRegistry::RegisterELFStreamer(*T, createMCStreamer); - - // Register the asm target streamer. - TargetRegistry::RegisterAsmTargetStreamer(*T, createMipsAsmTargetStreamer); - - TargetRegistry::RegisterNullTargetStreamer(*T, - createMipsNullTargetStreamer); - - // Register the MC subtarget info. - TargetRegistry::RegisterMCSubtargetInfo(*T, createMipsMCSubtargetInfo); - - // Register the MC instruction analyzer. - TargetRegistry::RegisterMCInstrAnalysis(*T, createMipsMCInstrAnalysis); - - // Register the MCInstPrinter. - TargetRegistry::RegisterMCInstPrinter(*T, createMipsMCInstPrinter); - - TargetRegistry::RegisterObjectTargetStreamer( - *T, createMipsObjectTargetStreamer); - - // Register the asm backend. - TargetRegistry::RegisterMCAsmBackend(*T, createMipsAsmBackend); - } - - // Register the MC Code Emitter - for (Target *T : {&getTheMipsTarget(), &getTheMips64Target()}) - TargetRegistry::RegisterMCCodeEmitter(*T, createMipsMCCodeEmitterEB); - - for (Target *T : {&getTheMipselTarget(), &getTheMips64elTarget()}) - TargetRegistry::RegisterMCCodeEmitter(*T, createMipsMCCodeEmitterEL); -} diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h deleted file mode 100644 index 809be99ff3f4..000000000000 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h +++ /dev/null @@ -1,67 +0,0 @@ -//===-- MipsMCTargetDesc.h - Mips Target Descriptions -----------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file provides Mips specific target descriptions. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSMCTARGETDESC_H -#define LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSMCTARGETDESC_H - -#include "llvm/Support/DataTypes.h" - -#include <memory> - -namespace llvm { -class MCAsmBackend; -class MCCodeEmitter; -class MCContext; -class MCInstrInfo; -class MCObjectTargetWriter; -class MCRegisterInfo; -class MCSubtargetInfo; -class MCTargetOptions; -class StringRef; -class Target; -class Triple; -class raw_ostream; -class raw_pwrite_stream; - -MCCodeEmitter *createMipsMCCodeEmitterEB(const MCInstrInfo &MCII, - const MCRegisterInfo &MRI, - MCContext &Ctx); -MCCodeEmitter *createMipsMCCodeEmitterEL(const MCInstrInfo &MCII, - const MCRegisterInfo &MRI, - MCContext &Ctx); - -MCAsmBackend *createMipsAsmBackend(const Target &T, const MCSubtargetInfo &STI, - const MCRegisterInfo &MRI, - const MCTargetOptions &Options); - -std::unique_ptr<MCObjectTargetWriter> -createMipsELFObjectWriter(const Triple &TT, bool IsN32); - -namespace MIPS_MC { -StringRef selectMipsCPU(const Triple &TT, StringRef CPU); -} - -} // End llvm namespace - -// Defines symbolic names for Mips registers. This defines a mapping from -// register name to register number. -#define GET_REGINFO_ENUM -#include "MipsGenRegisterInfo.inc" - -// Defines symbolic names for the Mips instructions. -#define GET_INSTRINFO_ENUM -#include "MipsGenInstrInfo.inc" - -#define GET_SUBTARGETINFO_ENUM -#include "MipsGenSubtargetInfo.inc" - -#endif diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp deleted file mode 100644 index c050db8a17fd..000000000000 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp +++ /dev/null @@ -1,278 +0,0 @@ -//===-- MipsNaClELFStreamer.cpp - ELF Object Output for Mips NaCl ---------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements MCELFStreamer for Mips NaCl. It emits .o object files -// as required by NaCl's SFI sandbox. It inserts address-masking instructions -// before dangerous control-flow and memory access instructions. It inserts -// address-masking instructions after instructions that change the stack -// pointer. It ensures that the mask and the dangerous instruction are always -// emitted in the same bundle. It aligns call + branch delay to the bundle end, -// so that return address is always aligned to the start of next bundle. -// -//===----------------------------------------------------------------------===// - -#include "Mips.h" -#include "MipsELFStreamer.h" -#include "MipsMCNaCl.h" -#include "llvm/MC/MCAsmBackend.h" -#include "llvm/MC/MCAssembler.h" -#include "llvm/MC/MCCodeEmitter.h" -#include "llvm/MC/MCELFStreamer.h" -#include "llvm/MC/MCInst.h" -#include "llvm/MC/MCObjectWriter.h" -#include "llvm/Support/ErrorHandling.h" -#include <cassert> - -using namespace llvm; - -#define DEBUG_TYPE "mips-mc-nacl" - -namespace { - -const unsigned IndirectBranchMaskReg = Mips::T6; -const unsigned LoadStoreStackMaskReg = Mips::T7; - -/// Extend the generic MCELFStreamer class so that it can mask dangerous -/// instructions. - -class MipsNaClELFStreamer : public MipsELFStreamer { -public: - MipsNaClELFStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> TAB, - std::unique_ptr<MCObjectWriter> OW, - std::unique_ptr<MCCodeEmitter> Emitter) - : MipsELFStreamer(Context, std::move(TAB), std::move(OW), - std::move(Emitter)) {} - - ~MipsNaClELFStreamer() override = default; - -private: - // Whether we started the sandboxing sequence for calls. Calls are bundled - // with branch delays and aligned to the bundle end. - bool PendingCall = false; - - bool isIndirectJump(const MCInst &MI) { - if (MI.getOpcode() == Mips::JALR) { - // MIPS32r6/MIPS64r6 doesn't have a JR instruction and uses JALR instead. - // JALR is an indirect branch if the link register is $0. - assert(MI.getOperand(0).isReg()); - return MI.getOperand(0).getReg() == Mips::ZERO; - } - return MI.getOpcode() == Mips::JR; - } - - bool isStackPointerFirstOperand(const MCInst &MI) { - return (MI.getNumOperands() > 0 && MI.getOperand(0).isReg() - && MI.getOperand(0).getReg() == Mips::SP); - } - - bool isCall(const MCInst &MI, bool *IsIndirectCall) { - unsigned Opcode = MI.getOpcode(); - - *IsIndirectCall = false; - - switch (Opcode) { - default: - return false; - - case Mips::JAL: - case Mips::BAL: - case Mips::BAL_BR: - case Mips::BLTZAL: - case Mips::BGEZAL: - return true; - - case Mips::JALR: - // JALR is only a call if the link register is not $0. Otherwise it's an - // indirect branch. - assert(MI.getOperand(0).isReg()); - if (MI.getOperand(0).getReg() == Mips::ZERO) - return false; - - *IsIndirectCall = true; - return true; - } - } - - void emitMask(unsigned AddrReg, unsigned MaskReg, - const MCSubtargetInfo &STI) { - MCInst MaskInst; - MaskInst.setOpcode(Mips::AND); - MaskInst.addOperand(MCOperand::createReg(AddrReg)); - MaskInst.addOperand(MCOperand::createReg(AddrReg)); - MaskInst.addOperand(MCOperand::createReg(MaskReg)); - MipsELFStreamer::EmitInstruction(MaskInst, STI); - } - - // Sandbox indirect branch or return instruction by inserting mask operation - // before it. - void sandboxIndirectJump(const MCInst &MI, const MCSubtargetInfo &STI) { - unsigned AddrReg = MI.getOperand(0).getReg(); - - EmitBundleLock(false); - emitMask(AddrReg, IndirectBranchMaskReg, STI); - MipsELFStreamer::EmitInstruction(MI, STI); - EmitBundleUnlock(); - } - - // Sandbox memory access or SP change. Insert mask operation before and/or - // after the instruction. - void sandboxLoadStoreStackChange(const MCInst &MI, unsigned AddrIdx, - const MCSubtargetInfo &STI, bool MaskBefore, - bool MaskAfter) { - EmitBundleLock(false); - if (MaskBefore) { - // Sandbox memory access. - unsigned BaseReg = MI.getOperand(AddrIdx).getReg(); - emitMask(BaseReg, LoadStoreStackMaskReg, STI); - } - MipsELFStreamer::EmitInstruction(MI, STI); - if (MaskAfter) { - // Sandbox SP change. - unsigned SPReg = MI.getOperand(0).getReg(); - assert((Mips::SP == SPReg) && "Unexpected stack-pointer register."); - emitMask(SPReg, LoadStoreStackMaskReg, STI); - } - EmitBundleUnlock(); - } - -public: - /// This function is the one used to emit instruction data into the ELF - /// streamer. We override it to mask dangerous instructions. - void EmitInstruction(const MCInst &Inst, - const MCSubtargetInfo &STI) override { - // Sandbox indirect jumps. - if (isIndirectJump(Inst)) { - if (PendingCall) - report_fatal_error("Dangerous instruction in branch delay slot!"); - sandboxIndirectJump(Inst, STI); - return; - } - - // Sandbox loads, stores and SP changes. - unsigned AddrIdx; - bool IsStore; - bool IsMemAccess = isBasePlusOffsetMemoryAccess(Inst.getOpcode(), &AddrIdx, - &IsStore); - bool IsSPFirstOperand = isStackPointerFirstOperand(Inst); - if (IsMemAccess || IsSPFirstOperand) { - bool MaskBefore = (IsMemAccess - && baseRegNeedsLoadStoreMask(Inst.getOperand(AddrIdx) - .getReg())); - bool MaskAfter = IsSPFirstOperand && !IsStore; - if (MaskBefore || MaskAfter) { - if (PendingCall) - report_fatal_error("Dangerous instruction in branch delay slot!"); - sandboxLoadStoreStackChange(Inst, AddrIdx, STI, MaskBefore, MaskAfter); - return; - } - // fallthrough - } - - // Sandbox calls by aligning call and branch delay to the bundle end. - // For indirect calls, emit the mask before the call. - bool IsIndirectCall; - if (isCall(Inst, &IsIndirectCall)) { - if (PendingCall) - report_fatal_error("Dangerous instruction in branch delay slot!"); - - // Start the sandboxing sequence by emitting call. - EmitBundleLock(true); - if (IsIndirectCall) { - unsigned TargetReg = Inst.getOperand(1).getReg(); - emitMask(TargetReg, IndirectBranchMaskReg, STI); - } - MipsELFStreamer::EmitInstruction(Inst, STI); - PendingCall = true; - return; - } - if (PendingCall) { - // Finish the sandboxing sequence by emitting branch delay. - MipsELFStreamer::EmitInstruction(Inst, STI); - EmitBundleUnlock(); - PendingCall = false; - return; - } - - // None of the sandboxing applies, just emit the instruction. - MipsELFStreamer::EmitInstruction(Inst, STI); - } -}; - -} // end anonymous namespace - -namespace llvm { - -bool isBasePlusOffsetMemoryAccess(unsigned Opcode, unsigned *AddrIdx, - bool *IsStore) { - if (IsStore) - *IsStore = false; - - switch (Opcode) { - default: - return false; - - // Load instructions with base address register in position 1. - case Mips::LB: - case Mips::LBu: - case Mips::LH: - case Mips::LHu: - case Mips::LW: - case Mips::LWC1: - case Mips::LDC1: - case Mips::LL: - case Mips::LL_R6: - case Mips::LWL: - case Mips::LWR: - *AddrIdx = 1; - return true; - - // Store instructions with base address register in position 1. - case Mips::SB: - case Mips::SH: - case Mips::SW: - case Mips::SWC1: - case Mips::SDC1: - case Mips::SWL: - case Mips::SWR: - *AddrIdx = 1; - if (IsStore) - *IsStore = true; - return true; - - // Store instructions with base address register in position 2. - case Mips::SC: - case Mips::SC_R6: - *AddrIdx = 2; - if (IsStore) - *IsStore = true; - return true; - } -} - -bool baseRegNeedsLoadStoreMask(unsigned Reg) { - // The contents of SP and thread pointer register do not require masking. - return Reg != Mips::SP && Reg != Mips::T8; -} - -MCELFStreamer *createMipsNaClELFStreamer(MCContext &Context, - std::unique_ptr<MCAsmBackend> TAB, - std::unique_ptr<MCObjectWriter> OW, - std::unique_ptr<MCCodeEmitter> Emitter, - bool RelaxAll) { - MipsNaClELFStreamer *S = new MipsNaClELFStreamer( - Context, std::move(TAB), std::move(OW), std::move(Emitter)); - if (RelaxAll) - S->getAssembler().setRelaxAll(true); - - // Set bundle-alignment as required by the NaCl ABI for the target. - S->EmitBundleAlignMode(MIPS_NACL_BUNDLE_ALIGN); - - return S; -} - -} // end namespace llvm diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsOptionRecord.cpp b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsOptionRecord.cpp deleted file mode 100644 index b4ebb9d18b72..000000000000 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsOptionRecord.cpp +++ /dev/null @@ -1,100 +0,0 @@ -//===- MipsOptionRecord.cpp - Abstraction for storing information ---------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "MipsOptionRecord.h" -#include "MipsABIInfo.h" -#include "MipsELFStreamer.h" -#include "MipsTargetStreamer.h" -#include "llvm/BinaryFormat/ELF.h" -#include "llvm/MC/MCAssembler.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCRegisterInfo.h" -#include "llvm/MC/MCSectionELF.h" -#include <cassert> - -using namespace llvm; - -void MipsRegInfoRecord::EmitMipsOptionRecord() { - MCAssembler &MCA = Streamer->getAssembler(); - MipsTargetStreamer *MTS = - static_cast<MipsTargetStreamer *>(Streamer->getTargetStreamer()); - - Streamer->PushSection(); - - // We need to distinguish between N64 and the rest because at the moment - // we don't emit .Mips.options for other ELFs other than N64. - // Since .reginfo has the same information as .Mips.options (ODK_REGINFO), - // we can use the same abstraction (MipsRegInfoRecord class) to handle both. - if (MTS->getABI().IsN64()) { - // The EntrySize value of 1 seems strange since the records are neither - // 1-byte long nor fixed length but it matches the value GAS emits. - MCSectionELF *Sec = - Context.getELFSection(".MIPS.options", ELF::SHT_MIPS_OPTIONS, - ELF::SHF_ALLOC | ELF::SHF_MIPS_NOSTRIP, 1, ""); - MCA.registerSection(*Sec); - Sec->setAlignment(8); - Streamer->SwitchSection(Sec); - - Streamer->EmitIntValue(ELF::ODK_REGINFO, 1); // kind - Streamer->EmitIntValue(40, 1); // size - Streamer->EmitIntValue(0, 2); // section - Streamer->EmitIntValue(0, 4); // info - Streamer->EmitIntValue(ri_gprmask, 4); - Streamer->EmitIntValue(0, 4); // pad - Streamer->EmitIntValue(ri_cprmask[0], 4); - Streamer->EmitIntValue(ri_cprmask[1], 4); - Streamer->EmitIntValue(ri_cprmask[2], 4); - Streamer->EmitIntValue(ri_cprmask[3], 4); - Streamer->EmitIntValue(ri_gp_value, 8); - } else { - MCSectionELF *Sec = Context.getELFSection(".reginfo", ELF::SHT_MIPS_REGINFO, - ELF::SHF_ALLOC, 24, ""); - MCA.registerSection(*Sec); - Sec->setAlignment(MTS->getABI().IsN32() ? 8 : 4); - Streamer->SwitchSection(Sec); - - Streamer->EmitIntValue(ri_gprmask, 4); - Streamer->EmitIntValue(ri_cprmask[0], 4); - Streamer->EmitIntValue(ri_cprmask[1], 4); - Streamer->EmitIntValue(ri_cprmask[2], 4); - Streamer->EmitIntValue(ri_cprmask[3], 4); - assert((ri_gp_value & 0xffffffff) == ri_gp_value); - Streamer->EmitIntValue(ri_gp_value, 4); - } - - Streamer->PopSection(); -} - -void MipsRegInfoRecord::SetPhysRegUsed(unsigned Reg, - const MCRegisterInfo *MCRegInfo) { - unsigned Value = 0; - - for (MCSubRegIterator SubRegIt(Reg, MCRegInfo, true); SubRegIt.isValid(); - ++SubRegIt) { - unsigned CurrentSubReg = *SubRegIt; - - unsigned EncVal = MCRegInfo->getEncodingValue(CurrentSubReg); - Value |= 1 << EncVal; - - if (GPR32RegClass->contains(CurrentSubReg) || - GPR64RegClass->contains(CurrentSubReg)) - ri_gprmask |= Value; - else if (COP0RegClass->contains(CurrentSubReg)) - ri_cprmask[0] |= Value; - // MIPS COP1 is the FPU. - else if (FGR32RegClass->contains(CurrentSubReg) || - FGR64RegClass->contains(CurrentSubReg) || - AFGR64RegClass->contains(CurrentSubReg) || - MSA128BRegClass->contains(CurrentSubReg)) - ri_cprmask[1] |= Value; - else if (COP2RegClass->contains(CurrentSubReg)) - ri_cprmask[2] |= Value; - else if (COP3RegClass->contains(CurrentSubReg)) - ri_cprmask[3] |= Value; - } -} diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp deleted file mode 100644 index e3bdb3b140a8..000000000000 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp +++ /dev/null @@ -1,1313 +0,0 @@ -//===-- MipsTargetStreamer.cpp - Mips Target Streamer Methods -------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file provides Mips specific target streamer methods. -// -//===----------------------------------------------------------------------===// - -#include "MipsTargetStreamer.h" -#include "MipsInstPrinter.h" -#include "MCTargetDesc/MipsABIInfo.h" -#include "MipsELFStreamer.h" -#include "MipsMCExpr.h" -#include "MipsMCTargetDesc.h" -#include "MipsTargetObjectFile.h" -#include "llvm/BinaryFormat/ELF.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/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), GPReg(Mips::GP), 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(); } -void MipsTargetStreamer::emitDirectiveSetNoReorder() {} -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(); -} -void MipsTargetStreamer::emitDirectiveSetNoAt() { forbidModuleDirective(); } -void MipsTargetStreamer::emitDirectiveEnd(StringRef Name) {} -void MipsTargetStreamer::emitDirectiveEnt(const MCSymbol &Symbol) {} -void MipsTargetStreamer::emitDirectiveAbiCalls() {} -void MipsTargetStreamer::emitDirectiveNaN2008() {} -void MipsTargetStreamer::emitDirectiveNaNLegacy() {} -void MipsTargetStreamer::emitDirectiveOptionPic0() {} -void MipsTargetStreamer::emitDirectiveOptionPic2() {} -void MipsTargetStreamer::emitDirectiveInsn() { forbidModuleDirective(); } -void MipsTargetStreamer::emitFrame(unsigned StackReg, unsigned StackSize, - unsigned ReturnReg) {} -void MipsTargetStreamer::emitMask(unsigned CPUBitmask, int CPUTopSavedRegOff) {} -void MipsTargetStreamer::emitFMask(unsigned FPUBitmask, int FPUTopSavedRegOff) { -} -void MipsTargetStreamer::emitDirectiveSetArch(StringRef Arch) { - forbidModuleDirective(); -} -void MipsTargetStreamer::emitDirectiveSetMips0() { forbidModuleDirective(); } -void MipsTargetStreamer::emitDirectiveSetMips1() { forbidModuleDirective(); } -void MipsTargetStreamer::emitDirectiveSetMips2() { forbidModuleDirective(); } -void MipsTargetStreamer::emitDirectiveSetMips3() { forbidModuleDirective(); } -void MipsTargetStreamer::emitDirectiveSetMips4() { forbidModuleDirective(); } -void MipsTargetStreamer::emitDirectiveSetMips5() { forbidModuleDirective(); } -void MipsTargetStreamer::emitDirectiveSetMips32() { forbidModuleDirective(); } -void MipsTargetStreamer::emitDirectiveSetMips32R2() { forbidModuleDirective(); } -void MipsTargetStreamer::emitDirectiveSetMips32R3() { forbidModuleDirective(); } -void MipsTargetStreamer::emitDirectiveSetMips32R5() { forbidModuleDirective(); } -void MipsTargetStreamer::emitDirectiveSetMips32R6() { forbidModuleDirective(); } -void MipsTargetStreamer::emitDirectiveSetMips64() { forbidModuleDirective(); } -void MipsTargetStreamer::emitDirectiveSetMips64R2() { forbidModuleDirective(); } -void MipsTargetStreamer::emitDirectiveSetMips64R3() { forbidModuleDirective(); } -void MipsTargetStreamer::emitDirectiveSetMips64R5() { forbidModuleDirective(); } -void MipsTargetStreamer::emitDirectiveSetMips64R6() { forbidModuleDirective(); } -void MipsTargetStreamer::emitDirectiveSetPop() { forbidModuleDirective(); } -void MipsTargetStreamer::emitDirectiveSetPush() { forbidModuleDirective(); } -void MipsTargetStreamer::emitDirectiveSetSoftFloat() { - forbidModuleDirective(); -} -void MipsTargetStreamer::emitDirectiveSetHardFloat() { - forbidModuleDirective(); -} -void MipsTargetStreamer::emitDirectiveSetDsp() { forbidModuleDirective(); } -void MipsTargetStreamer::emitDirectiveSetDspr2() { forbidModuleDirective(); } -void MipsTargetStreamer::emitDirectiveSetNoDsp() { forbidModuleDirective(); } -void MipsTargetStreamer::emitDirectiveCpLoad(unsigned RegNo) {} -void MipsTargetStreamer::emitDirectiveCpLocal(unsigned RegNo) { - // .cplocal $reg - // This directive forces to use the alternate register for context pointer. - // For example - // .cplocal $4 - // jal foo - // expands to - // ld $25, %call16(foo)($4) - // jalr $25 - - if (!getABI().IsN32() && !getABI().IsN64()) - return; - - GPReg = RegNo; - - forbidModuleDirective(); -} -bool MipsTargetStreamer::emitDirectiveCpRestore( - int Offset, function_ref<unsigned()> GetATReg, SMLoc IDLoc, - const MCSubtargetInfo *STI) { - forbidModuleDirective(); - return true; -} -void MipsTargetStreamer::emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset, - const MCSymbol &Sym, bool IsReg) { -} -void MipsTargetStreamer::emitDirectiveCpreturn(unsigned SaveLocation, - bool SaveLocationIsRegister) {} - -void MipsTargetStreamer::emitDirectiveModuleFP() {} - -void MipsTargetStreamer::emitDirectiveModuleOddSPReg() { - if (!ABIFlagsSection.OddSPReg && !ABIFlagsSection.Is32BitABI) - report_fatal_error("+nooddspreg is only valid for O32"); -} -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(); -} -void MipsTargetStreamer::emitDirectiveSetOddSPReg() { forbidModuleDirective(); } -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, GPReg, Mips::SP, Offset, GPReg, 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) {} - -void MipsTargetAsmStreamer::emitDirectiveSetMicroMips() { - OS << "\t.set\tmicromips\n"; - forbidModuleDirective(); -} - -void MipsTargetAsmStreamer::emitDirectiveSetNoMicroMips() { - OS << "\t.set\tnomicromips\n"; - forbidModuleDirective(); -} - -void MipsTargetAsmStreamer::emitDirectiveSetMips16() { - OS << "\t.set\tmips16\n"; - forbidModuleDirective(); -} - -void MipsTargetAsmStreamer::emitDirectiveSetNoMips16() { - OS << "\t.set\tnomips16\n"; - MipsTargetStreamer::emitDirectiveSetNoMips16(); -} - -void MipsTargetAsmStreamer::emitDirectiveSetReorder() { - OS << "\t.set\treorder\n"; - MipsTargetStreamer::emitDirectiveSetReorder(); -} - -void MipsTargetAsmStreamer::emitDirectiveSetNoReorder() { - OS << "\t.set\tnoreorder\n"; - forbidModuleDirective(); -} - -void MipsTargetAsmStreamer::emitDirectiveSetMacro() { - OS << "\t.set\tmacro\n"; - MipsTargetStreamer::emitDirectiveSetMacro(); -} - -void MipsTargetAsmStreamer::emitDirectiveSetNoMacro() { - OS << "\t.set\tnomacro\n"; - MipsTargetStreamer::emitDirectiveSetNoMacro(); -} - -void MipsTargetAsmStreamer::emitDirectiveSetMsa() { - OS << "\t.set\tmsa\n"; - MipsTargetStreamer::emitDirectiveSetMsa(); -} - -void MipsTargetAsmStreamer::emitDirectiveSetNoMsa() { - OS << "\t.set\tnomsa\n"; - 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(); -} - -void MipsTargetAsmStreamer::emitDirectiveSetAtWithArg(unsigned RegNo) { - OS << "\t.set\tat=$" << Twine(RegNo) << "\n"; - MipsTargetStreamer::emitDirectiveSetAtWithArg(RegNo); -} - -void MipsTargetAsmStreamer::emitDirectiveSetNoAt() { - OS << "\t.set\tnoat\n"; - MipsTargetStreamer::emitDirectiveSetNoAt(); -} - -void MipsTargetAsmStreamer::emitDirectiveEnd(StringRef Name) { - OS << "\t.end\t" << Name << '\n'; -} - -void MipsTargetAsmStreamer::emitDirectiveEnt(const MCSymbol &Symbol) { - OS << "\t.ent\t" << Symbol.getName() << '\n'; -} - -void MipsTargetAsmStreamer::emitDirectiveAbiCalls() { OS << "\t.abicalls\n"; } - -void MipsTargetAsmStreamer::emitDirectiveNaN2008() { OS << "\t.nan\t2008\n"; } - -void MipsTargetAsmStreamer::emitDirectiveNaNLegacy() { - OS << "\t.nan\tlegacy\n"; -} - -void MipsTargetAsmStreamer::emitDirectiveOptionPic0() { - OS << "\t.option\tpic0\n"; -} - -void MipsTargetAsmStreamer::emitDirectiveOptionPic2() { - OS << "\t.option\tpic2\n"; -} - -void MipsTargetAsmStreamer::emitDirectiveInsn() { - MipsTargetStreamer::emitDirectiveInsn(); - OS << "\t.insn\n"; -} - -void MipsTargetAsmStreamer::emitFrame(unsigned StackReg, unsigned StackSize, - unsigned ReturnReg) { - OS << "\t.frame\t$" - << StringRef(MipsInstPrinter::getRegisterName(StackReg)).lower() << "," - << StackSize << ",$" - << StringRef(MipsInstPrinter::getRegisterName(ReturnReg)).lower() << '\n'; -} - -void MipsTargetAsmStreamer::emitDirectiveSetArch(StringRef Arch) { - OS << "\t.set arch=" << Arch << "\n"; - MipsTargetStreamer::emitDirectiveSetArch(Arch); -} - -void MipsTargetAsmStreamer::emitDirectiveSetMips0() { - OS << "\t.set\tmips0\n"; - MipsTargetStreamer::emitDirectiveSetMips0(); -} - -void MipsTargetAsmStreamer::emitDirectiveSetMips1() { - OS << "\t.set\tmips1\n"; - MipsTargetStreamer::emitDirectiveSetMips1(); -} - -void MipsTargetAsmStreamer::emitDirectiveSetMips2() { - OS << "\t.set\tmips2\n"; - MipsTargetStreamer::emitDirectiveSetMips2(); -} - -void MipsTargetAsmStreamer::emitDirectiveSetMips3() { - OS << "\t.set\tmips3\n"; - MipsTargetStreamer::emitDirectiveSetMips3(); -} - -void MipsTargetAsmStreamer::emitDirectiveSetMips4() { - OS << "\t.set\tmips4\n"; - MipsTargetStreamer::emitDirectiveSetMips4(); -} - -void MipsTargetAsmStreamer::emitDirectiveSetMips5() { - OS << "\t.set\tmips5\n"; - MipsTargetStreamer::emitDirectiveSetMips5(); -} - -void MipsTargetAsmStreamer::emitDirectiveSetMips32() { - OS << "\t.set\tmips32\n"; - MipsTargetStreamer::emitDirectiveSetMips32(); -} - -void MipsTargetAsmStreamer::emitDirectiveSetMips32R2() { - OS << "\t.set\tmips32r2\n"; - MipsTargetStreamer::emitDirectiveSetMips32R2(); -} - -void MipsTargetAsmStreamer::emitDirectiveSetMips32R3() { - OS << "\t.set\tmips32r3\n"; - MipsTargetStreamer::emitDirectiveSetMips32R3(); -} - -void MipsTargetAsmStreamer::emitDirectiveSetMips32R5() { - OS << "\t.set\tmips32r5\n"; - MipsTargetStreamer::emitDirectiveSetMips32R5(); -} - -void MipsTargetAsmStreamer::emitDirectiveSetMips32R6() { - OS << "\t.set\tmips32r6\n"; - MipsTargetStreamer::emitDirectiveSetMips32R6(); -} - -void MipsTargetAsmStreamer::emitDirectiveSetMips64() { - OS << "\t.set\tmips64\n"; - MipsTargetStreamer::emitDirectiveSetMips64(); -} - -void MipsTargetAsmStreamer::emitDirectiveSetMips64R2() { - OS << "\t.set\tmips64r2\n"; - MipsTargetStreamer::emitDirectiveSetMips64R2(); -} - -void MipsTargetAsmStreamer::emitDirectiveSetMips64R3() { - OS << "\t.set\tmips64r3\n"; - MipsTargetStreamer::emitDirectiveSetMips64R3(); -} - -void MipsTargetAsmStreamer::emitDirectiveSetMips64R5() { - OS << "\t.set\tmips64r5\n"; - MipsTargetStreamer::emitDirectiveSetMips64R5(); -} - -void MipsTargetAsmStreamer::emitDirectiveSetMips64R6() { - OS << "\t.set\tmips64r6\n"; - MipsTargetStreamer::emitDirectiveSetMips64R6(); -} - -void MipsTargetAsmStreamer::emitDirectiveSetDsp() { - OS << "\t.set\tdsp\n"; - MipsTargetStreamer::emitDirectiveSetDsp(); -} - -void MipsTargetAsmStreamer::emitDirectiveSetDspr2() { - OS << "\t.set\tdspr2\n"; - MipsTargetStreamer::emitDirectiveSetDspr2(); -} - -void MipsTargetAsmStreamer::emitDirectiveSetNoDsp() { - OS << "\t.set\tnodsp\n"; - MipsTargetStreamer::emitDirectiveSetNoDsp(); -} - -void MipsTargetAsmStreamer::emitDirectiveSetPop() { - OS << "\t.set\tpop\n"; - MipsTargetStreamer::emitDirectiveSetPop(); -} - -void MipsTargetAsmStreamer::emitDirectiveSetPush() { - OS << "\t.set\tpush\n"; - MipsTargetStreamer::emitDirectiveSetPush(); -} - -void MipsTargetAsmStreamer::emitDirectiveSetSoftFloat() { - OS << "\t.set\tsoftfloat\n"; - MipsTargetStreamer::emitDirectiveSetSoftFloat(); -} - -void MipsTargetAsmStreamer::emitDirectiveSetHardFloat() { - OS << "\t.set\thardfloat\n"; - MipsTargetStreamer::emitDirectiveSetHardFloat(); -} - -// Print a 32 bit hex number with all numbers. -static void printHex32(unsigned Value, raw_ostream &OS) { - OS << "0x"; - for (int i = 7; i >= 0; i--) - OS.write_hex((Value & (0xF << (i * 4))) >> (i * 4)); -} - -void MipsTargetAsmStreamer::emitMask(unsigned CPUBitmask, - int CPUTopSavedRegOff) { - OS << "\t.mask \t"; - printHex32(CPUBitmask, OS); - OS << ',' << CPUTopSavedRegOff << '\n'; -} - -void MipsTargetAsmStreamer::emitFMask(unsigned FPUBitmask, - int FPUTopSavedRegOff) { - OS << "\t.fmask\t"; - printHex32(FPUBitmask, OS); - OS << "," << FPUTopSavedRegOff << '\n'; -} - -void MipsTargetAsmStreamer::emitDirectiveCpLoad(unsigned RegNo) { - OS << "\t.cpload\t$" - << StringRef(MipsInstPrinter::getRegisterName(RegNo)).lower() << "\n"; - forbidModuleDirective(); -} - -void MipsTargetAsmStreamer::emitDirectiveCpLocal(unsigned RegNo) { - OS << "\t.cplocal\t$" - << StringRef(MipsInstPrinter::getRegisterName(RegNo)).lower() << "\n"; - MipsTargetStreamer::emitDirectiveCpLocal(RegNo); -} - -bool MipsTargetAsmStreamer::emitDirectiveCpRestore( - int Offset, function_ref<unsigned()> GetATReg, SMLoc IDLoc, - const MCSubtargetInfo *STI) { - MipsTargetStreamer::emitDirectiveCpRestore(Offset, GetATReg, IDLoc, STI); - OS << "\t.cprestore\t" << Offset << "\n"; - return true; -} - -void MipsTargetAsmStreamer::emitDirectiveCpsetup(unsigned RegNo, - int RegOrOffset, - const MCSymbol &Sym, - bool IsReg) { - OS << "\t.cpsetup\t$" - << StringRef(MipsInstPrinter::getRegisterName(RegNo)).lower() << ", "; - - if (IsReg) - OS << "$" - << StringRef(MipsInstPrinter::getRegisterName(RegOrOffset)).lower(); - else - OS << RegOrOffset; - - OS << ", "; - - OS << Sym.getName(); - forbidModuleDirective(); -} - -void MipsTargetAsmStreamer::emitDirectiveCpreturn(unsigned SaveLocation, - bool SaveLocationIsRegister) { - OS << "\t.cpreturn"; - forbidModuleDirective(); -} - -void MipsTargetAsmStreamer::emitDirectiveModuleFP() { - MipsABIFlagsSection::FpABIKind FpABI = ABIFlagsSection.getFpABI(); - if (FpABI == MipsABIFlagsSection::FpABIKind::SOFT) - OS << "\t.module\tsoftfloat\n"; - else - OS << "\t.module\tfp=" << ABIFlagsSection.getFpABIString(FpABI) << "\n"; -} - -void MipsTargetAsmStreamer::emitDirectiveSetFp( - MipsABIFlagsSection::FpABIKind Value) { - MipsTargetStreamer::emitDirectiveSetFp(Value); - - OS << "\t.set\tfp="; - OS << ABIFlagsSection.getFpABIString(Value) << "\n"; -} - -void MipsTargetAsmStreamer::emitDirectiveModuleOddSPReg() { - MipsTargetStreamer::emitDirectiveModuleOddSPReg(); - - OS << "\t.module\t" << (ABIFlagsSection.OddSPReg ? "" : "no") << "oddspreg\n"; -} - -void MipsTargetAsmStreamer::emitDirectiveSetOddSPReg() { - MipsTargetStreamer::emitDirectiveSetOddSPReg(); - OS << "\t.set\toddspreg\n"; -} - -void MipsTargetAsmStreamer::emitDirectiveSetNoOddSPReg() { - MipsTargetStreamer::emitDirectiveSetNoOddSPReg(); - OS << "\t.set\tnooddspreg\n"; -} - -void MipsTargetAsmStreamer::emitDirectiveModuleSoftFloat() { - OS << "\t.module\tsoftfloat\n"; -} - -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(); - - const FeatureBitset &Features = STI.getFeatureBits(); - - // Set the header flags that we can in the constructor. - // FIXME: This is a fairly terrible hack. We set the rest - // of these in the destructor. The problem here is two-fold: - // - // a: Some of the eflags can be set/reset by directives. - // b: There aren't any usage paths that initialize the ABI - // pointer until after we initialize either an assembler - // or the target machine. - // We can fix this by making the target streamer construct - // the ABI, but this is fraught with wide ranging dependency - // 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; - else if (Features[Mips::FeatureMips64r2] || - Features[Mips::FeatureMips64r3] || - Features[Mips::FeatureMips64r5]) - EFlags |= ELF::EF_MIPS_ARCH_64R2; - else if (Features[Mips::FeatureMips64]) - EFlags |= ELF::EF_MIPS_ARCH_64; - else if (Features[Mips::FeatureMips5]) - EFlags |= ELF::EF_MIPS_ARCH_5; - else if (Features[Mips::FeatureMips4]) - EFlags |= ELF::EF_MIPS_ARCH_4; - else if (Features[Mips::FeatureMips3]) - EFlags |= ELF::EF_MIPS_ARCH_3; - else if (Features[Mips::FeatureMips32r6]) - EFlags |= ELF::EF_MIPS_ARCH_32R6; - else if (Features[Mips::FeatureMips32r2] || - Features[Mips::FeatureMips32r3] || - Features[Mips::FeatureMips32r5]) - EFlags |= ELF::EF_MIPS_ARCH_32R2; - else if (Features[Mips::FeatureMips32]) - EFlags |= ELF::EF_MIPS_ARCH_32; - else if (Features[Mips::FeatureMips2]) - EFlags |= ELF::EF_MIPS_ARCH_2; - 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; - - MCA.setELFHeaderEFlags(EFlags); -} - -void MipsTargetELFStreamer::emitLabel(MCSymbol *S) { - auto *Symbol = cast<MCSymbolELF>(S); - getStreamer().getAssembler().registerSymbol(*Symbol); - uint8_t Type = Symbol->getType(); - if (Type != ELF::STT_FUNC) - return; - - if (isMicroMipsEnabled()) - Symbol->setOther(ELF::STO_MIPS_MICROMIPS); -} - -void MipsTargetELFStreamer::finish() { - MCAssembler &MCA = getStreamer().getAssembler(); - const MCObjectFileInfo &OFI = *MCA.getContext().getObjectFileInfo(); - - // .bss, .text and .data are always at least 16-byte aligned. - MCSection &TextSection = *OFI.getTextSection(); - MCA.registerSection(TextSection); - MCSection &DataSection = *OFI.getDataSection(); - MCA.registerSection(DataSection); - MCSection &BSSSection = *OFI.getBSSSection(); - MCA.registerSection(BSSSection); - - TextSection.setAlignment(std::max(16u, TextSection.getAlignment())); - 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 - // the constructor for a full rundown on this. - unsigned EFlags = MCA.getELFHeaderEFlags(); - - // ABI - // N64 does not require any ABI bits. - if (getABI().IsO32()) - EFlags |= ELF::EF_MIPS_ABI_O32; - else if (getABI().IsN32()) - EFlags |= ELF::EF_MIPS_ABI2; - - if (Features[Mips::FeatureGP64Bit]) { - if (getABI().IsO32()) - EFlags |= ELF::EF_MIPS_32BITMODE; /* Compatibility Mode */ - } 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; - - MCA.setELFHeaderEFlags(EFlags); - - // Emit all the option records. - // At the moment we are only emitting .Mips.options (ODK_REGINFO) and - // .reginfo. - MipsELFStreamer &MEF = static_cast<MipsELFStreamer &>(Streamer); - MEF.EmitMipsOptionRecords(); - - emitMipsAbiFlags(); -} - -void MipsTargetELFStreamer::emitAssignment(MCSymbol *S, const MCExpr *Value) { - auto *Symbol = cast<MCSymbolELF>(S); - // If on rhs is micromips symbol then mark Symbol as microMips. - if (Value->getKind() != MCExpr::SymbolRef) - return; - const auto &RhsSym = cast<MCSymbolELF>( - static_cast<const MCSymbolRefExpr *>(Value)->getSymbol()); - - if (!(RhsSym.getOther() & ELF::STO_MIPS_MICROMIPS)) - return; - - Symbol->setOther(ELF::STO_MIPS_MICROMIPS); -} - -MCELFStreamer &MipsTargetELFStreamer::getStreamer() { - return static_cast<MCELFStreamer &>(Streamer); -} - -void MipsTargetELFStreamer::emitDirectiveSetMicroMips() { - MicroMipsEnabled = true; - forbidModuleDirective(); -} - -void MipsTargetELFStreamer::emitDirectiveSetNoMicroMips() { - MicroMipsEnabled = false; - 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(); - Flags |= ELF::EF_MIPS_ARCH_ASE_M16; - MCA.setELFHeaderEFlags(Flags); - forbidModuleDirective(); -} - -void MipsTargetELFStreamer::emitDirectiveSetNoReorder() { - MCAssembler &MCA = getStreamer().getAssembler(); - unsigned Flags = MCA.getELFHeaderEFlags(); - Flags |= ELF::EF_MIPS_NOREORDER; - MCA.setELFHeaderEFlags(Flags); - forbidModuleDirective(); -} - -void MipsTargetELFStreamer::emitDirectiveEnd(StringRef Name) { - MCAssembler &MCA = getStreamer().getAssembler(); - MCContext &Context = MCA.getContext(); - MCStreamer &OS = getStreamer(); - - MCSectionELF *Sec = Context.getELFSection(".pdr", ELF::SHT_PROGBITS, 0); - - MCSymbol *Sym = Context.getOrCreateSymbol(Name); - const MCSymbolRefExpr *ExprRef = - MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Context); - - MCA.registerSection(*Sec); - Sec->setAlignment(4); - - OS.PushSection(); - - OS.SwitchSection(Sec); - - OS.EmitValueImpl(ExprRef, 4); - - OS.EmitIntValue(GPRInfoSet ? GPRBitMask : 0, 4); // reg_mask - OS.EmitIntValue(GPRInfoSet ? GPROffset : 0, 4); // reg_offset - - OS.EmitIntValue(FPRInfoSet ? FPRBitMask : 0, 4); // fpreg_mask - OS.EmitIntValue(FPRInfoSet ? FPROffset : 0, 4); // fpreg_offset - - OS.EmitIntValue(FrameInfoSet ? FrameOffset : 0, 4); // frame_offset - OS.EmitIntValue(FrameInfoSet ? FrameReg : 0, 4); // frame_reg - OS.EmitIntValue(FrameInfoSet ? ReturnReg : 0, 4); // return_reg - - // The .end directive marks the end of a procedure. Invalidate - // the information gathered up until this point. - GPRInfoSet = FPRInfoSet = FrameInfoSet = false; - - OS.PopSection(); - - // .end also implicitly sets the size. - MCSymbol *CurPCSym = Context.createTempSymbol(); - OS.EmitLabel(CurPCSym); - 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. - static_cast<MCSymbolELF *>(Sym)->setSize(Size); -} - -void MipsTargetELFStreamer::emitDirectiveEnt(const MCSymbol &Symbol) { - GPRInfoSet = FPRInfoSet = FrameInfoSet = false; - - // .ent also acts like an implicit '.type symbol, STT_FUNC' - static_cast<const MCSymbolELF &>(Symbol).setType(ELF::STT_FUNC); -} - -void MipsTargetELFStreamer::emitDirectiveAbiCalls() { - MCAssembler &MCA = getStreamer().getAssembler(); - unsigned Flags = MCA.getELFHeaderEFlags(); - Flags |= ELF::EF_MIPS_CPIC | ELF::EF_MIPS_PIC; - MCA.setELFHeaderEFlags(Flags); -} - -void MipsTargetELFStreamer::emitDirectiveNaN2008() { - MCAssembler &MCA = getStreamer().getAssembler(); - unsigned Flags = MCA.getELFHeaderEFlags(); - Flags |= ELF::EF_MIPS_NAN2008; - MCA.setELFHeaderEFlags(Flags); -} - -void MipsTargetELFStreamer::emitDirectiveNaNLegacy() { - MCAssembler &MCA = getStreamer().getAssembler(); - unsigned Flags = MCA.getELFHeaderEFlags(); - Flags &= ~ELF::EF_MIPS_NAN2008; - MCA.setELFHeaderEFlags(Flags); -} - -void MipsTargetELFStreamer::emitDirectiveOptionPic0() { - MCAssembler &MCA = getStreamer().getAssembler(); - unsigned Flags = MCA.getELFHeaderEFlags(); - // This option overrides other PIC options like -KPIC. - Pic = false; - Flags &= ~ELF::EF_MIPS_PIC; - MCA.setELFHeaderEFlags(Flags); -} - -void MipsTargetELFStreamer::emitDirectiveOptionPic2() { - MCAssembler &MCA = getStreamer().getAssembler(); - unsigned Flags = MCA.getELFHeaderEFlags(); - Pic = true; - // NOTE: We are following the GAS behaviour here which means the directive - // 'pic2' also sets the CPIC bit in the ELF header. This is different from - // what is stated in the SYSV ABI which consider the bits EF_MIPS_PIC and - // EF_MIPS_CPIC to be mutually exclusive. - Flags |= ELF::EF_MIPS_PIC | ELF::EF_MIPS_CPIC; - MCA.setELFHeaderEFlags(Flags); -} - -void MipsTargetELFStreamer::emitDirectiveInsn() { - MipsTargetStreamer::emitDirectiveInsn(); - MipsELFStreamer &MEF = static_cast<MipsELFStreamer &>(Streamer); - MEF.createPendingLabelRelocs(); -} - -void MipsTargetELFStreamer::emitFrame(unsigned StackReg, unsigned StackSize, - unsigned ReturnReg_) { - MCContext &Context = getStreamer().getAssembler().getContext(); - const MCRegisterInfo *RegInfo = Context.getRegisterInfo(); - - FrameInfoSet = true; - FrameReg = RegInfo->getEncodingValue(StackReg); - FrameOffset = StackSize; - ReturnReg = RegInfo->getEncodingValue(ReturnReg_); -} - -void MipsTargetELFStreamer::emitMask(unsigned CPUBitmask, - int CPUTopSavedRegOff) { - GPRInfoSet = true; - GPRBitMask = CPUBitmask; - GPROffset = CPUTopSavedRegOff; -} - -void MipsTargetELFStreamer::emitFMask(unsigned FPUBitmask, - int FPUTopSavedRegOff) { - FPRInfoSet = true; - FPRBitMask = FPUBitmask; - FPROffset = FPUTopSavedRegOff; -} - -void MipsTargetELFStreamer::emitDirectiveCpLoad(unsigned RegNo) { - // .cpload $reg - // This directive expands to: - // lui $gp, %hi(_gp_disp) - // addui $gp, $gp, %lo(_gp_disp) - // addu $gp, $gp, $reg - // when support for position independent code is enabled. - if (!Pic || (getABI().IsN32() || getABI().IsN64())) - return; - - // There's a GNU extension controlled by -mno-shared that allows - // locally-binding symbols to be accessed using absolute addresses. - // This is currently not supported. When supported -mno-shared makes - // .cpload expand to: - // lui $gp, %hi(__gnu_local_gp) - // addiu $gp, $gp, %lo(__gnu_local_gp) - - StringRef SymName("_gp_disp"); - MCAssembler &MCA = getStreamer().getAssembler(); - MCSymbol *GP_Disp = MCA.getContext().getOrCreateSymbol(SymName); - MCA.registerSymbol(*GP_Disp); - - MCInst TmpInst; - TmpInst.setOpcode(Mips::LUi); - TmpInst.addOperand(MCOperand::createReg(GPReg)); - const MCExpr *HiSym = MipsMCExpr::create( - MipsMCExpr::MEK_HI, - MCSymbolRefExpr::create("_gp_disp", MCSymbolRefExpr::VK_None, - MCA.getContext()), - MCA.getContext()); - TmpInst.addOperand(MCOperand::createExpr(HiSym)); - getStreamer().EmitInstruction(TmpInst, STI); - - TmpInst.clear(); - - TmpInst.setOpcode(Mips::ADDiu); - TmpInst.addOperand(MCOperand::createReg(GPReg)); - TmpInst.addOperand(MCOperand::createReg(GPReg)); - const MCExpr *LoSym = MipsMCExpr::create( - MipsMCExpr::MEK_LO, - MCSymbolRefExpr::create("_gp_disp", MCSymbolRefExpr::VK_None, - MCA.getContext()), - MCA.getContext()); - TmpInst.addOperand(MCOperand::createExpr(LoSym)); - getStreamer().EmitInstruction(TmpInst, STI); - - TmpInst.clear(); - - TmpInst.setOpcode(Mips::ADDu); - TmpInst.addOperand(MCOperand::createReg(GPReg)); - TmpInst.addOperand(MCOperand::createReg(GPReg)); - TmpInst.addOperand(MCOperand::createReg(RegNo)); - getStreamer().EmitInstruction(TmpInst, STI); - - forbidModuleDirective(); -} - -void MipsTargetELFStreamer::emitDirectiveCpLocal(unsigned RegNo) { - if (Pic) - MipsTargetStreamer::emitDirectiveCpLocal(RegNo); -} - -bool MipsTargetELFStreamer::emitDirectiveCpRestore( - int Offset, function_ref<unsigned()> GetATReg, SMLoc IDLoc, - const MCSubtargetInfo *STI) { - MipsTargetStreamer::emitDirectiveCpRestore(Offset, GetATReg, IDLoc, STI); - // .cprestore offset - // When PIC mode is enabled and the O32 ABI is used, this directive expands - // to: - // sw $gp, offset($sp) - // and adds a corresponding LW after every JAL. - - // 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; - - // Store the $gp on the stack. - emitStoreWithImmOffset(Mips::SW, GPReg, Mips::SP, Offset, GetATReg, IDLoc, - STI); - return true; -} - -void MipsTargetELFStreamer::emitDirectiveCpsetup(unsigned RegNo, - int RegOrOffset, - const MCSymbol &Sym, - bool IsReg) { - // Only N32 and N64 emit anything for .cpsetup iff PIC is set. - 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, GPReg, Mips::ZERO, SMLoc(), &STI); - } else { - // sd $gpreg, offset($sp) - emitRRI(Mips::SD, GPReg, 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, GPReg, MCOperand::createExpr(HiExpr), SMLoc(), &STI); - - // addiu $gp, $gp, %lo(__gnu_local_gp) - emitRRX(Mips::ADDiu, GPReg, GPReg, MCOperand::createExpr(LoExpr), SMLoc(), - &STI); - - return; - } - - 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()); - - // lui $gp, %hi(%neg(%gp_rel(funcSym))) - emitRX(Mips::LUi, GPReg, MCOperand::createExpr(HiExpr), SMLoc(), &STI); - - // addiu $gp, $gp, %lo(%neg(%gp_rel(funcSym))) - emitRRX(Mips::ADDiu, GPReg, GPReg, MCOperand::createExpr(LoExpr), SMLoc(), - &STI); - - // daddu $gp, $gp, $funcreg - emitRRR(Mips::DADDu, GPReg, GPReg, RegNo, SMLoc(), &STI); -} - -void MipsTargetELFStreamer::emitDirectiveCpreturn(unsigned SaveLocation, - bool SaveLocationIsRegister) { - // Only N32 and N64 emit anything for .cpreturn iff PIC is set. - if (!Pic || !(getABI().IsN32() || getABI().IsN64())) - return; - - MCInst Inst; - // Either restore the old $gp from a register or on the stack - if (SaveLocationIsRegister) { - Inst.setOpcode(Mips::OR); - Inst.addOperand(MCOperand::createReg(GPReg)); - Inst.addOperand(MCOperand::createReg(SaveLocation)); - Inst.addOperand(MCOperand::createReg(Mips::ZERO)); - } else { - Inst.setOpcode(Mips::LD); - Inst.addOperand(MCOperand::createReg(GPReg)); - Inst.addOperand(MCOperand::createReg(Mips::SP)); - Inst.addOperand(MCOperand::createImm(SaveLocation)); - } - getStreamer().EmitInstruction(Inst, STI); - - forbidModuleDirective(); -} - -void MipsTargetELFStreamer::emitMipsAbiFlags() { - MCAssembler &MCA = getStreamer().getAssembler(); - MCContext &Context = MCA.getContext(); - MCStreamer &OS = getStreamer(); - MCSectionELF *Sec = Context.getELFSection( - ".MIPS.abiflags", ELF::SHT_MIPS_ABIFLAGS, ELF::SHF_ALLOC, 24, ""); - MCA.registerSection(*Sec); - Sec->setAlignment(8); - OS.SwitchSection(Sec); - - OS << ABIFlagsSection; -} diff --git a/contrib/llvm/lib/Target/Mips/MSA.txt b/contrib/llvm/lib/Target/Mips/MSA.txt deleted file mode 100644 index 113375fa7f2f..000000000000 --- a/contrib/llvm/lib/Target/Mips/MSA.txt +++ /dev/null @@ -1,83 +0,0 @@ -Code Generation Notes for MSA -============================= - -Intrinsics are lowered to SelectionDAG nodes where possible in order to enable -optimisation, reduce the size of the ISel matcher, and reduce repetition in -the implementation. In a small number of cases, this can cause different -(semantically equivalent) instructions to be used in place of the requested -instruction, even when no optimisation has taken place. - -Instructions -============ - -This section describes any quirks of instruction selection for MSA. For -example, two instructions might be equally valid for some given IR and one is -chosen in preference to the other. - -bclri.b: - It is not possible to emit bclri.b since andi.b covers exactly the - same cases. andi.b should use fractionally less power than bclri.b in - most hardware implementations so it is used in preference to bclri.b. - -vshf.w: - It is not possible to emit vshf.w when the shuffle description is - constant since shf.w covers exactly the same cases. shf.w is used - instead. It is also impossible for the shuffle description to be - unknown at compile-time due to the definition of shufflevector in - LLVM IR. - -vshf.[bhwd] - When the shuffle description describes a splat operation, splat.[bhwd] - instructions will be selected instead of vshf.[bhwd]. Unlike the ilv*, - and pck* instructions, this is matched from MipsISD::VSHF instead of - a special-case MipsISD node. - -ilvl.d, pckev.d: - It is not possible to emit ilvl.d, or pckev.d since ilvev.d covers the - same shuffle. ilvev.d will be emitted instead. - -ilvr.d, ilvod.d, pckod.d: - It is not possible to emit ilvr.d, or pckod.d since ilvod.d covers the - same shuffle. ilvod.d will be emitted instead. - -splat.[bhwd] - The intrinsic will work as expected. However, unlike other intrinsics - it lowers directly to MipsISD::VSHF instead of using common IR. - -splati.w: - It is not possible to emit splati.w since shf.w covers the same cases. - shf.w will be emitted instead. - -copy_s.w: - On MIPS32, the copy_u.d intrinsic will emit this instruction instead of - copy_u.w. This is semantically equivalent since the general-purpose - register file is 32-bits wide. - -binsri.[bhwd], binsli.[bhwd]: - These two operations are equivalent to each other with the operands - swapped and condition inverted. The compiler may use either one as - appropriate. - Furthermore, the compiler may use bsel.[bhwd] for some masks that do - not survive the legalization process (this is a bug and will be fixed). - -bmnz.v, bmz.v, bsel.v: - These three operations differ only in the operand that is tied to the - result and the order of the operands. - It is (currently) not possible to emit bmz.v, or bsel.v since bmnz.v is - the same operation and will be emitted instead. - In future, the compiler may choose between these three instructions - according to register allocation. - These three operations can be very confusing so here is a mapping - between the instructions and the vselect node in one place: - bmz.v wd, ws, wt/i8 -> (vselect wt/i8, wd, ws) - bmnz.v wd, ws, wt/i8 -> (vselect wt/i8, ws, wd) - bsel.v wd, ws, wt/i8 -> (vselect wd, wt/i8, ws) - -bmnzi.b, bmzi.b: - Like their non-immediate counterparts, bmnzi.v and bmzi.v are the same - operation with the operands swapped. bmnzi.v will (currently) be emitted - for both cases. - -bseli.v: - Unlike the non-immediate versions, bseli.v is distinguishable from - bmnzi.b and bmzi.b and can be emitted. diff --git a/contrib/llvm/lib/Target/Mips/MicroMips32r6InstrFormats.td b/contrib/llvm/lib/Target/Mips/MicroMips32r6InstrFormats.td deleted file mode 100644 index dbff0f6200f2..000000000000 --- a/contrib/llvm/lib/Target/Mips/MicroMips32r6InstrFormats.td +++ /dev/null @@ -1,1030 +0,0 @@ -//=- MicroMips32r6InstrFormats.td - Mips32r6 Instruction Formats -*- tablegen -*-==// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file describes microMIPS32r6 instruction formats. -// -//===----------------------------------------------------------------------===// - -class MMR6Arch<string opstr> { - string Arch = "micromipsr6"; - string BaseOpcode = opstr; - string DecoderNamespace = "MicroMipsR6"; -} - -//===----------------------------------------------------------------------===// -// -// Disambiguators -// -//===----------------------------------------------------------------------===// -// -// Some encodings are ambiguous except by comparing field values. - -class MMDecodeDisambiguatedBy<string Name> : DecodeDisambiguates<Name> { - string DecoderNamespace = "MicroMipsR6_Ambiguous"; -} - -//===----------------------------------------------------------------------===// -// -// Encoding Formats -// -//===----------------------------------------------------------------------===// - -class BC16_FM_MM16R6 { - bits<10> offset; - - bits<16> Inst; - - let Inst{15-10} = 0x33; - let Inst{9-0} = offset; -} - -class BEQZC_BNEZC_FM_MM16R6<bits<6> op> { - bits<3> rs; - bits<7> offset; - - bits<16> Inst; - - let Inst{15-10} = op; - let Inst{9-7} = rs; - let Inst{6-0} = offset; -} - -class POOL16C_JALRC_FM_MM16R6<bits<5> op> { - bits<5> rs; - - bits<16> Inst; - - let Inst{15-10} = 0x11; - let Inst{9-5} = rs; - let Inst{4-0} = op; -} - -class POP35_BOVC_FM_MMR6<string instr_asm> : MipsR6Inst, MMR6Arch<instr_asm> { - bits<5> rt; - bits<5> rs; - bits<16> offset; - - bits<32> Inst; - - let Inst{31-26} = 0b011101; - let Inst{25-21} = rt; - let Inst{20-16} = rs; - let Inst{15-0} = offset; -} - -class POP37_BNVC_FM_MMR6<string instr_asm> : MipsR6Inst, MMR6Arch<instr_asm> { - bits<5> rt; - bits<5> rs; - bits<16> offset; - - bits<32> Inst; - - let Inst{31-26} = 0b011111; - let Inst{25-21} = rt; - let Inst{20-16} = rs; - let Inst{15-0} = offset; -} - -class POOL16C_JRCADDIUSP_FM_MM16R6<bits<5> op> { - bits<5> imm; - - bits<16> Inst; - - let Inst{15-10} = 0x11; - let Inst{9-5} = imm; - let Inst{4-0} = op; -} - -class POOL16C_LWM_SWM_FM_MM16R6<bits<4> funct> { - bits<2> rt; - bits<4> addr; - - bits<16> Inst; - - let Inst{15-10} = 0x11; - let Inst{9-8} = rt; - let Inst{7-4} = addr; - let Inst{3-0} = funct; -} - -class POOL32A_BITSWAP_FM_MMR6<bits<6> funct> : MipsR6Inst { - bits<5> rd; - bits<5> rt; - - bits<32> Inst; - - let Inst{31-26} = 0b000000; - let Inst{25-21} = rt; - let Inst{20-16} = rd; - let Inst{15-12} = 0b0000; - let Inst{11-6} = funct; - let Inst{5-0} = 0b111100; -} - -class CACHE_PREF_FM_MMR6<bits<6> opgroup, bits<4> funct> : MipsR6Inst { - bits<21> addr; - bits<5> hint; - - bits<32> Inst; - - let Inst{31-26} = opgroup; - let Inst{25-21} = hint; - let Inst{20-16} = addr{20-16}; - let Inst{15-12} = funct; - let Inst{11-0} = addr{11-0}; -} - -class ARITH_FM_MMR6<string instr_asm, bits<10> funct> : MMR6Arch<instr_asm> { - bits<5> rd; - bits<5> rt; - bits<5> rs; - - bits<32> Inst; - - let Inst{31-26} = 0; - let Inst{25-21} = rt; - let Inst{20-16} = rs; - let Inst{15-11} = rd; - let Inst{10} = 0; - let Inst{9-0} = funct; -} - -class ADDI_FM_MMR6<string instr_asm, bits<6> op> : MMR6Arch<instr_asm> { - bits<5> rt; - bits<5> rs; - bits<16> imm16; - - bits<32> Inst; - - let Inst{31-26} = op; - let Inst{25-21} = rt; - let Inst{20-16} = rs; - let Inst{15-0} = imm16; -} - -class LB32_FM_MMR6 : MipsR6Inst { - bits<21> addr; - bits<5> rt; - bits<5> base = addr{20-16}; - bits<16> offset = addr{15-0}; - - bits<32> Inst; - - let Inst{31-26} = 0b000111; - let Inst{25-21} = rt; - let Inst{20-16} = base; - let Inst{15-0} = offset; -} - -class LBU32_FM_MMR6 : MipsR6Inst { - bits<21> addr; - bits<5> rt; - bits<5> base = addr{20-16}; - bits<16> offset = addr{15-0}; - - bits<32> Inst; - - let Inst{31-26} = 0b000101; - let Inst{25-21} = rt; - let Inst{20-16} = base; - let Inst{15-0} = offset; -} - -class PCREL19_FM_MMR6<bits<2> funct> : MipsR6Inst { - bits<5> rt; - bits<19> imm; - - bits<32> Inst; - - let Inst{31-26} = 0b011110; - let Inst{25-21} = rt; - let Inst{20-19} = funct; - let Inst{18-0} = imm; -} - -class PCREL16_FM_MMR6<bits<5> funct> : MipsR6Inst { - bits<5> rt; - bits<16> imm; - - bits<32> Inst; - - let Inst{31-26} = 0b011110; - let Inst{25-21} = rt; - let Inst{20-16} = funct; - let Inst{15-0} = imm; -} - -class POOL32A_FM_MMR6<bits<10> funct> : MipsR6Inst { - bits<5> rd; - bits<5> rs; - bits<5> rt; - - bits<32> Inst; - - let Inst{31-26} = 0b000000; - let Inst{25-21} = rt; - let Inst{20-16} = rs; - let Inst{15-11} = rd; - let Inst{10} = 0; - let Inst{9-0} = funct; -} - -class POOL32A_PAUSE_FM_MMR6<string instr_asm, bits<5> op> : MMR6Arch<instr_asm> { - bits<32> Inst; - - let Inst{31-26} = 0; - let Inst{25-21} = 0; - let Inst{20-16} = 0; - let Inst{15-11} = op; - let Inst{10-6} = 0; - let Inst{5-0} = 0; -} - -class POOL32A_RDPGPR_FM_MMR6<bits<10> funct> { - bits<5> rt; - bits<5> rd; - bits<32> Inst; - - let Inst{31-26} = 0; - let Inst{25-21} = rt; - let Inst{20-16} = rd; - let Inst{15-6} = funct; - let Inst{5-0} = 0b111100; -} - -class POOL32A_RDHWR_FM_MMR6 { - bits<5> rt; - bits<5> rs; - bits<3> sel; - bits<32> Inst; - - let Inst{31-26} = 0; - let Inst{25-21} = rt; - let Inst{20-16} = rs; - let Inst{15-14} = 0; - let Inst{13-11} = sel; - let Inst{10} = 0; - let Inst{9-0} = 0b0111000000; -} - -class POOL32A_SYNC_FM_MMR6 { - bits<5> stype; - - bits<32> Inst; - - let Inst{31-26} = 0; - let Inst{25-21} = 0; - let Inst{20-16} = stype; - let Inst{15-6} = 0b0110101101; - let Inst{5-0} = 0b111100; -} - -class POOL32I_SYNCI_FM_MMR6 { - bits<21> addr; - bits<5> base = addr{20-16}; - bits<16> immediate = addr{15-0}; - - bits<32> Inst; - - let Inst{31-26} = 0b010000; - let Inst{25-21} = 0b01100; - let Inst{20-16} = base; - let Inst{15-0} = immediate; -} - -class POOL32A_2R_FM_MMR6<bits<10> funct> : MipsR6Inst { - bits<5> rs; - bits<5> rt; - - bits<32> Inst; - - let Inst{31-26} = 0b000000; - let Inst{25-21} = rt; - let Inst{20-16} = rs; - let Inst{15-6} = funct; - let Inst{5-0} = 0b111100; -} - -class SPECIAL_2R_FM_MMR6<bits<6> funct> : MipsR6Inst { - bits<5> rs; - bits<5> rt; - - bits<32> Inst; - - let Inst{31-26} = 0b000000; - let Inst{25-21} = rs; - let Inst{20-16} = 0b00000; - let Inst{15-11} = rt; - let Inst{10-6} = 0b00001; - let Inst{5-0} = funct; -} - -class POOL32A_ALIGN_FM_MMR6<bits<6> funct> : MipsR6Inst { - bits<5> rd; - bits<5> rs; - bits<5> rt; - bits<2> bp; - - bits<32> Inst; - - let Inst{31-26} = 0b000000; - let Inst{25-21} = rs; - let Inst{20-16} = rt; - let Inst{15-11} = rd; - let Inst{10-9} = bp; - let Inst{8-6} = 0b000; - let Inst{5-0} = funct; -} - -class AUI_FM_MMR6 : MipsR6Inst { - bits<5> rs; - bits<5> rt; - bits<16> imm; - - bits<32> Inst; - - let Inst{31-26} = 0b000100; - let Inst{25-21} = rt; - let Inst{20-16} = rs; - let Inst{15-0} = imm; -} - -class POOL32A_LSA_FM<bits<6> funct> : MipsR6Inst { - bits<5> rd; - bits<5> rs; - bits<5> rt; - bits<2> imm2; - - bits<32> Inst; - - let Inst{31-26} = 0b000000; - let Inst{25-21} = rt; - let Inst{20-16} = rs; - let Inst{15-11} = rd; - let Inst{10-9} = imm2; - let Inst{8-6} = 0b000; - let Inst{5-0} = funct; -} - -class SB32_SH32_STORE_FM_MMR6<bits<6> op> { - bits<5> rt; - bits<21> addr; - bits<5> base = addr{20-16}; - bits<16> offset = addr{15-0}; - - bits<32> Inst; - - let Inst{31-26} = op; - let Inst{25-21} = rt; - let Inst{20-16} = base; - let Inst{15-0} = offset; -} - -class LOAD_WORD_FM_MMR6 { - bits<5> rt; - bits<21> addr; - bits<5> base = addr{20-16}; - bits<16> offset = addr{15-0}; - - bits<32> Inst; - - let Inst{31-26} = 0b111111; - let Inst{25-21} = rt; - let Inst{20-16} = base; - let Inst{15-0} = offset; -} - -class LOAD_UPPER_IMM_FM_MMR6 { - bits<5> rt; - bits<16> imm16; - - bits<32> Inst; - - let Inst{31-26} = 0b000100; - let Inst{25-21} = rt; - let Inst{20-16} = 0; - let Inst{15-0} = imm16; -} - -class CMP_BRANCH_1R_RT_OFF16_FM_MMR6<string instr_asm, bits<6> funct> - : MMR6Arch<instr_asm>, MipsR6Inst { - bits<5> rt; - bits<16> offset; - - bits<32> Inst; - - let Inst{31-26} = funct; - let Inst{25-21} = rt; - let Inst{20-16} = 0b00000; - let Inst{15-0} = offset; -} - -class CMP_BRANCH_1R_BOTH_OFF16_FM_MMR6<string instr_asm, bits<6> funct> - : MMR6Arch<instr_asm>, MipsR6Inst { - bits<5> rt; - bits<16> offset; - - bits<32> Inst; - - let Inst{31-26} = funct; - let Inst{25-21} = rt; - let Inst{20-16} = rt; - let Inst{15-0} = offset; -} - -class POOL32A_JALRC_FM_MMR6<string instr_asm, bits<10> funct> - : MipsR6Inst, MMR6Arch<instr_asm> { - bits<5> rt; - bits<5> rs; - - bits<32> Inst; - - let Inst{31-26} = 0; - let Inst{25-21} = rt; - let Inst{20-16} = rs; - let Inst{15-6} = funct; - let Inst{5-0} = 0b111100; -} - -class POOL32A_EXT_INS_FM_MMR6<string instr_asm, bits<6> funct> - : MMR6Arch<instr_asm>, MipsR6Inst { - bits<5> rt; - bits<5> rs; - bits<5> size; - bits<5> pos; - - bits<32> Inst; - - let Inst{31-26} = 0; - let Inst{25-21} = rt; - let Inst{20-16} = rs; - let Inst{15-11} = size; - let Inst{10-6} = pos; - let Inst{5-0} = funct; -} - -class POOL32A_ERET_FM_MMR6<string instr_asm, bits<10> funct> - : MMR6Arch<instr_asm> { - bits<32> Inst; - - let Inst{31-26} = 0x00; - let Inst{25-16} = 0x00; - let Inst{15-6} = funct; - let Inst{5-0} = 0x3c; -} - -class ERETNC_FM_MMR6<string instr_asm> : MMR6Arch<instr_asm> { - bits<32> Inst; - - let Inst{31-26} = 0x00; - let Inst{25-17} = 0x00; - let Inst{16-16} = 0x01; - let Inst{15-6} = 0x3cd; - let Inst{5-0} = 0x3c; -} - -class BREAK_MMR6_ENC<string instr_asm> : MMR6Arch<instr_asm> { - bits<10> code_1; - bits<10> code_2; - bits<32> Inst; - let Inst{31-26} = 0x0; - let Inst{25-16} = code_1; - let Inst{15-6} = code_2; - let Inst{5-0} = 0x07; -} - -class BARRIER_MMR6_ENC<string instr_asm, bits<5> op> : MMR6Arch<instr_asm> { - bits<32> Inst; - - let Inst{31-26} = 0x0; - let Inst{25-21} = 0x0; - let Inst{20-16} = 0x0; - let Inst{15-11} = op; - let Inst{10-6} = 0x0; - let Inst{5-0} = 0x0; -} - -class POOL32A_EIDI_MMR6_ENC<string instr_asm, bits<10> funct> - : MMR6Arch<instr_asm> { - bits<32> Inst; - bits<5> rt; // Actually rs but we're sharing code with the standard encodings which call it rt - - let Inst{31-26} = 0x00; - let Inst{25-21} = 0x00; - let Inst{20-16} = rt; - let Inst{15-6} = funct; - let Inst{5-0} = 0x3c; -} - -class SHIFT_MMR6_ENC<string instr_asm, bits<10> funct, bit rotate> : MMR6Arch<instr_asm> { - bits<5> rd; - bits<5> rt; - bits<5> shamt; - - bits<32> Inst; - - let Inst{31-26} = 0; - let Inst{25-21} = rd; - let Inst{20-16} = rt; - let Inst{15-11} = shamt; - let Inst{10} = rotate; - let Inst{9-0} = funct; -} - -class SW32_FM_MMR6<string instr_asm, bits<6> op> : MMR6Arch<instr_asm> { - bits<5> rt; - bits<21> addr; - - bits<32> Inst; - - let Inst{31-26} = op; - let Inst{25-21} = rt; - let Inst{20-16} = addr{20-16}; - let Inst{15-0} = addr{15-0}; -} - -class POOL32F_ARITH_FM_MMR6<string instr_asm, bits<2> fmt, bits<8> funct> - : MMR6Arch<instr_asm>, MipsR6Inst { - bits<5> ft; - bits<5> fs; - bits<5> fd; - - bits<32> Inst; - - let Inst{31-26} = 0b010101; - let Inst{25-21} = ft; - let Inst{20-16} = fs; - let Inst{15-11} = fd; - let Inst{10} = 0; - let Inst{9-8} = fmt; - let Inst{7-0} = funct; -} - -class POOL32F_ARITHF_FM_MMR6<string instr_asm, bits<2> fmt, bits<9> funct> - : MMR6Arch<instr_asm>, MipsR6Inst { - bits<5> ft; - bits<5> fs; - bits<5> fd; - - bits<32> Inst; - - let Inst{31-26} = 0b010101; - let Inst{25-21} = ft; - let Inst{20-16} = fs; - let Inst{15-11} = fd; - let Inst{10-9} = fmt; - let Inst{8-0} = funct; -} - -class POOL32F_MOV_NEG_FM_MMR6<string instr_asm, bits<2> fmt, bits<7> funct> - : MMR6Arch<instr_asm>, MipsR6Inst { - bits<5> ft; - bits<5> fs; - - bits<32> Inst; - - let Inst{31-26} = 0b010101; - let Inst{25-21} = ft; - let Inst{20-16} = fs; - let Inst{15} = 0; - let Inst{14-13} = fmt; - let Inst{12-6} = funct; - let Inst{5-0} = 0b111011; -} - -class POOL32F_MINMAX_FM<string instr_asm, bits<2> fmt, bits<9> funct> - : MMR6Arch<instr_asm>, MipsR6Inst { - bits<5> ft; - bits<5> fs; - bits<5> fd; - - bits<32> Inst; - - let Inst{31-26} = 0b010101; - let Inst{25-21} = ft; - let Inst{20-16} = fs; - let Inst{15-11} = fd; - let Inst{10-9} = fmt; - let Inst{8-0} = funct; -} - -class POOL32F_CMP_FM<string instr_asm, bits<6> format, FIELD_CMP_COND Cond> - : MMR6Arch<instr_asm>, MipsR6Inst { - bits<5> ft; - bits<5> fs; - bits<5> fd; - - bits<32> Inst; - - let Inst{31-26} = 0b010101; - let Inst{25-21} = ft; - let Inst{20-16} = fs; - let Inst{15-11} = fd; - let Inst{10-6} = Cond.Value; - let Inst{5-0} = format; -} - -class POOL32F_CVT_LW_FM<string instr_asm, bit fmt, bits<8> funct> - : MMR6Arch<instr_asm>, MipsR6Inst { - bits<5> ft; - bits<5> fs; - - bits<32> Inst; - let Inst{31-26} = 0b010101; - let Inst{25-21} = ft; - let Inst{20-16} = fs; - let Inst{15} = 0; - let Inst{14} = fmt; - let Inst{13-6} = funct; - let Inst{5-0} = 0b111011; -} - -class POOL32F_CVT_DS_FM<string instr_asm, bits<2> fmt, bits<7> funct> - : MMR6Arch<instr_asm>, MipsR6Inst { - bits<5> ft; - bits<5> fs; - - bits<32> Inst; - let Inst{31-26} = 0b010101; - let Inst{25-21} = ft; - let Inst{20-16} = fs; - let Inst{15} = 0; - let Inst{14-13} = fmt; - let Inst{12-6} = funct; - let Inst{5-0} = 0b111011; -} - -class POOL32F_ABS_FM_MMR6<string instr_asm, bits<2> fmt, bits<7> funct> - : MMR6Arch<instr_asm>, MipsR6Inst { - bits<5> ft; - bits<5> fs; - - bits<32> Inst; - - let Inst{31-26} = 0b010101; - let Inst{25-21} = ft; - let Inst{20-16} = fs; - let Inst{15} = 0; - let Inst{14-13} = fmt; - let Inst{12-6} = funct; - let Inst{5-0} = 0b111011; -} - -class POOL32F_MATH_FM_MMR6<string instr_asm, bits<1> fmt, bits<8> funct> - : MMR6Arch<instr_asm>, MipsR6Inst { - bits<5> ft; - bits<5> fs; - - bits<32> Inst; - - let Inst{31-26} = 0b010101; - let Inst{25-21} = ft; - let Inst{20-16} = fs; - let Inst{15} = 0; - let Inst{14} = fmt; - let Inst{13-6} = funct; - let Inst{5-0} = 0b111011; -} - -class POOL16A_ADDU16_FM_MMR6 { - bits<3> rs; - bits<3> rt; - bits<3> rd; - - bits<16> Inst; - - let Inst{15-10} = 0b000001; - let Inst{9-7} = rs; - let Inst{6-4} = rt; - let Inst{3-1} = rd; - let Inst{0} = 0; -} - -class POOL16C_AND16_FM_MMR6 { - bits<3> rt; - bits<3> rs; - - bits<16> Inst; - - let Inst{15-10} = 0b010001; - let Inst{9-7} = rt; - let Inst{6-4} = rs; - let Inst{3-0} = 0b0001; -} - -class POOL16C_NOT16_FM_MMR6 { - bits<3> rt; - bits<3> rs; - - bits<16> Inst; - - let Inst{15-10} = 0x11; - let Inst{9-7} = rt; - let Inst{6-4} = rs; - let Inst{3-0} = 0b0000; -} - -class POOL16C_MOVEP16_FM_MMR6 { - bits<3> dst_regs; - bits<3> rt; - bits<3> rs; - - bits<16> Inst; - - let Inst{15-10} = 0b010001; - let Inst{9-7} = dst_regs; - let Inst{6-4} = rt; - let Inst{3} = rs{2}; - let Inst{2} = 0b1; - let Inst{1-0} = rs{1-0}; -} - -class POOL16C_OR16_XOR16_FM_MMR6<bits<4> op> { - bits<3> rt; - bits<3> rs; - - bits<16> Inst; - - let Inst{15-10} = 0b010001; - let Inst{9-7} = rt; - let Inst{6-4} = rs; - let Inst{3-0} = op; -} - -class POOL16C_BREAKPOINT_FM_MMR6<bits<6> op> { - bits<4> code_; - bits<16> Inst; - - let Inst{15-10} = 0b010001; - let Inst{9-6} = code_; - let Inst{5-0} = op; -} - -class POOL16A_SUBU16_FM_MMR6 { - bits<3> rs; - bits<3> rt; - bits<3> rd; - - bits<16> Inst; - - let Inst{15-10} = 0b000001; - let Inst{9-7} = rs; - let Inst{6-4} = rt; - let Inst{3-1} = rd; - let Inst{0} = 0b1; -} - -class POOL32A_WRPGPR_WSBH_FM_MMR6<string instr_asm, bits<10> funct> - : MMR6Arch<instr_asm>, MipsR6Inst { - bits<5> rt; - bits<5> rs; - - bits<32> Inst; - - let Inst{31-26} = 0x00; - let Inst{25-21} = rt; - let Inst{20-16} = rs; - let Inst{15-6} = funct; - let Inst{5-0} = 0x3c; -} - -class POOL32F_RECIP_ROUND_FM_MMR6<string instr_asm, bits<1> fmt, bits<8> funct> - : MMR6Arch<instr_asm>, MipsR6Inst { - bits<5> ft; - bits<5> fs; - - bits<32> Inst; - - let Inst{31-26} = 0b010101; - let Inst{25-21} = ft; - let Inst{20-16} = fs; - let Inst{15} = 0; - let Inst{14} = fmt; - let Inst{13-6} = funct; - let Inst{5-0} = 0b111011; -} - -class POOL32F_RINT_FM_MMR6<string instr_asm, bits<2> fmt> - : MMR6Arch<instr_asm>, MipsR6Inst { - bits<5> fs; - bits<5> fd; - - bits<32> Inst; - - let Inst{31-26} = 0b010101; - let Inst{25-21} = fs; - let Inst{20-16} = fd; - let Inst{15-11} = 0; - let Inst{10-9} = fmt; - let Inst{8-0} = 0b000100000; -} - -class POOL32F_SEL_FM_MMR6<string instr_asm, bits<2> fmt, bits<9> funct> - : MMR6Arch<instr_asm>, MipsR6Inst { - bits<5> ft; - bits<5> fs; - bits<5> fd; - - bits<32> Inst; - - let Inst{31-26} = 0b010101; - let Inst{25-21} = ft; - let Inst{20-16} = fs; - let Inst{15-11} = fd; - let Inst{10-9} = fmt; - let Inst{8-0} = funct; -} - -class POOL32F_CLASS_FM_MMR6<string instr_asm, bits<2> fmt, bits<9> funct> - : MMR6Arch<instr_asm>, MipsR6Inst { - bits<5> fs; - bits<5> fd; - - bits<32> Inst; - - let Inst{31-26} = 0b010101; - let Inst{25-21} = fs; - let Inst{20-16} = fd; - let Inst{15-11} = 0b00000; - let Inst{10-9} = fmt; - let Inst{8-0} = funct; -} - -class POOL32A_TLBINV_FM_MMR6<string instr_asm, bits<10> funct> - : MMR6Arch<instr_asm>, MipsR6Inst { - bits<32> Inst; - - let Inst{31-26} = 0x0; - let Inst{25-16} = 0x0; - let Inst{15-6} = funct; - let Inst{5-0} = 0b111100; -} - -class POOL32A_MFTC0_FM_MMR6<string instr_asm, bits<5> funct, bits<6> opcode> - : MMR6Arch<instr_asm>, MipsR6Inst { - bits<5> rt; - bits<5> rs; - bits<3> sel; - - bits<32> Inst; - - let Inst{31-26} = 0b000000; - let Inst{25-21} = rt; - let Inst{20-16} = rs; - let Inst{15-14} = 0; - let Inst{13-11} = sel; - let Inst{10-6} = funct; - let Inst{5-0} = opcode; -} - -class POOL32A_GINV_FM_MMR6<string instr_asm, bits<2> ginv> - : MMR6Arch<instr_asm>, MipsR6Inst { - bits<5> rs; - bits<2> type; - - bits<32> Inst; - - let Inst{31-26} = 0x0; - let Inst{25-21} = 0x0; - let Inst{20-16} = rs; - let Inst{15-13} = 0b011; - let Inst{12-11} = ginv; - let Inst{10-9} = type; - let Inst{8-6} = 0b101; - let Inst{5-0} = 0b111100; -} - -class POOL32F_MFTC1_FM_MMR6<string instr_asm, bits<8> funct> - : MMR6Arch<instr_asm> { - bits<5> rt; - bits<5> fs; - - bits<32> Inst; - - let Inst{31-26} = 0b010101; - let Inst{25-21} = rt; - let Inst{20-16} = fs; - let Inst{15-14} = 0; - let Inst{13-6} = funct; - let Inst{5-0} = 0b111011; -} - -class POOL32A_MFTC2_FM_MMR6<string instr_asm, bits<10> funct> - : MMR6Arch<instr_asm>, MipsR6Inst { - bits<5> rt; - bits<5> impl; - - bits<32> Inst; - - let Inst{31-26} = 0b000000; - let Inst{25-21} = rt; - let Inst{20-16} = impl; - let Inst{15-6} = funct; - let Inst{5-0} = 0b111100; -} - -class CMP_BRANCH_2R_OFF16_FM_MMR6<string opstr, bits<6> funct> - : MipsR6Inst, MMR6Arch<opstr> { - bits<5> rt; - bits<5> rs; - bits<16> offset; - - bits<32> Inst; - - let Inst{31-26} = funct; - let Inst{25-21} = rt; - let Inst{20-16} = rs; - let Inst{15-0} = offset; -} - -class POOL32A_DVPEVP_FM_MMR6<string instr_asm, bits<10> funct> - : MMR6Arch<instr_asm>, MipsR6Inst { - bits<5> rs; - - bits<32> Inst; - - let Inst{31-26} = 0b000000; - let Inst{25-21} = 0b00000; - let Inst{20-16} = rs; - let Inst{15-6} = funct; - let Inst{5-0} = 0b111100; -} - -class CMP_BRANCH_OFF21_FM_MMR6<string opstr, bits<6> funct> : MipsR6Inst { - bits<5> rs; - bits<21> offset; - - bits<32> Inst; - - let Inst{31-26} = funct; - let Inst{25-21} = rs; - let Inst{20-0} = offset; -} - -class POOL32I_BRANCH_COP_1_2_FM_MMR6<string instr_asm, bits<5> funct> - : MMR6Arch<instr_asm> { - bits<5> rt; - bits<16> offset; - - bits<32> Inst; - - let Inst{31-26} = 0b010000; - let Inst{25-21} = funct; - let Inst{20-16} = rt; - let Inst{15-0} = offset; -} - -class LDWC1_SDWC1_FM_MMR6<string instr_asm, bits<6> funct> - : MMR6Arch<instr_asm> { - bits<5> ft; - bits<21> addr; - bits<5> base = addr{20-16}; - bits<16> offset = addr{15-0}; - - bits<32> Inst; - - let Inst{31-26} = funct; - let Inst{25-21} = ft; - let Inst{20-16} = base; - let Inst{15-0} = offset; -} - -class POOL32B_LDWC2_SDWC2_FM_MMR6<string instr_asm, bits<4> funct> - : MMR6Arch<instr_asm>, MipsR6Inst { - bits<5> rt; - bits<21> addr; - bits<5> base = addr{20-16}; - bits<11> offset = addr{10-0}; - - bits<32> Inst; - - let Inst{31-26} = 0b001000; - let Inst{25-21} = rt; - let Inst{20-16} = base; - let Inst{15-12} = funct; - let Inst{11} = 0; - let Inst{10-0} = offset; -} - -class POOL32C_LL_E_SC_E_FM_MMR6<string instr_asm, bits<4> majorFunc, - bits<3> minorFunc> - : MMR6Arch<instr_asm>, MipsR6Inst { - bits<5> rt; - bits<21> addr; - bits<5> base = addr{20-16}; - bits<9> offset = addr{8-0}; - - bits<32> Inst; - - let Inst{31-26} = 0b011000; - let Inst{25-21} = rt; - let Inst{20-16} = base; - let Inst{15-12} = majorFunc; - let Inst{11-9} = minorFunc; - let Inst{8-0} = offset; -} diff --git a/contrib/llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td b/contrib/llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td deleted file mode 100644 index 425773dc57f1..000000000000 --- a/contrib/llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td +++ /dev/null @@ -1,1837 +0,0 @@ -//=- MicroMips32r6InstrInfo.td - MicroMips r6 Instruction Information -*- tablegen -*-=// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file describes microMIPSr6 instructions. -// -//===----------------------------------------------------------------------===// - -def brtarget21_mm : Operand<OtherVT> { - let EncoderMethod = "getBranchTarget21OpValueMM"; - let OperandType = "OPERAND_PCREL"; - let DecoderMethod = "DecodeBranchTarget21MM"; - let ParserMatchClass = MipsJumpTargetAsmOperand; -} - -def brtarget26_mm : Operand<OtherVT> { - let EncoderMethod = "getBranchTarget26OpValueMM"; - let OperandType = "OPERAND_PCREL"; - let DecoderMethod = "DecodeBranchTarget26MM"; - let ParserMatchClass = MipsJumpTargetAsmOperand; -} - -def brtargetr6 : Operand<OtherVT> { - let EncoderMethod = "getBranchTargetOpValueMMR6"; - let OperandType = "OPERAND_PCREL"; - let DecoderMethod = "DecodeBranchTargetMM"; - let ParserMatchClass = MipsJumpTargetAsmOperand; -} - -def brtarget_lsl2_mm : Operand<OtherVT> { - let EncoderMethod = "getBranchTargetOpValueLsl2MMR6"; - let OperandType = "OPERAND_PCREL"; - // Instructions that use this operand have their decoder method - // set with DecodeDisambiguates - let DecoderMethod = ""; - let ParserMatchClass = MipsJumpTargetAsmOperand; -} - -//===----------------------------------------------------------------------===// -// -// Instruction Encodings -// -//===----------------------------------------------------------------------===// -class ADD_MMR6_ENC : ARITH_FM_MMR6<"add", 0x110>; -class ADDIU_MMR6_ENC : ADDI_FM_MMR6<"addiu", 0xc>; -class ADDU_MMR6_ENC : ARITH_FM_MMR6<"addu", 0x150>; -class ADDIUPC_MMR6_ENC : PCREL19_FM_MMR6<0b00>; -class ALUIPC_MMR6_ENC : PCREL16_FM_MMR6<0b11111>; -class AND_MMR6_ENC : ARITH_FM_MMR6<"and", 0x250>; -class ANDI_MMR6_ENC : ADDI_FM_MMR6<"andi", 0x34>; -class AUIPC_MMR6_ENC : PCREL16_FM_MMR6<0b11110>; -class ALIGN_MMR6_ENC : POOL32A_ALIGN_FM_MMR6<0b011111>; -class AUI_MMR6_ENC : AUI_FM_MMR6; -class BALC_MMR6_ENC : BRANCH_OFF26_FM<0b101101>; -class BC_MMR6_ENC : BRANCH_OFF26_FM<0b100101>; -class BC16_MMR6_ENC : BC16_FM_MM16R6; -class BEQZC16_MMR6_ENC : BEQZC_BNEZC_FM_MM16R6<0x23>; -class BNEZC16_MMR6_ENC : BEQZC_BNEZC_FM_MM16R6<0x2b>; -class BITSWAP_MMR6_ENC : POOL32A_BITSWAP_FM_MMR6<0b101100>; -class BRK_MMR6_ENC : BREAK_MMR6_ENC<"break">; -class BEQZC_MMR6_ENC : CMP_BRANCH_OFF21_FM_MMR6<"beqzc", 0b100000>; -class BNEZC_MMR6_ENC : CMP_BRANCH_OFF21_FM_MMR6<"bnezc", 0b101000>; -class BGEC_MMR6_ENC : CMP_BRANCH_2R_OFF16_FM_MMR6<"bgec", 0b111101>, - DecodeDisambiguates<"POP75GroupBranchMMR6">; -class BGEUC_MMR6_ENC : CMP_BRANCH_2R_OFF16_FM_MMR6<"bgeuc", 0b110000>, - DecodeDisambiguates<"BlezGroupBranchMMR6">; -class BLTC_MMR6_ENC : CMP_BRANCH_2R_OFF16_FM_MMR6<"bltc", 0b110101>, - DecodeDisambiguates<"POP65GroupBranchMMR6">; -class BLTUC_MMR6_ENC : CMP_BRANCH_2R_OFF16_FM_MMR6<"bltuc", 0b111000>, - DecodeDisambiguates<"BgtzGroupBranchMMR6">; -class BEQC_MMR6_ENC : CMP_BRANCH_2R_OFF16_FM_MMR6<"beqc", 0b011101>; -class BNEC_MMR6_ENC : CMP_BRANCH_2R_OFF16_FM_MMR6<"bnec", 0b011111>; -class BLTZC_MMR6_ENC : CMP_BRANCH_1R_BOTH_OFF16_FM_MMR6<"bltzc", 0b110101>, - DecodeDisambiguates<"POP65GroupBranchMMR6">; -class BLEZC_MMR6_ENC : CMP_BRANCH_1R_RT_OFF16_FM_MMR6<"blezc", 0b111101>, - DecodeDisambiguates<"POP75GroupBranchMMR6">; -class BGEZC_MMR6_ENC : CMP_BRANCH_1R_BOTH_OFF16_FM_MMR6<"bgezc", 0b111101>, - DecodeDisambiguates<"POP75GroupBranchMMR6">; -class BGTZC_MMR6_ENC : CMP_BRANCH_1R_RT_OFF16_FM_MMR6<"bgtzc", 0b110101>, - DecodeDisambiguates<"POP65GroupBranchMMR6">; -class BEQZALC_MMR6_ENC : CMP_BRANCH_1R_RT_OFF16_FM_MMR6<"beqzalc", 0b011101>, - DecodeDisambiguates<"POP35GroupBranchMMR6">; -class BNEZALC_MMR6_ENC : CMP_BRANCH_1R_RT_OFF16_FM_MMR6<"bnezalc", 0b011111>, - DecodeDisambiguates<"POP37GroupBranchMMR6">; -class BGTZALC_MMR6_ENC : CMP_BRANCH_1R_RT_OFF16_FM_MMR6<"bgtzalc", 0b111000>, - MMDecodeDisambiguatedBy<"BgtzGroupBranchMMR6">; -class BLTZALC_MMR6_ENC : CMP_BRANCH_1R_BOTH_OFF16_FM_MMR6<"bltzalc", 0b111000>, - MMDecodeDisambiguatedBy<"BgtzGroupBranchMMR6">; -class BGEZALC_MMR6_ENC : CMP_BRANCH_1R_BOTH_OFF16_FM_MMR6<"bgezalc", 0b110000>, - MMDecodeDisambiguatedBy<"BlezGroupBranchMMR6">; -class BLEZALC_MMR6_ENC : CMP_BRANCH_1R_RT_OFF16_FM_MMR6<"blezalc", 0b110000>, - MMDecodeDisambiguatedBy<"BlezGroupBranchMMR6">; -class CACHE_MMR6_ENC : CACHE_PREF_FM_MMR6<0b001000, 0b0110>; -class CLO_MMR6_ENC : POOL32A_2R_FM_MMR6<0b0100101100>; -class CLZ_MMR6_ENC : SPECIAL_2R_FM_MMR6<0b010000>; -class DIV_MMR6_ENC : ARITH_FM_MMR6<"div", 0x118>; -class DIVU_MMR6_ENC : ARITH_FM_MMR6<"divu", 0x198>; -class EHB_MMR6_ENC : BARRIER_MMR6_ENC<"ehb", 0x3>; -class EI_MMR6_ENC : POOL32A_EIDI_MMR6_ENC<"ei", 0x15d>; -class DI_MMR6_ENC : POOL32A_EIDI_MMR6_ENC<"di", 0b0100011101>; -class ERET_MMR6_ENC : POOL32A_ERET_FM_MMR6<"eret", 0x3cd>; -class DERET_MMR6_ENC : POOL32A_ERET_FM_MMR6<"eret", 0b1110001101>; -class ERETNC_MMR6_ENC : ERETNC_FM_MMR6<"eretnc">; -class GINVI_MMR6_ENC : POOL32A_GINV_FM_MMR6<"ginvi", 0b00>; -class GINVT_MMR6_ENC : POOL32A_GINV_FM_MMR6<"ginvt", 0b10>; -class JALRC16_MMR6_ENC : POOL16C_JALRC_FM_MM16R6<0xb>; -class JIALC_MMR6_ENC : JMP_IDX_COMPACT_FM<0b100000>; -class JIC_MMR6_ENC : JMP_IDX_COMPACT_FM<0b101000>; -class JRC16_MMR6_ENC: POOL16C_JALRC_FM_MM16R6<0x3>; -class JRCADDIUSP_MMR6_ENC : POOL16C_JRCADDIUSP_FM_MM16R6<0x13>; -class LSA_MMR6_ENC : POOL32A_LSA_FM<0b001111>; -class LWPC_MMR6_ENC : PCREL19_FM_MMR6<0b01>; -class LWM16_MMR6_ENC : POOL16C_LWM_SWM_FM_MM16R6<0x2>; -class MFC0_MMR6_ENC : POOL32A_MFTC0_FM_MMR6<"mfc0", 0b00011, 0b111100>; -class MFC1_MMR6_ENC : POOL32F_MFTC1_FM_MMR6<"mfc1", 0b10000000>; -class MFC2_MMR6_ENC : POOL32A_MFTC2_FM_MMR6<"mfc2", 0b0100110100>; -class MFHC0_MMR6_ENC : POOL32A_MFTC0_FM_MMR6<"mfhc0", 0b00011, 0b110100>; -class MFHC2_MMR6_ENC : POOL32A_MFTC2_FM_MMR6<"mfhc2", 0b1000110100>; -class MOD_MMR6_ENC : ARITH_FM_MMR6<"mod", 0x158>; -class MODU_MMR6_ENC : ARITH_FM_MMR6<"modu", 0x1d8>; -class MUL_MMR6_ENC : ARITH_FM_MMR6<"mul", 0x18>; -class MUH_MMR6_ENC : ARITH_FM_MMR6<"muh", 0x58>; -class MULU_MMR6_ENC : ARITH_FM_MMR6<"mulu", 0x98>; -class MUHU_MMR6_ENC : ARITH_FM_MMR6<"muhu", 0xd8>; -class MTC0_MMR6_ENC : POOL32A_MFTC0_FM_MMR6<"mtc0", 0b01011, 0b111100>; -class MTC1_MMR6_ENC : POOL32F_MFTC1_FM_MMR6<"mtc1", 0b10100000>; -class MTC2_MMR6_ENC : POOL32A_MFTC2_FM_MMR6<"mtc2", 0b0101110100>; -class MTHC0_MMR6_ENC : POOL32A_MFTC0_FM_MMR6<"mthc0", 0b01011, 0b110100>; -class MTHC2_MMR6_ENC : POOL32A_MFTC2_FM_MMR6<"mthc2", 0b1001110100>; -class NOR_MMR6_ENC : ARITH_FM_MMR6<"nor", 0x2d0>; -class OR_MMR6_ENC : ARITH_FM_MMR6<"or", 0x290>; -class ORI_MMR6_ENC : ADDI_FM_MMR6<"ori", 0x14>; -class PREF_MMR6_ENC : CACHE_PREF_FM_MMR6<0b011000, 0b0010>; -class SB16_MMR6_ENC : LOAD_STORE_FM_MM16<0x22>; -class SELEQZ_MMR6_ENC : POOL32A_FM_MMR6<0b0101000000>; -class SELNEZ_MMR6_ENC : POOL32A_FM_MMR6<0b0110000000>; -class SH16_MMR6_ENC : LOAD_STORE_FM_MM16<0x2a>; -class SLL_MMR6_ENC : SHIFT_MMR6_ENC<"sll", 0x00, 0b0>; -class SUB_MMR6_ENC : ARITH_FM_MMR6<"sub", 0x190>; -class SUBU_MMR6_ENC : ARITH_FM_MMR6<"subu", 0x1d0>; -class SW_MMR6_ENC : SW32_FM_MMR6<"sw", 0x3e>; -class SW16_MMR6_ENC : LOAD_STORE_FM_MM16<0x3a>; -class SWM16_MMR6_ENC : POOL16C_LWM_SWM_FM_MM16R6<0xa>; -class SWSP_MMR6_ENC : LOAD_STORE_SP_FM_MM16<0x32>; -class WRPGPR_MMR6_ENC : POOL32A_WRPGPR_WSBH_FM_MMR6<"wrpgpr", 0x3c5>; -class WSBH_MMR6_ENC : POOL32A_WRPGPR_WSBH_FM_MMR6<"wsbh", 0x1ec>; -class LB_MMR6_ENC : LB32_FM_MMR6; -class LBU_MMR6_ENC : LBU32_FM_MMR6; -class PAUSE_MMR6_ENC : POOL32A_PAUSE_FM_MMR6<"pause", 0b00101>; -class RDHWR_MMR6_ENC : POOL32A_RDHWR_FM_MMR6; -class WAIT_MMR6_ENC : WAIT_FM_MM, MMR6Arch<"wait">; -class SSNOP_MMR6_ENC : BARRIER_FM_MM<0x1>, MMR6Arch<"ssnop">; -class SYNC_MMR6_ENC : POOL32A_SYNC_FM_MMR6; -class SYNCI_MMR6_ENC : POOL32I_SYNCI_FM_MMR6, MMR6Arch<"synci">; -class RDPGPR_MMR6_ENC : POOL32A_RDPGPR_FM_MMR6<0b1110000101>; -class SDBBP_MMR6_ENC : SDBBP_FM_MM, MMR6Arch<"sdbbp">; -class SIGRIE_MMR6_ENC : SIGRIE_FM_MM, MMR6Arch<"sigrie">; -class XOR_MMR6_ENC : ARITH_FM_MMR6<"xor", 0x310>; -class XORI_MMR6_ENC : ADDI_FM_MMR6<"xori", 0x1c>; -class ABS_S_MMR6_ENC : POOL32F_ABS_FM_MMR6<"abs.s", 0, 0b0001101>; -class ABS_D_MMR6_ENC : POOL32F_ABS_FM_MMR6<"abs.d", 1, 0b0001101>; -class FLOOR_L_S_MMR6_ENC : POOL32F_MATH_FM_MMR6<"floor.l.s", 0, 0b00001100>; -class FLOOR_L_D_MMR6_ENC : POOL32F_MATH_FM_MMR6<"floor.l.d", 1, 0b00001100>; -class FLOOR_W_S_MMR6_ENC : POOL32F_MATH_FM_MMR6<"floor.w.s", 0, 0b00101100>; -class FLOOR_W_D_MMR6_ENC : POOL32F_MATH_FM_MMR6<"floor.w.d", 1, 0b00101100>; -class CEIL_L_S_MMR6_ENC : POOL32F_MATH_FM_MMR6<"ceil.l.s", 0, 0b01001100>; -class CEIL_L_D_MMR6_ENC : POOL32F_MATH_FM_MMR6<"ceil.l.d", 1, 0b01001100>; -class CEIL_W_S_MMR6_ENC : POOL32F_MATH_FM_MMR6<"ceil.w.s", 0, 0b01101100>; -class CEIL_W_D_MMR6_ENC : POOL32F_MATH_FM_MMR6<"ceil.w.d", 1, 0b01101100>; -class TRUNC_L_S_MMR6_ENC : POOL32F_MATH_FM_MMR6<"trunc.l.s", 0, 0b10001100>; -class TRUNC_L_D_MMR6_ENC : POOL32F_MATH_FM_MMR6<"trunc.l.d", 1, 0b10001100>; -class TRUNC_W_S_MMR6_ENC : POOL32F_MATH_FM_MMR6<"trunc.w.s", 0, 0b10101100>; -class TRUNC_W_D_MMR6_ENC : POOL32F_MATH_FM_MMR6<"trunc.w.d", 1, 0b10101100>; -class SB_MMR6_ENC : SB32_SH32_STORE_FM_MMR6<0b000110>; -class SH_MMR6_ENC : SB32_SH32_STORE_FM_MMR6<0b001110>; -class LW_MMR6_ENC : LOAD_WORD_FM_MMR6; -class LUI_MMR6_ENC : LOAD_UPPER_IMM_FM_MMR6; -class JALRC_HB_MMR6_ENC : POOL32A_JALRC_FM_MMR6<"jalrc.hb", 0b0001111100>; -class RINT_S_MMR6_ENC : POOL32F_RINT_FM_MMR6<"rint.s", 0>; -class RINT_D_MMR6_ENC : POOL32F_RINT_FM_MMR6<"rint.d", 1>; -class ROUND_L_S_MMR6_ENC : POOL32F_RECIP_ROUND_FM_MMR6<"round.l.s", 0, - 0b11001100>; -class ROUND_L_D_MMR6_ENC : POOL32F_RECIP_ROUND_FM_MMR6<"round.l.d", 1, - 0b11001100>; -class ROUND_W_S_MMR6_ENC : POOL32F_RECIP_ROUND_FM_MMR6<"round.w.s", 0, - 0b11101100>; -class ROUND_W_D_MMR6_ENC : POOL32F_RECIP_ROUND_FM_MMR6<"round.w.d", 1, - 0b11101100>; -class SEL_S_MMR6_ENC : POOL32F_SEL_FM_MMR6<"sel.s", 0, 0b010111000>; -class SEL_D_MMR6_ENC : POOL32F_SEL_FM_MMR6<"sel.d", 1, 0b010111000>; -class SELEQZ_S_MMR6_ENC : POOL32F_SEL_FM_MMR6<"seleqz.s", 0, 0b000111000>; -class SELEQZ_D_MMR6_ENC : POOL32F_SEL_FM_MMR6<"seleqz.d", 1, 0b000111000>; -class SELNEZ_S_MMR6_ENC : POOL32F_SEL_FM_MMR6<"selnez.s", 0, 0b001111000>; -class SELNEZ_D_MMR6_ENC : POOL32F_SEL_FM_MMR6<"selnez.d", 1, 0b001111000>; -class CLASS_S_MMR6_ENC : POOL32F_CLASS_FM_MMR6<"class.s", 0, 0b001100000>; -class CLASS_D_MMR6_ENC : POOL32F_CLASS_FM_MMR6<"class.d", 1, 0b001100000>; -class EXT_MMR6_ENC : POOL32A_EXT_INS_FM_MMR6<"ext", 0b101100>; -class INS_MMR6_ENC : POOL32A_EXT_INS_FM_MMR6<"ins", 0b001100>; -class JALRC_MMR6_ENC : POOL32A_JALRC_FM_MMR6<"jalrc", 0b0000111100>; -class BOVC_MMR6_ENC : POP35_BOVC_FM_MMR6<"bovc">; -class BNVC_MMR6_ENC : POP37_BNVC_FM_MMR6<"bnvc">; -class ADDU16_MMR6_ENC : POOL16A_ADDU16_FM_MMR6; -class AND16_MMR6_ENC : POOL16C_AND16_FM_MMR6; -class ANDI16_MMR6_ENC : ANDI_FM_MM16<0b001011>; -class NOT16_MMR6_ENC : POOL16C_NOT16_FM_MMR6; -class OR16_MMR6_ENC : POOL16C_OR16_XOR16_FM_MMR6<0b1001>; -class SLL16_MMR6_ENC : SHIFT_FM_MM16<0>; -class SRL16_MMR6_ENC : SHIFT_FM_MM16<1>; -class BREAK16_MMR6_ENC : POOL16C_BREAKPOINT_FM_MMR6<0b011011>; -class LI16_MMR6_ENC : LI_FM_MM16; -class MOVE16_MMR6_ENC : MOVE_FM_MM16<0b000011>; -class MOVEP_MMR6_ENC : POOL16C_MOVEP16_FM_MMR6; -class SDBBP16_MMR6_ENC : POOL16C_BREAKPOINT_FM_MMR6<0b111011>; -class SUBU16_MMR6_ENC : POOL16A_SUBU16_FM_MMR6; -class XOR16_MMR6_ENC : POOL16C_OR16_XOR16_FM_MMR6<0b1000>; -class TLBINV_MMR6_ENC : POOL32A_TLBINV_FM_MMR6<"tlbinv", 0x10d>; -class TLBINVF_MMR6_ENC : POOL32A_TLBINV_FM_MMR6<"tlbinvf", 0x14d>; -class DVP_MMR6_ENC : POOL32A_DVPEVP_FM_MMR6<"dvp", 0b0001100101>; -class EVP_MMR6_ENC : POOL32A_DVPEVP_FM_MMR6<"evp", 0b0011100101>; -class BC1EQZC_MMR6_ENC : POOL32I_BRANCH_COP_1_2_FM_MMR6<"bc1eqzc", 0b01000>; -class BC1NEZC_MMR6_ENC : POOL32I_BRANCH_COP_1_2_FM_MMR6<"bc1nezc", 0b01001>; -class BC2EQZC_MMR6_ENC : POOL32I_BRANCH_COP_1_2_FM_MMR6<"bc2eqzc", 0b01010>; -class BC2NEZC_MMR6_ENC : POOL32I_BRANCH_COP_1_2_FM_MMR6<"bc2nezc", 0b01011>; -class LDC1_MMR6_ENC : LDWC1_SDWC1_FM_MMR6<"ldc1", 0b101111>; -class SDC1_MMR6_ENC : LDWC1_SDWC1_FM_MMR6<"sdc1", 0b101110>; -class LDC2_MMR6_ENC : POOL32B_LDWC2_SDWC2_FM_MMR6<"ldc2", 0b0010>; -class SDC2_MMR6_ENC : POOL32B_LDWC2_SDWC2_FM_MMR6<"sdc2", 0b1010>; -class LWC2_MMR6_ENC : POOL32B_LDWC2_SDWC2_FM_MMR6<"lwc2", 0b0000>; -class SWC2_MMR6_ENC : POOL32B_LDWC2_SDWC2_FM_MMR6<"swc2", 0b1000>; - -class LL_MMR6_ENC : POOL32C_LL_E_SC_E_FM_MMR6<"ll", 0b0011, 0b000>; -class SC_MMR6_ENC : POOL32C_LL_E_SC_E_FM_MMR6<"sc", 0b1011, 0b000>; - -/// Floating Point Instructions -class FADD_S_MMR6_ENC : POOL32F_ARITH_FM_MMR6<"add.s", 0, 0b00110000>; -class FSUB_S_MMR6_ENC : POOL32F_ARITH_FM_MMR6<"sub.s", 0, 0b01110000>; -class FMUL_S_MMR6_ENC : POOL32F_ARITH_FM_MMR6<"mul.s", 0, 0b10110000>; -class FDIV_S_MMR6_ENC : POOL32F_ARITH_FM_MMR6<"div.s", 0, 0b11110000>; -class MADDF_S_MMR6_ENC : POOL32F_ARITHF_FM_MMR6<"maddf.s", 0, 0b110111000>; -class MADDF_D_MMR6_ENC : POOL32F_ARITHF_FM_MMR6<"maddf.d", 1, 0b110111000>; -class MSUBF_S_MMR6_ENC : POOL32F_ARITHF_FM_MMR6<"msubf.s", 0, 0b111111000>; -class MSUBF_D_MMR6_ENC : POOL32F_ARITHF_FM_MMR6<"msubf.d", 1, 0b111111000>; -class FMOV_S_MMR6_ENC : POOL32F_MOV_NEG_FM_MMR6<"mov.s", 0, 0b0000001>; -class FMOV_D_MMR6_ENC : POOL32F_MOV_NEG_FM_MMR6<"mov.d", 1, 0b0000001>; -class FNEG_S_MMR6_ENC : POOL32F_MOV_NEG_FM_MMR6<"neg.s", 0, 0b0101101>; -class MAX_S_MMR6_ENC : POOL32F_MINMAX_FM<"max.s", 0, 0b000001011>; -class MAX_D_MMR6_ENC : POOL32F_MINMAX_FM<"max.d", 1, 0b000001011>; -class MAXA_S_MMR6_ENC : POOL32F_MINMAX_FM<"maxa.s", 0, 0b000101011>; -class MAXA_D_MMR6_ENC : POOL32F_MINMAX_FM<"maxa.d", 1, 0b000101011>; -class MIN_S_MMR6_ENC : POOL32F_MINMAX_FM<"min.s", 0, 0b000000011>; -class MIN_D_MMR6_ENC : POOL32F_MINMAX_FM<"min.d", 1, 0b000000011>; -class MINA_S_MMR6_ENC : POOL32F_MINMAX_FM<"mina.s", 0, 0b000100011>; -class MINA_D_MMR6_ENC : POOL32F_MINMAX_FM<"mina.d", 1, 0b000100011>; - -class CVT_L_S_MMR6_ENC : POOL32F_CVT_LW_FM<"cvt.l.s", 0, 0b00000100>; -class CVT_L_D_MMR6_ENC : POOL32F_CVT_LW_FM<"cvt.l.d", 1, 0b00000100>; -class CVT_W_S_MMR6_ENC : POOL32F_CVT_LW_FM<"cvt.w.s", 0, 0b00100100>; -class CVT_D_L_MMR6_ENC : POOL32F_CVT_DS_FM<"cvt.d.l", 2, 0b1001101>; -class CVT_S_W_MMR6_ENC : POOL32F_CVT_DS_FM<"cvt.s.w", 1, 0b1101101>; -class CVT_S_L_MMR6_ENC : POOL32F_CVT_DS_FM<"cvt.s.l", 2, 0b1101101>; - -//===----------------------------------------------------------------------===// -// -// Instruction Descriptions -// -//===----------------------------------------------------------------------===// - -class CMP_CBR_RT_Z_MMR6_DESC_BASE<string instr_asm, DAGOperand opnd, - RegisterOperand GPROpnd> - : BRANCH_DESC_BASE { - dag InOperandList = (ins GPROpnd:$rt, opnd:$offset); - dag OutOperandList = (outs); - string AsmString = !strconcat(instr_asm, "\t$rt, $offset"); - list<Register> Defs = [AT]; - InstrItinClass Itinerary = II_BCCZC; -} - -class BEQZALC_MMR6_DESC : CMP_CBR_RT_Z_MMR6_DESC_BASE<"beqzalc", brtarget_mm, - GPR32Opnd> { - list<Register> Defs = [RA]; -} - -class BGEZALC_MMR6_DESC : CMP_CBR_RT_Z_MMR6_DESC_BASE<"bgezalc", brtarget_mm, - GPR32Opnd> { - list<Register> Defs = [RA]; -} - -class BGTZALC_MMR6_DESC : CMP_CBR_RT_Z_MMR6_DESC_BASE<"bgtzalc", brtarget_mm, - GPR32Opnd> { - list<Register> Defs = [RA]; -} - -class BLEZALC_MMR6_DESC : CMP_CBR_RT_Z_MMR6_DESC_BASE<"blezalc", brtarget_mm, - GPR32Opnd> { - list<Register> Defs = [RA]; -} - -class BLTZALC_MMR6_DESC : CMP_CBR_RT_Z_MMR6_DESC_BASE<"bltzalc", brtarget_mm, - GPR32Opnd> { - list<Register> Defs = [RA]; -} - -class BNEZALC_MMR6_DESC : CMP_CBR_RT_Z_MMR6_DESC_BASE<"bnezalc", brtarget_mm, - GPR32Opnd> { - list<Register> Defs = [RA]; -} - -class BLTZC_MMR6_DESC : CMP_CBR_RT_Z_MMR6_DESC_BASE<"bltzc", brtarget_lsl2_mm, - GPR32Opnd>; -class BLEZC_MMR6_DESC : CMP_CBR_RT_Z_MMR6_DESC_BASE<"blezc", brtarget_lsl2_mm, - GPR32Opnd>; -class BGEZC_MMR6_DESC : CMP_CBR_RT_Z_MMR6_DESC_BASE<"bgezc", brtarget_lsl2_mm, - GPR32Opnd>; -class BGTZC_MMR6_DESC : CMP_CBR_RT_Z_MMR6_DESC_BASE<"bgtzc", brtarget_lsl2_mm, - GPR32Opnd>; - -class CMP_CBR_2R_MMR6_DESC_BASE<string instr_asm, DAGOperand opnd, - RegisterOperand GPROpnd> : BRANCH_DESC_BASE { - dag InOperandList = (ins GPROpnd:$rs, GPROpnd:$rt, opnd:$offset); - dag OutOperandList = (outs); - string AsmString = !strconcat(instr_asm, "\t$rs, $rt, $offset"); - list<Register> Defs = [AT]; - InstrItinClass Itinerary = II_BCCC; -} - -class BGEC_MMR6_DESC : CMP_CBR_2R_MMR6_DESC_BASE<"bgec", brtarget_lsl2_mm, - GPR32Opnd>; -class BGEUC_MMR6_DESC : CMP_CBR_2R_MMR6_DESC_BASE<"bgeuc", brtarget_lsl2_mm, - GPR32Opnd>; -class BLTC_MMR6_DESC : CMP_CBR_2R_MMR6_DESC_BASE<"bltc", brtarget_lsl2_mm, - GPR32Opnd>; -class BLTUC_MMR6_DESC : CMP_CBR_2R_MMR6_DESC_BASE<"bltuc", brtarget_lsl2_mm, - GPR32Opnd>; -class BEQC_MMR6_DESC : CMP_CBR_2R_MMR6_DESC_BASE<"beqc", brtarget_lsl2_mm, - GPR32Opnd>; -class BNEC_MMR6_DESC : CMP_CBR_2R_MMR6_DESC_BASE<"bnec", brtarget_lsl2_mm, - GPR32Opnd>; - -class ADD_MMR6_DESC : ArithLogicR<"add", GPR32Opnd, 1, II_ADD>; -class ADDIU_MMR6_DESC : ArithLogicI<"addiu", simm16, GPR32Opnd, II_ADDIU, immSExt16, add>; -class ADDU_MMR6_DESC : ArithLogicR<"addu", GPR32Opnd, 1, II_ADDU>; -class MUL_MMR6_DESC : ArithLogicR<"mul", GPR32Opnd, 1, II_MUL, mul>; -class MUH_MMR6_DESC : ArithLogicR<"muh", GPR32Opnd, 1, II_MUH, mulhs>; -class MULU_MMR6_DESC : ArithLogicR<"mulu", GPR32Opnd, 1, II_MULU>; -class MUHU_MMR6_DESC : ArithLogicR<"muhu", GPR32Opnd, 1, II_MUHU, mulhu>; - -class BC_MMR6_DESC_BASE<string instr_asm, DAGOperand opnd, InstrItinClass Itin> - : BRANCH_DESC_BASE, MMR6Arch<instr_asm> { - dag InOperandList = (ins opnd:$offset); - dag OutOperandList = (outs); - string AsmString = !strconcat(instr_asm, "\t$offset"); - bit isBarrier = 1; - InstrItinClass Itinerary = Itin; -} - -class BALC_MMR6_DESC : BC_MMR6_DESC_BASE<"balc", brtarget26_mm, II_BALC> { - bit isCall = 1; - list<Register> Defs = [RA]; -} -class BC_MMR6_DESC : BC_MMR6_DESC_BASE<"bc", brtarget26_mm, II_BC> { - list<dag> Pattern = [(br bb:$offset)]; -} - -class BC16_MMR6_DESC : MicroMipsInst16<(outs), (ins brtarget10_mm:$offset), - !strconcat("bc16", "\t$offset"), [], - II_BC, FrmI>, - MMR6Arch<"bc16"> { - let isBranch = 1; - let isTerminator = 1; - let isBarrier = 1; - let hasDelaySlot = 0; - let AdditionalPredicates = [RelocPIC]; - let Defs = [AT]; -} - -class BEQZC_BNEZC_MM16R6_DESC_BASE<string instr_asm> - : CBranchZeroMM<instr_asm, brtarget7_mm, GPRMM16Opnd>, - MMR6Arch<instr_asm> { - let isBranch = 1; - let isTerminator = 1; - let hasDelaySlot = 0; - let Defs = [AT]; -} -class BEQZC16_MMR6_DESC : BEQZC_BNEZC_MM16R6_DESC_BASE<"beqzc16">; -class BNEZC16_MMR6_DESC : BEQZC_BNEZC_MM16R6_DESC_BASE<"bnezc16">; - -class SUB_MMR6_DESC : ArithLogicR<"sub", GPR32Opnd, 0, II_SUB>; -class SUBU_MMR6_DESC : ArithLogicR<"subu", GPR32Opnd, 0,II_SUBU>; - -class BITSWAP_MMR6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> - : MMR6Arch<instr_asm> { - dag OutOperandList = (outs GPROpnd:$rd); - dag InOperandList = (ins GPROpnd:$rt); - string AsmString = !strconcat(instr_asm, "\t$rd, $rt"); - list<dag> Pattern = []; - InstrItinClass Itinerary = II_BITSWAP; -} - -class BITSWAP_MMR6_DESC : BITSWAP_MMR6_DESC_BASE<"bitswap", GPR32Opnd>; - -class BRK_MMR6_DESC : BRK_FT<"break">; - -class CACHE_HINT_MMR6_DESC<string instr_asm, Operand MemOpnd, - RegisterOperand GPROpnd, InstrItinClass Itin> - : MMR6Arch<instr_asm> { - dag OutOperandList = (outs); - dag InOperandList = (ins MemOpnd:$addr, uimm5:$hint); - string AsmString = !strconcat(instr_asm, "\t$hint, $addr"); - list<dag> Pattern = []; - string DecoderMethod = "DecodeCacheOpMM"; - InstrItinClass Itinerary = Itin; -} - -class CACHE_MMR6_DESC : CACHE_HINT_MMR6_DESC<"cache", mem_mm_12, GPR32Opnd, - II_CACHE>; -class PREF_MMR6_DESC : CACHE_HINT_MMR6_DESC<"pref", mem_mm_12, GPR32Opnd, - II_PREF>; - -class LB_LBU_MMR6_DESC_BASE<string instr_asm, Operand MemOpnd, - RegisterOperand GPROpnd, InstrItinClass Itin> - : MMR6Arch<instr_asm> { - dag OutOperandList = (outs GPROpnd:$rt); - dag InOperandList = (ins MemOpnd:$addr); - string AsmString = !strconcat(instr_asm, "\t$rt, $addr"); - string DecoderMethod = "DecodeLoadByte15"; - bit mayLoad = 1; - InstrItinClass Itinerary = Itin; -} -class LB_MMR6_DESC : LB_LBU_MMR6_DESC_BASE<"lb", mem_mm_16, GPR32Opnd, II_LB>; -class LBU_MMR6_DESC : LB_LBU_MMR6_DESC_BASE<"lbu", mem_mm_16, GPR32Opnd, - II_LBU>; - -class CLO_CLZ_MMR6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, - InstrItinClass Itin> : MMR6Arch<instr_asm> { - dag OutOperandList = (outs GPROpnd:$rt); - dag InOperandList = (ins GPROpnd:$rs); - string AsmString = !strconcat(instr_asm, "\t$rt, $rs"); - InstrItinClass Itinerary = Itin; -} - -class CLO_MMR6_DESC : CLO_CLZ_MMR6_DESC_BASE<"clo", GPR32Opnd, II_CLO>; -class CLZ_MMR6_DESC : CLO_CLZ_MMR6_DESC_BASE<"clz", GPR32Opnd, II_CLZ>; - -class EHB_MMR6_DESC : Barrier<"ehb", II_EHB>; -class EI_MMR6_DESC : DEI_FT<"ei", GPR32Opnd, II_EI>; -class DI_MMR6_DESC : DEI_FT<"di", GPR32Opnd, II_DI>; - -class ERET_MMR6_DESC : ER_FT<"eret", II_ERET>; -class DERET_MMR6_DESC : ER_FT<"deret", II_DERET>; -class ERETNC_MMR6_DESC : ER_FT<"eretnc", II_ERETNC>; - -class JALRC16_MMR6_DESC_BASE<string opstr, RegisterOperand RO> - : MicroMipsInst16<(outs), (ins RO:$rs), !strconcat(opstr, "\t$rs"), - [(MipsJmpLink RO:$rs)], II_JALR, FrmR>, - MMR6Arch<opstr> { - let isCall = 1; - let hasDelaySlot = 0; - let Defs = [RA]; - let hasPostISelHook = 1; -} -class JALRC16_MMR6_DESC : JALRC16_MMR6_DESC_BASE<"jalr", GPR32Opnd>; - -class JMP_MMR6_IDX_COMPACT_DESC_BASE<string opstr, DAGOperand opnd, - RegisterOperand GPROpnd, - InstrItinClass Itin> - : MMR6Arch<opstr> { - dag InOperandList = (ins GPROpnd:$rt, opnd:$offset); - string AsmString = !strconcat(opstr, "\t$rt, $offset"); - list<dag> Pattern = []; - bit isTerminator = 1; - bit hasDelaySlot = 0; - InstrItinClass Itinerary = Itin; -} - -class JIALC_MMR6_DESC : JMP_MMR6_IDX_COMPACT_DESC_BASE<"jialc", calloffset16, - GPR32Opnd, II_JIALC> { - bit isCall = 1; - list<Register> Defs = [RA]; -} - -class JIC_MMR6_DESC : JMP_MMR6_IDX_COMPACT_DESC_BASE<"jic", jmpoffset16, - GPR32Opnd, II_JIC> { - bit isBarrier = 1; - list<Register> Defs = [AT]; -} - -class JRC16_MMR6_DESC_BASE<string opstr, RegisterOperand RO> - : MicroMipsInst16<(outs), (ins RO:$rs), !strconcat(opstr, "\t$rs"), - [], II_JR, FrmR>, - MMR6Arch<opstr> { - let hasDelaySlot = 0; - let isBranch = 1; - let isIndirectBranch = 1; -} -class JRC16_MMR6_DESC : JRC16_MMR6_DESC_BASE<"jrc16", GPR32Opnd>; - -class JRCADDIUSP_MMR6_DESC - : MicroMipsInst16<(outs), (ins uimm5_lsl2:$imm), "jrcaddiusp\t$imm", - [], II_JRADDIUSP, FrmR>, - MMR6Arch<"jrcaddiusp"> { - let hasDelaySlot = 0; - let isTerminator = 1; - let isBarrier = 1; - let isBranch = 1; - let isIndirectBranch = 1; -} - -class ALIGN_MMR6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, - Operand ImmOpnd, InstrItinClass Itin> - : MMR6Arch<instr_asm> { - dag OutOperandList = (outs GPROpnd:$rd); - dag InOperandList = (ins GPROpnd:$rs, GPROpnd:$rt, ImmOpnd:$bp); - string AsmString = !strconcat(instr_asm, "\t$rd, $rs, $rt, $bp"); - list<dag> Pattern = []; - InstrItinClass Itinerary = Itin; -} - -class ALIGN_MMR6_DESC : ALIGN_MMR6_DESC_BASE<"align", GPR32Opnd, uimm2, - II_ALIGN>; - -class AUI_MMR6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, - InstrItinClass Itin> : MMR6Arch<instr_asm> { - dag OutOperandList = (outs GPROpnd:$rt); - dag InOperandList = (ins GPROpnd:$rs, uimm16:$imm); - string AsmString = !strconcat(instr_asm, "\t$rt, $rs, $imm"); - list<dag> Pattern = []; - InstrItinClass Itinerary = Itin; -} - -class AUI_MMR6_DESC : AUI_MMR6_DESC_BASE<"aui", GPR32Opnd, II_AUI>; - -class ALUIPC_MMR6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, - InstrItinClass Itin> : MMR6Arch<instr_asm> { - dag OutOperandList = (outs GPROpnd:$rt); - dag InOperandList = (ins simm16:$imm); - string AsmString = !strconcat(instr_asm, "\t$rt, $imm"); - list<dag> Pattern = []; - InstrItinClass Itinerary = Itin; -} - -class ALUIPC_MMR6_DESC : ALUIPC_MMR6_DESC_BASE<"aluipc", GPR32Opnd, II_ALUIPC>; -class AUIPC_MMR6_DESC : ALUIPC_MMR6_DESC_BASE<"auipc", GPR32Opnd, II_AUIPC>; - -class LSA_MMR6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, - Operand ImmOpnd, InstrItinClass Itin> - : MMR6Arch<instr_asm> { - dag OutOperandList = (outs GPROpnd:$rd); - dag InOperandList = (ins GPROpnd:$rs, GPROpnd:$rt, ImmOpnd:$imm2); - string AsmString = !strconcat(instr_asm, "\t$rt, $rs, $rd, $imm2"); - list<dag> Pattern = []; - InstrItinClass Itinerary = Itin; -} - -class LSA_MMR6_DESC : LSA_MMR6_DESC_BASE<"lsa", GPR32Opnd, uimm2_plus1, II_LSA>; - -class PCREL_MMR6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, - Operand ImmOpnd, InstrItinClass Itin> - : MMR6Arch<instr_asm> { - dag OutOperandList = (outs GPROpnd:$rt); - dag InOperandList = (ins ImmOpnd:$imm); - string AsmString = !strconcat(instr_asm, "\t$rt, $imm"); - list<dag> Pattern = []; - InstrItinClass Itinerary = Itin; -} - -class ADDIUPC_MMR6_DESC : PCREL_MMR6_DESC_BASE<"addiupc", GPR32Opnd, - simm19_lsl2, II_ADDIUPC>; -class LWPC_MMR6_DESC: PCREL_MMR6_DESC_BASE<"lwpc", GPR32Opnd, simm19_lsl2, - II_LWPC>; - -class SELEQNE_Z_MMR6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, - InstrItinClass Itin> : MMR6Arch<instr_asm> { - dag OutOperandList = (outs GPROpnd:$rd); - dag InOperandList = (ins GPROpnd:$rs, GPROpnd:$rt); - string AsmString = !strconcat(instr_asm, "\t$rd, $rs, $rt"); - list<dag> Pattern = []; - InstrItinClass Itinerary = Itin; -} - -class SELEQZ_MMR6_DESC : SELEQNE_Z_MMR6_DESC_BASE<"seleqz", GPR32Opnd, - II_SELCCZ>; -class SELNEZ_MMR6_DESC : SELEQNE_Z_MMR6_DESC_BASE<"selnez", GPR32Opnd, - II_SELCCZ>; -class PAUSE_MMR6_DESC : Barrier<"pause", II_PAUSE>; -class RDHWR_MMR6_DESC : MMR6Arch<"rdhwr">, MipsR6Inst { - dag OutOperandList = (outs GPR32Opnd:$rt); - dag InOperandList = (ins HWRegsOpnd:$rs, uimm3:$sel); - string AsmString = !strconcat("rdhwr", "\t$rt, $rs, $sel"); - list<dag> Pattern = []; - InstrItinClass Itinerary = II_RDHWR; - Format Form = FrmR; -} - -class WAIT_MMR6_DESC : WaitMM<"wait">; -// FIXME: ssnop should not be defined for R6. Per MD000582 microMIPS32 6.03: -// Assemblers targeting specifically Release 6 should reject the SSNOP -// instruction with an error. -class SSNOP_MMR6_DESC : Barrier<"ssnop", II_SSNOP>; -class SLL_MMR6_DESC : shift_rotate_imm<"sll", uimm5, GPR32Opnd, II_SLL>; - -class DIVMOD_MMR6_DESC_BASE<string opstr, RegisterOperand GPROpnd, - InstrItinClass Itin, - SDPatternOperator OpNode=null_frag> - : MipsR6Inst { - dag OutOperandList = (outs GPROpnd:$rd); - dag InOperandList = (ins GPROpnd:$rs, GPROpnd:$rt); - string AsmString = !strconcat(opstr, "\t$rd, $rs, $rt"); - list<dag> Pattern = [(set GPROpnd:$rd, (OpNode GPROpnd:$rs, GPROpnd:$rt))]; - string BaseOpcode = opstr; - Format f = FrmR; - let isCommutable = 0; - let isReMaterializable = 1; - InstrItinClass Itinerary = Itin; - - // This instruction doesn't trap division by zero itself. We must insert - // teq instructions as well. - bit usesCustomInserter = 1; -} -class DIV_MMR6_DESC : DIVMOD_MMR6_DESC_BASE<"div", GPR32Opnd, II_DIV, sdiv>; -class DIVU_MMR6_DESC : DIVMOD_MMR6_DESC_BASE<"divu", GPR32Opnd, II_DIVU, udiv>; -class MOD_MMR6_DESC : DIVMOD_MMR6_DESC_BASE<"mod", GPR32Opnd, II_MOD, srem>; -class MODU_MMR6_DESC : DIVMOD_MMR6_DESC_BASE<"modu", GPR32Opnd, II_MODU, urem>; -class AND_MMR6_DESC : ArithLogicR<"and", GPR32Opnd, 1, II_AND, and>; -class ANDI_MMR6_DESC : ArithLogicI<"andi", uimm16, GPR32Opnd, II_ANDI>; -class NOR_MMR6_DESC : LogicNOR<"nor", GPR32Opnd>; -class OR_MMR6_DESC : ArithLogicR<"or", GPR32Opnd, 1, II_OR, or>; -class ORI_MMR6_DESC : ArithLogicI<"ori", uimm16, GPR32Opnd, II_ORI, immZExt16, - or> { - int AddedComplexity = 1; -} -class XOR_MMR6_DESC : ArithLogicR<"xor", GPR32Opnd, 1, II_XOR, xor>; -class XORI_MMR6_DESC : ArithLogicI<"xori", uimm16, GPR32Opnd, II_XORI, - immZExt16, xor>; -class SW_MMR6_DESC : Store<"sw", GPR32Opnd> { - InstrItinClass Itinerary = II_SW; -} -class WRPGPR_WSBH_MMR6_DESC_BASE<string instr_asm, RegisterOperand RO, - InstrItinClass Itin> { - dag InOperandList = (ins RO:$rs); - dag OutOperandList = (outs RO:$rt); - string AsmString = !strconcat(instr_asm, "\t$rt, $rs"); - list<dag> Pattern = []; - Format f = FrmR; - string BaseOpcode = instr_asm; - bit hasSideEffects = 0; - InstrItinClass Itinerary = Itin; -} -class WRPGPR_MMR6_DESC : WRPGPR_WSBH_MMR6_DESC_BASE<"wrpgpr", GPR32Opnd, - II_WRPGPR>; -class WSBH_MMR6_DESC : WRPGPR_WSBH_MMR6_DESC_BASE<"wsbh", GPR32Opnd, II_WSBH>; - -class MTC0_MMR6_DESC_BASE<string opstr, RegisterOperand DstRC, - RegisterOperand SrcRC, InstrItinClass Itin> { - dag InOperandList = (ins SrcRC:$rt, uimm3:$sel); - dag OutOperandList = (outs DstRC:$rs); - string AsmString = !strconcat(opstr, "\t$rt, $rs, $sel"); - list<dag> Pattern = []; - Format f = FrmFR; - string BaseOpcode = opstr; - InstrItinClass Itinerary = Itin; -} -class MTC1_MMR6_DESC_BASE< - string opstr, RegisterOperand DstRC, RegisterOperand SrcRC, - InstrItinClass Itin = NoItinerary, SDPatternOperator OpNode = null_frag> - : MipsR6Inst { - dag InOperandList = (ins SrcRC:$rt); - dag OutOperandList = (outs DstRC:$fs); - string AsmString = !strconcat(opstr, "\t$rt, $fs"); - list<dag> Pattern = [(set DstRC:$fs, (OpNode SrcRC:$rt))]; - Format f = FrmFR; - InstrItinClass Itinerary = Itin; - string BaseOpcode = opstr; -} -class MTC1_64_MMR6_DESC_BASE< - string opstr, RegisterOperand DstRC, RegisterOperand SrcRC, - InstrItinClass Itin = NoItinerary> : MipsR6Inst { - dag InOperandList = (ins DstRC:$fs_in, SrcRC:$rt); - dag OutOperandList = (outs DstRC:$fs); - string AsmString = !strconcat(opstr, "\t$rt, $fs"); - list<dag> Pattern = []; - Format f = FrmFR; - InstrItinClass Itinerary = Itin; - string BaseOpcode = opstr; - // $fs_in is part of a white lie to work around a widespread bug in the FPU - // implementation. See expandBuildPairF64 for details. - let Constraints = "$fs = $fs_in"; -} -class MTC2_MMR6_DESC_BASE<string opstr, RegisterOperand DstRC, - RegisterOperand SrcRC, InstrItinClass Itin> { - dag InOperandList = (ins SrcRC:$rt); - dag OutOperandList = (outs DstRC:$impl); - string AsmString = !strconcat(opstr, "\t$rt, $impl"); - list<dag> Pattern = []; - Format f = FrmFR; - string BaseOpcode = opstr; - InstrItinClass Itinerary = Itin; -} - -class MTC0_MMR6_DESC : MTC0_MMR6_DESC_BASE<"mtc0", COP0Opnd, GPR32Opnd, - II_MTC0>; -class MTC1_MMR6_DESC : MTC1_MMR6_DESC_BASE<"mtc1", FGR32Opnd, GPR32Opnd, - II_MTC1, bitconvert>, HARDFLOAT; -class MTC2_MMR6_DESC : MTC2_MMR6_DESC_BASE<"mtc2", COP2Opnd, GPR32Opnd, - II_MTC2>; -class MTHC0_MMR6_DESC : MTC0_MMR6_DESC_BASE<"mthc0", COP0Opnd, GPR32Opnd, - II_MTHC0>; -class MTHC2_MMR6_DESC : MTC2_MMR6_DESC_BASE<"mthc2", COP2Opnd, GPR32Opnd, - II_MTC2>; - -class MFC0_MMR6_DESC_BASE<string opstr, RegisterOperand DstRC, - RegisterOperand SrcRC, InstrItinClass Itin> { - dag InOperandList = (ins SrcRC:$rs, uimm3:$sel); - dag OutOperandList = (outs DstRC:$rt); - string AsmString = !strconcat(opstr, "\t$rt, $rs, $sel"); - list<dag> Pattern = []; - Format f = FrmFR; - string BaseOpcode = opstr; - InstrItinClass Itinerary = Itin; -} -class MFC1_MMR6_DESC_BASE<string opstr, RegisterOperand DstRC, - RegisterOperand SrcRC, - InstrItinClass Itin = NoItinerary, - SDPatternOperator OpNode = null_frag> : MipsR6Inst { - dag InOperandList = (ins SrcRC:$fs); - dag OutOperandList = (outs DstRC:$rt); - string AsmString = !strconcat(opstr, "\t$rt, $fs"); - list<dag> Pattern = [(set DstRC:$rt, (OpNode SrcRC:$fs))]; - Format f = FrmFR; - InstrItinClass Itinerary = Itin; - string BaseOpcode = opstr; -} -class MFC2_MMR6_DESC_BASE<string opstr, RegisterOperand DstRC, - RegisterOperand SrcRC, InstrItinClass Itin> { - dag InOperandList = (ins SrcRC:$impl); - dag OutOperandList = (outs DstRC:$rt); - string AsmString = !strconcat(opstr, "\t$rt, $impl"); - list<dag> Pattern = []; - Format f = FrmFR; - string BaseOpcode = opstr; - InstrItinClass Itinerary = Itin; -} -class MFC0_MMR6_DESC : MFC0_MMR6_DESC_BASE<"mfc0", GPR32Opnd, COP0Opnd, - II_MFC0>; -class MFC1_MMR6_DESC : MFC1_MMR6_DESC_BASE<"mfc1", GPR32Opnd, FGR32Opnd, - II_MFC1, bitconvert>, HARDFLOAT; -class MFC2_MMR6_DESC : MFC2_MMR6_DESC_BASE<"mfc2", GPR32Opnd, COP2Opnd, - II_MFC2>; -class MFHC0_MMR6_DESC : MFC0_MMR6_DESC_BASE<"mfhc0", GPR32Opnd, COP0Opnd, - II_MFHC0>; -class MFHC2_MMR6_DESC : MFC2_MMR6_DESC_BASE<"mfhc2", GPR32Opnd, COP2Opnd, - II_MFC2>; - -class LDC1_D64_MMR6_DESC : MipsR6Inst, HARDFLOAT, FGR_64 { - dag InOperandList = (ins mem_mm_16:$addr); - dag OutOperandList = (outs FGR64Opnd:$ft); - string AsmString = !strconcat("ldc1", "\t$ft, $addr"); - list<dag> Pattern = [(set FGR64Opnd:$ft, (load addrimm16:$addr))]; - Format f = FrmFI; - InstrItinClass Itinerary = II_LDC1; - string BaseOpcode = "ldc1"; - bit mayLoad = 1; - let DecoderMethod = "DecodeFMemMMR2"; -} - -class SDC1_D64_MMR6_DESC : MipsR6Inst, HARDFLOAT, FGR_64 { - dag InOperandList = (ins FGR64Opnd:$ft, mem_mm_16:$addr); - dag OutOperandList = (outs); - string AsmString = !strconcat("sdc1", "\t$ft, $addr"); - list<dag> Pattern = [(store FGR64Opnd:$ft, addrimm16:$addr)]; - Format f = FrmFI; - InstrItinClass Itinerary = II_SDC1; - string BaseOpcode = "sdc1"; - bit mayStore = 1; - let DecoderMethod = "DecodeFMemMMR2"; -} - -class LDC2_LWC2_MMR6_DESC_BASE<string opstr, InstrItinClass itin> { - dag OutOperandList = (outs COP2Opnd:$rt); - dag InOperandList = (ins mem_mm_11:$addr); - string AsmString = !strconcat(opstr, "\t$rt, $addr"); - list<dag> Pattern = [(set COP2Opnd:$rt, (load addrimm11:$addr))]; - Format f = FrmFI; - InstrItinClass Itinerary = itin; - string BaseOpcode = opstr; - bit mayLoad = 1; - string DecoderMethod = "DecodeFMemCop2MMR6"; -} -class LDC2_MMR6_DESC : LDC2_LWC2_MMR6_DESC_BASE<"ldc2", II_LDC2>; -class LWC2_MMR6_DESC : LDC2_LWC2_MMR6_DESC_BASE<"lwc2", II_LWC2>; - -class SDC2_SWC2_MMR6_DESC_BASE<string opstr, InstrItinClass itin> { - dag OutOperandList = (outs); - dag InOperandList = (ins COP2Opnd:$rt, mem_mm_11:$addr); - string AsmString = !strconcat(opstr, "\t$rt, $addr"); - list<dag> Pattern = [(store COP2Opnd:$rt, addrimm11:$addr)]; - Format f = FrmFI; - InstrItinClass Itinerary = itin; - string BaseOpcode = opstr; - bit mayStore = 1; - string DecoderMethod = "DecodeFMemCop2MMR6"; -} -class SDC2_MMR6_DESC : SDC2_SWC2_MMR6_DESC_BASE<"sdc2", II_SDC2>; -class SWC2_MMR6_DESC : SDC2_SWC2_MMR6_DESC_BASE<"swc2", II_SWC2>; - -class GINV_MMR6_DESC_BASE<string opstr, - RegisterOperand SrcRC, InstrItinClass Itin> { - dag InOperandList = (ins SrcRC:$rs, uimm2:$type); - dag OutOperandList = (outs); - string AsmString = !strconcat(opstr, "\t$rs, $type"); - list<dag> Pattern = []; - Format f = FrmFR; - string BaseOpcode = opstr; - InstrItinClass Itinerary = Itin; -} - -class GINVI_MMR6_DESC : GINV_MMR6_DESC_BASE<"ginvi", GPR32Opnd, - II_GINVI> { - dag InOperandList = (ins GPR32Opnd:$rs); - string AsmString = "ginvi\t$rs"; -} -class GINVT_MMR6_DESC : GINV_MMR6_DESC_BASE<"ginvt", GPR32Opnd, - II_GINVT>; - -class SC_MMR6_DESC_BASE<string opstr, InstrItinClass itin> { - dag OutOperandList = (outs GPR32Opnd:$dst); - dag InOperandList = (ins GPR32Opnd:$rt, mem_mm_9:$addr); - string AsmString = !strconcat(opstr, "\t$rt, $addr"); - InstrItinClass Itinerary = itin; - string BaseOpcode = opstr; - bit mayStore = 1; - string Constraints = "$rt = $dst"; - string DecoderMethod = "DecodeMemMMImm9"; -} - -class LL_MMR6_DESC_BASE<string opstr, InstrItinClass itin> { - dag OutOperandList = (outs GPR32Opnd:$rt); - dag InOperandList = (ins mem_mm_9:$addr); - string AsmString = !strconcat(opstr, "\t$rt, $addr"); - InstrItinClass Itinerary = itin; - string BaseOpcode = opstr; - bit mayLoad = 1; - string DecoderMethod = "DecodeMemMMImm9"; -} - -class SC_MMR6_DESC : SC_MMR6_DESC_BASE<"sc", II_SC>; -class LL_MMR6_DESC : LL_MMR6_DESC_BASE<"ll", II_LL>; - -/// Floating Point Instructions -class FARITH_MMR6_DESC_BASE<string instr_asm, RegisterOperand RC, - InstrItinClass Itin, bit isComm, - SDPatternOperator OpNode = null_frag> : HARDFLOAT { - dag OutOperandList = (outs RC:$fd); - dag InOperandList = (ins RC:$ft, RC:$fs); - string AsmString = !strconcat(instr_asm, "\t$fd, $fs, $ft"); - list<dag> Pattern = [(set RC:$fd, (OpNode RC:$fs, RC:$ft))]; - InstrItinClass Itinerary = Itin; - bit isCommutable = isComm; -} -class FADD_S_MMR6_DESC - : FARITH_MMR6_DESC_BASE<"add.s", FGR32Opnd, II_ADD_S, 1, fadd>; -class FSUB_S_MMR6_DESC - : FARITH_MMR6_DESC_BASE<"sub.s", FGR32Opnd, II_SUB_S, 0, fsub>; -class FMUL_S_MMR6_DESC - : FARITH_MMR6_DESC_BASE<"mul.s", FGR32Opnd, II_MUL_S, 1, fmul>; -class FDIV_S_MMR6_DESC - : FARITH_MMR6_DESC_BASE<"div.s", FGR32Opnd, II_DIV_S, 0, fdiv>; -class MADDF_S_MMR6_DESC : COP1_4R_DESC_BASE<"maddf.s", FGR32Opnd, - II_MADDF_S>, HARDFLOAT; -class MADDF_D_MMR6_DESC : COP1_4R_DESC_BASE<"maddf.d", FGR64Opnd, - II_MADDF_D>, HARDFLOAT; -class MSUBF_S_MMR6_DESC : COP1_4R_DESC_BASE<"msubf.s", FGR32Opnd, - II_MSUBF_S>, HARDFLOAT; -class MSUBF_D_MMR6_DESC : COP1_4R_DESC_BASE<"msubf.d", FGR64Opnd, - II_MSUBF_D>, HARDFLOAT; - -class FMOV_FNEG_MMR6_DESC_BASE<string instr_asm, RegisterOperand DstRC, - RegisterOperand SrcRC, InstrItinClass Itin, - SDPatternOperator OpNode = null_frag> - : HARDFLOAT, NeverHasSideEffects { - dag OutOperandList = (outs DstRC:$ft); - dag InOperandList = (ins SrcRC:$fs); - string AsmString = !strconcat(instr_asm, "\t$ft, $fs"); - list<dag> Pattern = [(set DstRC:$ft, (OpNode SrcRC:$fs))]; - InstrItinClass Itinerary = Itin; - Format Form = FrmFR; -} -class FMOV_S_MMR6_DESC - : FMOV_FNEG_MMR6_DESC_BASE<"mov.s", FGR32Opnd, FGR32Opnd, II_MOV_S>; -class FMOV_D_MMR6_DESC - : FMOV_FNEG_MMR6_DESC_BASE<"mov.d", FGR64Opnd, FGR64Opnd, II_MOV_D>; -class FNEG_S_MMR6_DESC - : FMOV_FNEG_MMR6_DESC_BASE<"neg.s", FGR32Opnd, FGR32Opnd, II_NEG, fneg>; - -class MAX_S_MMR6_DESC : MAX_MIN_DESC_BASE<"max.s", FGR32Opnd, II_MAX_S>, - HARDFLOAT; -class MAX_D_MMR6_DESC : MAX_MIN_DESC_BASE<"max.d", FGR64Opnd, II_MAX_D>, - HARDFLOAT; -class MIN_S_MMR6_DESC : MAX_MIN_DESC_BASE<"min.s", FGR32Opnd, II_MIN_S>, - HARDFLOAT; -class MIN_D_MMR6_DESC : MAX_MIN_DESC_BASE<"min.d", FGR64Opnd, II_MIN_D>, - HARDFLOAT; - -class MAXA_S_MMR6_DESC : MAX_MIN_DESC_BASE<"maxa.s", FGR32Opnd, II_MAXA_S>, - HARDFLOAT; -class MAXA_D_MMR6_DESC : MAX_MIN_DESC_BASE<"maxa.d", FGR64Opnd, II_MAXA_D>, - HARDFLOAT; -class MINA_S_MMR6_DESC : MAX_MIN_DESC_BASE<"mina.s", FGR32Opnd, II_MINA_S>, - HARDFLOAT; -class MINA_D_MMR6_DESC : MAX_MIN_DESC_BASE<"mina.d", FGR64Opnd, II_MINA_D>, - HARDFLOAT; - -class CVT_MMR6_DESC_BASE< - string instr_asm, RegisterOperand DstRC, RegisterOperand SrcRC, - InstrItinClass Itin, SDPatternOperator OpNode = null_frag> - : HARDFLOAT, NeverHasSideEffects { - dag OutOperandList = (outs DstRC:$ft); - dag InOperandList = (ins SrcRC:$fs); - string AsmString = !strconcat(instr_asm, "\t$ft, $fs"); - list<dag> Pattern = [(set DstRC:$ft, (OpNode SrcRC:$fs))]; - InstrItinClass Itinerary = Itin; - Format Form = FrmFR; -} - -class CVT_L_S_MMR6_DESC : CVT_MMR6_DESC_BASE<"cvt.l.s", FGR64Opnd, FGR32Opnd, - II_CVT>; -class CVT_L_D_MMR6_DESC : CVT_MMR6_DESC_BASE<"cvt.l.d", FGR64Opnd, FGR64Opnd, - II_CVT>; -class CVT_W_S_MMR6_DESC : CVT_MMR6_DESC_BASE<"cvt.w.s", FGR32Opnd, FGR32Opnd, - II_CVT>; -class CVT_D_L_MMR6_DESC : CVT_MMR6_DESC_BASE<"cvt.d.l", FGR64Opnd, FGR64Opnd, - II_CVT>, FGR_64; -class CVT_S_W_MMR6_DESC : CVT_MMR6_DESC_BASE<"cvt.s.w", FGR32Opnd, FGR32Opnd, - II_CVT>; -class CVT_S_L_MMR6_DESC : CVT_MMR6_DESC_BASE<"cvt.s.l", FGR64Opnd, FGR32Opnd, - II_CVT>, FGR_64; - -multiclass CMP_CC_MMR6<bits<6> format, string Typestr, - RegisterOperand FGROpnd, InstrItinClass Itin> { - def CMP_AF_#NAME : R6MMR6Rel, POOL32F_CMP_FM< - !strconcat("cmp.af.", Typestr), format, FIELD_CMP_COND_AF>, - CMP_CONDN_DESC_BASE<"af", Typestr, FGROpnd, Itin>, HARDFLOAT, - ISA_MICROMIPS32R6; - def CMP_UN_#NAME : R6MMR6Rel, POOL32F_CMP_FM< - !strconcat("cmp.un.", Typestr), format, FIELD_CMP_COND_UN>, - CMP_CONDN_DESC_BASE<"un", Typestr, FGROpnd, Itin, setuo>, HARDFLOAT, - ISA_MICROMIPS32R6; - def CMP_EQ_#NAME : R6MMR6Rel, POOL32F_CMP_FM< - !strconcat("cmp.eq.", Typestr), format, FIELD_CMP_COND_EQ>, - CMP_CONDN_DESC_BASE<"eq", Typestr, FGROpnd, Itin, setoeq>, HARDFLOAT, - ISA_MICROMIPS32R6; - def CMP_UEQ_#NAME : R6MMR6Rel, POOL32F_CMP_FM< - !strconcat("cmp.ueq.", Typestr), format, FIELD_CMP_COND_UEQ>, - CMP_CONDN_DESC_BASE<"ueq", Typestr, FGROpnd, Itin, setueq>, HARDFLOAT, - ISA_MICROMIPS32R6; - def CMP_LT_#NAME : R6MMR6Rel, POOL32F_CMP_FM< - !strconcat("cmp.lt.", Typestr), format, FIELD_CMP_COND_LT>, - CMP_CONDN_DESC_BASE<"lt", Typestr, FGROpnd, Itin, setolt>, HARDFLOAT, - ISA_MICROMIPS32R6; - def CMP_ULT_#NAME : R6MMR6Rel, POOL32F_CMP_FM< - !strconcat("cmp.ult.", Typestr), format, FIELD_CMP_COND_ULT>, - CMP_CONDN_DESC_BASE<"ult", Typestr, FGROpnd, Itin, setult>, HARDFLOAT, - ISA_MICROMIPS32R6; - def CMP_LE_#NAME : R6MMR6Rel, POOL32F_CMP_FM< - !strconcat("cmp.le.", Typestr), format, FIELD_CMP_COND_LE>, - CMP_CONDN_DESC_BASE<"le", Typestr, FGROpnd, Itin, setole>, HARDFLOAT, - ISA_MICROMIPS32R6; - def CMP_ULE_#NAME : R6MMR6Rel, POOL32F_CMP_FM< - !strconcat("cmp.ule.", Typestr), format, FIELD_CMP_COND_ULE>, - CMP_CONDN_DESC_BASE<"ule", Typestr, FGROpnd, Itin, setule>, HARDFLOAT, - ISA_MICROMIPS32R6; - def CMP_SAF_#NAME : R6MMR6Rel, POOL32F_CMP_FM< - !strconcat("cmp.saf.", Typestr), format, FIELD_CMP_COND_SAF>, - CMP_CONDN_DESC_BASE<"saf", Typestr, FGROpnd, Itin>, HARDFLOAT, - ISA_MICROMIPS32R6; - def CMP_SUN_#NAME : R6MMR6Rel, POOL32F_CMP_FM< - !strconcat("cmp.sun.", Typestr), format, FIELD_CMP_COND_SUN>, - CMP_CONDN_DESC_BASE<"sun", Typestr, FGROpnd, Itin>, HARDFLOAT, - ISA_MICROMIPS32R6; - def CMP_SEQ_#NAME : R6MMR6Rel, POOL32F_CMP_FM< - !strconcat("cmp.seq.", Typestr), format, FIELD_CMP_COND_SEQ>, - CMP_CONDN_DESC_BASE<"seq", Typestr, FGROpnd, Itin>, HARDFLOAT, - ISA_MICROMIPS32R6; - def CMP_SUEQ_#NAME : R6MMR6Rel, POOL32F_CMP_FM< - !strconcat("cmp.sueq.", Typestr), format, FIELD_CMP_COND_SUEQ>, - CMP_CONDN_DESC_BASE<"sueq", Typestr, FGROpnd, Itin>, HARDFLOAT, - ISA_MICROMIPS32R6; - def CMP_SLT_#NAME : R6MMR6Rel, POOL32F_CMP_FM< - !strconcat("cmp.slt.", Typestr), format, FIELD_CMP_COND_SLT>, - CMP_CONDN_DESC_BASE<"slt", Typestr, FGROpnd, Itin>, HARDFLOAT, - ISA_MICROMIPS32R6; - def CMP_SULT_#NAME : R6MMR6Rel, POOL32F_CMP_FM< - !strconcat("cmp.sult.", Typestr), format, FIELD_CMP_COND_SULT>, - CMP_CONDN_DESC_BASE<"sult", Typestr, FGROpnd, Itin>, HARDFLOAT, - ISA_MICROMIPS32R6; - def CMP_SLE_#NAME : R6MMR6Rel, POOL32F_CMP_FM< - !strconcat("cmp.sle.", Typestr), format, FIELD_CMP_COND_SLE>, - CMP_CONDN_DESC_BASE<"sle", Typestr, FGROpnd, Itin>, HARDFLOAT, - ISA_MICROMIPS32R6; - def CMP_SULE_#NAME : R6MMR6Rel, POOL32F_CMP_FM< - !strconcat("cmp.sule.", Typestr), format, FIELD_CMP_COND_SULE>, - CMP_CONDN_DESC_BASE<"sule", Typestr, FGROpnd, Itin>, HARDFLOAT, - ISA_MICROMIPS32R6; -} - -class ABSS_FT_MMR6_DESC_BASE<string instr_asm, RegisterOperand DstRC, - RegisterOperand SrcRC, InstrItinClass Itin, - SDPatternOperator OpNode = null_frag> - : HARDFLOAT, NeverHasSideEffects { - dag OutOperandList = (outs DstRC:$ft); - dag InOperandList = (ins SrcRC:$fs); - string AsmString = !strconcat(instr_asm, "\t$ft, $fs"); - list<dag> Pattern = [(set DstRC:$ft, (OpNode SrcRC:$fs))]; - InstrItinClass Itinerary = Itin; - Format Form = FrmFR; - list<Predicate> EncodingPredicates = [HasStdEnc]; -} - -class FLOOR_L_S_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"floor.l.s", FGR64Opnd, - FGR32Opnd, II_FLOOR>; -class FLOOR_L_D_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"floor.l.d", FGR64Opnd, - FGR64Opnd, II_FLOOR>; -class FLOOR_W_S_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"floor.w.s", FGR32Opnd, - FGR32Opnd, II_FLOOR>; -class FLOOR_W_D_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"floor.w.d", FGR32Opnd, - AFGR64Opnd, II_FLOOR>; -class CEIL_L_S_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"ceil.l.s", FGR64Opnd, - FGR32Opnd, II_CEIL>; -class CEIL_L_D_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"ceil.l.d", FGR64Opnd, - FGR64Opnd, II_CEIL>; -class CEIL_W_S_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"ceil.w.s", FGR32Opnd, - FGR32Opnd, II_CEIL>; -class CEIL_W_D_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"ceil.w.d", FGR32Opnd, - AFGR64Opnd, II_CEIL>; -class TRUNC_L_S_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"trunc.l.s", FGR64Opnd, - FGR32Opnd, II_TRUNC>; -class TRUNC_L_D_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"trunc.l.d", FGR64Opnd, - FGR64Opnd, II_TRUNC>; -class TRUNC_W_S_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"trunc.w.s", FGR32Opnd, - FGR32Opnd, II_TRUNC>; -class TRUNC_W_D_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"trunc.w.d", FGR32Opnd, - FGR64Opnd, II_TRUNC>; -class SQRT_S_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"sqrt.s", FGR32Opnd, FGR32Opnd, - II_SQRT_S, fsqrt>; -class SQRT_D_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"sqrt.d", AFGR64Opnd, AFGR64Opnd, - II_SQRT_D, fsqrt>; -class ROUND_L_S_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"round.l.s", FGR64Opnd, - FGR32Opnd, II_ROUND>; -class ROUND_L_D_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"round.l.d", FGR64Opnd, - FGR64Opnd, II_ROUND>; -class ROUND_W_S_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"round.w.s", FGR32Opnd, - FGR32Opnd, II_ROUND>; -class ROUND_W_D_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"round.w.d", FGR64Opnd, - FGR64Opnd, II_ROUND>; - -class SEL_S_MMR6_DESC : COP1_SEL_DESC_BASE<"sel.s", FGR32Opnd, II_SEL_S>; -class SEL_D_MMR6_DESC : COP1_SEL_D_DESC_BASE<"sel.d", FGR64Opnd, II_SEL_D>; - -class SELEQZ_S_MMR6_DESC : SELEQNEZ_DESC_BASE<"seleqz.s", FGR32Opnd, - II_SELCCZ_S>; -class SELEQZ_D_MMR6_DESC : SELEQNEZ_DESC_BASE<"seleqz.d", FGR64Opnd, - II_SELCCZ_D>; -class SELNEZ_S_MMR6_DESC : SELEQNEZ_DESC_BASE<"selnez.s", FGR32Opnd, - II_SELCCZ_S>; -class SELNEZ_D_MMR6_DESC : SELEQNEZ_DESC_BASE<"selnez.d", FGR64Opnd, - II_SELCCZ_D>; -class RINT_S_MMR6_DESC : CLASS_RINT_DESC_BASE<"rint.s", FGR32Opnd, - II_RINT_S>; -class RINT_D_MMR6_DESC : CLASS_RINT_DESC_BASE<"rint.d", FGR64Opnd, - II_RINT_S>; -class CLASS_S_MMR6_DESC : CLASS_RINT_DESC_BASE<"class.s", FGR32Opnd, - II_CLASS_S>; -class CLASS_D_MMR6_DESC : CLASS_RINT_DESC_BASE<"class.d", FGR64Opnd, - II_CLASS_S>; - -class STORE_MMR6_DESC_BASE<string opstr, DAGOperand RO, - InstrItinClass Itin> - : Store<opstr, RO>, MMR6Arch<opstr> { - let DecoderMethod = "DecodeMemMMImm16"; - InstrItinClass Itinerary = Itin; -} -class SB_MMR6_DESC : STORE_MMR6_DESC_BASE<"sb", GPR32Opnd, II_SB>; - -class SH_MMR6_DESC : STORE_MMR6_DESC_BASE<"sh", GPR32Opnd, II_SH>; -class ADDU16_MMR6_DESC : ArithRMM16<"addu16", GPRMM16Opnd, 1, II_ADDU, add>, - MMR6Arch<"addu16"> { - int AddedComplexity = 1; -} -class AND16_MMR6_DESC : LogicRMM16<"and16", GPRMM16Opnd, II_AND>, - MMR6Arch<"and16">; -class ANDI16_MMR6_DESC : AndImmMM16<"andi16", GPRMM16Opnd, II_AND>, - MMR6Arch<"andi16">; -class NOT16_MMR6_DESC : NotMM16<"not16", GPRMM16Opnd>, MMR6Arch<"not16"> { - int AddedComplexity = 1; -} -class OR16_MMR6_DESC : LogicRMM16<"or16", GPRMM16Opnd, II_OR>, MMR6Arch<"or16">; -class SLL16_MMR6_DESC : ShiftIMM16<"sll16", uimm3_shift, GPRMM16Opnd, II_SLL>, - MMR6Arch<"sll16">; -class SRL16_MMR6_DESC : ShiftIMM16<"srl16", uimm3_shift, GPRMM16Opnd, II_SRL>, - MMR6Arch<"srl16">; -class BREAK16_MMR6_DESC : BrkSdbbp16MM<"break16", II_BREAK>, MMR6Arch<"break16">; -class LI16_MMR6_DESC : LoadImmMM16<"li16", li16_imm, GPRMM16Opnd>, - MMR6Arch<"li16">, IsAsCheapAsAMove; -class MOVE16_MMR6_DESC : MoveMM16<"move16", GPR32Opnd>, MMR6Arch<"move16">; -class MOVEP_MMR6_DESC : MovePMM16<"movep", GPRMM16OpndMovePPairFirst, - GPRMM16OpndMovePPairSecond, GPRMM16OpndMoveP>, - MMR6Arch<"movep">; -class SDBBP16_MMR6_DESC : BrkSdbbp16MM<"sdbbp16", II_SDBBP>, MMR6Arch<"sdbbp16">; -class SUBU16_MMR6_DESC : ArithRMM16<"subu16", GPRMM16Opnd, 0, II_SUBU, sub>, - MMR6Arch<"subu16"> { - int AddedComplexity = 1; -} -class XOR16_MMR6_DESC : LogicRMM16<"xor16", GPRMM16Opnd, II_XOR>, - MMR6Arch<"xor16">; - -class LW_MMR6_DESC : MMR6Arch<"lw">, MipsR6Inst { - dag OutOperandList = (outs GPR32Opnd:$rt); - dag InOperandList = (ins mem:$addr); - string AsmString = "lw\t$rt, $addr"; - let DecoderMethod = "DecodeMemMMImm16"; - let canFoldAsLoad = 1; - let mayLoad = 1; - list<dag> Pattern = [(set GPR32Opnd:$rt, (load addrDefault:$addr))]; - InstrItinClass Itinerary = II_LW; -} - -class LUI_MMR6_DESC : IsAsCheapAsAMove, MMR6Arch<"lui">, MipsR6Inst{ - dag OutOperandList = (outs GPR32Opnd:$rt); - dag InOperandList = (ins uimm16:$imm16); - string AsmString = "lui\t$rt, $imm16"; - list<dag> Pattern = []; - bit hasSideEffects = 0; - bit isReMaterializable = 1; - InstrItinClass Itinerary = II_LUI; - Format Form = FrmI; -} - -class SYNC_MMR6_DESC : MMR6Arch<"sync">, MipsR6Inst { - dag OutOperandList = (outs); - dag InOperandList = (ins uimm5:$stype); - string AsmString = !strconcat("sync", "\t$stype"); - list<dag> Pattern = [(MipsSync immZExt5:$stype)]; - InstrItinClass Itinerary = II_SYNC; - bit HasSideEffects = 1; -} - -class SYNCI_MMR6_DESC : SYNCI_FT<"synci", mem_mm_16> { - let DecoderMethod = "DecodeSynciR6"; -} - -class RDPGPR_MMR6_DESC : MMR6Arch<"rdpgpr">, MipsR6Inst { - dag OutOperandList = (outs GPR32Opnd:$rt); - dag InOperandList = (ins GPR32Opnd:$rd); - string AsmString = !strconcat("rdpgpr", "\t$rt, $rd"); - InstrItinClass Itinerary = II_RDPGPR; -} - -class SDBBP_MMR6_DESC : MipsR6Inst { - dag OutOperandList = (outs); - dag InOperandList = (ins uimm20:$code_); - string AsmString = !strconcat("sdbbp", "\t$code_"); - list<dag> Pattern = []; - InstrItinClass Itinerary = II_SDBBP; -} - -class SIGRIE_MMR6_DESC : MipsR6Inst { - dag OutOperandList = (outs); - dag InOperandList = (ins uimm16:$code_); - string AsmString = !strconcat("sigrie", "\t$code_"); - list<dag> Pattern = []; - InstrItinClass Itinerary = II_SIGRIE; -} - -class LWM16_MMR6_DESC - : MicroMipsInst16<(outs reglist16:$rt), (ins mem_mm_4sp:$addr), - !strconcat("lwm16", "\t$rt, $addr"), [], - II_LWM, FrmI>, - MMR6Arch<"lwm16"> { - let DecoderMethod = "DecodeMemMMReglistImm4Lsl2"; - let mayLoad = 1; - ComplexPattern Addr = addr; -} - -class SWM16_MMR6_DESC - : MicroMipsInst16<(outs), (ins reglist16:$rt, mem_mm_4sp:$addr), - !strconcat("swm16", "\t$rt, $addr"), [], - II_SWM, FrmI>, - MMR6Arch<"swm16"> { - let DecoderMethod = "DecodeMemMMReglistImm4Lsl2"; - let mayStore = 1; - ComplexPattern Addr = addr; -} - -class SB16_MMR6_DESC_BASE<string opstr, DAGOperand RTOpnd, DAGOperand RO, - SDPatternOperator OpNode, InstrItinClass Itin, - Operand MemOpnd> - : MicroMipsInst16<(outs), (ins RTOpnd:$rt, MemOpnd:$addr), - !strconcat(opstr, "\t$rt, $addr"), [], Itin, FrmI>, - MMR6Arch<opstr> { - let DecoderMethod = "DecodeMemMMImm4"; - let mayStore = 1; -} -class SB16_MMR6_DESC : SB16_MMR6_DESC_BASE<"sb16", GPRMM16OpndZero, GPRMM16Opnd, - truncstorei8, II_SB, mem_mm_4>; -class SH16_MMR6_DESC : SB16_MMR6_DESC_BASE<"sh16", GPRMM16OpndZero, GPRMM16Opnd, - truncstorei16, II_SH, mem_mm_4_lsl1>; -class SW16_MMR6_DESC : SB16_MMR6_DESC_BASE<"sw16", GPRMM16OpndZero, GPRMM16Opnd, - store, II_SW, mem_mm_4_lsl2>; - -class SWSP_MMR6_DESC - : MicroMipsInst16<(outs), (ins GPR32Opnd:$rt, mem_mm_sp_imm5_lsl2:$offset), - !strconcat("sw", "\t$rt, $offset"), [], II_SW, FrmI>, - MMR6Arch<"swsp"> { - let DecoderMethod = "DecodeMemMMSPImm5Lsl2"; - let mayStore = 1; -} - -class JALRC_HB_MMR6_DESC { - dag OutOperandList = (outs GPR32Opnd:$rt); - dag InOperandList = (ins GPR32Opnd:$rs); - string AsmString = !strconcat("jalrc.hb", "\t$rt, $rs"); - list<dag> Pattern = []; - InstrItinClass Itinerary = II_JALR_HB; - Format Form = FrmJ; - bit isIndirectBranch = 1; - bit hasDelaySlot = 0; -} - -class TLBINV_MMR6_DESC_BASE<string opstr, InstrItinClass Itin> { - dag OutOperandList = (outs); - dag InOperandList = (ins); - string AsmString = opstr; - list<dag> Pattern = []; - InstrItinClass Itinerary = Itin; -} - -class TLBINV_MMR6_DESC : TLBINV_MMR6_DESC_BASE<"tlbinv", II_TLBINV>; -class TLBINVF_MMR6_DESC : TLBINV_MMR6_DESC_BASE<"tlbinvf", II_TLBINVF>; - -class DVPEVP_MMR6_DESC_BASE<string opstr, InstrItinClass Itin> { - dag OutOperandList = (outs GPR32Opnd:$rs); - dag InOperandList = (ins); - string AsmString = !strconcat(opstr, "\t$rs"); - list<dag> Pattern = []; - InstrItinClass Itinerary = Itin; - bit hasUnModeledSideEffects = 1; -} - -class DVP_MMR6_DESC : DVPEVP_MMR6_DESC_BASE<"dvp", II_DVP>; -class EVP_MMR6_DESC : DVPEVP_MMR6_DESC_BASE<"evp", II_EVP>; - -class BEQZC_MMR6_DESC - : CMP_CBR_EQNE_Z_DESC_BASE<"beqzc", brtarget21_mm, GPR32Opnd>, - MMR6Arch<"beqzc">; -class BNEZC_MMR6_DESC - : CMP_CBR_EQNE_Z_DESC_BASE<"bnezc", brtarget21_mm, GPR32Opnd>, - MMR6Arch<"bnezc">; - -class BRANCH_COP1_MMR6_DESC_BASE<string opstr> : - InstSE<(outs), (ins FGR64Opnd:$rt, brtarget_mm:$offset), - !strconcat(opstr, "\t$rt, $offset"), [], II_BC1CCZ, FrmI>, - HARDFLOAT, BRANCH_DESC_BASE { - list<Register> Defs = [AT]; -} - -class BC1EQZC_MMR6_DESC : BRANCH_COP1_MMR6_DESC_BASE<"bc1eqzc">; -class BC1NEZC_MMR6_DESC : BRANCH_COP1_MMR6_DESC_BASE<"bc1nezc">; - -class BRANCH_COP2_MMR6_DESC_BASE<string opstr, InstrItinClass Itin> - : BRANCH_DESC_BASE { - dag InOperandList = (ins COP2Opnd:$rt, brtarget_mm:$offset); - dag OutOperandList = (outs); - string AsmString = !strconcat(opstr, "\t$rt, $offset"); - list<Register> Defs = [AT]; - InstrItinClass Itinerary = Itin; -} - -class BC2EQZC_MMR6_DESC : BRANCH_COP2_MMR6_DESC_BASE<"bc2eqzc", II_BC2CCZ>; -class BC2NEZC_MMR6_DESC : BRANCH_COP2_MMR6_DESC_BASE<"bc2nezc", II_BC2CCZ>; - -class EXT_MMR6_DESC { - dag OutOperandList = (outs GPR32Opnd:$rt); - dag InOperandList = (ins GPR32Opnd:$rs, uimm5:$pos, uimm5_plus1:$size); - string AsmString = !strconcat("ext", "\t$rt, $rs, $pos, $size"); - list<dag> Pattern = [(set GPR32Opnd:$rt, (MipsExt GPR32Opnd:$rs, imm:$pos, - imm:$size))]; - InstrItinClass Itinerary = II_EXT; - Format Form = FrmR; - string BaseOpcode = "ext"; -} - -class INS_MMR6_DESC { - dag OutOperandList = (outs GPR32Opnd:$rt); - dag InOperandList = (ins GPR32Opnd:$rs, uimm5:$pos, uimm5_inssize_plus1:$size, - GPR32Opnd:$src); - string AsmString = !strconcat("ins", "\t$rt, $rs, $pos, $size"); - list<dag> Pattern = [(set GPR32Opnd:$rt, (MipsIns GPR32Opnd:$rs, imm:$pos, - imm:$size, GPR32Opnd:$src))]; - InstrItinClass Itinerary = II_INS; - Format Form = FrmR; - string BaseOpcode = "ins"; - string Constraints = "$src = $rt"; -} - -class JALRC_MMR6_DESC { - dag OutOperandList = (outs GPR32Opnd:$rt); - dag InOperandList = (ins GPR32Opnd:$rs); - string AsmString = !strconcat("jalrc", "\t$rt, $rs"); - list<dag> Pattern = []; - InstrItinClass Itinerary = II_JALRC; - bit isCall = 1; - bit hasDelaySlot = 0; - list<Register> Defs = [RA]; -} - -class BOVC_BNVC_MMR6_DESC_BASE<string instr_asm, Operand opnd, - RegisterOperand GPROpnd> - : BRANCH_DESC_BASE { - dag InOperandList = (ins GPROpnd:$rt, GPROpnd:$rs, opnd:$offset); - dag OutOperandList = (outs); - string AsmString = !strconcat(instr_asm, "\t$rt, $rs, $offset"); - list<Register> Defs = [AT]; - InstrItinClass Itinerary = II_BCCC; -} - -class BOVC_MMR6_DESC : BOVC_BNVC_MMR6_DESC_BASE<"bovc", brtargetr6, GPR32Opnd>; -class BNVC_MMR6_DESC : BOVC_BNVC_MMR6_DESC_BASE<"bnvc", brtargetr6, GPR32Opnd>; - -//===----------------------------------------------------------------------===// -// -// Instruction Definitions -// -//===----------------------------------------------------------------------===// - -let DecoderNamespace = "MicroMipsR6" in { -def ADD_MMR6 : StdMMR6Rel, ADD_MMR6_DESC, ADD_MMR6_ENC, ISA_MICROMIPS32R6; -def ADDIU_MMR6 : StdMMR6Rel, ADDIU_MMR6_DESC, ADDIU_MMR6_ENC, ISA_MICROMIPS32R6; -def ADDU_MMR6 : StdMMR6Rel, ADDU_MMR6_DESC, ADDU_MMR6_ENC, ISA_MICROMIPS32R6; -def ADDIUPC_MMR6 : R6MMR6Rel, ADDIUPC_MMR6_ENC, ADDIUPC_MMR6_DESC, - ISA_MICROMIPS32R6; -def ALUIPC_MMR6 : R6MMR6Rel, ALUIPC_MMR6_ENC, ALUIPC_MMR6_DESC, - ISA_MICROMIPS32R6; -def AND_MMR6 : StdMMR6Rel, AND_MMR6_DESC, AND_MMR6_ENC, ISA_MICROMIPS32R6; -def ANDI_MMR6 : StdMMR6Rel, ANDI_MMR6_DESC, ANDI_MMR6_ENC, ISA_MICROMIPS32R6; -def AUIPC_MMR6 : R6MMR6Rel, AUIPC_MMR6_ENC, AUIPC_MMR6_DESC, ISA_MICROMIPS32R6; -def ALIGN_MMR6 : R6MMR6Rel, ALIGN_MMR6_ENC, ALIGN_MMR6_DESC, ISA_MICROMIPS32R6; -def AUI_MMR6 : R6MMR6Rel, AUI_MMR6_ENC, AUI_MMR6_DESC, ISA_MICROMIPS32R6; -def BALC_MMR6 : R6MMR6Rel, BALC_MMR6_ENC, BALC_MMR6_DESC, ISA_MICROMIPS32R6; -def BC_MMR6 : R6MMR6Rel, BC_MMR6_ENC, BC_MMR6_DESC, ISA_MICROMIPS32R6; -def BC16_MMR6 : StdMMR6Rel, BC16_MMR6_DESC, BC16_MMR6_ENC, ISA_MICROMIPS32R6; -def BEQZC_MMR6 : R6MMR6Rel, BEQZC_MMR6_ENC, BEQZC_MMR6_DESC, - ISA_MICROMIPS32R6; -def BEQZC16_MMR6 : StdMMR6Rel, BEQZC16_MMR6_DESC, BEQZC16_MMR6_ENC, - ISA_MICROMIPS32R6; -def BNEZC_MMR6 : R6MMR6Rel, BNEZC_MMR6_ENC, BNEZC_MMR6_DESC, - ISA_MICROMIPS32R6; -def BNEZC16_MMR6 : StdMMR6Rel, BNEZC16_MMR6_DESC, BNEZC16_MMR6_ENC, - ISA_MICROMIPS32R6; -def BITSWAP_MMR6 : R6MMR6Rel, BITSWAP_MMR6_ENC, BITSWAP_MMR6_DESC, - ISA_MICROMIPS32R6; -def BEQZALC_MMR6 : R6MMR6Rel, BEQZALC_MMR6_ENC, BEQZALC_MMR6_DESC, - ISA_MICROMIPS32R6; -def BNEZALC_MMR6 : R6MMR6Rel, BNEZALC_MMR6_ENC, BNEZALC_MMR6_DESC, - ISA_MICROMIPS32R6; -def BREAK_MMR6 : StdMMR6Rel, BRK_MMR6_DESC, BRK_MMR6_ENC, ISA_MICROMIPS32R6; -def CACHE_MMR6 : R6MMR6Rel, CACHE_MMR6_ENC, CACHE_MMR6_DESC, ISA_MICROMIPS32R6; -def CLO_MMR6 : R6MMR6Rel, CLO_MMR6_ENC, CLO_MMR6_DESC, ISA_MICROMIPS32R6; -def CLZ_MMR6 : R6MMR6Rel, CLZ_MMR6_ENC, CLZ_MMR6_DESC, ISA_MICROMIPS32R6; -def DIV_MMR6 : R6MMR6Rel, DIV_MMR6_DESC, DIV_MMR6_ENC, ISA_MICROMIPS32R6; -def DIVU_MMR6 : R6MMR6Rel, DIVU_MMR6_DESC, DIVU_MMR6_ENC, ISA_MICROMIPS32R6; -def EHB_MMR6 : StdMMR6Rel, EHB_MMR6_DESC, EHB_MMR6_ENC, ISA_MICROMIPS32R6; -def EI_MMR6 : StdMMR6Rel, EI_MMR6_DESC, EI_MMR6_ENC, ISA_MICROMIPS32R6; -def DI_MMR6 : StdMMR6Rel, DI_MMR6_DESC, DI_MMR6_ENC, ISA_MICROMIPS32R6; -def ERET_MMR6 : StdMMR6Rel, ERET_MMR6_DESC, ERET_MMR6_ENC, ISA_MICROMIPS32R6; -def DERET_MMR6 : StdMMR6Rel, DERET_MMR6_DESC, DERET_MMR6_ENC, ISA_MICROMIPS32R6; -def ERETNC_MMR6 : R6MMR6Rel, ERETNC_MMR6_DESC, ERETNC_MMR6_ENC, - ISA_MICROMIPS32R6; -def GINVI_MMR6 : R6MMR6Rel, GINVI_MMR6_ENC, GINVI_MMR6_DESC, - ISA_MICROMIPS32R6, ASE_GINV; -def GINVT_MMR6 : R6MMR6Rel, GINVT_MMR6_ENC, GINVT_MMR6_DESC, - ISA_MICROMIPS32R6, ASE_GINV; -let FastISelShouldIgnore = 1 in -def JALRC16_MMR6 : R6MMR6Rel, JALRC16_MMR6_DESC, JALRC16_MMR6_ENC, - ISA_MICROMIPS32R6; -def JIALC_MMR6 : R6MMR6Rel, JIALC_MMR6_ENC, JIALC_MMR6_DESC, ISA_MICROMIPS32R6; -def JIC_MMR6 : R6MMR6Rel, JIC_MMR6_ENC, JIC_MMR6_DESC, ISA_MICROMIPS32R6; -def JRC16_MMR6 : R6MMR6Rel, JRC16_MMR6_DESC, JRC16_MMR6_ENC, ISA_MICROMIPS32R6; -def JRCADDIUSP_MMR6 : R6MMR6Rel, JRCADDIUSP_MMR6_DESC, JRCADDIUSP_MMR6_ENC, - ISA_MICROMIPS32R6; -def LSA_MMR6 : R6MMR6Rel, LSA_MMR6_ENC, LSA_MMR6_DESC, ISA_MICROMIPS32R6; -def LWPC_MMR6 : R6MMR6Rel, LWPC_MMR6_ENC, LWPC_MMR6_DESC, ISA_MICROMIPS32R6; -def LWM16_MMR6 : StdMMR6Rel, LWM16_MMR6_DESC, LWM16_MMR6_ENC, ISA_MICROMIPS32R6; -def MTC0_MMR6 : StdMMR6Rel, MTC0_MMR6_ENC, MTC0_MMR6_DESC, ISA_MICROMIPS32R6; -def MTC1_MMR6 : StdMMR6Rel, MTC1_MMR6_DESC, MTC1_MMR6_ENC, ISA_MICROMIPS32R6; -def MTC2_MMR6 : StdMMR6Rel, MTC2_MMR6_ENC, MTC2_MMR6_DESC, ISA_MICROMIPS32R6; -def MTHC0_MMR6 : R6MMR6Rel, MTHC0_MMR6_ENC, MTHC0_MMR6_DESC, ISA_MICROMIPS32R6; -def MTHC2_MMR6 : StdMMR6Rel, MTHC2_MMR6_ENC, MTHC2_MMR6_DESC, ISA_MICROMIPS32R6; -def MFC0_MMR6 : StdMMR6Rel, MFC0_MMR6_ENC, MFC0_MMR6_DESC, ISA_MICROMIPS32R6; -def MFC1_MMR6 : StdMMR6Rel, MFC1_MMR6_DESC, MFC1_MMR6_ENC, ISA_MICROMIPS32R6; -def MFC2_MMR6 : StdMMR6Rel, MFC2_MMR6_ENC, MFC2_MMR6_DESC, ISA_MICROMIPS32R6; -def MFHC0_MMR6 : R6MMR6Rel, MFHC0_MMR6_ENC, MFHC0_MMR6_DESC, ISA_MICROMIPS32R6; -def MFHC2_MMR6 : StdMMR6Rel, MFHC2_MMR6_ENC, MFHC2_MMR6_DESC, ISA_MICROMIPS32R6; -def MOD_MMR6 : R6MMR6Rel, MOD_MMR6_DESC, MOD_MMR6_ENC, ISA_MICROMIPS32R6; -def MODU_MMR6 : R6MMR6Rel, MODU_MMR6_DESC, MODU_MMR6_ENC, ISA_MICROMIPS32R6; -def MUL_MMR6 : R6MMR6Rel, MUL_MMR6_DESC, MUL_MMR6_ENC, ISA_MICROMIPS32R6; -def MUH_MMR6 : R6MMR6Rel, MUH_MMR6_DESC, MUH_MMR6_ENC, ISA_MICROMIPS32R6; -def MULU_MMR6 : R6MMR6Rel, MULU_MMR6_DESC, MULU_MMR6_ENC, ISA_MICROMIPS32R6; -def MUHU_MMR6 : R6MMR6Rel, MUHU_MMR6_DESC, MUHU_MMR6_ENC, ISA_MICROMIPS32R6; -def NOR_MMR6 : StdMMR6Rel, NOR_MMR6_DESC, NOR_MMR6_ENC, ISA_MICROMIPS32R6; -def OR_MMR6 : StdMMR6Rel, OR_MMR6_DESC, OR_MMR6_ENC, ISA_MICROMIPS32R6; -def ORI_MMR6 : StdMMR6Rel, ORI_MMR6_DESC, ORI_MMR6_ENC, ISA_MICROMIPS32R6; -def PREF_MMR6 : R6MMR6Rel, PREF_MMR6_ENC, PREF_MMR6_DESC, ISA_MICROMIPS32R6; -def SB16_MMR6 : StdMMR6Rel, SB16_MMR6_DESC, SB16_MMR6_ENC, ISA_MICROMIPS32R6; -def SELEQZ_MMR6 : R6MMR6Rel, SELEQZ_MMR6_ENC, SELEQZ_MMR6_DESC, - ISA_MICROMIPS32R6; -def SELNEZ_MMR6 : R6MMR6Rel, SELNEZ_MMR6_ENC, SELNEZ_MMR6_DESC, - ISA_MICROMIPS32R6; -def SH16_MMR6 : StdMMR6Rel, SH16_MMR6_DESC, SH16_MMR6_ENC, ISA_MICROMIPS32R6; -def SLL_MMR6 : StdMMR6Rel, SLL_MMR6_DESC, SLL_MMR6_ENC, ISA_MICROMIPS32R6; -def SUB_MMR6 : StdMMR6Rel, SUB_MMR6_DESC, SUB_MMR6_ENC, ISA_MICROMIPS32R6; -def SUBU_MMR6 : StdMMR6Rel, SUBU_MMR6_DESC, SUBU_MMR6_ENC, ISA_MICROMIPS32R6; -def SW16_MMR6 : StdMMR6Rel, SW16_MMR6_DESC, SW16_MMR6_ENC, ISA_MICROMIPS32R6; -def SWM16_MMR6 : StdMMR6Rel, SWM16_MMR6_DESC, SWM16_MMR6_ENC, ISA_MICROMIPS32R6; -def SWSP_MMR6 : StdMMR6Rel, SWSP_MMR6_DESC, SWSP_MMR6_ENC, ISA_MICROMIPS32R6; -def WRPGPR_MMR6 : StdMMR6Rel, WRPGPR_MMR6_ENC, WRPGPR_MMR6_DESC, - ISA_MICROMIPS32R6; -def WSBH_MMR6 : StdMMR6Rel, WSBH_MMR6_ENC, WSBH_MMR6_DESC, ISA_MICROMIPS32R6; -def LB_MMR6 : R6MMR6Rel, LB_MMR6_ENC, LB_MMR6_DESC, ISA_MICROMIPS32R6; -def LBU_MMR6 : R6MMR6Rel, LBU_MMR6_ENC, LBU_MMR6_DESC, ISA_MICROMIPS32R6; -def PAUSE_MMR6 : StdMMR6Rel, PAUSE_MMR6_DESC, PAUSE_MMR6_ENC, ISA_MICROMIPS32R6; -def RDHWR_MMR6 : R6MMR6Rel, RDHWR_MMR6_DESC, RDHWR_MMR6_ENC, ISA_MICROMIPS32R6; -def WAIT_MMR6 : StdMMR6Rel, WAIT_MMR6_DESC, WAIT_MMR6_ENC, ISA_MICROMIPS32R6; -def SSNOP_MMR6 : StdMMR6Rel, SSNOP_MMR6_DESC, SSNOP_MMR6_ENC, ISA_MICROMIPS32R6; -def SYNC_MMR6 : StdMMR6Rel, SYNC_MMR6_DESC, SYNC_MMR6_ENC, ISA_MICROMIPS32R6; -def SYNCI_MMR6 : StdMMR6Rel, SYNCI_MMR6_DESC, SYNCI_MMR6_ENC, ISA_MICROMIPS32R6; -def RDPGPR_MMR6 : R6MMR6Rel, RDPGPR_MMR6_DESC, RDPGPR_MMR6_ENC, - ISA_MICROMIPS32R6; -def SDBBP_MMR6 : R6MMR6Rel, SDBBP_MMR6_DESC, SDBBP_MMR6_ENC, ISA_MICROMIPS32R6; -def SIGRIE_MMR6 : R6MMR6Rel, SIGRIE_MMR6_DESC, SIGRIE_MMR6_ENC, ISA_MICROMIPS32R6; -def XOR_MMR6 : StdMMR6Rel, XOR_MMR6_DESC, XOR_MMR6_ENC, ISA_MICROMIPS32R6; -def XORI_MMR6 : StdMMR6Rel, XORI_MMR6_DESC, XORI_MMR6_ENC, ISA_MICROMIPS32R6; -let DecoderMethod = "DecodeMemMMImm16" in { - def SW_MMR6 : StdMMR6Rel, SW_MMR6_DESC, SW_MMR6_ENC, ISA_MICROMIPS32R6; -} -/// Floating Point Instructions -def FADD_S_MMR6 : StdMMR6Rel, FADD_S_MMR6_ENC, FADD_S_MMR6_DESC, - ISA_MICROMIPS32R6; -def FSUB_S_MMR6 : StdMMR6Rel, FSUB_S_MMR6_ENC, FSUB_S_MMR6_DESC, - ISA_MICROMIPS32R6; -def FMUL_S_MMR6 : StdMMR6Rel, FMUL_S_MMR6_ENC, FMUL_S_MMR6_DESC, - ISA_MICROMIPS32R6; -def FDIV_S_MMR6 : StdMMR6Rel, FDIV_S_MMR6_ENC, FDIV_S_MMR6_DESC, - ISA_MICROMIPS32R6; -def MADDF_S_MMR6 : R6MMR6Rel, MADDF_S_MMR6_ENC, MADDF_S_MMR6_DESC, - ISA_MICROMIPS32R6; -def MADDF_D_MMR6 : R6MMR6Rel, MADDF_D_MMR6_ENC, MADDF_D_MMR6_DESC, - ISA_MICROMIPS32R6; -def MSUBF_S_MMR6 : R6MMR6Rel, MSUBF_S_MMR6_ENC, MSUBF_S_MMR6_DESC, - ISA_MICROMIPS32R6; -def MSUBF_D_MMR6 : R6MMR6Rel, MSUBF_D_MMR6_ENC, MSUBF_D_MMR6_DESC, - ISA_MICROMIPS32R6; -def FMOV_S_MMR6 : StdMMR6Rel, FMOV_S_MMR6_ENC, FMOV_S_MMR6_DESC, - ISA_MICROMIPS32R6; -def FMOV_D_MMR6 : StdMMR6Rel, FMOV_D_MMR6_ENC, FMOV_D_MMR6_DESC, - ISA_MICROMIPS32R6; -def FNEG_S_MMR6 : StdMMR6Rel, FNEG_S_MMR6_ENC, FNEG_S_MMR6_DESC, - ISA_MICROMIPS32R6; -def MAX_S_MMR6 : R6MMR6Rel, MAX_S_MMR6_ENC, MAX_S_MMR6_DESC, ISA_MICROMIPS32R6; -def MAX_D_MMR6 : R6MMR6Rel, MAX_D_MMR6_ENC, MAX_D_MMR6_DESC, ISA_MICROMIPS32R6; -def MIN_S_MMR6 : R6MMR6Rel, MIN_S_MMR6_ENC, MIN_S_MMR6_DESC, ISA_MICROMIPS32R6; -def MIN_D_MMR6 : R6MMR6Rel, MIN_D_MMR6_ENC, MIN_D_MMR6_DESC, ISA_MICROMIPS32R6; -def MAXA_S_MMR6 : R6MMR6Rel, MAXA_S_MMR6_ENC, MAXA_S_MMR6_DESC, - ISA_MICROMIPS32R6; -def MAXA_D_MMR6 : R6MMR6Rel, MAXA_D_MMR6_ENC, MAXA_D_MMR6_DESC, - ISA_MICROMIPS32R6; -def MINA_S_MMR6 : R6MMR6Rel, MINA_S_MMR6_ENC, MINA_S_MMR6_DESC, - ISA_MICROMIPS32R6; -def MINA_D_MMR6 : R6MMR6Rel, MINA_D_MMR6_ENC, MINA_D_MMR6_DESC, - ISA_MICROMIPS32R6; -def CVT_L_S_MMR6 : StdMMR6Rel, CVT_L_S_MMR6_ENC, CVT_L_S_MMR6_DESC, - ISA_MICROMIPS32R6; -def CVT_L_D_MMR6 : StdMMR6Rel, CVT_L_D_MMR6_ENC, CVT_L_D_MMR6_DESC, - ISA_MICROMIPS32R6; -def CVT_W_S_MMR6 : StdMMR6Rel, CVT_W_S_MMR6_ENC, CVT_W_S_MMR6_DESC, - ISA_MICROMIPS32R6; -def CVT_D_L_MMR6 : StdMMR6Rel, CVT_D_L_MMR6_ENC, CVT_D_L_MMR6_DESC, - ISA_MICROMIPS32R6; -def CVT_S_W_MMR6 : StdMMR6Rel, CVT_S_W_MMR6_ENC, CVT_S_W_MMR6_DESC, - ISA_MICROMIPS32R6; -def CVT_S_L_MMR6 : StdMMR6Rel, CVT_S_L_MMR6_ENC, CVT_S_L_MMR6_DESC, - ISA_MICROMIPS32R6; -defm S_MMR6 : CMP_CC_MMR6<0b000101, "s", FGR32Opnd, II_CMP_CC_S>; -defm D_MMR6 : CMP_CC_MMR6<0b010101, "d", FGR64Opnd, II_CMP_CC_D>; -def FLOOR_L_S_MMR6 : StdMMR6Rel, FLOOR_L_S_MMR6_ENC, FLOOR_L_S_MMR6_DESC, - ISA_MICROMIPS32R6; -def FLOOR_L_D_MMR6 : StdMMR6Rel, FLOOR_L_D_MMR6_ENC, FLOOR_L_D_MMR6_DESC, - ISA_MICROMIPS32R6; -def FLOOR_W_S_MMR6 : StdMMR6Rel, FLOOR_W_S_MMR6_ENC, FLOOR_W_S_MMR6_DESC, - ISA_MICROMIPS32R6; -def FLOOR_W_D_MMR6 : StdMMR6Rel, FLOOR_W_D_MMR6_ENC, FLOOR_W_D_MMR6_DESC, - ISA_MICROMIPS32R6; -def CEIL_L_S_MMR6 : StdMMR6Rel, CEIL_L_S_MMR6_ENC, CEIL_L_S_MMR6_DESC, - ISA_MICROMIPS32R6; -def CEIL_L_D_MMR6 : StdMMR6Rel, CEIL_L_D_MMR6_ENC, CEIL_L_D_MMR6_DESC, - ISA_MICROMIPS32R6; -def CEIL_W_S_MMR6 : StdMMR6Rel, CEIL_W_S_MMR6_ENC, CEIL_W_S_MMR6_DESC, - ISA_MICROMIPS32R6; -def CEIL_W_D_MMR6 : StdMMR6Rel, CEIL_W_D_MMR6_ENC, CEIL_W_D_MMR6_DESC, - ISA_MICROMIPS32R6; -def TRUNC_L_S_MMR6 : StdMMR6Rel, TRUNC_L_S_MMR6_ENC, TRUNC_L_S_MMR6_DESC, - ISA_MICROMIPS32R6; -def TRUNC_L_D_MMR6 : StdMMR6Rel, TRUNC_L_D_MMR6_ENC, TRUNC_L_D_MMR6_DESC, - ISA_MICROMIPS32R6; -def TRUNC_W_S_MMR6 : StdMMR6Rel, TRUNC_W_S_MMR6_ENC, TRUNC_W_S_MMR6_DESC, - ISA_MICROMIPS32R6; -def TRUNC_W_D_MMR6 : StdMMR6Rel, TRUNC_W_D_MMR6_ENC, TRUNC_W_D_MMR6_DESC, - ISA_MICROMIPS32R6; -def SB_MMR6 : StdMMR6Rel, SB_MMR6_DESC, SB_MMR6_ENC, ISA_MICROMIPS32R6; -def SH_MMR6 : StdMMR6Rel, SH_MMR6_DESC, SH_MMR6_ENC, ISA_MICROMIPS32R6; -def LW_MMR6 : StdMMR6Rel, LW_MMR6_DESC, LW_MMR6_ENC, ISA_MICROMIPS32R6; -def LUI_MMR6 : R6MMR6Rel, LUI_MMR6_DESC, LUI_MMR6_ENC, ISA_MICROMIPS32R6; -def ADDU16_MMR6 : StdMMR6Rel, ADDU16_MMR6_DESC, ADDU16_MMR6_ENC, - ISA_MICROMIPS32R6; -def AND16_MMR6 : StdMMR6Rel, AND16_MMR6_DESC, AND16_MMR6_ENC, - ISA_MICROMIPS32R6; -def ANDI16_MMR6 : StdMMR6Rel, ANDI16_MMR6_DESC, ANDI16_MMR6_ENC, - ISA_MICROMIPS32R6; -def NOT16_MMR6 : StdMMR6Rel, NOT16_MMR6_DESC, NOT16_MMR6_ENC, - ISA_MICROMIPS32R6; -def OR16_MMR6 : StdMMR6Rel, OR16_MMR6_DESC, OR16_MMR6_ENC, - ISA_MICROMIPS32R6; -def SLL16_MMR6 : StdMMR6Rel, SLL16_MMR6_DESC, SLL16_MMR6_ENC, - ISA_MICROMIPS32R6; -def SRL16_MMR6 : StdMMR6Rel, SRL16_MMR6_DESC, SRL16_MMR6_ENC, - ISA_MICROMIPS32R6; -def BREAK16_MMR6 : StdMMR6Rel, BREAK16_MMR6_DESC, BREAK16_MMR6_ENC, - ISA_MICROMIPS32R6; -def LI16_MMR6 : StdMMR6Rel, LI16_MMR6_DESC, LI16_MMR6_ENC, - ISA_MICROMIPS32R6; -def MOVE16_MMR6 : StdMMR6Rel, MOVE16_MMR6_DESC, MOVE16_MMR6_ENC, - ISA_MICROMIPS32R6; -def MOVEP_MMR6 : StdMMR6Rel, MOVEP_MMR6_DESC, MOVEP_MMR6_ENC, - ISA_MICROMIPS32R6; -def SDBBP16_MMR6 : StdMMR6Rel, SDBBP16_MMR6_DESC, SDBBP16_MMR6_ENC, - ISA_MICROMIPS32R6; -def SUBU16_MMR6 : StdMMR6Rel, SUBU16_MMR6_DESC, SUBU16_MMR6_ENC, - ISA_MICROMIPS32R6; -def XOR16_MMR6 : StdMMR6Rel, XOR16_MMR6_DESC, XOR16_MMR6_ENC, - ISA_MICROMIPS32R6; -def JALRC_HB_MMR6 : R6MMR6Rel, JALRC_HB_MMR6_ENC, JALRC_HB_MMR6_DESC, - ISA_MICROMIPS32R6; -def EXT_MMR6 : StdMMR6Rel, EXT_MMR6_ENC, EXT_MMR6_DESC, ISA_MICROMIPS32R6; -def INS_MMR6 : StdMMR6Rel, INS_MMR6_ENC, INS_MMR6_DESC, ISA_MICROMIPS32R6; -def JALRC_MMR6 : R6MMR6Rel, JALRC_MMR6_ENC, JALRC_MMR6_DESC, ISA_MICROMIPS32R6; -def RINT_S_MMR6 : StdMMR6Rel, RINT_S_MMR6_ENC, RINT_S_MMR6_DESC, - ISA_MICROMIPS32R6; -def RINT_D_MMR6 : StdMMR6Rel, RINT_D_MMR6_ENC, RINT_D_MMR6_DESC, ISA_MICROMIPS32R6; -def ROUND_L_S_MMR6 : StdMMR6Rel, ROUND_L_S_MMR6_ENC, ROUND_L_S_MMR6_DESC, - ISA_MICROMIPS32R6; -def ROUND_L_D_MMR6 : StdMMR6Rel, ROUND_L_D_MMR6_ENC, ROUND_L_D_MMR6_DESC, - ISA_MICROMIPS32R6; -def ROUND_W_S_MMR6 : StdMMR6Rel, ROUND_W_S_MMR6_ENC, ROUND_W_S_MMR6_DESC, - ISA_MICROMIPS32R6; -def ROUND_W_D_MMR6 : StdMMR6Rel, ROUND_W_D_MMR6_ENC, ROUND_W_D_MMR6_DESC, - ISA_MICROMIPS32R6; -def SEL_S_MMR6 : R6MMR6Rel, SEL_S_MMR6_ENC, SEL_S_MMR6_DESC, ISA_MICROMIPS32R6; -def SEL_D_MMR6 : R6MMR6Rel, SEL_D_MMR6_ENC, SEL_D_MMR6_DESC, ISA_MICROMIPS32R6; -def SELEQZ_S_MMR6 : R6MMR6Rel, SELEQZ_S_MMR6_ENC, SELEQZ_S_MMR6_DESC, - ISA_MICROMIPS32R6; -def SELEQZ_D_MMR6 : R6MMR6Rel, SELEQZ_D_MMR6_ENC, SELEQZ_D_MMR6_DESC, - ISA_MICROMIPS32R6; -def SELNEZ_S_MMR6 : R6MMR6Rel, SELNEZ_S_MMR6_ENC, SELNEZ_S_MMR6_DESC, - ISA_MICROMIPS32R6; -def SELNEZ_D_MMR6 : R6MMR6Rel, SELNEZ_D_MMR6_ENC, SELNEZ_D_MMR6_DESC, - ISA_MICROMIPS32R6; -def CLASS_S_MMR6 : StdMMR6Rel, CLASS_S_MMR6_ENC, CLASS_S_MMR6_DESC, - ISA_MICROMIPS32R6; -def CLASS_D_MMR6 : StdMMR6Rel, CLASS_D_MMR6_ENC, CLASS_D_MMR6_DESC, - ISA_MICROMIPS32R6; -def TLBINV_MMR6 : StdMMR6Rel, TLBINV_MMR6_ENC, TLBINV_MMR6_DESC, - ISA_MICROMIPS32R6; -def TLBINVF_MMR6 : StdMMR6Rel, TLBINVF_MMR6_ENC, TLBINVF_MMR6_DESC, - ISA_MICROMIPS32R6; -def DVP_MMR6 : R6MMR6Rel, DVP_MMR6_ENC, DVP_MMR6_DESC, ISA_MICROMIPS32R6; -def EVP_MMR6 : R6MMR6Rel, EVP_MMR6_ENC, EVP_MMR6_DESC, ISA_MICROMIPS32R6; -def BC1EQZC_MMR6 : R6MMR6Rel, BC1EQZC_MMR6_DESC, BC1EQZC_MMR6_ENC, - ISA_MICROMIPS32R6; -def BC1NEZC_MMR6 : R6MMR6Rel, BC1NEZC_MMR6_DESC, BC1NEZC_MMR6_ENC, - ISA_MICROMIPS32R6; -def BC2EQZC_MMR6 : R6MMR6Rel, MipsR6Inst, BC2EQZC_MMR6_ENC, BC2EQZC_MMR6_DESC, - ISA_MICROMIPS32R6; -def BC2NEZC_MMR6 : R6MMR6Rel, MipsR6Inst, BC2NEZC_MMR6_ENC, BC2NEZC_MMR6_DESC, - ISA_MICROMIPS32R6; -let DecoderNamespace = "MicroMipsFP64" in { - def LDC1_D64_MMR6 : StdMMR6Rel, LDC1_D64_MMR6_DESC, LDC1_MMR6_ENC, - ISA_MICROMIPS32R6 { - let BaseOpcode = "LDC164"; - } - def SDC1_D64_MMR6 : StdMMR6Rel, SDC1_D64_MMR6_DESC, SDC1_MMR6_ENC, - ISA_MICROMIPS32R6; -} -def LDC2_MMR6 : StdMMR6Rel, LDC2_MMR6_ENC, LDC2_MMR6_DESC, ISA_MICROMIPS32R6; -def SDC2_MMR6 : StdMMR6Rel, SDC2_MMR6_ENC, SDC2_MMR6_DESC, ISA_MICROMIPS32R6; -def LWC2_MMR6 : StdMMR6Rel, LWC2_MMR6_ENC, LWC2_MMR6_DESC, ISA_MICROMIPS32R6; -def SWC2_MMR6 : StdMMR6Rel, SWC2_MMR6_ENC, SWC2_MMR6_DESC, ISA_MICROMIPS32R6; -def LL_MMR6 : R6MMR6Rel, LL_MMR6_ENC, LL_MMR6_DESC, ISA_MICROMIPS32R6; -def SC_MMR6 : R6MMR6Rel, SC_MMR6_ENC, SC_MMR6_DESC, ISA_MICROMIPS32R6; -} - -def BOVC_MMR6 : R6MMR6Rel, BOVC_MMR6_ENC, BOVC_MMR6_DESC, ISA_MICROMIPS32R6, - MMDecodeDisambiguatedBy<"POP35GroupBranchMMR6">; -def BNVC_MMR6 : R6MMR6Rel, BNVC_MMR6_ENC, BNVC_MMR6_DESC, ISA_MICROMIPS32R6, - MMDecodeDisambiguatedBy<"POP37GroupBranchMMR6">; -def BGEC_MMR6 : R6MMR6Rel, BGEC_MMR6_ENC, BGEC_MMR6_DESC, ISA_MICROMIPS32R6; -def BGEUC_MMR6 : R6MMR6Rel, BGEUC_MMR6_ENC, BGEUC_MMR6_DESC, ISA_MICROMIPS32R6; -def BLTC_MMR6 : R6MMR6Rel, BLTC_MMR6_ENC, BLTC_MMR6_DESC, ISA_MICROMIPS32R6; -def BLTUC_MMR6 : R6MMR6Rel, BLTUC_MMR6_ENC, BLTUC_MMR6_DESC, ISA_MICROMIPS32R6; -def BEQC_MMR6 : R6MMR6Rel, BEQC_MMR6_ENC, BEQC_MMR6_DESC, ISA_MICROMIPS32R6, - DecodeDisambiguates<"POP35GroupBranchMMR6">; -def BNEC_MMR6 : R6MMR6Rel, BNEC_MMR6_ENC, BNEC_MMR6_DESC, ISA_MICROMIPS32R6, - DecodeDisambiguates<"POP37GroupBranchMMR6">; -def BLTZC_MMR6 : R6MMR6Rel, BLTZC_MMR6_ENC, BLTZC_MMR6_DESC, ISA_MICROMIPS32R6; -def BLEZC_MMR6 : R6MMR6Rel, BLEZC_MMR6_ENC, BLEZC_MMR6_DESC, ISA_MICROMIPS32R6; -def BGEZC_MMR6 : R6MMR6Rel, BGEZC_MMR6_ENC, BGEZC_MMR6_DESC, ISA_MICROMIPS32R6; -def BGTZC_MMR6 : R6MMR6Rel, BGTZC_MMR6_ENC, BGTZC_MMR6_DESC, ISA_MICROMIPS32R6; -def BGEZALC_MMR6 : R6MMR6Rel, BGEZALC_MMR6_ENC, BGEZALC_MMR6_DESC, - ISA_MICROMIPS32R6; -def BGTZALC_MMR6 : R6MMR6Rel, BGTZALC_MMR6_ENC, BGTZALC_MMR6_DESC, - ISA_MICROMIPS32R6; -def BLEZALC_MMR6 : R6MMR6Rel, BLEZALC_MMR6_ENC, BLEZALC_MMR6_DESC, - ISA_MICROMIPS32R6; -def BLTZALC_MMR6 : R6MMR6Rel, BLTZALC_MMR6_ENC, BLTZALC_MMR6_DESC, - ISA_MICROMIPS32R6; - -//===----------------------------------------------------------------------===// -// -// MicroMips instruction aliases -// -//===----------------------------------------------------------------------===// - -def : MipsInstAlias<"ei", (EI_MMR6 ZERO), 1>, ISA_MICROMIPS32R6; -def : MipsInstAlias<"di", (DI_MMR6 ZERO), 1>, ISA_MICROMIPS32R6; -def : MipsInstAlias<"nop", (SLL_MMR6 ZERO, ZERO, 0), 1>, ISA_MICROMIPS32R6; -def B_MMR6_Pseudo : MipsAsmPseudoInst<(outs), (ins brtarget_mm:$offset), - !strconcat("b", "\t$offset")> { - string DecoderNamespace = "MicroMipsR6"; -} -def : MipsInstAlias<"sync", (SYNC_MMR6 0), 1>, ISA_MICROMIPS32R6; -def : MipsInstAlias<"sdbbp", (SDBBP_MMR6 0), 1>, ISA_MICROMIPS32R6; -def : MipsInstAlias<"sigrie", (SIGRIE_MMR6 0), 1>, ISA_MICROMIPS32R6; -def : MipsInstAlias<"rdhwr $rt, $rs", - (RDHWR_MMR6 GPR32Opnd:$rt, HWRegsOpnd:$rs, 0), 1>, - ISA_MICROMIPS32R6; -def : MipsInstAlias<"mtc0 $rt, $rs", - (MTC0_MMR6 COP0Opnd:$rs, GPR32Opnd:$rt, 0), 0>, - ISA_MICROMIPS32R6; -def : MipsInstAlias<"mthc0 $rt, $rs", - (MTHC0_MMR6 COP0Opnd:$rs, GPR32Opnd:$rt, 0), 0>, - ISA_MICROMIPS32R6; -def : MipsInstAlias<"mfc0 $rt, $rs", - (MFC0_MMR6 GPR32Opnd:$rt, COP0Opnd:$rs, 0), 0>, - ISA_MICROMIPS32R6; -def : MipsInstAlias<"mfhc0 $rt, $rs", - (MFHC0_MMR6 GPR32Opnd:$rt, COP0Opnd:$rs, 0), 0>, - ISA_MICROMIPS32R6; -def : MipsInstAlias<"jalrc.hb $rs", (JALRC_HB_MMR6 RA, GPR32Opnd:$rs), 1>, - ISA_MICROMIPS32R6; -def : MipsInstAlias<"jal $offset", (BALC_MMR6 brtarget26_mm:$offset), 0>, - ISA_MICROMIPS32R6; -def : MipsInstAlias<"dvp", (DVP_MMR6 ZERO), 0>, ISA_MICROMIPS32R6; -def : MipsInstAlias<"evp", (EVP_MMR6 ZERO), 0>, ISA_MICROMIPS32R6; -def : MipsInstAlias<"jalrc $rs", (JALRC_MMR6 RA, GPR32Opnd:$rs), 1>, - ISA_MICROMIPS32R6; -def : MipsInstAlias<"and $rs, $rt, $imm", - (ANDI_MMR6 GPR32Opnd:$rs, GPR32Opnd:$rt, uimm16:$imm), 0>, - ISA_MICROMIPS32R6; -def : MipsInstAlias<"and $rs, $imm", - (ANDI_MMR6 GPR32Opnd:$rs, GPR32Opnd:$rs, uimm16:$imm), 0>, - ISA_MICROMIPS32R6; -def : MipsInstAlias<"or $rs, $rt, $imm", - (ORI_MMR6 GPR32Opnd:$rs, GPR32Opnd:$rt, uimm16:$imm), 0>, - ISA_MICROMIPS32R6; -def : MipsInstAlias<"or $rs, $imm", - (ORI_MMR6 GPR32Opnd:$rs, GPR32Opnd:$rs, uimm16:$imm), 0>, - ISA_MICROMIPS32R6; -def : MipsInstAlias<"xor $rs, $rt, $imm", - (XORI_MMR6 GPR32Opnd:$rs, GPR32Opnd:$rt, uimm16:$imm), 0>, - ISA_MICROMIPS32R6; -def : MipsInstAlias<"xor $rs, $imm", - (XORI_MMR6 GPR32Opnd:$rs, GPR32Opnd:$rs, uimm16:$imm), 0>, - ISA_MICROMIPS32R6; -def : MipsInstAlias<"not $rt, $rs", - (NOR_MMR6 GPR32Opnd:$rt, GPR32Opnd:$rs, ZERO), 0>, - ISA_MICROMIPS32R6; -def : MipsInstAlias<"not $rt", - (NOR_MMR6 GPR32Opnd:$rt, GPR32Opnd:$rt, ZERO), 0>, - ISA_MICROMIPS32R6; -def : MipsInstAlias<"lapc $rd, $imm", - (ADDIUPC_MMR6 GPR32Opnd:$rd, simm19_lsl2:$imm)>, - ISA_MICROMIPS32R6; -def : MipsInstAlias<"neg $rt, $rs", - (SUB_MMR6 GPR32Opnd:$rt, ZERO, GPR32Opnd:$rs), 1>, - ISA_MICROMIPS32R6; -def : MipsInstAlias<"neg $rt", - (SUB_MMR6 GPR32Opnd:$rt, ZERO, GPR32Opnd:$rt), 1>, - ISA_MICROMIPS32R6; -def : MipsInstAlias<"negu $rt, $rs", - (SUBU_MMR6 GPR32Opnd:$rt, ZERO, GPR32Opnd:$rs), 1>, - ISA_MICROMIPS32R6; -def : MipsInstAlias<"negu $rt", - (SUBU_MMR6 GPR32Opnd:$rt, ZERO, GPR32Opnd:$rt), 1>, - ISA_MICROMIPS32R6; -def : MipsInstAlias<"beqz16 $rs, $offset", (BEQZC16_MMR6 GPRMM16Opnd:$rs, - brtarget7_mm:$offset), - 0>, ISA_MICROMIPS32R6; -def : MipsInstAlias<"bnez16 $rs, $offset", (BNEZC16_MMR6 GPRMM16Opnd:$rs, - brtarget7_mm:$offset), - 0>, ISA_MICROMIPS32R6; -def : MipsInstAlias<"b16 $offset", (BC16_MMR6 brtarget10_mm:$offset), 0>, - ISA_MICROMIPS32R6; - -//===----------------------------------------------------------------------===// -// -// MicroMips arbitrary patterns that map to one or more instructions -// -//===----------------------------------------------------------------------===// - -def : MipsPat<(store GPRMM16:$src, addrimm4lsl2:$addr), - (SW16_MMR6 GPRMM16:$src, addrimm4lsl2:$addr)>, ISA_MICROMIPS32R6; -def : MipsPat<(subc GPR32:$lhs, GPR32:$rhs), - (SUBU_MMR6 GPR32:$lhs, GPR32:$rhs)>, ISA_MICROMIPS32R6; - -def : MipsPat<(select i32:$cond, i32:$t, i32:$f), - (OR_MM (SELNEZ_MMR6 i32:$t, i32:$cond), - (SELEQZ_MMR6 i32:$f, i32:$cond))>, - ISA_MICROMIPS32R6; -def : MipsPat<(select i32:$cond, i32:$t, immz), - (SELNEZ_MMR6 i32:$t, i32:$cond)>, - ISA_MICROMIPS32R6; -def : MipsPat<(select i32:$cond, immz, i32:$f), - (SELEQZ_MMR6 i32:$f, i32:$cond)>, - ISA_MICROMIPS32R6; - -defm : SelectInt_Pats<i32, OR_MM, XORI_MMR6, SLTi_MM, SLTiu_MM, SELEQZ_MMR6, - SELNEZ_MMR6, immZExt16, i32>, ISA_MICROMIPS32R6; - -defm S_MMR6 : Cmp_Pats<f32, NOR_MMR6, ZERO>, ISA_MICROMIPS32R6; -defm D_MMR6 : Cmp_Pats<f64, NOR_MMR6, ZERO>, ISA_MICROMIPS32R6; - -def : MipsPat<(f32 fpimm0), (MTC1_MMR6 ZERO)>, ISA_MICROMIPS32R6; -def : MipsPat<(f32 fpimm0neg), (FNEG_S_MMR6 (MTC1_MMR6 ZERO))>, ISA_MICROMIPS32R6; -def : MipsPat<(MipsTruncIntFP FGR64Opnd:$src), - (TRUNC_W_D_MMR6 FGR64Opnd:$src)>, ISA_MICROMIPS32R6; -def : MipsPat<(MipsTruncIntFP FGR32Opnd:$src), - (TRUNC_W_S_MMR6 FGR32Opnd:$src)>, ISA_MICROMIPS32R6; - -def : MipsPat<(and GPRMM16:$src, immZExtAndi16:$imm), - (ANDI16_MMR6 GPRMM16:$src, immZExtAndi16:$imm)>, - ISA_MICROMIPS32R6; -def : MipsPat<(and GPR32:$src, immZExt16:$imm), - (ANDI_MMR6 GPR32:$src, immZExt16:$imm)>, ISA_MICROMIPS32R6; -def : MipsPat<(i32 immZExt16:$imm), - (XORI_MMR6 ZERO, immZExt16:$imm)>, ISA_MICROMIPS32R6; -def : MipsPat<(not GPRMM16:$in), - (NOT16_MMR6 GPRMM16:$in)>, ISA_MICROMIPS32R6; -def : MipsPat<(not GPR32:$in), - (NOR_MMR6 GPR32Opnd:$in, ZERO)>, ISA_MICROMIPS32R6; -// Patterns for load with a reg+imm operand. -let AddedComplexity = 41 in { - def : LoadRegImmPat<LDC1_D64_MMR6, f64, load>, FGR_64, ISA_MICROMIPS32R6; - def : StoreRegImmPat<SDC1_D64_MMR6, f64>, FGR_64, ISA_MICROMIPS32R6; -} - -let isCall=1, hasDelaySlot=0, isCTI=1, Defs = [RA] in { - class JumpLinkMMR6<Instruction JumpInst, DAGOperand Opnd> : - PseudoSE<(outs), (ins calltarget:$target), [], II_JAL>, - PseudoInstExpansion<(JumpInst Opnd:$target)>; -} - -def JAL_MMR6 : JumpLinkMMR6<BALC_MMR6, brtarget26_mm>, ISA_MICROMIPS32R6; - -def : MipsPat<(MipsJmpLink (i32 texternalsym:$dst)), - (JAL_MMR6 texternalsym:$dst)>, ISA_MICROMIPS32R6; -def : MipsPat<(MipsJmpLink (iPTR tglobaladdr:$dst)), - (JAL_MMR6 tglobaladdr:$dst)>, ISA_MICROMIPS32R6; - -def TAILCALL_MMR6 : TailCall<BC_MMR6, brtarget26_mm>, ISA_MICROMIPS32R6; - -def TAILCALLREG_MMR6 : TailCallReg<JRC16_MM, GPR32Opnd>, ISA_MICROMIPS32R6; - -def PseudoIndirectBranch_MMR6 : PseudoIndirectBranchBase<JRC16_MMR6, - GPR32Opnd>, - ISA_MICROMIPS32R6; - -def : MipsPat<(MipsTailCall (iPTR tglobaladdr:$dst)), - (TAILCALL_MMR6 tglobaladdr:$dst)>, ISA_MICROMIPS32R6; - -def : MipsPat<(MipsTailCall (iPTR texternalsym:$dst)), - (TAILCALL_MMR6 texternalsym:$dst)>, ISA_MICROMIPS32R6; - - -def : MipsPat<(brcond (i32 (setne GPR32:$lhs, 0)), bb:$dst), - (BNEZC_MMR6 GPR32:$lhs, bb:$dst)>, ISA_MICROMIPS32R6; -def : MipsPat<(brcond (i32 (seteq GPR32:$lhs, 0)), bb:$dst), - (BEQZC_MMR6 GPR32:$lhs, bb:$dst)>, ISA_MICROMIPS32R6; - -def : MipsPat<(brcond (i32 (setge GPR32:$lhs, GPR32:$rhs)), bb:$dst), - (BEQZC_MMR6 (SLT_MM GPR32:$lhs, GPR32:$rhs), bb:$dst)>, - ISA_MICROMIPS32R6; -def : MipsPat<(brcond (i32 (setuge GPR32:$lhs, GPR32:$rhs)), bb:$dst), - (BEQZC_MMR6 (SLTu_MM GPR32:$lhs, GPR32:$rhs), bb:$dst)>, - ISA_MICROMIPS32R6; -def : MipsPat<(brcond (i32 (setge GPR32:$lhs, immSExt16:$rhs)), bb:$dst), - (BEQZC_MMR6 (SLTi_MM GPR32:$lhs, immSExt16:$rhs), bb:$dst)>, - ISA_MICROMIPS32R6; -def : MipsPat<(brcond (i32 (setuge GPR32:$lhs, immSExt16:$rhs)), bb:$dst), - (BEQZC_MMR6 (SLTiu_MM GPR32:$lhs, immSExt16:$rhs), bb:$dst)>, - ISA_MICROMIPS32R6; -def : MipsPat<(brcond (i32 (setgt GPR32:$lhs, immSExt16Plus1:$rhs)), bb:$dst), - (BEQZC_MMR6 (SLTi_MM GPR32:$lhs, (Plus1 imm:$rhs)), bb:$dst)>, - ISA_MICROMIPS32R6; -def : MipsPat<(brcond (i32 (setugt GPR32:$lhs, immSExt16Plus1:$rhs)), bb:$dst), - (BEQZC_MMR6 (SLTiu_MM GPR32:$lhs, (Plus1 imm:$rhs)), bb:$dst)>, - ISA_MICROMIPS32R6; - -def : MipsPat<(brcond (i32 (setle GPR32:$lhs, GPR32:$rhs)), bb:$dst), - (BEQZC_MMR6 (SLT_MM GPR32:$rhs, GPR32:$lhs), bb:$dst)>, - ISA_MICROMIPS32R6; -def : MipsPat<(brcond (i32 (setule GPR32:$lhs, GPR32:$rhs)), bb:$dst), - (BEQZC_MMR6 (SLTu_MM GPR32:$rhs, GPR32:$lhs), bb:$dst)>, - ISA_MICROMIPS32R6; - -def : MipsPat<(brcond GPR32:$cond, bb:$dst), - (BNEZC_MMR6 GPR32:$cond, bb:$dst)>, ISA_MICROMIPS32R6; diff --git a/contrib/llvm/lib/Target/Mips/MicroMipsDSPInstrFormats.td b/contrib/llvm/lib/Target/Mips/MicroMipsDSPInstrFormats.td deleted file mode 100644 index 26b6cf8994ca..000000000000 --- a/contrib/llvm/lib/Target/Mips/MicroMipsDSPInstrFormats.td +++ /dev/null @@ -1,301 +0,0 @@ -//===-- MicroMipsDSPInstrFormats.td - Instruction Formats --*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -class MMDSPInst<string opstr = ""> - : MipsInst<(outs), (ins), "", [], NoItinerary, FrmOther> { - let ASEPredicate = [HasDSP]; - let EncodingPredicates = [InMicroMips]; - string BaseOpcode = opstr; - string Arch = "mmdsp"; - let DecoderNamespace = "MicroMips"; -} - -class MMDSPInstAlias<string Asm, dag Result, bit Emit = 0b1> - : InstAlias<Asm, Result, Emit>, PredicateControl { - let ASEPredicate = [HasDSP]; - let AdditionalPredicates = [InMicroMips]; -} - -class POOL32A_3R_FMT<string opstr, bits<11> op> : MMDSPInst<opstr> { - bits<5> rd; - bits<5> rs; - bits<5> rt; - - let Inst{31-26} = 0b000000; - let Inst{25-21} = rt; - let Inst{20-16} = rs; - let Inst{15-11} = rd; - let Inst{10-0} = op; -} - -class POOL32A_2R_FMT<string opstr, bits<10> op> : MMDSPInst<opstr> { - bits<5> rt; - bits<5> rs; - - let Inst{31-26} = 0b000000; - let Inst{25-21} = rt; - let Inst{20-16} = rs; - let Inst{15-6} = op; - let Inst{5-0} = 0b111100; -} - -class POOL32A_2RAC_FMT<string opstr, bits<8> op> : MMDSPInst<opstr> { - bits<5> rt; - bits<5> rs; - bits<2> ac; - - let Inst{31-26} = 0b000000; - let Inst{25-21} = rt; - let Inst{20-16} = rs; - let Inst{15-14} = ac; - let Inst{13-6} = op; - let Inst{5-0} = 0b111100; -} - -class POOL32A_3RB0_FMT<string opstr, bits<10> op> : MMDSPInst<opstr> { - bits<5> rd; - bits<5> rs; - bits<5> rt; - - let Inst{31-26} = 0b000000; - let Inst{25-21} = rt; - let Inst{20-16} = rs; - let Inst{15-11} = rd; - let Inst{10} = 0b0; - let Inst{9-0} = op; -} - -class POOL32A_2RSA4_FMT<string opstr, bits<12> op> : MMDSPInst<opstr> { - bits<5> rt; - bits<5> rs; - bits<4> sa; - - let Inst{31-26} = 0b000000; - let Inst{25-21} = rt; - let Inst{20-16} = rs; - let Inst{15-12} = sa; - let Inst{11-0} = op; -} - -class POOL32A_2RSA3_FMT<string opstr, bits<7> op> : MMDSPInst<opstr> { - bits<5> rt; - bits<5> rs; - bits<3> sa; - - let Inst{31-26} = 0b000000; - let Inst{25-21} = rt; - let Inst{20-16} = rs; - let Inst{15-13} = sa; - let Inst{12-6} = op; - let Inst{5-0} = 0b111100; -} - -class POOL32A_2RSA5B0_FMT<string opstr, bits<10> op> : MMDSPInst<opstr> { - bits<5> rt; - bits<5> rs; - bits<5> sa; - - let Inst{31-26} = 0b000000; - let Inst{25-21} = rt; - let Inst{20-16} = rs; - let Inst{15-11} = sa; - let Inst{10} = 0b0; - let Inst{9-0} = op; -} - -class POOL32A_2RSA4B0_FMT<string opstr, bits<11> op> : MMDSPInst<opstr> { - bits<5> rt; - bits<5> rs; - bits<4> sa; - - let Inst{31-26} = 0b000000; - let Inst{25-21} = rt; - let Inst{20-16} = rs; - let Inst{15-12} = sa; - let Inst{11} = 0b0; - let Inst{10-0} = op; -} - -class POOL32A_2RSA4OP6_FMT<string opstr, bits<6> op> : MMDSPInst<opstr> { - bits<5> rt; - bits<5> rs; - bits<4> sa; - - let Inst{31-26} = 0b000000; - let Inst{25-21} = rt; - let Inst{20-16} = rs; - let Inst{15-12} = sa; - let Inst{11-6} = op; - let Inst{5-0} = 0b111100; -} - -class POOL32A_1RIMM5AC_FMT<string opstr, bits<8> funct> : MMDSPInst<opstr> { - bits<5> rt; - bits<5> imm; - bits<2> ac; - - let Inst{31-26} = 0b000000; - let Inst{25-21} = rt; - let Inst{20-16} = imm; - let Inst{15-14} = ac; - let Inst{13-6} = funct; - let Inst{5-0} = 0b111100; -} - -class POOL32A_2RSA5_FMT<string opstr, bits<11> op> : MMDSPInst<opstr> { - bits<5> rt; - bits<5> rs; - bits<5> sa; - - let Inst{31-26} = 0b000000; - let Inst{25-21} = rt; - let Inst{20-16} = rs; - let Inst{15-11} = sa; - let Inst{10-0} = op; -} - -class POOL32A_1RMEMB0_FMT<string opstr, bits<10> funct> : MMDSPInst<opstr> { - bits<5> index; - bits<5> base; - bits<5> rd; - - let Inst{31-26} = 0; - let Inst{25-21} = index; - let Inst{20-16} = base; - let Inst{15-11} = rd; - let Inst{10} = 0b0; - let Inst{9-0} = funct; -} - -class POOL32A_1RAC_FMT<string instr_asm, bits<8> funct> : MMDSPInst<instr_asm> { - bits<5> rs; - bits<2> ac; - - let Inst{31-26} = 0; - let Inst{25-21} = 0; - let Inst{20-16} = rs; - let Inst{15-14} = ac; - let Inst{13-6} = funct; - let Inst{5-0} = 0b111100; -} - -class POOL32A_1RMASK7_FMT<string opstr, bits<8> op> : MMDSPInst<opstr> { - bits<5> rt; - bits<7> mask; - - let Inst{31-26} = 0b000000; - let Inst{25-21} = rt; - let Inst{20-14} = mask; - let Inst{13-6} = op; - let Inst{5-0} = 0b111100; -} - -class POOL32A_1RIMM10_FMT<string opstr, bits<10> op> : MMDSPInst<opstr> { - bits<5> rd; - bits<10> imm; - - let Inst{31-26} = 0; - let Inst{25-16} = imm; - let Inst{15-11} = rd; - let Inst{10} = 0; - let Inst{9-0} = op; -} - -class POOL32A_1RIMM8_FMT<string opstr, bits<6> op> : MMDSPInst<opstr> { - bits<5> rt; - bits<8> imm; - - let Inst{31-26} = 0; - let Inst{25-21} = rt; - let Inst{20-13} = imm; - let Inst{12} = 0; - let Inst{11-6} = op; - let Inst{5-0} = 0b111100; -} - -class POOL32A_4B0SHIFT6AC4B0_FMT<string opstr, bits<10> op> : MMDSPInst<opstr> { - bits<6> shift; - bits<2> ac; - - let Inst{31-26} = 0b000000; - let Inst{25-22} = 0b0000; - let Inst{21-16} = shift; - let Inst{15-14} = ac; - let Inst{13-10} = 0b0000; - let Inst{9-0} = op; -} - -class POOL32A_5B01RAC_FMT<string opstr, bits<8> op> : MMDSPInst<opstr> { - bits<5> rs; - bits<2> ac; - - let Inst{31-26} = 0b000000; - let Inst{25-21} = 0b00000; - let Inst{20-16} = rs; - let Inst{15-14} = ac; - let Inst{13-6} = op; - let Inst{5-0} = 0b111100; -} - -class POOL32I_IMMB0_FMT<string opstr, bits<5> op> : MMDSPInst<opstr> { - bits<16> offset; - - let Inst{31-26} = 0b010000; - let Inst{25-21} = op; - let Inst{20-16} = 0; - let Inst{15-0} = offset; -} - -class POOL32A_2RBP_FMT<string opstr> : MMDSPInst<opstr> { - bits<5> rt; - bits<5> rs; - bits<2> bp; - - let Inst{31-26} = 0; - let Inst{25-21} = rt; - let Inst{20-16} = rs; - let Inst{15-14} = bp; - let Inst{13-6} = 0b00100010; - let Inst{5-0} = 0b111100; -} - -class POOL32A_2RB0_FMT<string opstr, bits<10> op> : MMDSPInst<opstr> { - bits<5> rt; - bits<5> rs; - - let Inst{31-26} = 0; - let Inst{25-21} = rt; - let Inst{20-16} = rs; - let Inst{15-10} = 0; - let Inst{9-0} = op; -} - -class POOL32S_3RB0_FMT<string opstr, bits<10> op> : MMDSPInst<opstr> { - bits<5> rt; - bits<5> rs; - bits<5> rd; - - let Inst{31-26} = 0b010110; - let Inst{25-21} = rt; - let Inst{20-16} = rs; - let Inst{15-11} = rd; - let Inst{10} = 0b0; - let Inst{9-0} = op; -} - -class POOL32A_2R2B0_FMT<string opstr, bits<10> op> : MMDSPInst<opstr> { - bits<5> rt; - bits<5> rs; - - let Inst{31-26} = 0; - let Inst{25-21} = rt; - let Inst{20-16} = rs; - let Inst{15-11} = 0; - let Inst{10} = 0; - let Inst{9-0} = op; -} diff --git a/contrib/llvm/lib/Target/Mips/MicroMipsDSPInstrInfo.td b/contrib/llvm/lib/Target/Mips/MicroMipsDSPInstrInfo.td deleted file mode 100644 index 5a12568893af..000000000000 --- a/contrib/llvm/lib/Target/Mips/MicroMipsDSPInstrInfo.td +++ /dev/null @@ -1,608 +0,0 @@ -//===- MicroMipsDSPInstrInfo.td - Micromips DSP instructions -*- tablegen *-=// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file describes MicroMips DSP instructions. -// -//===----------------------------------------------------------------------===// - -// Instruction encoding. -class ADDQ_PH_MM_ENC : POOL32A_3R_FMT<"addq.ph", 0b00000001101>; -class ADDQ_S_PH_MM_ENC : POOL32A_3R_FMT<"addq_s.ph", 0b10000001101>; -class ADDQ_S_W_MM_ENC : POOL32A_3RB0_FMT<"addq_s.w", 0b1100000101>; -class ADDQH_PH_MMR2_ENC : POOL32A_3R_FMT<"addqh.ph", 0b00001001101>; -class ADDQH_R_PH_MMR2_ENC : POOL32A_3R_FMT<"addqh_r.ph", 0b10001001101>; -class ADDQH_W_MMR2_ENC: POOL32A_3R_FMT<"addqh.w", 0b00010001101>; -class ADDQH_R_W_MMR2_ENC : POOL32A_3R_FMT<"addqh_r.w", 0b10010001101>; -class ADDU_PH_MMR2_ENC : POOL32A_3R_FMT<"addu.ph", 0b00100001101>; -class ADDU_S_PH_MMR2_ENC : POOL32A_3R_FMT<"addu_s.ph", 0b10100001101>; -class ADDU_QB_MM_ENC : POOL32A_3R_FMT<"addu.qb", 0b00011001101>; -class ADDU_S_QB_MM_ENC : POOL32A_3R_FMT<"addu_s.qb", 0b10011001101>; -class ADDUH_QB_MMR2_ENC : POOL32A_3R_FMT<"adduh.qb", 0b00101001101>; -class ADDUH_R_QB_MMR2_ENC : POOL32A_3R_FMT<"adduh_r.qb", 0b10101001101>; -class ADDSC_MM_ENC : POOL32A_3RB0_FMT<"addsc", 0b1110000101>; -class ADDWC_MM_ENC : POOL32A_3RB0_FMT<"addwc", 0b1111000101>; -class DPA_W_PH_MMR2_ENC : POOL32A_2RAC_FMT<"dpa.w.ph", 0b00000010>; -class DPAQ_S_W_PH_MM_ENC : POOL32A_2RAC_FMT<"dpaq_s.w.ph", 0b00001010>; -class DPAQ_SA_L_W_MM_ENC : POOL32A_2RAC_FMT<"dpaq_sa.l.w", 0b01001010>; -class DPAQX_S_W_PH_MMR2_ENC : POOL32A_2RAC_FMT<"dpaqx_s.w.ph", 0b10001010>; -class DPAQX_SA_W_PH_MMR2_ENC : POOL32A_2RAC_FMT<"dpaqx_sa.w.ph", 0b11001010>; -class DPAU_H_QBL_MM_ENC : POOL32A_2RAC_FMT<"dpau.h.qbl", 0b10000010>; -class DPAU_H_QBR_MM_ENC : POOL32A_2RAC_FMT<"dpau.h.qbr", 0b11000010>; -class DPAX_W_PH_MMR2_ENC : POOL32A_2RAC_FMT<"dpax.w.ph", 0b01000010>; -class ABSQ_S_PH_MM_ENC : POOL32A_2R_FMT<"absq_s.ph", 0b0001000100>; -class ABSQ_S_W_MM_ENC : POOL32A_2R_FMT<"absq_s.w", 0b0010000100>; -class ABSQ_S_QB_MMR2_ENC : POOL32A_2R_FMT<"absq_s.qb", 0b0000000100>; -class INSV_MM_ENC : POOL32A_2R_FMT<"insv", 0b0100000100>; -class MADD_DSP_MM_ENC : POOL32A_2RAC_FMT<"madd", 0b00101010>; -class MADDU_DSP_MM_ENC : POOL32A_2RAC_FMT<"maddu", 0b01101010>; -class MSUB_DSP_MM_ENC : POOL32A_2RAC_FMT<"msub", 0b10101010>; -class MSUBU_DSP_MM_ENC : POOL32A_2RAC_FMT<"msubu", 0b11101010>; -class MULT_DSP_MM_ENC : POOL32A_2RAC_FMT<"mult", 0b00110010>; -class MULTU_DSP_MM_ENC : POOL32A_2RAC_FMT<"multu", 0b01110010>; -class SHLL_PH_MM_ENC : POOL32A_2RSA4_FMT<"shll.ph", 0b001110110101>; -class SHLL_S_PH_MM_ENC : POOL32A_2RSA4_FMT<"shll_s.ph", 0b101110110101>; -class SHLL_QB_MM_ENC : POOL32A_2RSA3_FMT<"shll.qb", 0b0100001>; -class SHLLV_PH_MM_ENC : POOL32A_3R_FMT<"shllv.ph", 0b00000001110>; -class SHLLV_S_PH_MM_ENC : POOL32A_3R_FMT<"shllv_s.ph", 0b10000001110>; -class SHLLV_QB_MM_ENC : POOL32A_3RB0_FMT<"shllv.qb", 0b1110010101>; -class SHLLV_S_W_MM_ENC : POOL32A_3RB0_FMT<"shllv_s.w", 0b1111010101>; -class SHLL_S_W_MM_ENC : POOL32A_2RSA5B0_FMT<"shll_s.w", 0b1111110101>; -class SHRA_QB_MMR2_ENC : POOL32A_2RSA3_FMT<"shra.qb", 0b0000111>; -class SHRA_R_QB_MMR2_ENC : POOL32A_2RSA3_FMT<"shra_r.qb", 0b1000111>; -class SHRA_PH_MM_ENC : POOL32A_2RSA4B0_FMT<"shra.ph", 0b01100110101>; -class SHRA_R_PH_MM_ENC : POOL32A_2RSA4B0_FMT<"shra_r.ph", 0b11100110101>; -class SHRAV_PH_MM_ENC : POOL32A_3R_FMT<"shrav.ph", 0b00110001101>; -class SHRAV_R_PH_MM_ENC : POOL32A_3R_FMT<"shrav_r.ph", 0b10110001101>; -class SHRAV_QB_MMR2_ENC : POOL32A_3R_FMT<"shrav.qb", 0b00111001101>; -class SHRAV_R_QB_MMR2_ENC : POOL32A_3R_FMT<"shrav_r.qb", 0b10111001101>; -class SHRAV_R_W_MM_ENC : POOL32A_3RB0_FMT<"shrav_r.w", 0b1011010101>; -class SHRA_R_W_MM_ENC : POOL32A_2RSA5B0_FMT<"shra_r.w", 0b1011110101>; -class SHRL_PH_MMR2_ENC : POOL32A_2RSA4OP6_FMT<"shrl.ph", 0b001111>; -class SHRL_QB_MM_ENC : POOL32A_2RSA3_FMT<"shrl.qb", 0b1100001>; -class SHRLV_PH_MMR2_ENC : POOL32A_3RB0_FMT<"shrlv.ph", 0b1100010101>; -class SHRLV_QB_MM_ENC : POOL32A_3RB0_FMT<"shrlv.qb", 0b1101010101>; -class PRECEQ_W_PHL_MM_ENC : POOL32A_2R_FMT<"preceq.w.phl", 0b0101000100>; -class PRECEQ_W_PHR_MM_ENC : POOL32A_2R_FMT<"preceq.w.phr", 0b0110000100>; -class PRECEQU_PH_QBL_MM_ENC : POOL32A_2R_FMT<"precequ.ph.qbl", 0b0111000100>; -class PRECEQU_PH_QBLA_MM_ENC : POOL32A_2R_FMT<"precequ.ph.qbla", 0b0111001100>; -class PRECEQU_PH_QBR_MM_ENC : POOL32A_2R_FMT<"precequ.ph.qbr", 0b1001000100>; -class PRECEQU_PH_QBRA_MM_ENC : POOL32A_2R_FMT<"precequ.ph.qbra", 0b1001001100>; -class PRECEU_PH_QBL_MM_ENC : POOL32A_2R_FMT<"preceu.ph.qbl", 0b1011000100>; -class PRECEU_PH_QBLA_MM_ENC : POOL32A_2R_FMT<"preceu.ph.qbla", 0b1011001100>; -class PRECEU_PH_QBR_MM_ENC : POOL32A_2R_FMT<"preceu.ph.qbr", 0b1101000100>; -class PRECEU_PH_QBRA_MM_ENC : POOL32A_2R_FMT<"preceu.ph.qbra", 0b1101001100>; -class SUBQ_PH_MM_ENC : POOL32A_3R_FMT<"subq.ph", 0b01000001101>; -class SUBQ_S_PH_MM_ENC : POOL32A_3R_FMT<"subq_s.ph", 0b11000001101>; -class SUBQ_S_W_MM_ENC : POOL32A_3RB0_FMT<"subq_s.w", 0b1101000101>; -class SUBQH_PH_MMR2_ENC : POOL32A_3R_FMT<"subqh.ph", 0b01001001101>; -class SUBQH_R_PH_MMR2_ENC : POOL32A_3R_FMT<"subqh_r.ph", 0b11001001101>; -class SUBQH_W_MMR2_ENC : POOL32A_3R_FMT<"subqh.w", 0b01010001101>; -class SUBQH_R_W_MMR2_ENC : POOL32A_3R_FMT<"subqh_r.w", 0b11010001101>; -class SUBU_PH_MMR2_ENC : POOL32A_3R_FMT<"subu.ph", 0b01100001101>; -class SUBU_S_PH_MMR2_ENC : POOL32A_3R_FMT<"subu_s.ph", 0b11100001101>; -class SUBU_QB_MM_ENC : POOL32A_3R_FMT<"subu.qb", 0b01011001101>; -class SUBU_S_QB_MM_ENC : POOL32A_3R_FMT<"subu_s.qb", 0b11011001101>; -class SUBUH_QB_MMR2_ENC : POOL32A_3R_FMT<"subuh.qb", 0b01101001101>; -class SUBUH_R_QB_MMR2_ENC : POOL32A_3R_FMT<"subuh_r.qb", 0b11101001101>; -class EXTP_MM_ENC : POOL32A_1RIMM5AC_FMT<"extp", 0b10011001>; -class EXTPDP_MM_ENC : POOL32A_1RIMM5AC_FMT<"extpdp", 0b11011001>; -class EXTPDPV_MM_ENC : POOL32A_2RAC_FMT<"extpdpv", 0b11100010>; -class EXTPV_MM_ENC : POOL32A_2RAC_FMT<"extpv", 0b10100010>; -class EXTR_W_MM_ENC : POOL32A_1RIMM5AC_FMT<"extr.w", 0b00111001>; -class EXTR_R_W_MM_ENC : POOL32A_1RIMM5AC_FMT<"extr_r.w", 0b01111001>; -class EXTR_RS_W_MM_ENC : POOL32A_1RIMM5AC_FMT<"extr_rs.w", 0b10111001>; -class EXTR_S_H_MM_ENC : POOL32A_1RIMM5AC_FMT<"extr_s.h", 0b11111001>; -class EXTRV_W_MM_ENC : POOL32A_2RAC_FMT<"extrv.w", 0b00111010>; -class EXTRV_R_W_MM_ENC : POOL32A_2RAC_FMT<"extrv_r.w", 0b01111010>; -class EXTRV_RS_W_MM_ENC : POOL32A_2RAC_FMT<"extrv_rs.w", 0b10111010>; -class EXTRV_S_H_MM_ENC : POOL32A_2RAC_FMT<"extrv_s.h", 0b11111010>; -class DPS_W_PH_MMR2_ENC : POOL32A_2RAC_FMT<"dps.w.ph", 0b00010010>; -class DPSQ_S_W_PH_MM_ENC : POOL32A_2RAC_FMT<"dpsq_s.w.ph", 0b00011010>; -class DPSQ_SA_L_W_MM_ENC : POOL32A_2RAC_FMT<"dpsq_sa.l.w", 0b01011010>; -class DPSQX_S_W_PH_MMR2_ENC : POOL32A_2RAC_FMT<"dpsqx_s.w.ph", 0b10011010>; -class DPSQX_SA_W_PH_MMR2_ENC : POOL32A_2RAC_FMT<"dpsqx_sa.w.ph", 0b11011010>; -class DPSU_H_QBL_MM_ENC : POOL32A_2RAC_FMT<"dpsu.h.qbl", 0b10010010>; -class DPSU_H_QBR_MM_ENC : POOL32A_2RAC_FMT<"dpsu.h.qbr", 0b11010010>; -class DPSX_W_PH_MMR2_ENC : POOL32A_2RAC_FMT<"dpsx.w.ph", 0b01010010>; -class MUL_PH_MMR2_ENC : POOL32A_3R_FMT<"mul.ph", 0b00000101101>; -class MUL_S_PH_MMR2_ENC : POOL32A_3R_FMT<"mul_s.ph", 0b10000101101>; -class MULEQ_S_W_PHL_MM_ENC : POOL32A_3RB0_FMT<"muleq_s.w.phl", 0b0000100101>; -class MULEQ_S_W_PHR_MM_ENC : POOL32A_3RB0_FMT<"muleq_s.w.phr", 0b0001100101>; -class MULEU_S_PH_QBL_MM_ENC : POOL32A_3RB0_FMT<"muleu_s.ph.qbl", 0b0010010101>; -class MULEU_S_PH_QBR_MM_ENC : POOL32A_3RB0_FMT<"muleu_s.ph.qbr", 0b0011010101>; -class MULQ_RS_PH_MM_ENC : POOL32A_3RB0_FMT<"mulq_rs.ph", 0b0100010101>; -class MULQ_RS_W_MMR2_ENC : POOL32A_3RB0_FMT<"mulq_rs.w", 0b0110010101>; -class MULQ_S_PH_MMR2_ENC : POOL32A_3RB0_FMT<"mulq_s.ph", 0b0101010101>; -class MULQ_S_W_MMR2_ENC : POOL32A_3RB0_FMT<"mulq_s.w", 0b0111010101>; -class PRECR_QB_PH_MMR2_ENC : POOL32A_3RB0_FMT<"precr.qb.ph", 0b0001101101>; -class PRECR_SRA_PH_W_MMR2_ENC - : POOL32A_2RSA5_FMT<"precr_sra.ph.w", 0b01111001101>; -class PRECR_SRA_R_PH_W_MMR2_ENC - : POOL32A_2RSA5_FMT<"precr_sra_r.ph.w", 0b11111001101>; -class PRECRQ_PH_W_MM_ENC : POOL32A_3RB0_FMT<"precrq.ph.w", 0b0011101101>; -class PRECRQ_QB_PH_MM_ENC : POOL32A_3RB0_FMT<"precrq.qb.ph", 0b0010101101>; -class PRECRQU_S_QB_PH_MM_ENC - : POOL32A_3RB0_FMT<"precrqu_s.qb.ph", 0b0101101101>; -class PRECRQ_RS_PH_W_MM_ENC : POOL32A_3RB0_FMT<"precrq_rs.ph.w", 0b0100101101>; -class LBUX_MM_ENC : POOL32A_1RMEMB0_FMT<"lbux", 0b1000100101>; -class LHX_MM_ENC : POOL32A_1RMEMB0_FMT<"lhx", 0b0101100101>; -class LWX_MM_ENC : POOL32A_1RMEMB0_FMT<"lwx", 0b0110100101>; -class MAQ_S_W_PHL_MM_ENC : POOL32A_2RAC_FMT<"maq_s.w.phl", 0b01101001>; -class MAQ_SA_W_PHL_MM_ENC : POOL32A_2RAC_FMT<"maq_sa.w.phl", 0b11101001>; -class MAQ_S_W_PHR_MM_ENC : POOL32A_2RAC_FMT<"maq_s.w.phr", 0b00101001>; -class MAQ_SA_W_PHR_MM_ENC : POOL32A_2RAC_FMT<"maq_sa.w.phr", 0b10101001>; -class MFHI_MM_ENC : POOL32A_1RAC_FMT<"mfhi", 0b00000001>; -class MFLO_MM_ENC : POOL32A_1RAC_FMT<"mflo", 0b01000001>; -class MTHI_MM_ENC : POOL32A_1RAC_FMT<"mthi", 0b10000001>; -class MTLO_MM_ENC : POOL32A_1RAC_FMT<"mthi", 0b11000001>; -class PREPEND_MMR2_ENC : POOL32A_2RSA5B0_FMT<"prepend", 0b1001010101>; -class RADDU_W_QB_MM_ENC : POOL32A_2R_FMT<"raddu.w.qb", 0b1111000100>; -class RDDSP_MM_ENC : POOL32A_1RMASK7_FMT<"rddsp", 0b00011001>; -class REPL_PH_MM_ENC : POOL32A_1RIMM10_FMT<"repl.ph", 0b0000111101>; -class REPL_QB_MM_ENC : POOL32A_1RIMM8_FMT<"repl.qb", 0b010111>; -class REPLV_PH_MM_ENC : POOL32A_2R_FMT<"replv.ph", 0b0000001100>; -class REPLV_QB_MM_ENC : POOL32A_2R_FMT<"replv.qb", 0b0001001100>; -class MTHLIP_MM_ENC : POOL32A_1RAC_FMT<"mthlip", 0b00001001>; -class PACKRL_PH_MM_ENC : POOL32A_3RB0_FMT<"packrl.ph", 0b0110101101>; -class PICK_PH_MM_ENC : POOL32A_3RB0_FMT<"pick.ph", 0b1000101101>; -class PICK_QB_MM_ENC : POOL32A_3RB0_FMT<"pick.qb", 0b0111101101>; -class SHILO_MM_ENC : POOL32A_4B0SHIFT6AC4B0_FMT<"shilo", 0b0000011101>; -class SHILOV_MM_ENC : POOL32A_5B01RAC_FMT<"shilov", 0b01001001>; -class WRDSP_MM_ENC : POOL32A_1RMASK7_FMT<"wrdsp", 0b01011001>; -class APPEND_MMR2_ENC : POOL32A_2RSA5B0_FMT<"append", 0b1000010101>; -class MODSUB_MM_ENC : POOL32A_3RB0_FMT<"modsub", 0b1010010101>; -class MULSA_W_PH_MMR2_ENC : POOL32A_2RAC_FMT<"mulsa.w.ph", 0b10110010>; -class MULSAQ_S_W_PH_MM_ENC : POOL32A_2RAC_FMT<"mulsaq_s.w.ph", 0b11110010>; -class BPOSGE32C_MMR3_ENC : POOL32I_IMMB0_FMT<"bposge32c", 0b11001>; -class BITREV_MM_ENC : POOL32A_2R_FMT<"bitrev", 0b0011000100>; -class BALIGN_MMR2_ENC : POOL32A_2RBP_FMT<"balign">; -class BPOSGE32_MM_ENC : POOL32I_IMMB0_FMT<"bposge32", 0b11011>; -class CMP_EQ_PH_MM_ENC : POOL32A_2RB0_FMT<"cmp.eq.ph", 0b0000000101>; -class CMP_LE_PH_MM_ENC : POOL32A_2RB0_FMT<"cmp.le.ph", 0b0010000101>; -class CMP_LT_PH_MM_ENC : POOL32A_2RB0_FMT<"cmp.lt.ph", 0b0001000101>; -class CMPGDU_EQ_QB_MMR2_ENC : POOL32A_3RB0_FMT<"cmpgdu.eq.qb", 0b0110000101>; -class CMPGDU_LT_QB_MMR2_ENC : POOL32A_3RB0_FMT<"cmpgdu.lt.qb", 0b0111000101>; -class CMPGDU_LE_QB_MMR2_ENC : POOL32A_3RB0_FMT<"cmpgdu.le.qb", 0b1000000101>; -class CMPGU_EQ_QB_MM_ENC : POOL32S_3RB0_FMT<"cmpgu.eq.qb", 0b0011000101>; -class CMPGU_LT_QB_MM_ENC : POOL32S_3RB0_FMT<"cmpgu.lt.qb", 0b0100000101>; -class CMPGU_LE_QB_MM_ENC : POOL32S_3RB0_FMT<"cmpgu.le.qb", 0b0101000101>; -class CMPU_EQ_QB_MM_ENC : POOL32A_2R2B0_FMT<"cmpu.eq.qb", 0b1001000101>; -class CMPU_LT_QB_MM_ENC : POOL32A_2R2B0_FMT<"cmpu.lt.qb", 0b1010000101>; -class CMPU_LE_QB_MM_ENC : POOL32A_2R2B0_FMT<"cmpu.le.qb", 0b1011000101>; - -// Instruction desc. -class ABSQ_S_PH_MM_R2_DESC_BASE<string opstr, SDPatternOperator OpNode, - InstrItinClass itin, RegisterOperand ROD, - RegisterOperand ROS = ROD> { - dag OutOperandList = (outs ROD:$rt); - dag InOperandList = (ins ROS:$rs); - string AsmString = !strconcat(opstr, "\t$rt, $rs"); - list<dag> Pattern = [(set ROD:$rt, (OpNode ROS:$rs))]; - InstrItinClass Itinerary = itin; -} -class ABSQ_S_PH_MM_DESC : ABSQ_S_PH_MM_R2_DESC_BASE< - "absq_s.ph", int_mips_absq_s_ph, NoItinerary, DSPROpnd>, Defs<[DSPOutFlag20]>; -class ABSQ_S_W_MM_DESC : ABSQ_S_PH_MM_R2_DESC_BASE< - "absq_s.w", int_mips_absq_s_w, NoItinerary, GPR32Opnd>, Defs<[DSPOutFlag20]>; -class ABSQ_S_QB_MMR2_DESC : ABSQ_S_PH_MM_R2_DESC_BASE< - "absq_s.qb", int_mips_absq_s_qb, NoItinerary, DSPROpnd>, Defs<[DSPOutFlag20]>; -class PRECEQ_W_PHL_MM_DESC : ABSQ_S_PH_MM_R2_DESC_BASE< - "preceq.w.phl", int_mips_preceq_w_phl, NoItinerary, GPR32Opnd, DSPROpnd>; -class PRECEQ_W_PHR_MM_DESC : ABSQ_S_PH_MM_R2_DESC_BASE< - "preceq.w.phr", int_mips_preceq_w_phr, NoItinerary, GPR32Opnd, DSPROpnd>; -class PRECEQU_PH_QBL_MM_DESC : ABSQ_S_PH_MM_R2_DESC_BASE< - "precequ.ph.qbl", int_mips_precequ_ph_qbl, NoItinerary, DSPROpnd>; -class PRECEQU_PH_QBLA_MM_DESC : ABSQ_S_PH_MM_R2_DESC_BASE< - "precequ.ph.qbla", int_mips_precequ_ph_qbla, NoItinerary, DSPROpnd>; -class PRECEQU_PH_QBR_MM_DESC : ABSQ_S_PH_MM_R2_DESC_BASE< - "precequ.ph.qbr", int_mips_precequ_ph_qbr, NoItinerary, DSPROpnd>; -class PRECEQU_PH_QBRA_MM_DESC : ABSQ_S_PH_MM_R2_DESC_BASE< - "precequ.ph.qbra", int_mips_precequ_ph_qbra, NoItinerary, DSPROpnd>; -class PRECEU_PH_QBL_MM_DESC : ABSQ_S_PH_MM_R2_DESC_BASE< - "preceu.ph.qbl", int_mips_preceu_ph_qbl, NoItinerary, DSPROpnd>; -class PRECEU_PH_QBLA_MM_DESC : ABSQ_S_PH_MM_R2_DESC_BASE< - "preceu.ph.qbla", int_mips_preceu_ph_qbla, NoItinerary, DSPROpnd>; -class PRECEU_PH_QBR_MM_DESC : ABSQ_S_PH_MM_R2_DESC_BASE< - "preceu.ph.qbr", int_mips_preceu_ph_qbr, NoItinerary, DSPROpnd>; -class PRECEU_PH_QBRA_MM_DESC : ABSQ_S_PH_MM_R2_DESC_BASE< - "preceu.ph.qbra", int_mips_preceu_ph_qbra, NoItinerary, DSPROpnd>; - -class SHLL_R2_MM_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - SDPatternOperator ImmPat, InstrItinClass itin, - RegisterOperand RO, Operand ImmOpnd> { - dag OutOperandList = (outs RO:$rt); - dag InOperandList = (ins RO:$rs, ImmOpnd:$sa); - string AsmString = !strconcat(instr_asm, "\t$rt, $rs, $sa"); - list<dag> Pattern = [(set RO:$rt, (OpNode RO:$rs, ImmPat:$sa))]; - InstrItinClass Itinerary = itin; - bit hasSideEffects = 1; -} -class SHLL_PH_MM_DESC : SHLL_R2_MM_DESC_BASE< - "shll.ph", null_frag, immZExt4, NoItinerary, DSPROpnd, uimm4>, - Defs<[DSPOutFlag22]>; -class SHLL_S_PH_MM_DESC : SHLL_R2_MM_DESC_BASE< - "shll_s.ph", int_mips_shll_s_ph, immZExt4, NoItinerary, DSPROpnd, uimm4>, - Defs<[DSPOutFlag22]>; -class SHLL_QB_MM_DESC : SHLL_R2_MM_DESC_BASE< - "shll.qb", null_frag, immZExt3, NoItinerary, DSPROpnd, uimm3>, - Defs<[DSPOutFlag22]>; -class SHLL_S_W_MM_DESC : SHLL_R2_MM_DESC_BASE< - "shll_s.w", int_mips_shll_s_w, immZExt5, NoItinerary, GPR32Opnd, uimm5>, - Defs<[DSPOutFlag22]>; -class SHRA_QB_MMR2_DESC : SHLL_R2_MM_DESC_BASE< - "shra.qb", null_frag, immZExt3, NoItinerary, DSPROpnd, uimm3>; -class SHRA_R_QB_MMR2_DESC : SHLL_R2_MM_DESC_BASE< - "shra_r.qb", int_mips_shra_r_qb, immZExt3, NoItinerary, DSPROpnd, uimm3>; -class SHRA_PH_MM_DESC : SHLL_R2_MM_DESC_BASE< - "shra.ph", null_frag, immZExt4, NoItinerary, DSPROpnd, uimm4>; -class SHRA_R_PH_MM_DESC : SHLL_R2_MM_DESC_BASE< - "shra_r.ph", int_mips_shra_r_ph, immZExt4, NoItinerary, DSPROpnd, uimm4>; -class SHRA_R_W_MM_DESC : SHLL_R2_MM_DESC_BASE< - "shra_r.w", int_mips_shra_r_w, immZExt5, NoItinerary, GPR32Opnd, uimm5>; -class SHRL_QB_MM_DESC : SHLL_R2_MM_DESC_BASE< - "shrl.qb", null_frag, immZExt3, NoItinerary, DSPROpnd, uimm3>; -class SHRL_PH_MMR2_DESC : SHLL_R2_MM_DESC_BASE< - "shrl.ph", null_frag, immZExt4, NoItinerary, DSPROpnd, uimm4>; - -class SHLLV_R3_MM_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - InstrItinClass itin, RegisterOperand RO> { - dag OutOperandList = (outs RO:$rd); - dag InOperandList = (ins RO:$rt, GPR32Opnd:$rs); - string AsmString = !strconcat(instr_asm, "\t$rd, $rt, $rs"); - list<dag> Pattern = [(set RO:$rd, (OpNode RO:$rt, GPR32Opnd:$rs))]; - InstrItinClass Itinerary = itin; -} -class SHLLV_PH_MM_DESC : SHLLV_R3_MM_DESC_BASE< - "shllv.ph", int_mips_shll_ph, NoItinerary, DSPROpnd>, Defs<[DSPOutFlag22]>; -class SHLLV_S_PH_MM_DESC : SHLLV_R3_MM_DESC_BASE< - "shllv_s.ph", int_mips_shll_s_ph, NoItinerary, DSPROpnd>, - Defs<[DSPOutFlag22]>; -class SHLLV_QB_MM_DESC : SHLLV_R3_MM_DESC_BASE< - "shllv.qb", int_mips_shll_qb, NoItinerary, DSPROpnd>, Defs<[DSPOutFlag22]>; -class SHLLV_S_W_MM_DESC : SHLLV_R3_MM_DESC_BASE< - "shllv_s.w", int_mips_shll_s_w, NoItinerary, GPR32Opnd>, Defs<[DSPOutFlag22]>; -class SHRAV_PH_MM_DESC : SHLLV_R3_MM_DESC_BASE< - "shrav.ph", int_mips_shra_ph, NoItinerary, DSPROpnd>; -class SHRAV_R_PH_MM_DESC : SHLLV_R3_MM_DESC_BASE< - "shrav_r.ph", int_mips_shra_r_ph, NoItinerary, DSPROpnd>; -class SHRAV_QB_MMR2_DESC : SHLLV_R3_MM_DESC_BASE< - "shrav.qb", int_mips_shra_qb, NoItinerary, DSPROpnd>; -class SHRAV_R_QB_MMR2_DESC : SHLLV_R3_MM_DESC_BASE< - "shrav_r.qb", int_mips_shra_r_qb, NoItinerary, DSPROpnd>; -class SHRAV_R_W_MM_DESC : SHLLV_R3_MM_DESC_BASE< - "shrav_r.w", int_mips_shra_r_w, NoItinerary, GPR32Opnd>; -class SHRLV_PH_MMR2_DESC : SHLLV_R3_MM_DESC_BASE< - "shrlv.ph", int_mips_shrl_ph, NoItinerary, DSPROpnd>; -class SHRLV_QB_MM_DESC : SHLLV_R3_MM_DESC_BASE< - "shrlv.qb", int_mips_shrl_qb, NoItinerary, DSPROpnd>; - -class EXT_MM_2R_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - InstrItinClass itin> { - dag OutOperandList = (outs GPR32Opnd:$rt); - dag InOperandList = (ins ACC64DSPOpnd:$ac, GPR32Opnd:$rs); - string AsmString = !strconcat(instr_asm, "\t$rt, $ac, $rs"); - InstrItinClass Itinerary = itin; -} -class EXT_MM_1R_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - InstrItinClass itin> { - dag OutOperandList = (outs GPR32Opnd:$rt); - dag InOperandList = (ins ACC64DSPOpnd:$ac, uimm5:$imm); - string AsmString = !strconcat(instr_asm, "\t$rt, $ac, $imm"); - InstrItinClass Itinerary = itin; -} - -class EXTP_MM_DESC - : EXT_MM_1R_DESC_BASE<"extp", MipsEXTP, NoItinerary>, - Uses<[DSPPos]>, Defs<[DSPEFI]>; -class EXTPDP_MM_DESC - : EXT_MM_1R_DESC_BASE<"extpdp", MipsEXTPDP, NoItinerary>, - Uses<[DSPPos]>, Defs<[DSPPos, DSPEFI]>; -class EXTPDPV_MM_DESC - : EXT_MM_2R_DESC_BASE<"extpdpv", MipsEXTPDP, NoItinerary>, - Uses<[DSPPos]>, Defs<[DSPPos, DSPEFI]>; -class EXTPV_MM_DESC - : EXT_MM_2R_DESC_BASE<"extpv", MipsEXTP, NoItinerary>, - Uses<[DSPPos]>, Defs<[DSPEFI]>; -class EXTR_W_MM_DESC - : EXT_MM_1R_DESC_BASE<"extr.w", MipsEXTR_W, NoItinerary>, - Defs<[DSPOutFlag23]>; -class EXTR_R_W_MM_DESC - : EXT_MM_1R_DESC_BASE<"extr_r.w", MipsEXTR_R_W, NoItinerary>, - Defs<[DSPOutFlag23]>; -class EXTR_RS_W_MM_DESC - : EXT_MM_1R_DESC_BASE<"extr_rs.w", MipsEXTR_RS_W, NoItinerary>, - Defs<[DSPOutFlag23]>; -class EXTR_S_H_MM_DESC - : EXT_MM_1R_DESC_BASE<"extr_s.h", MipsEXTR_S_H, NoItinerary>, - Defs<[DSPOutFlag23]>; -class EXTRV_W_MM_DESC - : EXT_MM_2R_DESC_BASE<"extrv.w", MipsEXTR_W, NoItinerary>, - Defs<[DSPOutFlag23]>; -class EXTRV_R_W_MM_DESC - : EXT_MM_2R_DESC_BASE<"extrv_r.w", MipsEXTR_R_W, NoItinerary>, - Defs<[DSPOutFlag23]>; -class EXTRV_RS_W_MM_DESC - : EXT_MM_2R_DESC_BASE<"extrv_rs.w", MipsEXTR_RS_W, NoItinerary>, - Defs<[DSPOutFlag23]>; -class EXTRV_S_H_MM_DESC - : EXT_MM_2R_DESC_BASE<"extrv_s.h", MipsEXTR_S_H, NoItinerary>, - Defs<[DSPOutFlag23]>; - -class MFHI_MM_DESC_BASE<string instr_asm, RegisterOperand RO, SDNode OpNode, - InstrItinClass itin> { - dag OutOperandList = (outs GPR32Opnd:$rs); - dag InOperandList = (ins RO:$ac); - string AsmString = !strconcat(instr_asm, "\t$rs, $ac"); - list<dag> Pattern = [(set GPR32Opnd:$rs, (OpNode RO:$ac))]; - InstrItinClass Itinerary = itin; -} - -class MFHI_MM_DESC : MFHI_MM_DESC_BASE<"mfhi", ACC64DSPOpnd, MipsMFHI, - NoItinerary>; -class MFLO_MM_DESC : MFHI_MM_DESC_BASE<"mflo", ACC64DSPOpnd, MipsMFLO, - NoItinerary>; - -class RADDU_W_QB_MM_DESC { - dag OutOperandList = (outs GPR32Opnd:$rt); - dag InOperandList = (ins DSPROpnd:$rs); - string AsmString = !strconcat("raddu.w.qb", "\t$rt, $rs"); - list<dag> Pattern = [(set GPR32Opnd:$rt, (int_mips_raddu_w_qb DSPROpnd:$rs))]; - InstrItinClass Itinerary = NoItinerary; - string BaseOpcode = "raddu.w.qb"; -} - -class RDDSP_MM_DESC { - dag OutOperandList = (outs GPR32Opnd:$rt); - dag InOperandList = (ins uimm7:$mask); - string AsmString = !strconcat("rddsp", "\t$rt, $mask"); - list<dag> Pattern = [(set GPR32Opnd:$rt, (int_mips_rddsp immZExt7:$mask))]; - InstrItinClass Itinerary = NoItinerary; -} - -class REPL_QB_MM_DESC { - dag OutOperandList = (outs DSPROpnd:$rt); - dag InOperandList = (ins uimm8:$imm); - string AsmString = !strconcat("repl.qb", "\t$rt, $imm"); - list<dag> Pattern = [(set DSPROpnd:$rt, (int_mips_repl_qb immZExt8:$imm))]; - InstrItinClass Itinerary = NoItinerary; -} - -class REPLV_PH_MM_DESC : ABSQ_S_PH_MM_R2_DESC_BASE<"replv.ph", int_mips_repl_ph, - NoItinerary, DSPROpnd, - GPR32Opnd>; -class REPLV_QB_MM_DESC : ABSQ_S_PH_MM_R2_DESC_BASE<"replv.qb", int_mips_repl_qb, - NoItinerary, DSPROpnd, - GPR32Opnd>; - -class WRDSP_MM_DESC { - dag OutOperandList = (outs); - dag InOperandList = (ins GPR32Opnd:$rt, uimm7:$mask); - string AsmString = !strconcat("wrdsp", "\t$rt, $mask"); - list<dag> Pattern = [(int_mips_wrdsp GPR32Opnd:$rt, immZExt7:$mask)]; - InstrItinClass Itinerary = NoItinerary; - bit isMoveReg = 1; -} - -class BPOSGE32C_MMR3_DESC { - dag OutOperandList = (outs); - dag InOperandList = (ins brtarget1SImm16:$offset); - string AsmString = !strconcat("bposge32c", "\t$offset"); - InstrItinClass Itinerary = NoItinerary; - bit isBranch = 1; - bit isTerminator = 1; - bit hasDelaySlot = 0; -} - -class BALIGN_MMR2_DESC { - dag OutOperandList = (outs GPR32Opnd:$rt); - dag InOperandList = (ins GPR32Opnd:$rs, uimm2:$bp, GPR32Opnd:$src); - string AsmString = !strconcat("balign", "\t$rt, $rs, $bp"); - list<dag> Pattern = [(set GPR32Opnd:$rt, (int_mips_balign GPR32Opnd:$src, - GPR32Opnd:$rs, - immZExt2:$bp))]; - InstrItinClass Itinerary = NoItinerary; - string Constraints = "$src = $rt"; -} - -class BITREV_MM_DESC : ABSQ_S_PH_MM_R2_DESC_BASE<"bitrev", int_mips_bitrev, - NoItinerary, GPR32Opnd>; - -class BPOSGE32_MM_DESC : BPOSGE32_DESC_BASE<"bposge32", brtarget_mm, - NoItinerary>; - -let DecoderNamespace = "MicroMipsDSP", Arch = "mmdsp", - EncodingPredicates = [InMicroMips], ASEPredicate = [HasDSP] in { - def LWDSP_MM : Load<"lw", DSPROpnd, null_frag, II_LW>, DspMMRel, - LW_FM_MM<0x3f>; - def SWDSP_MM : Store<"sw", DSPROpnd, null_frag, II_SW>, DspMMRel, - LW_FM_MM<0x3e>; -} -// Instruction defs. -// microMIPS DSP Rev 1 -def ADDQ_PH_MM : DspMMRel, ADDQ_PH_MM_ENC, ADDQ_PH_DESC; -def ADDQ_S_PH_MM : DspMMRel, ADDQ_S_PH_MM_ENC, ADDQ_S_PH_DESC; -def ADDQ_S_W_MM : DspMMRel, ADDQ_S_W_MM_ENC, ADDQ_S_W_DESC; -def ADDU_QB_MM : DspMMRel, ADDU_QB_MM_ENC, ADDU_QB_DESC; -def ADDU_S_QB_MM : DspMMRel, ADDU_S_QB_MM_ENC, ADDU_S_QB_DESC; -def ADDSC_MM : DspMMRel, ADDSC_MM_ENC, ADDSC_DESC; -def ADDWC_MM : DspMMRel, ADDWC_MM_ENC, ADDWC_DESC; -def DPAQ_S_W_PH_MM : DspMMRel, DPAQ_S_W_PH_MM_ENC, DPAQ_S_W_PH_DESC; -def DPAQ_SA_L_W_MM : DspMMRel, DPAQ_SA_L_W_MM_ENC, DPAQ_SA_L_W_DESC; -def DPAU_H_QBL_MM : DspMMRel, DPAU_H_QBL_MM_ENC, DPAU_H_QBL_DESC; -def DPAU_H_QBR_MM : DspMMRel, DPAU_H_QBR_MM_ENC, DPAU_H_QBR_DESC; -def ABSQ_S_PH_MM : DspMMRel, ABSQ_S_PH_MM_ENC, ABSQ_S_PH_MM_DESC; -def ABSQ_S_W_MM : DspMMRel, ABSQ_S_W_MM_ENC, ABSQ_S_W_MM_DESC; -def INSV_MM : DspMMRel, INSV_MM_ENC, INSV_DESC; -def MADD_DSP_MM : DspMMRel, MADD_DSP_MM_ENC, MADD_DSP_DESC; -def MADDU_DSP_MM : DspMMRel, MADDU_DSP_MM_ENC, MADDU_DSP_DESC; -def MSUB_DSP_MM : DspMMRel, MSUB_DSP_MM_ENC, MSUB_DSP_DESC; -def MSUBU_DSP_MM : DspMMRel, MSUBU_DSP_MM_ENC, MSUBU_DSP_DESC; -def MULT_DSP_MM : DspMMRel, MULT_DSP_MM_ENC, MULT_DSP_DESC; -def MULTU_DSP_MM : DspMMRel, MULTU_DSP_MM_ENC, MULTU_DSP_DESC; -def SHLL_PH_MM : DspMMRel, SHLL_PH_MM_ENC, SHLL_PH_MM_DESC; -def SHLL_S_PH_MM : DspMMRel, SHLL_S_PH_MM_ENC, SHLL_S_PH_MM_DESC; -def SHLL_QB_MM : DspMMRel, SHLL_QB_MM_ENC, SHLL_QB_MM_DESC; -def SHLLV_PH_MM : DspMMRel, SHLLV_PH_MM_ENC, SHLLV_PH_MM_DESC; -def SHLLV_S_PH_MM : DspMMRel, SHLLV_S_PH_MM_ENC, SHLLV_S_PH_MM_DESC; -def SHLLV_QB_MM : DspMMRel, SHLLV_QB_MM_ENC, SHLLV_QB_MM_DESC; -def SHLLV_S_W_MM : DspMMRel, SHLLV_S_W_MM_ENC, SHLLV_S_W_MM_DESC; -def SHLL_S_W_MM : DspMMRel, SHLL_S_W_MM_ENC, SHLL_S_W_MM_DESC; -def SHRA_PH_MM : DspMMRel, SHRA_PH_MM_ENC, SHRA_PH_MM_DESC; -def SHRA_R_PH_MM : DspMMRel, SHRA_R_PH_MM_ENC, SHRA_R_PH_MM_DESC; -def SHRAV_PH_MM : DspMMRel, SHRAV_PH_MM_ENC, SHRAV_PH_MM_DESC; -def SHRAV_R_PH_MM : DspMMRel, SHRAV_R_PH_MM_ENC, SHRAV_R_PH_MM_DESC; -def SHRAV_R_W_MM : DspMMRel, SHRAV_R_W_MM_ENC, SHRAV_R_W_MM_DESC; -def SHRA_R_W_MM : DspMMRel, SHRA_R_W_MM_ENC, SHRA_R_W_MM_DESC; -def SHRL_QB_MM : DspMMRel, SHRL_QB_MM_ENC, SHRL_QB_MM_DESC; -def SHRLV_QB_MM : DspMMRel, SHRLV_QB_MM_ENC, SHRLV_QB_MM_DESC; -def PRECEQ_W_PHL_MM : DspMMRel, PRECEQ_W_PHL_MM_ENC, PRECEQ_W_PHL_MM_DESC; -def PRECEQ_W_PHR_MM : DspMMRel, PRECEQ_W_PHR_MM_ENC, PRECEQ_W_PHR_MM_DESC; -def PRECEQU_PH_QBL_MM : DspMMRel, PRECEQU_PH_QBL_MM_ENC, PRECEQU_PH_QBL_MM_DESC; -def PRECEQU_PH_QBLA_MM : DspMMRel, PRECEQU_PH_QBLA_MM_ENC, - PRECEQU_PH_QBLA_MM_DESC; -def PRECEQU_PH_QBR_MM : DspMMRel, PRECEQU_PH_QBR_MM_ENC, PRECEQU_PH_QBR_MM_DESC; -def PRECEQU_PH_QBRA_MM : DspMMRel, PRECEQU_PH_QBRA_MM_ENC, - PRECEQU_PH_QBRA_MM_DESC; -def PRECEU_PH_QBL_MM : DspMMRel, PRECEU_PH_QBL_MM_ENC, PRECEU_PH_QBL_MM_DESC; -def PRECEU_PH_QBLA_MM : DspMMRel, PRECEU_PH_QBLA_MM_ENC, PRECEU_PH_QBLA_MM_DESC; -def PRECEU_PH_QBR_MM : DspMMRel, PRECEU_PH_QBR_MM_ENC, PRECEU_PH_QBR_MM_DESC; -def PRECEU_PH_QBRA_MM : DspMMRel, PRECEU_PH_QBRA_MM_ENC, PRECEU_PH_QBRA_MM_DESC; -def SUBQ_PH_MM : DspMMRel, SUBQ_PH_MM_ENC, SUBQ_PH_DESC; -def SUBQ_S_PH_MM : DspMMRel, SUBQ_S_PH_MM_ENC, SUBQ_S_PH_DESC; -def SUBQ_S_W_MM : DspMMRel, SUBQ_S_W_MM_ENC, SUBQ_S_W_DESC; -def SUBU_QB_MM : DspMMRel, SUBU_QB_MM_ENC, SUBU_QB_DESC; -def SUBU_S_QB_MM : DspMMRel, SUBU_S_QB_MM_ENC, SUBU_S_QB_DESC; -def EXTP_MM : DspMMRel, EXTP_MM_ENC, EXTP_MM_DESC; -def EXTPDP_MM : DspMMRel, EXTPDP_MM_ENC, EXTPDP_MM_DESC; -def EXTPDPV_MM : DspMMRel, EXTPDPV_MM_ENC, EXTPDPV_MM_DESC; -def EXTPV_MM : DspMMRel, EXTPV_MM_ENC, EXTPV_MM_DESC; -def EXTR_W_MM : DspMMRel, EXTR_W_MM_ENC, EXTR_W_MM_DESC; -def EXTR_R_W_MM : DspMMRel, EXTR_R_W_MM_ENC, EXTR_R_W_MM_DESC; -def EXTR_RS_W_MM : DspMMRel, EXTR_RS_W_MM_ENC, EXTR_RS_W_MM_DESC; -def EXTR_S_H_MM : DspMMRel, EXTR_S_H_MM_ENC, EXTR_S_H_MM_DESC; -def EXTRV_W_MM : DspMMRel, EXTRV_W_MM_ENC, EXTRV_W_MM_DESC; -def EXTRV_R_W_MM : DspMMRel, EXTRV_R_W_MM_ENC, EXTRV_R_W_MM_DESC; -def EXTRV_RS_W_MM : DspMMRel, EXTRV_RS_W_MM_ENC, EXTRV_RS_W_MM_DESC; -def EXTRV_S_H_MM : DspMMRel, EXTRV_S_H_MM_ENC, EXTRV_S_H_MM_DESC; -def DPSQ_S_W_PH_MM : DspMMRel, DPSQ_S_W_PH_MM_ENC, DPSQ_S_W_PH_DESC; -def DPSQ_SA_L_W_MM : DspMMRel, DPSQ_SA_L_W_MM_ENC, DPSQ_SA_L_W_DESC; -def DPSU_H_QBL_MM : DspMMRel, DPSU_H_QBL_MM_ENC, DPSU_H_QBL_DESC; -def DPSU_H_QBR_MM : DspMMRel, DPSU_H_QBR_MM_ENC, DPSU_H_QBR_DESC; -def MULEQ_S_W_PHL_MM : DspMMRel, MULEQ_S_W_PHL_MM_ENC, MULEQ_S_W_PHL_DESC; -def MULEQ_S_W_PHR_MM : DspMMRel, MULEQ_S_W_PHR_MM_ENC, MULEQ_S_W_PHR_DESC; -def MULEU_S_PH_QBL_MM : DspMMRel, MULEU_S_PH_QBL_MM_ENC, MULEU_S_PH_QBL_DESC; -def MULEU_S_PH_QBR_MM : DspMMRel, MULEU_S_PH_QBR_MM_ENC, MULEU_S_PH_QBR_DESC; -def MULQ_RS_PH_MM : DspMMRel, MULQ_RS_PH_MM_ENC, MULQ_RS_PH_DESC; -def PRECRQ_PH_W_MM : DspMMRel, PRECRQ_PH_W_MM_ENC, PRECRQ_PH_W_DESC; -def PRECRQ_QB_PH_MM : DspMMRel, PRECRQ_QB_PH_MM_ENC, PRECRQ_QB_PH_DESC; -def PRECRQU_S_QB_PH_MM : DspMMRel, PRECRQU_S_QB_PH_MM_ENC, PRECRQU_S_QB_PH_DESC; -def PRECRQ_RS_PH_W_MM : DspMMRel, PRECRQ_RS_PH_W_MM_ENC, PRECRQ_RS_PH_W_DESC; -def LBUX_MM : DspMMRel, LBUX_MM_ENC, LBUX_DESC; -def LHX_MM : DspMMRel, LHX_MM_ENC, LHX_DESC; -def LWX_MM : DspMMRel, LWX_MM_ENC, LWX_DESC; -def MAQ_S_W_PHL_MM : DspMMRel, MAQ_S_W_PHL_MM_ENC, MAQ_S_W_PHL_DESC; -def MAQ_SA_W_PHL_MM : DspMMRel, MAQ_SA_W_PHL_MM_ENC, MAQ_SA_W_PHL_DESC; -def MAQ_S_W_PHR_MM : DspMMRel, MAQ_S_W_PHR_MM_ENC, MAQ_S_W_PHR_DESC; -def MAQ_SA_W_PHR_MM : DspMMRel, MAQ_SA_W_PHR_MM_ENC, MAQ_SA_W_PHR_DESC; -def MFHI_DSP_MM : DspMMRel, MFHI_MM_ENC, MFHI_MM_DESC; -def MFLO_DSP_MM : DspMMRel, MFLO_MM_ENC, MFLO_MM_DESC; -def MTHI_DSP_MM : DspMMRel, MTHI_MM_ENC, MTHI_DESC; -def MTLO_DSP_MM : DspMMRel, MTLO_MM_ENC, MTLO_DESC; -def RADDU_W_QB_MM : DspMMRel, RADDU_W_QB_MM_ENC, RADDU_W_QB_MM_DESC; -def RDDSP_MM : DspMMRel, RDDSP_MM_ENC, RDDSP_MM_DESC; -def REPL_PH_MM : DspMMRel, REPL_PH_MM_ENC, REPL_PH_DESC; -def REPL_QB_MM : DspMMRel, REPL_QB_MM_ENC, REPL_QB_MM_DESC; -def REPLV_PH_MM : DspMMRel, REPLV_PH_MM_ENC, REPLV_PH_MM_DESC; -def REPLV_QB_MM : DspMMRel, REPLV_QB_MM_ENC, REPLV_QB_MM_DESC; -def MTHLIP_MM : DspMMRel, MTHLIP_MM_ENC, MTHLIP_DESC; -def PACKRL_PH_MM : DspMMRel, PACKRL_PH_MM_ENC, PACKRL_PH_DESC; -def PICK_PH_MM : DspMMRel, PICK_PH_MM_ENC, PICK_PH_DESC; -def PICK_QB_MM : DspMMRel, PICK_QB_MM_ENC, PICK_QB_DESC; -def SHILO_MM : DspMMRel, SHILO_MM_ENC, SHILO_DESC; -def SHILOV_MM : DspMMRel, SHILOV_MM_ENC, SHILOV_DESC; -def WRDSP_MM : DspMMRel, WRDSP_MM_ENC, WRDSP_MM_DESC; -def MODSUB_MM : DspMMRel, MODSUB_MM_ENC, MODSUB_DESC; -def MULSAQ_S_W_PH_MM : DspMMRel, MULSAQ_S_W_PH_MM_ENC, MULSAQ_S_W_PH_DESC; -def BITREV_MM : DspMMRel, BITREV_MM_ENC, BITREV_MM_DESC; -def BPOSGE32_MM : DspMMRel, BPOSGE32_MM_ENC, BPOSGE32_MM_DESC, - ISA_MICROMIPS32_NOT_MIPS32R6; -def CMP_EQ_PH_MM : DspMMRel, CMP_EQ_PH_MM_ENC, CMP_EQ_PH_DESC; -def CMP_LT_PH_MM : DspMMRel, CMP_LT_PH_MM_ENC, CMP_LT_PH_DESC; -def CMP_LE_PH_MM : DspMMRel, CMP_LE_PH_MM_ENC, CMP_LE_PH_DESC; -def CMPGU_EQ_QB_MM : DspMMRel, CMPGU_EQ_QB_MM_ENC, CMPGU_EQ_QB_DESC; -def CMPGU_LT_QB_MM : DspMMRel, CMPGU_LT_QB_MM_ENC, CMPGU_LT_QB_DESC; -def CMPGU_LE_QB_MM : DspMMRel, CMPGU_LE_QB_MM_ENC, CMPGU_LE_QB_DESC; -def CMPU_EQ_QB_MM : DspMMRel, CMPU_EQ_QB_MM_ENC, CMPU_EQ_QB_DESC; -def CMPU_LT_QB_MM : DspMMRel, CMPU_LT_QB_MM_ENC, CMPU_LT_QB_DESC; -def CMPU_LE_QB_MM : DspMMRel, CMPU_LE_QB_MM_ENC, CMPU_LE_QB_DESC; -// microMIPS DSP Rev 2 -def ABSQ_S_QB_MMR2 : DspMMRel, ABSQ_S_QB_MMR2_ENC, ABSQ_S_QB_MMR2_DESC, - ISA_DSPR2; -def ADDQH_PH_MMR2 : DspMMRel, ADDQH_PH_MMR2_ENC, ADDQH_PH_DESC, ISA_DSPR2; -def ADDQH_R_PH_MMR2 : DspMMRel, ADDQH_R_PH_MMR2_ENC, ADDQH_R_PH_DESC, ISA_DSPR2; -def ADDQH_W_MMR2 : DspMMRel, ADDQH_W_MMR2_ENC, ADDQH_W_DESC, ISA_DSPR2; -def ADDQH_R_W_MMR2 : DspMMRel, ADDQH_R_W_MMR2_ENC, ADDQH_R_W_DESC, ISA_DSPR2; -def ADDU_PH_MMR2 : DspMMRel, ADDU_PH_MMR2_ENC, ADDU_PH_DESC, ISA_DSPR2; -def ADDU_S_PH_MMR2 : DspMMRel, ADDU_S_PH_MMR2_ENC, ADDU_S_PH_DESC, ISA_DSPR2; -def ADDUH_QB_MMR2 : DspMMRel, ADDUH_QB_MMR2_ENC, ADDUH_QB_DESC, ISA_DSPR2; -def ADDUH_R_QB_MMR2 : DspMMRel, ADDUH_R_QB_MMR2_ENC, ADDUH_R_QB_DESC, ISA_DSPR2; -def DPA_W_PH_MMR2 : DspMMRel, DPA_W_PH_MMR2_ENC, DPA_W_PH_DESC, ISA_DSPR2; -def DPAQX_S_W_PH_MMR2 : DspMMRel, DPAQX_S_W_PH_MMR2_ENC, DPAQX_S_W_PH_DESC, - ISA_DSPR2; -def DPAQX_SA_W_PH_MMR2 : DspMMRel, DPAQX_SA_W_PH_MMR2_ENC, DPAQX_SA_W_PH_DESC, - ISA_DSPR2; -def DPAX_W_PH_MMR2 : DspMMRel, DPAX_W_PH_MMR2_ENC, DPAX_W_PH_DESC, ISA_DSPR2; -def SHRA_QB_MMR2 : DspMMRel, SHRA_QB_MMR2_ENC, SHRA_QB_MMR2_DESC, ISA_DSPR2; -def SHRA_R_QB_MMR2 : DspMMRel, SHRA_R_QB_MMR2_ENC, SHRA_R_QB_MMR2_DESC, - ISA_DSPR2; -def SHRAV_QB_MMR2 : DspMMRel, SHRAV_QB_MMR2_ENC, SHRAV_QB_MMR2_DESC, ISA_DSPR2; -def SHRAV_R_QB_MMR2 : DspMMRel, SHRAV_R_QB_MMR2_ENC, SHRAV_R_QB_MMR2_DESC, - ISA_DSPR2; -def BALIGN_MMR2 : DspMMRel, BALIGN_MMR2_ENC, BALIGN_MMR2_DESC, ISA_DSPR2; -def CMPGDU_EQ_QB_MMR2 : DspMMRel, CMPGDU_EQ_QB_MMR2_ENC, CMPGDU_EQ_QB_DESC, - ISA_DSPR2; -def CMPGDU_LT_QB_MMR2 : DspMMRel, CMPGDU_LT_QB_MMR2_ENC, CMPGDU_LT_QB_DESC, - ISA_DSPR2; -def CMPGDU_LE_QB_MMR2 : DspMMRel, CMPGDU_LE_QB_MMR2_ENC, CMPGDU_LE_QB_DESC, - ISA_DSPR2; -def SHRL_PH_MMR2 : DspMMRel, SHRL_PH_MMR2_ENC, SHRL_PH_MMR2_DESC, ISA_DSPR2; -def SHRLV_PH_MMR2 : DspMMRel, SHRLV_PH_MMR2_ENC, SHRLV_PH_MMR2_DESC, ISA_DSPR2; -def SUBQH_PH_MMR2 : DspMMRel, SUBQH_PH_MMR2_ENC, SUBQH_PH_DESC, ISA_DSPR2; -def SUBQH_R_PH_MMR2 : DspMMRel, SUBQH_R_PH_MMR2_ENC, SUBQH_R_PH_DESC, ISA_DSPR2; -def SUBQH_W_MMR2 : DspMMRel, SUBQH_W_MMR2_ENC, SUBQH_W_DESC, ISA_DSPR2; -def SUBQH_R_W_MMR2 : DspMMRel, SUBQH_R_W_MMR2_ENC, SUBQH_R_W_DESC, ISA_DSPR2; -def SUBU_PH_MMR2 : DspMMRel, SUBU_PH_MMR2_ENC, SUBU_PH_DESC, ISA_DSPR2; -def SUBU_S_PH_MMR2 : DspMMRel, SUBU_S_PH_MMR2_ENC, SUBU_S_PH_DESC, ISA_DSPR2; -def SUBUH_QB_MMR2 : DspMMRel, SUBUH_QB_MMR2_ENC, SUBUH_QB_DESC, ISA_DSPR2; -def SUBUH_R_QB_MMR2 : DspMMRel, SUBUH_R_QB_MMR2_ENC, SUBUH_R_QB_DESC, ISA_DSPR2; -def DPS_W_PH_MMR2 : DspMMRel, DPS_W_PH_MMR2_ENC, DPS_W_PH_DESC, ISA_DSPR2; -def DPSQX_S_W_PH_MMR2 : DspMMRel, DPSQX_S_W_PH_MMR2_ENC, DPSQX_S_W_PH_DESC, - ISA_DSPR2; -def DPSQX_SA_W_PH_MMR2 : DspMMRel, DPSQX_SA_W_PH_MMR2_ENC, DPSQX_SA_W_PH_DESC, - ISA_DSPR2; -def DPSX_W_PH_MMR2 : DspMMRel, DPSX_W_PH_MMR2_ENC, DPSX_W_PH_DESC, ISA_DSPR2; -def MUL_PH_MMR2 : DspMMRel, MUL_PH_MMR2_ENC, MUL_PH_DESC, ISA_DSPR2; -def MUL_S_PH_MMR2 : DspMMRel, MUL_S_PH_MMR2_ENC, MUL_S_PH_DESC, ISA_DSPR2; -def MULQ_RS_W_MMR2 : DspMMRel, MULQ_RS_W_MMR2_ENC, MULQ_RS_W_DESC, ISA_DSPR2; -def MULQ_S_PH_MMR2 : DspMMRel, MULQ_S_PH_MMR2_ENC, MULQ_S_PH_DESC, ISA_DSPR2; -def MULQ_S_W_MMR2 : DspMMRel, MULQ_S_W_MMR2_ENC, MULQ_S_W_DESC, ISA_DSPR2; -def PRECR_QB_PH_MMR2 : DspMMRel, PRECR_QB_PH_MMR2_ENC, PRECR_QB_PH_DESC, - ISA_DSPR2; -def PRECR_SRA_PH_W_MMR2 : DspMMRel, PRECR_SRA_PH_W_MMR2_ENC, - PRECR_SRA_PH_W_DESC, ISA_DSPR2; -def PRECR_SRA_R_PH_W_MMR2 : DspMMRel, PRECR_SRA_R_PH_W_MMR2_ENC, - PRECR_SRA_R_PH_W_DESC, ISA_DSPR2; -def PREPEND_MMR2 : DspMMRel, PREPEND_MMR2_ENC, PREPEND_DESC, ISA_DSPR2; - -// Instruction alias. -def : MMDSPInstAlias<"wrdsp $rt", (WRDSP_MM GPR32Opnd:$rt, 0x1F), 1>; -def APPEND_MMR2 : DspMMRel, APPEND_MMR2_ENC, APPEND_DESC, ISA_DSPR2; -def MULSA_W_PH_MMR2 : DspMMRel, MULSA_W_PH_MMR2_ENC, MULSA_W_PH_DESC, ISA_DSPR2; -// microMIPS DSP Rev 3 -def BPOSGE32C_MMR3 : DspMMRel, BPOSGE32C_MMR3_ENC, BPOSGE32C_MMR3_DESC, - ISA_DSPR3; diff --git a/contrib/llvm/lib/Target/Mips/MicroMipsInstrFPU.td b/contrib/llvm/lib/Target/Mips/MicroMipsInstrFPU.td deleted file mode 100644 index 5d87068ff407..000000000000 --- a/contrib/llvm/lib/Target/Mips/MicroMipsInstrFPU.td +++ /dev/null @@ -1,447 +0,0 @@ -//==- MicroMipsInstrFPU.td - microMIPS FPU Instruction Info -*- tablegen -*-==// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file describes the microMIPS FPU instruction set. -// -//===----------------------------------------------------------------------===// - -multiclass ADDS_MMM<string opstr, InstrItinClass Itin, bit IsComm, - SDPatternOperator OpNode = null_frag> { - def _D32_MM : MMRel, ADDS_FT<opstr, AFGR64Opnd, Itin, IsComm, OpNode>, - FGR_32 { - string DecoderNamespace = "MicroMips"; - } - // FIXME: This needs to be part of the instruction mapping tables. - def _D64_MM : ADDS_FT<opstr, FGR64Opnd, Itin, IsComm, OpNode>, FGR_64 { - string DecoderNamespace = "MicroMipsFP64"; - } -} - -def FADD_S_MM : MMRel, ADDS_FT<"add.s", FGR32Opnd, II_ADD_S, 1, fadd>, - ADDS_FM_MM<0, 0x30>, ISA_MICROMIPS; -def FDIV_S_MM : MMRel, ADDS_FT<"div.s", FGR32Opnd, II_DIV_S, 0, fdiv>, - ADDS_FM_MM<0, 0xf0>, ISA_MICROMIPS; -def FMUL_S_MM : MMRel, ADDS_FT<"mul.s", FGR32Opnd, II_MUL_S, 1, fmul>, - ADDS_FM_MM<0, 0xb0>, ISA_MICROMIPS; -def FSUB_S_MM : MMRel, ADDS_FT<"sub.s", FGR32Opnd, II_SUB_S, 0, fsub>, - ADDS_FM_MM<0, 0x70>, ISA_MICROMIPS; - -defm FADD : ADDS_MMM<"add.d", II_ADD_D, 1, fadd>, - ADDS_FM_MM<1, 0x30>, ISA_MICROMIPS; -defm FDIV : ADDS_MMM<"div.d", II_DIV_D, 0, fdiv>, - ADDS_FM_MM<1, 0xf0>, ISA_MICROMIPS; -defm FMUL : ADDS_MMM<"mul.d", II_MUL_D, 1, fmul>, - ADDS_FM_MM<1, 0xb0>, ISA_MICROMIPS; -defm FSUB : ADDS_MMM<"sub.d", II_SUB_D, 0, fsub>, - ADDS_FM_MM<1, 0x70>, ISA_MICROMIPS; - -let DecoderNamespace = "MicroMips" in { - def LWXC1_MM : MMRel, LWXC1_FT<"lwxc1", FGR32Opnd, II_LWXC1, load>, - LWXC1_FM_MM<0x48>, ISA_MICROMIPS32_NOT_MIPS32R6; - def SWXC1_MM : MMRel, SWXC1_FT<"swxc1", FGR32Opnd, II_SWXC1, store>, - SWXC1_FM_MM<0x88>, ISA_MICROMIPS32_NOT_MIPS32R6; - - def LUXC1_MM : MMRel, LWXC1_FT<"luxc1", FGR64Opnd, II_LUXC1>, - LWXC1_FM_MM<0x148>, FGR_64, ISA_MICROMIPS32_NOT_MIPS32R6; - def SUXC1_MM : MMRel, SWXC1_FT<"suxc1", FGR64Opnd, II_SUXC1>, - SWXC1_FM_MM<0x188>, FGR_64, ISA_MICROMIPS32_NOT_MIPS32R6; -} -let isCodeGenOnly = 1 in { -def FCMP_S32_MM : MMRel, CEQS_FT<"s", FGR32, II_C_CC_S, MipsFPCmp>, - CEQS_FM_MM<0>, ISA_MICROMIPS32_NOT_MIPS32R6 { - // FIXME: This is a required to work around the fact that these instructions - // only use $fcc0. Ideally, MipsFPCmp nodes could be removed and the - // fcc register set is used directly. - bits<3> fcc = 0; -} - -def FCMP_D32_MM : MMRel, CEQS_FT<"d", AFGR64, II_C_CC_D, MipsFPCmp>, - CEQS_FM_MM<1>, ISA_MICROMIPS32_NOT_MIPS32R6 { - // FIXME: This is a required to work around the fact that these instructions - // only use $fcc0. Ideally, MipsFPCmp nodes could be removed and the - // fcc register set is used directly. - bits<3> fcc = 0; -} - -} - -let DecoderNamespace = "MicroMips" in { - def BC1F_MM : MMRel, BC1F_FT<"bc1f", brtarget_mm, II_BC1F, MIPS_BRANCH_F>, - BC1F_FM_MM<0x1c>, ISA_MICROMIPS32_NOT_MIPS32R6; - def BC1T_MM : MMRel, BC1F_FT<"bc1t", brtarget_mm, II_BC1T, MIPS_BRANCH_T>, - BC1F_FM_MM<0x1d>, ISA_MICROMIPS32_NOT_MIPS32R6; - def CVT_W_S_MM : MMRel, ABSS_FT<"cvt.w.s", FGR32Opnd, FGR32Opnd, II_CVT>, - ROUND_W_FM_MM<0, 0x24>, ISA_MICROMIPS; -} - -let DecoderNamespace = "MicroMips" in { - def ROUND_W_S_MM : MMRel, StdMMR6Rel, ABSS_FT<"round.w.s", FGR32Opnd, - FGR32Opnd, II_ROUND>, - ROUND_W_FM_MM<0, 0xec>, ISA_MICROMIPS; - - def CEIL_W_MM : MMRel, ABSS_FT<"ceil.w.d", FGR32Opnd, AFGR64Opnd, II_CEIL>, - ROUND_W_FM_MM<1, 0x6c>, ISA_MICROMIPS, FGR_32; - def FLOOR_W_MM : MMRel, ABSS_FT<"floor.w.d", FGR32Opnd, AFGR64Opnd, II_FLOOR>, - ROUND_W_FM_MM<1, 0x2c>, ISA_MICROMIPS, FGR_32; - def ROUND_W_MM : MMRel, StdMMR6Rel, ABSS_FT<"round.w.d", FGR32Opnd, - AFGR64Opnd, II_ROUND>, - ROUND_W_FM_MM<1, 0xec>, ISA_MICROMIPS, FGR_32; - def TRUNC_W_MM : MMRel, ABSS_FT<"trunc.w.d", FGR32Opnd, AFGR64Opnd, II_TRUNC>, - ROUND_W_FM_MM<1, 0xac>, ISA_MICROMIPS, FGR_32; - - def CVT_L_S_MM : MMRel, ABSS_FT<"cvt.l.s", FGR64Opnd, FGR32Opnd, II_CVT>, - ROUND_W_FM_MM<0, 0x4>, ISA_MICROMIPS, FGR_64; - def CVT_L_D64_MM : MMRel, ABSS_FT<"cvt.l.d", FGR64Opnd, FGR64Opnd, II_CVT>, - ROUND_W_FM_MM<1, 0x4>, ISA_MICROMIPS, FGR_64; - - def CVT_W_D32_MM : MMRel, ABSS_FT<"cvt.w.d", FGR32Opnd, AFGR64Opnd, II_CVT>, - ROUND_W_FM_MM<1, 0x24>, ISA_MICROMIPS, FGR_32; -} -let DecoderNamespace = "MicroMipsFP64" in { - def CVT_W_D64_MM : ABSS_FT<"cvt.w.d", FGR32Opnd, FGR64Opnd, II_CVT>, - ROUND_W_FM_MM<1, 0x24>, ISA_MICROMIPS, FGR_64; -} - -multiclass ABSS_MMM<string opstr, InstrItinClass Itin, - SDPatternOperator OpNode = null_frag> { - def _D32_MM : MMRel, ABSS_FT<opstr, AFGR64Opnd, AFGR64Opnd, Itin, OpNode>, - ISA_MICROMIPS, FGR_32 { - string DecoderNamespace = "MicroMips"; - } - def _D64_MM : StdMMR6Rel, ABSS_FT<opstr, FGR64Opnd, FGR64Opnd, Itin, OpNode>, - ISA_MICROMIPS, FGR_64 { - string DecoderNamespace = "MicroMipsFP64"; - } -} - -defm FSQRT : ABSS_MMM<"sqrt.d", II_SQRT_D, fsqrt>, ROUND_W_FM_MM<1, 0x28>; -defm FABS : ABSS_MMM<"abs.d", II_SQRT_D, fabs>, ABS_FM_MM<1, 0xd>; - -let DecoderNamespace = "MicroMips", AdditionalPredicates = [UseAbs] in { - def FABS_S_MM : MMRel, ABSS_FT<"abs.s", FGR32Opnd, FGR32Opnd, II_ABS, fabs>, - ABS_FM_MM<0, 0xd>, ISA_MICROMIPS; -} - -def FMOV_S_MM : MMRel, ABSS_FT<"mov.s", FGR32Opnd, FGR32Opnd, II_MOV_S>, - ABS_FM_MM<0, 0x1>, ISA_MICROMIPS { - let isMoveReg = 1; -} -def FNEG_S_MM : MMRel, ABSS_FT<"neg.s", FGR32Opnd, FGR32Opnd, II_NEG, fneg>, - ABS_FM_MM<0, 0x2d>, ISA_MICROMIPS; - -let DecoderNamespace = "MicroMips" in { - def CVT_D32_S_MM : MMRel, ABSS_FT<"cvt.d.s", AFGR64Opnd, FGR32Opnd, II_CVT>, - ABS_FM_MM<0, 0x4d>, ISA_MICROMIPS, FGR_32; - def CVT_D32_W_MM : MMRel, ABSS_FT<"cvt.d.w", AFGR64Opnd, FGR32Opnd, II_CVT>, - ABS_FM_MM<1, 0x4d>, ISA_MICROMIPS, FGR_32; -} - -let DecoderNamespace = "MicroMipsFP64" in { - def CVT_D64_S_MM : ABSS_FT<"cvt.d.s", FGR64Opnd, FGR32Opnd, II_CVT>, - ABS_FM_MM<0, 0x4d>, ISA_MICROMIPS, FGR_64; - def CVT_D64_W_MM : ABSS_FT<"cvt.d.w", FGR64Opnd, FGR32Opnd, II_CVT>, - ABS_FM_MM<1, 0x4d>, ISA_MICROMIPS, FGR_64; - def CVT_S_D64_MM : ABSS_FT<"cvt.s.d", FGR32Opnd, FGR64Opnd, II_CVT>, - ABS_FM_MM<0, 0x6d>, ISA_MICROMIPS, FGR_64; -} - -let DecoderNamespace = "MicroMips" in { - def CVT_S_D32_MM : MMRel, ABSS_FT<"cvt.s.d", FGR32Opnd, AFGR64Opnd, II_CVT>, - ABS_FM_MM<0, 0x6d>, ISA_MICROMIPS, FGR_32; - def CVT_S_W_MM : MMRel, ABSS_FT<"cvt.s.w", FGR32Opnd, FGR32Opnd, II_CVT>, - ABS_FM_MM<1, 0x6d>, ISA_MICROMIPS; -} - - -defm FNEG : ABSS_MMM<"neg.d", II_NEG, fneg>, ABS_FM_MM<1, 0x2d>; -defm FMOV : ABSS_MMM<"mov.d", II_MOV_D>, ABS_FM_MM<1, 0x1>; - -let DecoderNamespace = "MicroMips" in { - def MOVZ_I_S_MM : MMRel, CMov_I_F_FT<"movz.s", GPR32Opnd, FGR32Opnd, - II_MOVZ_S>, CMov_I_F_FM_MM<0x78, 0>, - ISA_MICROMIPS32_NOT_MIPS32R6; - def MOVN_I_S_MM : MMRel, CMov_I_F_FT<"movn.s", GPR32Opnd, FGR32Opnd, - II_MOVN_S>, CMov_I_F_FM_MM<0x38, 0>, - ISA_MICROMIPS32_NOT_MIPS32R6; - def MOVZ_I_D32_MM : MMRel, CMov_I_F_FT<"movz.d", GPR32Opnd, AFGR64Opnd, - II_MOVZ_D>, CMov_I_F_FM_MM<0x78, 1>, - ISA_MICROMIPS32_NOT_MIPS32R6, FGR_32; - def MOVN_I_D32_MM : MMRel, CMov_I_F_FT<"movn.d", GPR32Opnd, AFGR64Opnd, - II_MOVN_D>, CMov_I_F_FM_MM<0x38, 1>, - ISA_MICROMIPS32_NOT_MIPS32R6, FGR_32; - - def MOVT_S_MM : MMRel, CMov_F_F_FT<"movt.s", FGR32Opnd, II_MOVT_S, - MipsCMovFP_T>, CMov_F_F_FM_MM<0x60, 0>, - ISA_MICROMIPS32_NOT_MIPS32R6; - def MOVF_S_MM : MMRel, CMov_F_F_FT<"movf.s", FGR32Opnd, II_MOVF_S, - MipsCMovFP_F>, CMov_F_F_FM_MM<0x20, 0>, - ISA_MICROMIPS32_NOT_MIPS32R6; - def MOVT_D32_MM : MMRel, CMov_F_F_FT<"movt.d", AFGR64Opnd, II_MOVT_D, - MipsCMovFP_T>, CMov_F_F_FM_MM<0x60, 1>, - ISA_MICROMIPS32_NOT_MIPS32R6, FGR_32; - def MOVF_D32_MM : MMRel, CMov_F_F_FT<"movf.d", AFGR64Opnd, II_MOVF_D, - MipsCMovFP_F>, CMov_F_F_FM_MM<0x20, 1>, - ISA_MICROMIPS32_NOT_MIPS32R6, FGR_32; - - def MFC1_MM : MMRel, MFC1_FT<"mfc1", GPR32Opnd, FGR32Opnd, - II_MFC1, bitconvert>, MFC1_FM_MM<0x80>, - ISA_MICROMIPS; - def MTC1_MM : MMRel, MTC1_FT<"mtc1", FGR32Opnd, GPR32Opnd, - II_MTC1, bitconvert>, MFC1_FM_MM<0xa0>, - ISA_MICROMIPS; - - def MADD_S_MM : MMRel, MADDS_FT<"madd.s", FGR32Opnd, II_MADD_S>, - MADDS_FM_MM<0x1>, ISA_MICROMIPS32_NOT_MIPS32R6, MADD4; - def MSUB_S_MM : MMRel, MADDS_FT<"msub.s", FGR32Opnd, II_MSUB_S>, - MADDS_FM_MM<0x21>, ISA_MICROMIPS32_NOT_MIPS32R6, MADD4; - let AdditionalPredicates = [NoNaNsFPMath, HasMadd4] in { - def NMADD_S_MM : MMRel, NMADDS_FT<"nmadd.s", FGR32Opnd, II_NMADD_S>, - MADDS_FM_MM<0x2>, ISA_MICROMIPS32_NOT_MIPS32R6; - def NMSUB_S_MM : MMRel, NMADDS_FT<"nmsub.s", FGR32Opnd, II_NMSUB_S>, - MADDS_FM_MM<0x22>, ISA_MICROMIPS32_NOT_MIPS32R6; - } - def MADD_D32_MM : MMRel, MADDS_FT<"madd.d", AFGR64Opnd, II_MADD_D>, - MADDS_FM_MM<0x9>, ISA_MICROMIPS32_NOT_MIPS32R6, FGR_32, - MADD4; - def MSUB_D32_MM : MMRel, MADDS_FT<"msub.d", AFGR64Opnd, II_MSUB_D>, - MADDS_FM_MM<0x29>, ISA_MICROMIPS32_NOT_MIPS32R6, FGR_32, - MADD4; - let AdditionalPredicates = [NoNaNsFPMath, HasMadd4] in { - def NMADD_D32_MM : MMRel, NMADDS_FT<"nmadd.d", AFGR64Opnd, II_NMADD_D>, - MADDS_FM_MM<0xa>, ISA_MICROMIPS32_NOT_MIPS32R6, FGR_32; - def NMSUB_D32_MM : MMRel, NMADDS_FT<"nmsub.d", AFGR64Opnd, II_NMSUB_D>, - MADDS_FM_MM<0x2a>, ISA_MICROMIPS32_NOT_MIPS32R6, FGR_32; - } - - def FLOOR_W_S_MM : MMRel, ABSS_FT<"floor.w.s", FGR32Opnd, FGR32Opnd, - II_FLOOR>, ROUND_W_FM_MM<0, 0x2c>, - ISA_MICROMIPS; - def TRUNC_W_S_MM : MMRel, StdMMR6Rel, ABSS_FT<"trunc.w.s", FGR32Opnd, - FGR32Opnd, II_TRUNC>, - ROUND_W_FM_MM<0, 0xac>, ISA_MICROMIPS; - def CEIL_W_S_MM : MMRel, ABSS_FT<"ceil.w.s", FGR32Opnd, FGR32Opnd, II_CEIL>, - ROUND_W_FM_MM<0, 0x6c>, ISA_MICROMIPS; - - def FSQRT_S_MM : MMRel, ABSS_FT<"sqrt.s", FGR32Opnd, FGR32Opnd, II_SQRT_S, - fsqrt>, ROUND_W_FM_MM<0, 0x28>, ISA_MICROMIPS; - - def MTHC1_D32_MM : MMRel, MTC1_64_FT<"mthc1", AFGR64Opnd, GPR32Opnd, II_MTHC1>, - MFC1_FM_MM<0xe0>, ISA_MICROMIPS, FGR_32; - def MFHC1_D32_MM : MMRel, MFC1_FT<"mfhc1", GPR32Opnd, AFGR64Opnd, II_MFHC1>, - MFC1_FM_MM<0xc0>, ISA_MICROMIPS, FGR_32; -} - -let DecoderNamespace = "MicroMipsFP64" in { - def MTHC1_D64_MM : MTC1_64_FT<"mthc1", FGR64Opnd, GPR32Opnd, II_MTHC1>, - MFC1_FM_MM<0xe0>, ISA_MICROMIPS, FGR_64; - def MFHC1_D64_MM : MFC1_FT<"mfhc1", GPR32Opnd, FGR64Opnd, II_MFHC1>, - MFC1_FM_MM<0xc0>, ISA_MICROMIPS, FGR_64; - def MTC1_D64_MM : MTC1_FT<"mtc1", FGR64Opnd, GPR32Opnd, II_MTC1>, - MFC1_FM_MM<0xa0>, ISA_MICROMIPS, FGR_64; -} - -let DecoderNamespace = "MicroMips" in { - def CFC1_MM : MMRel, MFC1_FT<"cfc1", GPR32Opnd, CCROpnd, II_CFC1>, - MFC1_FM_MM<0x40>, ISA_MICROMIPS; - def CTC1_MM : MMRel, MTC1_FT<"ctc1", CCROpnd, GPR32Opnd, II_CTC1>, - MFC1_FM_MM<0x60>, ISA_MICROMIPS; - def RECIP_S_MM : MMRel, ABSS_FT<"recip.s", FGR32Opnd, FGR32Opnd, - II_RECIP_S>, - ROUND_W_FM_MM<0b0, 0b01001000>, ISA_MICROMIPS; - def RECIP_D32_MM : MMRel, ABSS_FT<"recip.d", AFGR64Opnd, AFGR64Opnd, - II_RECIP_D>, - ROUND_W_FM_MM<0b1, 0b01001000>, ISA_MICROMIPS, FGR_32 { - let BaseOpcode = "RECIP_D32"; - } - let DecoderNamespace = "MicroMipsFP64" in - def RECIP_D64_MM : MMRel, ABSS_FT<"recip.d", FGR64Opnd, FGR64Opnd, - II_RECIP_D>, - ROUND_W_FM_MM<0b1, 0b01001000>, ISA_MICROMIPS, FGR_64; - def RSQRT_S_MM : MMRel, ABSS_FT<"rsqrt.s", FGR32Opnd, FGR32Opnd, - II_RECIP_S>, - ROUND_W_FM_MM<0b0, 0b00001000>, ISA_MICROMIPS; - def RSQRT_D32_MM : MMRel, ABSS_FT<"rsqrt.d", AFGR64Opnd, AFGR64Opnd, - II_RECIP_D>, - ROUND_W_FM_MM<0b1, 0b00001000>, ISA_MICROMIPS, FGR_32 { - let BaseOpcode = "RSQRT_D32"; - } - let DecoderNamespace = "MicroMipsFP64" in - def RSQRT_D64_MM : MMRel, ABSS_FT<"rsqrt.d", FGR64Opnd, FGR64Opnd, - II_RECIP_D>, - ROUND_W_FM_MM<0b1, 0b00001000>, ISA_MICROMIPS, FGR_64; -} - -let DecoderNamespace = "MicroMips", DecoderMethod = "DecodeFMemMMR2" in { - def LDC1_MM : MMRel, LW_FT<"ldc1", AFGR64Opnd, mem_mm_16, II_LDC1, load>, - LW_FM_MM<0x2f>, ISA_MICROMIPS, FGR_32 { - let BaseOpcode = "LDC132"; - } - def SDC1_MM : MMRel, SW_FT<"sdc1", AFGR64Opnd, mem_mm_16, II_SDC1, store>, - LW_FM_MM<0x2e>, ISA_MICROMIPS, FGR_32; - def LWC1_MM : MMRel, LW_FT<"lwc1", FGR32Opnd, mem_mm_16, II_LWC1, load>, - LW_FM_MM<0x27>, ISA_MICROMIPS; - def SWC1_MM : MMRel, SW_FT<"swc1", FGR32Opnd, mem_mm_16, II_SWC1, store>, - LW_FM_MM<0x26>, ISA_MICROMIPS; -} - -multiclass C_COND_MM<string TypeStr, RegisterOperand RC, bits<2> fmt, - InstrItinClass itin> { - def C_F_#NAME#_MM : MMRel, C_COND_FT<"f", TypeStr, RC, itin>, - C_COND_FM_MM<fmt, 0> { - let BaseOpcode = "c.f."#NAME; - let isCommutable = 1; - } - def C_UN_#NAME#_MM : MMRel, C_COND_FT<"un", TypeStr, RC, itin>, - C_COND_FM_MM<fmt, 1> { - let BaseOpcode = "c.un."#NAME; - let isCommutable = 1; - } - def C_EQ_#NAME#_MM : MMRel, C_COND_FT<"eq", TypeStr, RC, itin>, - C_COND_FM_MM<fmt, 2> { - let BaseOpcode = "c.eq."#NAME; - let isCommutable = 1; - } - def C_UEQ_#NAME#_MM : MMRel, C_COND_FT<"ueq", TypeStr, RC, itin>, - C_COND_FM_MM<fmt, 3> { - let BaseOpcode = "c.ueq."#NAME; - let isCommutable = 1; - } - def C_OLT_#NAME#_MM : MMRel, C_COND_FT<"olt", TypeStr, RC, itin>, - C_COND_FM_MM<fmt, 4> { - let BaseOpcode = "c.olt."#NAME; - } - def C_ULT_#NAME#_MM : MMRel, C_COND_FT<"ult", TypeStr, RC, itin>, - C_COND_FM_MM<fmt, 5> { - let BaseOpcode = "c.ult."#NAME; - } - def C_OLE_#NAME#_MM : MMRel, C_COND_FT<"ole", TypeStr, RC, itin>, - C_COND_FM_MM<fmt, 6> { - let BaseOpcode = "c.ole."#NAME; - } - def C_ULE_#NAME#_MM : MMRel, C_COND_FT<"ule", TypeStr, RC, itin>, - C_COND_FM_MM<fmt, 7> { - let BaseOpcode = "c.ule."#NAME; - } - def C_SF_#NAME#_MM : MMRel, C_COND_FT<"sf", TypeStr, RC, itin>, - C_COND_FM_MM<fmt, 8> { - let BaseOpcode = "c.sf."#NAME; - let isCommutable = 1; - } - def C_NGLE_#NAME#_MM : MMRel, C_COND_FT<"ngle", TypeStr, RC, itin>, - C_COND_FM_MM<fmt, 9> { - let BaseOpcode = "c.ngle."#NAME; - } - def C_SEQ_#NAME#_MM : MMRel, C_COND_FT<"seq", TypeStr, RC, itin>, - C_COND_FM_MM<fmt, 10> { - let BaseOpcode = "c.seq."#NAME; - let isCommutable = 1; - } - def C_NGL_#NAME#_MM : MMRel, C_COND_FT<"ngl", TypeStr, RC, itin>, - C_COND_FM_MM<fmt, 11> { - let BaseOpcode = "c.ngl."#NAME; - } - def C_LT_#NAME#_MM : MMRel, C_COND_FT<"lt", TypeStr, RC, itin>, - C_COND_FM_MM<fmt, 12> { - let BaseOpcode = "c.lt."#NAME; - } - def C_NGE_#NAME#_MM : MMRel, C_COND_FT<"nge", TypeStr, RC, itin>, - C_COND_FM_MM<fmt, 13> { - let BaseOpcode = "c.nge."#NAME; - } - def C_LE_#NAME#_MM : MMRel, C_COND_FT<"le", TypeStr, RC, itin>, - C_COND_FM_MM<fmt, 14> { - let BaseOpcode = "c.le."#NAME; - } - def C_NGT_#NAME#_MM : MMRel, C_COND_FT<"ngt", TypeStr, RC, itin>, - C_COND_FM_MM<fmt, 15> { - let BaseOpcode = "c.ngt."#NAME; - } -} -let DecoderNamespace = "MicroMips" in { - defm S : C_COND_MM<"s", FGR32Opnd, 0b00, II_C_CC_S>, - ISA_MICROMIPS32_NOT_MIPS32R6; - defm D32 : C_COND_MM<"d", AFGR64Opnd, 0b01, II_C_CC_D>, - ISA_MICROMIPS32_NOT_MIPS32R6, FGR_32; -} - -let DecoderNamespace = "Mips64" in - defm D64 : C_COND_MM<"d", FGR64Opnd, 0b01, II_C_CC_D>, - ISA_MICROMIPS32_NOT_MIPS32R6, FGR_64; - -defm S_MM : C_COND_ALIASES<"s", FGR32Opnd>, HARDFLOAT, - ISA_MICROMIPS32_NOT_MIPS32R6; -defm D32_MM : C_COND_ALIASES<"d", AFGR64Opnd>, HARDFLOAT, - ISA_MICROMIPS32_NOT_MIPS32R6, FGR_32; -defm D64_MM : C_COND_ALIASES<"d", FGR64Opnd>, HARDFLOAT, - ISA_MICROMIPS32_NOT_MIPS32R6, FGR_64; - -defm : BC1_ALIASES<BC1T_MM, "bc1t", BC1F_MM, "bc1f">, - ISA_MICROMIPS32_NOT_MIPS32R6, HARDFLOAT; - - -// To generate NMADD and NMSUB instructions when fneg node is present -let AdditionalPredicates = [NoNaNsFPMath, HasMadd4, - InMicroMips, NotMips32r6] in { - defm : NMADD_NMSUB<NMADD_S_MM, NMSUB_S_MM, FGR32Opnd>, - ISA_MICROMIPS32_NOT_MIPS32R6; - defm : NMADD_NMSUB<NMADD_D32_MM, NMSUB_D32_MM, AFGR64Opnd>, - ISA_MICROMIPS32_NOT_MIPS32R6, FGR_32; -} - -//===----------------------------------------------------------------------===// -// Floating Point Patterns -//===----------------------------------------------------------------------===// - -// Patterns for loads/stores with a reg+imm operand. -let AddedComplexity = 40 in { - def : LoadRegImmPat<LDC1_MM, f64, load>, ISA_MICROMIPS, FGR_32; - def : StoreRegImmPat<SDC1_MM, f64>, ISA_MICROMIPS, FGR_32; - def : LoadRegImmPat<LWC1_MM, f32, load>, ISA_MICROMIPS; - def : StoreRegImmPat<SWC1_MM, f32>, ISA_MICROMIPS; -} - -def : MipsPat<(MipsMTC1_D64 GPR32Opnd:$src), - (MTC1_D64_MM GPR32Opnd:$src)>, ISA_MICROMIPS, FGR_64; - -def : MipsPat<(f32 fpimm0), (MTC1_MM ZERO)>, ISA_MICROMIPS32_NOT_MIPS32R6; -def : MipsPat<(f32 fpimm0neg), (FNEG_S_MM (MTC1_MM ZERO))>, - ISA_MICROMIPS32_NOT_MIPS32R6; - -def : MipsPat<(f32 (fpround FGR64Opnd:$src)), - (CVT_S_D64_MM FGR64Opnd:$src)>, ISA_MICROMIPS, FGR_64; -def : MipsPat<(f64 (fpextend FGR32Opnd:$src)), - (CVT_D64_S_MM FGR32Opnd:$src)>, ISA_MICROMIPS, FGR_64; -def : MipsPat<(f32 (fpround AFGR64Opnd:$src)), - (CVT_S_D32_MM AFGR64Opnd:$src)>, ISA_MICROMIPS, FGR_32; -def : MipsPat<(f64 (fpextend FGR32Opnd:$src)), - (CVT_D32_S_MM FGR32Opnd:$src)>, ISA_MICROMIPS, FGR_32; -def : MipsPat<(MipsTruncIntFP AFGR64Opnd:$src), - (TRUNC_W_MM AFGR64Opnd:$src)>, ISA_MICROMIPS32_NOT_MIPS32R6, - FGR_32; -def : MipsPat<(MipsTruncIntFP FGR64Opnd:$src), - (CVT_W_D64_MM FGR64Opnd:$src)>, ISA_MICROMIPS32_NOT_MIPS32R6, - FGR_64; -def : MipsPat<(MipsTruncIntFP FGR32Opnd:$src), - (TRUNC_W_S_MM FGR32Opnd:$src)>, ISA_MICROMIPS32_NOT_MIPS32R6; - -// Selects -defm : MovzPats0<GPR32, FGR32, MOVZ_I_S_MM, SLT_MM, SLTu_MM, SLTi_MM, SLTiu_MM>, - ISA_MICROMIPS32_NOT_MIPS32R6; -defm : MovzPats1<GPR32, FGR32, MOVZ_I_S_MM, XOR_MM>, - ISA_MICROMIPS32_NOT_MIPS32R6; - -defm : MovnPats<GPR32, FGR32, MOVN_I_S_MM, XOR_MM>, - ISA_MICROMIPS32_NOT_MIPS32R6; - -defm : MovzPats0<GPR32, AFGR64, MOVZ_I_D32_MM, SLT_MM, SLTu_MM, SLTi_MM, - SLTiu_MM>, - ISA_MICROMIPS32_NOT_MIPS32R6, FGR_32; -defm : MovzPats1<GPR32, AFGR64, MOVZ_I_D32_MM, XOR_MM>, - ISA_MICROMIPS32_NOT_MIPS32R6, FGR_32; -defm : MovnPats<GPR32, AFGR64, MOVN_I_D32_MM, XOR_MM>, - ISA_MICROMIPS32_NOT_MIPS32R6, FGR_32; diff --git a/contrib/llvm/lib/Target/Mips/MicroMipsInstrFormats.td b/contrib/llvm/lib/Target/Mips/MicroMipsInstrFormats.td deleted file mode 100644 index e9fb9b310e3b..000000000000 --- a/contrib/llvm/lib/Target/Mips/MicroMipsInstrFormats.td +++ /dev/null @@ -1,1114 +0,0 @@ -//===-- MicroMipsInstrFormats.td - microMIPS Inst Formats -*- tablegen -*--===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This files descributes the formats of the microMIPS instruction set. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// MicroMIPS Base Classes -//===----------------------------------------------------------------------===// - -// -// Base class for MicroMips instructions. -// This class does not depend on the instruction size. -// -class MicroMipsInstBase<dag outs, dag ins, string asmstr, list<dag> pattern, - InstrItinClass itin, Format f> : Instruction, - PredicateControl { - let Namespace = "Mips"; - let DecoderNamespace = "MicroMips"; - - let OutOperandList = outs; - let InOperandList = ins; - - let AsmString = asmstr; - let Pattern = pattern; - let Itinerary = itin; - - let EncodingPredicates = [InMicroMips]; - - Format Form = f; -} - -// -// Base class for MicroMIPS 16-bit instructions. -// -class MicroMipsInst16<dag outs, dag ins, string asmstr, list<dag> pattern, - InstrItinClass itin, Format f> : - MicroMipsInstBase<outs, ins, asmstr, pattern, itin, f> -{ - let Size = 2; - field bits<16> Inst; - field bits<16> SoftFail = 0; - bits<6> Opcode = 0x0; -} - -//===----------------------------------------------------------------------===// -// MicroMIPS 16-bit Instruction Formats -//===----------------------------------------------------------------------===// - -class ARITH_FM_MM16<bit funct> { - bits<3> rd; - bits<3> rt; - bits<3> rs; - - bits<16> Inst; - - let Inst{15-10} = 0x01; - let Inst{9-7} = rd; - let Inst{6-4} = rt; - let Inst{3-1} = rs; - let Inst{0} = funct; -} - -class ANDI_FM_MM16<bits<6> funct> { - bits<3> rd; - bits<3> rs; - bits<4> imm; - - bits<16> Inst; - - let Inst{15-10} = funct; - let Inst{9-7} = rd; - let Inst{6-4} = rs; - let Inst{3-0} = imm; -} - -class LOGIC_FM_MM16<bits<4> funct> { - bits<3> rt; - bits<3> rs; - - bits<16> Inst; - - let Inst{15-10} = 0x11; - let Inst{9-6} = funct; - let Inst{5-3} = rt; - let Inst{2-0} = rs; -} - -class SHIFT_FM_MM16<bits<1> funct> { - bits<3> rd; - bits<3> rt; - bits<3> shamt; - - bits<16> Inst; - - let Inst{15-10} = 0x09; - let Inst{9-7} = rd; - let Inst{6-4} = rt; - let Inst{3-1} = shamt; - let Inst{0} = funct; -} - -class ADDIUR2_FM_MM16 { - bits<3> rd; - bits<3> rs; - bits<3> imm; - - bits<16> Inst; - - let Inst{15-10} = 0x1b; - let Inst{9-7} = rd; - let Inst{6-4} = rs; - let Inst{3-1} = imm; - let Inst{0} = 0; -} - -class LOAD_STORE_FM_MM16<bits<6> op> { - bits<3> rt; - bits<7> addr; - - bits<16> Inst; - - let Inst{15-10} = op; - let Inst{9-7} = rt; - let Inst{6-4} = addr{6-4}; - let Inst{3-0} = addr{3-0}; -} - -class LOAD_STORE_SP_FM_MM16<bits<6> op> { - bits<5> rt; - bits<5> offset; - - bits<16> Inst; - - let Inst{15-10} = op; - let Inst{9-5} = rt; - let Inst{4-0} = offset; -} - -class LOAD_GP_FM_MM16<bits<6> op> { - bits<3> rt; - bits<7> offset; - - bits<16> Inst; - - let Inst{15-10} = op; - let Inst{9-7} = rt; - let Inst{6-0} = offset; -} - -class ADDIUS5_FM_MM16 { - bits<5> rd; - bits<4> imm; - - bits<16> Inst; - - let Inst{15-10} = 0x13; - let Inst{9-5} = rd; - let Inst{4-1} = imm; - let Inst{0} = 0; -} - -class ADDIUSP_FM_MM16 { - bits<9> imm; - - bits<16> Inst; - - let Inst{15-10} = 0x13; - let Inst{9-1} = imm; - let Inst{0} = 1; -} - -class MOVE_FM_MM16<bits<6> funct> { - bits<5> rs; - bits<5> rd; - - bits<16> Inst; - - let Inst{15-10} = funct; - let Inst{9-5} = rd; - let Inst{4-0} = rs; -} - -class LI_FM_MM16 { - bits<3> rd; - bits<7> imm; - - bits<16> Inst; - - let Inst{15-10} = 0x3b; - let Inst{9-7} = rd; - let Inst{6-0} = imm; -} - -class JALR_FM_MM16<bits<5> op> { - bits<5> rs; - - bits<16> Inst; - - let Inst{15-10} = 0x11; - let Inst{9-5} = op; - let Inst{4-0} = rs; -} - -class MFHILO_FM_MM16<bits<5> funct> { - bits<5> rd; - - bits<16> Inst; - - let Inst{15-10} = 0x11; - let Inst{9-5} = funct; - let Inst{4-0} = rd; -} - -class JRADDIUSP_FM_MM16<bits<5> op> { - bits<5> rs; - bits<5> imm; - - bits<16> Inst; - - let Inst{15-10} = 0x11; - let Inst{9-5} = op; - let Inst{4-0} = imm; -} - -class ADDIUR1SP_FM_MM16 { - bits<3> rd; - bits<6> imm; - - bits<16> Inst; - - let Inst{15-10} = 0x1b; - let Inst{9-7} = rd; - let Inst{6-1} = imm; - let Inst{0} = 1; -} - -class BRKSDBBP16_FM_MM<bits<6> op> { - bits<4> code_; - bits<16> Inst; - - let Inst{15-10} = 0x11; - let Inst{9-4} = op; - let Inst{3-0} = code_; -} - -class BEQNEZ_FM_MM16<bits<6> op> { - bits<3> rs; - bits<7> offset; - - bits<16> Inst; - - let Inst{15-10} = op; - let Inst{9-7} = rs; - let Inst{6-0} = offset; -} - -class B16_FM { - bits<10> offset; - - bits<16> Inst; - - let Inst{15-10} = 0x33; - let Inst{9-0} = offset; -} - -class MOVEP_FM_MM16 { - bits<3> dst_regs; - bits<3> rt; - bits<3> rs; - - bits<16> Inst; - - let Inst{15-10} = 0x21; - let Inst{9-7} = dst_regs; - let Inst{6-4} = rt; - let Inst{3-1} = rs; - let Inst{0} = 0; -} - -//===----------------------------------------------------------------------===// -// MicroMIPS 32-bit Instruction Formats -//===----------------------------------------------------------------------===// - -class MMArch { - string Arch = "micromips"; -} - -class ADD_FM_MM<bits<6> op, bits<10> funct> : MMArch { - bits<5> rt; - bits<5> rs; - bits<5> rd; - - bits<32> Inst; - - let Inst{31-26} = op; - let Inst{25-21} = rt; - let Inst{20-16} = rs; - let Inst{15-11} = rd; - let Inst{10} = 0; - let Inst{9-0} = funct; -} - -class ADDI_FM_MM<bits<6> op> : MMArch { - bits<5> rs; - bits<5> rt; - bits<16> imm16; - - bits<32> Inst; - - let Inst{31-26} = op; - let Inst{25-21} = rt; - let Inst{20-16} = rs; - let Inst{15-0} = imm16; -} - -class SLTI_FM_MM<bits<6> op> : MMArch { - bits<5> rt; - bits<5> rs; - bits<16> imm16; - - bits<32> Inst; - - let Inst{31-26} = op; - let Inst{25-21} = rt; - let Inst{20-16} = rs; - let Inst{15-0} = imm16; -} - -class LUI_FM_MM : MMArch { - bits<5> rt; - bits<16> imm16; - - bits<32> Inst; - - let Inst{31-26} = 0x10; - let Inst{25-21} = 0xd; - let Inst{20-16} = rt; - let Inst{15-0} = imm16; -} - -class MULT_FM_MM<bits<10> funct> : MMArch { - bits<5> rs; - bits<5> rt; - - bits<32> Inst; - - let Inst{31-26} = 0x00; - let Inst{25-21} = rt; - let Inst{20-16} = rs; - let Inst{15-6} = funct; - let Inst{5-0} = 0x3c; -} - -class SRA_FM_MM<bits<10> funct, bit rotate> : MMArch { - bits<5> rd; - bits<5> rt; - bits<5> shamt; - - bits<32> Inst; - - let Inst{31-26} = 0; - let Inst{25-21} = rd; - let Inst{20-16} = rt; - let Inst{15-11} = shamt; - let Inst{10} = rotate; - let Inst{9-0} = funct; -} - -class SRLV_FM_MM<bits<10> funct, bit rotate> : MMArch { - bits<5> rd; - bits<5> rt; - bits<5> rs; - - bits<32> Inst; - - let Inst{31-26} = 0; - let Inst{25-21} = rt; - let Inst{20-16} = rs; - let Inst{15-11} = rd; - let Inst{10} = rotate; - let Inst{9-0} = funct; -} - -class LW_FM_MM<bits<6> op> : MMArch { - bits<5> rt; - bits<21> addr; - bits<5> base = addr{20-16}; - bits<16> offset = addr{15-0}; - - bits<32> Inst; - - let Inst{31-26} = op; - let Inst{25-21} = rt; - let Inst{20-16} = base; - let Inst{15-0} = offset; -} - -class POOL32C_LHUE_FM_MM<bits<6> op, bits<4> fmt, bits<3> funct> : MMArch { - bits<5> rt; - bits<21> addr; - bits<5> base = addr{20-16}; - bits<9> offset = addr{8-0}; - - bits<32> Inst; - - let Inst{31-26} = op; - let Inst{25-21} = rt; - let Inst{20-16} = base; - let Inst{15-12} = fmt; - let Inst{11-9} = funct; - let Inst{8-0} = offset; -} - -class LWL_FM_MM<bits<4> funct> : MMArch { - bits<5> rt; - bits<21> addr; - - bits<32> Inst; - - let Inst{31-26} = 0x18; - let Inst{25-21} = rt; - let Inst{20-16} = addr{20-16}; - let Inst{15-12} = funct; - let Inst{11-0} = addr{11-0}; -} - -class POOL32C_STEVA_LDEVA_FM_MM<bits<4> type, bits<3> funct> : MMArch { - bits<5> rt; - bits<21> addr; - bits<5> base = addr{20-16}; - bits<9> offset = addr{8-0}; - - bits<32> Inst; - - let Inst{31-26} = 0x18; - let Inst{25-21} = rt; - let Inst{20-16} = base; - let Inst{15-12} = type; - let Inst{11-9} = funct; - let Inst{8-0} = offset; -} - -class CMov_F_I_FM_MM<bits<7> func> : MMArch { - bits<5> rd; - bits<5> rs; - bits<3> fcc; - - bits<32> Inst; - - let Inst{31-26} = 0x15; - let Inst{25-21} = rd; - let Inst{20-16} = rs; - let Inst{15-13} = fcc; - let Inst{12-6} = func; - let Inst{5-0} = 0x3b; -} - -class MTLO_FM_MM<bits<10> funct> : MMArch { - bits<5> rs; - - bits<32> Inst; - - let Inst{31-26} = 0x00; - let Inst{25-21} = 0x00; - let Inst{20-16} = rs; - let Inst{15-6} = funct; - let Inst{5-0} = 0x3c; -} - -class MFLO_FM_MM<bits<10> funct> : MMArch { - bits<5> rd; - - bits<32> Inst; - - let Inst{31-26} = 0x00; - let Inst{25-21} = 0x00; - let Inst{20-16} = rd; - let Inst{15-6} = funct; - let Inst{5-0} = 0x3c; -} - -class CLO_FM_MM<bits<10> funct> : MMArch { - bits<5> rd; - bits<5> rs; - - bits<32> Inst; - - let Inst{31-26} = 0x00; - let Inst{25-21} = rd; - let Inst{20-16} = rs; - let Inst{15-6} = funct; - let Inst{5-0} = 0x3c; -} - -class SEB_FM_MM<bits<10> funct> : MMArch { - bits<5> rd; - bits<5> rt; - - bits<32> Inst; - - let Inst{31-26} = 0x00; - let Inst{25-21} = rd; - let Inst{20-16} = rt; - let Inst{15-6} = funct; - let Inst{5-0} = 0x3c; -} - -class EXT_FM_MM<bits<6> funct> : MMArch { - bits<5> rt; - bits<5> rs; - bits<5> pos; - bits<5> size; - - bits<32> Inst; - - let Inst{31-26} = 0x00; - let Inst{25-21} = rt; - let Inst{20-16} = rs; - let Inst{15-11} = size; - let Inst{10-6} = pos; - let Inst{5-0} = funct; -} - -class J_FM_MM<bits<6> op> : MMArch { - bits<26> target; - - bits<32> Inst; - - let Inst{31-26} = op; - let Inst{25-0} = target; -} - -class JR_FM_MM<bits<8> funct> : MMArch { - bits<5> rs; - - bits<32> Inst; - - let Inst{31-21} = 0x00; - let Inst{20-16} = rs; - let Inst{15-14} = 0x0; - let Inst{13-6} = funct; - let Inst{5-0} = 0x3c; -} - -class JALR_FM_MM<bits<10> funct> { - bits<5> rs; - bits<5> rd; - - bits<32> Inst; - - let Inst{31-26} = 0x00; - let Inst{25-21} = rd; - let Inst{20-16} = rs; - let Inst{15-6} = funct; - let Inst{5-0} = 0x3c; -} - -class BEQ_FM_MM<bits<6> op> : MMArch { - bits<5> rs; - bits<5> rt; - bits<16> offset; - - bits<32> Inst; - - let Inst{31-26} = op; - let Inst{25-21} = rt; - let Inst{20-16} = rs; - let Inst{15-0} = offset; -} - -class BGEZ_FM_MM<bits<5> funct> : MMArch { - bits<5> rs; - bits<16> offset; - - bits<32> Inst; - - let Inst{31-26} = 0x10; - let Inst{25-21} = funct; - let Inst{20-16} = rs; - let Inst{15-0} = offset; -} - -class BGEZAL_FM_MM<bits<5> funct> : MMArch { - bits<5> rs; - bits<16> offset; - - bits<32> Inst; - - let Inst{31-26} = 0x10; - let Inst{25-21} = funct; - let Inst{20-16} = rs; - let Inst{15-0} = offset; -} - -class SYNC_FM_MM : MMArch { - bits<5> stype; - - bits<32> Inst; - - let Inst{31-26} = 0x00; - let Inst{25-21} = 0x0; - let Inst{20-16} = stype; - let Inst{15-6} = 0x1ad; - let Inst{5-0} = 0x3c; -} - -class SYNCI_FM_MM : MMArch { - bits<21> addr; - bits<5> rs = addr{20-16}; - bits<16> offset = addr{15-0}; - bits<32> Inst; - - let Inst{31-26} = 0b010000; - let Inst{25-21} = 0b10000; - let Inst{20-16} = rs; - let Inst{15-0} = offset; -} - -class BRK_FM_MM : MMArch { - bits<10> code_1; - bits<10> code_2; - bits<32> Inst; - let Inst{31-26} = 0x0; - let Inst{25-16} = code_1; - let Inst{15-6} = code_2; - let Inst{5-0} = 0x07; -} - -class SYS_FM_MM : MMArch { - bits<10> code_; - bits<32> Inst; - let Inst{31-26} = 0x0; - let Inst{25-16} = code_; - let Inst{15-6} = 0x22d; - let Inst{5-0} = 0x3c; -} - -class WAIT_FM_MM : MMArch { - bits<10> code_; - bits<32> Inst; - - let Inst{31-26} = 0x00; - let Inst{25-16} = code_; - let Inst{15-6} = 0x24d; - let Inst{5-0} = 0x3c; -} - -class ER_FM_MM<bits<10> funct> : MMArch { - bits<32> Inst; - - let Inst{31-26} = 0x00; - let Inst{25-16} = 0x00; - let Inst{15-6} = funct; - let Inst{5-0} = 0x3c; -} - -class EI_FM_MM<bits<10> funct> : MMArch { - bits<32> Inst; - bits<5> rt; - - let Inst{31-26} = 0x00; - let Inst{25-21} = 0x00; - let Inst{20-16} = rt; - let Inst{15-6} = funct; - let Inst{5-0} = 0x3c; -} - -class TEQ_FM_MM<bits<6> funct> : MMArch { - bits<5> rs; - bits<5> rt; - bits<4> code_; - - bits<32> Inst; - - let Inst{31-26} = 0x00; - let Inst{25-21} = rt; - let Inst{20-16} = rs; - let Inst{15-12} = code_; - let Inst{11-6} = funct; - let Inst{5-0} = 0x3c; -} - -class TEQI_FM_MM<bits<5> funct> : MMArch { - bits<5> rs; - bits<16> imm16; - - bits<32> Inst; - - let Inst{31-26} = 0x10; - let Inst{25-21} = funct; - let Inst{20-16} = rs; - let Inst{15-0} = imm16; -} - -class LL_FM_MM<bits<4> funct> : MMArch { - bits<5> rt; - bits<21> addr; - - bits<32> Inst; - - let Inst{31-26} = 0x18; - let Inst{25-21} = rt; - let Inst{20-16} = addr{20-16}; - let Inst{15-12} = funct; - let Inst{11-0} = addr{11-0}; -} - -class LLE_FM_MM<bits<4> funct> : MMArch { - bits<5> rt; - bits<21> addr; - bits<5> base = addr{20-16}; - bits<9> offset = addr{8-0}; - - bits<32> Inst; - - let Inst{31-26} = 0x18; - let Inst{25-21} = rt; - let Inst{20-16} = base; - let Inst{15-12} = funct; - let Inst{11-9} = 0x6; - let Inst{8-0} = offset; -} - -class ADDS_FM_MM<bits<2> fmt, bits<8> funct> : MMArch { - bits<5> ft; - bits<5> fs; - bits<5> fd; - - bits<32> Inst; - - let Inst{31-26} = 0x15; - let Inst{25-21} = ft; - let Inst{20-16} = fs; - let Inst{15-11} = fd; - let Inst{10} = 0; - let Inst{9-8} = fmt; - let Inst{7-0} = funct; - -} - -class LWXC1_FM_MM<bits<9> funct> : MMArch { - bits<5> fd; - bits<5> base; - bits<5> index; - - bits<32> Inst; - - let Inst{31-26} = 0x15; - let Inst{25-21} = index; - let Inst{20-16} = base; - let Inst{15-11} = fd; - let Inst{10-9} = 0x0; - let Inst{8-0} = funct; -} - -class SWXC1_FM_MM<bits<9> funct> : MMArch { - bits<5> fs; - bits<5> base; - bits<5> index; - - bits<32> Inst; - - let Inst{31-26} = 0x15; - let Inst{25-21} = index; - let Inst{20-16} = base; - let Inst{15-11} = fs; - let Inst{10-9} = 0x0; - let Inst{8-0} = funct; -} - -class CEQS_FM_MM<bits<2> fmt> : MMArch { - bits<5> fs; - bits<5> ft; - bits<3> fcc; - bits<4> cond; - - bits<32> Inst; - - let Inst{31-26} = 0x15; - let Inst{25-21} = ft; - let Inst{20-16} = fs; - let Inst{15-13} = fcc; - let Inst{12} = 0; - let Inst{11-10} = fmt; - let Inst{9-6} = cond; - let Inst{5-0} = 0x3c; -} - -class C_COND_FM_MM<bits <2> fmt, bits<4> c> : CEQS_FM_MM<fmt> { - let cond = c; -} - -class BC1F_FM_MM<bits<5> tf> : MMArch { - bits<3> fcc; - bits<16> offset; - - bits<32> Inst; - - let Inst{31-26} = 0x10; - let Inst{25-21} = tf; - let Inst{20-18} = fcc; // cc - let Inst{17-16} = 0x0; - let Inst{15-0} = offset; -} - -class ROUND_W_FM_MM<bits<1> fmt, bits<8> funct> : MMArch { - bits<5> fd; - bits<5> fs; - - bits<32> Inst; - - let Inst{31-26} = 0x15; - let Inst{25-21} = fd; - let Inst{20-16} = fs; - let Inst{15} = 0; - let Inst{14} = fmt; - let Inst{13-6} = funct; - let Inst{5-0} = 0x3b; -} - -class ABS_FM_MM<bits<2> fmt, bits<7> funct> : MMArch { - bits<5> fd; - bits<5> fs; - - bits<32> Inst; - - let Inst{31-26} = 0x15; - let Inst{25-21} = fd; - let Inst{20-16} = fs; - let Inst{15} = 0; - let Inst{14-13} = fmt; - let Inst{12-6} = funct; - let Inst{5-0} = 0x3b; -} - -class CMov_F_F_FM_MM<bits<9> func, bits<2> fmt> : MMArch { - bits<5> fd; - bits<5> fs; - bits<3> fcc; - bits<32> Inst; - - let Inst{31-26} = 0x15; - let Inst{25-21} = fd; - let Inst{20-16} = fs; - let Inst{15-13} = fcc; //cc - let Inst{12-11} = 0x0; - let Inst{10-9} = fmt; - let Inst{8-0} = func; -} - -class CMov_I_F_FM_MM<bits<8> funct, bits<2> fmt> : MMArch { - bits<5> fd; - bits<5> fs; - bits<5> rt; - - bits<32> Inst; - - let Inst{31-26} = 0x15; - let Inst{25-21} = rt; - let Inst{20-16} = fs; - let Inst{15-11} = fd; - let Inst{9-8} = fmt; - let Inst{7-0} = funct; -} - -class MFC1_FM_MM<bits<8> funct> : MMArch { - bits<5> rt; - bits<5> fs; - - bits<32> Inst; - - let Inst{31-26} = 0x15; - let Inst{25-21} = rt; - let Inst{20-16} = fs; - let Inst{15-14} = 0x0; - let Inst{13-6} = funct; - let Inst{5-0} = 0x3b; -} - -class MADDS_FM_MM<bits<6> funct>: MMArch { - bits<5> ft; - bits<5> fs; - bits<5> fd; - bits<5> fr; - - bits<32> Inst; - - let Inst{31-26} = 0x15; - let Inst{25-21} = ft; - let Inst{20-16} = fs; - let Inst{15-11} = fd; - let Inst{10-6} = fr; - let Inst{5-0} = funct; -} - -class COMPACT_BRANCH_FM_MM<bits<5> funct> { - bits<5> rs; - bits<16> offset; - - bits<32> Inst; - - let Inst{31-26} = 0x10; - let Inst{25-21} = funct; - let Inst{20-16} = rs; - let Inst{15-0} = offset; -} - -class COP0_TLB_FM_MM<bits<10> op> : MMArch { - bits<32> Inst; - - let Inst{31-26} = 0x0; - let Inst{25-16} = 0x0; - let Inst{15-6} = op; - let Inst{5-0} = 0x3c; -} - -class SDBBP_FM_MM : MMArch { - bits<10> code_; - - bits<32> Inst; - - let Inst{31-26} = 0x0; - let Inst{25-16} = code_; - let Inst{15-6} = 0x36d; - let Inst{5-0} = 0x3c; -} - -class SIGRIE_FM_MM : MMArch { - bits<16> code_; - - bits<32> Inst; - - let Inst{31-26} = 0x0; - let Inst{25-22} = 0x0; - let Inst{21-6} = code_; - let Inst{5-0} = 0b111111; -} - -class RDHWR_FM_MM : MMArch { - bits<5> rt; - bits<5> rd; - - bits<32> Inst; - - let Inst{31-26} = 0x0; - let Inst{25-21} = rt; - let Inst{20-16} = rd; - let Inst{15-6} = 0x1ac; - let Inst{5-0} = 0x3c; -} - -class LWXS_FM_MM<bits<10> funct> { - bits<5> rd; - bits<5> base; - bits<5> index; - - bits<32> Inst; - - let Inst{31-26} = 0x0; - let Inst{25-21} = index; - let Inst{20-16} = base; - let Inst{15-11} = rd; - let Inst{10} = 0; - let Inst{9-0} = funct; -} - -class LWM_FM_MM<bits<4> funct> : MMArch { - bits<5> rt; - bits<21> addr; - - bits<32> Inst; - - let Inst{31-26} = 0x8; - let Inst{25-21} = rt; - let Inst{20-16} = addr{20-16}; - let Inst{15-12} = funct; - let Inst{11-0} = addr{11-0}; -} - -class LWM_FM_MM16<bits<4> funct> : MMArch { - bits<2> rt; - bits<4> addr; - - bits<16> Inst; - - let Inst{15-10} = 0x11; - let Inst{9-6} = funct; - let Inst{5-4} = rt; - let Inst{3-0} = addr; -} - -class CACHE_PREF_FM_MM<bits<6> op, bits<4> funct> : MMArch { - bits<21> addr; - bits<5> hint; - bits<5> base = addr{20-16}; - bits<12> offset = addr{11-0}; - - bits<32> Inst; - - let Inst{31-26} = op; - let Inst{25-21} = hint; - let Inst{20-16} = base; - let Inst{15-12} = funct; - let Inst{11-0} = offset; -} - -class CACHE_PREFE_FM_MM<bits<6> op, bits<3> funct> : MMArch { - bits<21> addr; - bits<5> hint; - bits<5> base = addr{20-16}; - bits<9> offset = addr{8-0}; - - bits<32> Inst; - - let Inst{31-26} = op; - let Inst{25-21} = hint; - let Inst{20-16} = base; - let Inst{15-12} = 0xA; - let Inst{11-9} = funct; - let Inst{8-0} = offset; -} - -class POOL32F_PREFX_FM_MM<bits<6> op, bits<9> funct> : MMArch { - bits<5> index; - bits<5> base; - bits<5> hint; - - bits<32> Inst; - - let Inst{31-26} = op; - let Inst{25-21} = index; - let Inst{20-16} = base; - let Inst{15-11} = hint; - let Inst{10-9} = 0x0; - let Inst{8-0} = funct; -} - -class BARRIER_FM_MM<bits<5> op> : MMArch { - bits<32> Inst; - - let Inst{31-26} = 0x0; - let Inst{25-21} = 0x0; - let Inst{20-16} = 0x0; - let Inst{15-11} = op; - let Inst{10-6} = 0x0; - let Inst{5-0} = 0x0; -} - -class ADDIUPC_FM_MM { - bits<3> rs; - bits<23> imm; - - bits<32> Inst; - - let Inst{31-26} = 0x1e; - let Inst{25-23} = rs; - let Inst{22-0} = imm; -} - -class POOL32A_CFTC2_FM_MM<bits<10> funct> : MMArch { - bits<5> rt; - bits<5> impl; - - bits<32> Inst; - - let Inst{31-26} = 0b000000; - let Inst{25-21} = rt; - let Inst{20-16} = impl; - let Inst{15-6} = funct; - let Inst{5-0} = 0b111100; -} - -class POOL32A_TLBINV_FM_MM<bits<10> funct> : MMArch { - bits<32> Inst; - - let Inst{31-26} = 0x0; - let Inst{25-16} = 0x0; - let Inst{15-6} = funct; - let Inst{5-0} = 0b111100; -} - -class POOL32A_MFTC0_FM_MM<bits<5> funct, bits<6> opcode> : MMArch { - bits<5> rt; - bits<5> rs; - bits<3> sel; - - bits<32> Inst; - - let Inst{31-26} = 0b000000; - let Inst{25-21} = rt; - let Inst{20-16} = rs; - let Inst{15-14} = 0; - let Inst{13-11} = sel; - let Inst{10-6} = funct; - let Inst{5-0} = opcode; -} - -class POOL32A_HYPCALL_FM_MM : MMArch { - bits<32> Inst; - - bits<10> code_; - - let Inst{31-26} = 0x0; - let Inst{25-16} = code_; - let Inst{15-6} = 0b1100001101; - let Inst{5-0} = 0b111100; -} diff --git a/contrib/llvm/lib/Target/Mips/MicroMipsInstrInfo.td b/contrib/llvm/lib/Target/Mips/MicroMipsInstrInfo.td deleted file mode 100644 index 9b7f7b25fa94..000000000000 --- a/contrib/llvm/lib/Target/Mips/MicroMipsInstrInfo.td +++ /dev/null @@ -1,1453 +0,0 @@ -//===--- MicroMipsInstrFormats.td - microMIPS Inst Defs -*- tablegen -*----===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This files describes the defintions of the microMIPSr3 instructions. -// -//===----------------------------------------------------------------------===// - -def addrimm11 : ComplexPattern<iPTR, 2, "selectIntAddr11MM", [frameindex]>; -def addrimm12 : ComplexPattern<iPTR, 2, "selectIntAddr12MM", [frameindex]>; -def addrimm16 : ComplexPattern<iPTR, 2, "selectIntAddr16MM", [frameindex]>; -def addrimm4lsl2 : ComplexPattern<iPTR, 2, "selectIntAddrLSL2MM", [frameindex]>; - -def simm9_addiusp : Operand<i32> { - let EncoderMethod = "getSImm9AddiuspValue"; - let DecoderMethod = "DecodeSimm9SP"; -} - -def uimm3_shift : Operand<i32> { - let EncoderMethod = "getUImm3Mod8Encoding"; - let DecoderMethod = "DecodePOOL16BEncodedField"; -} - -def simm3_lsa2 : Operand<i32> { - let EncoderMethod = "getSImm3Lsa2Value"; - let DecoderMethod = "DecodeAddiur2Simm7"; -} - -def uimm4_andi : Operand<i32> { - let EncoderMethod = "getUImm4AndValue"; - let DecoderMethod = "DecodeANDI16Imm"; -} - -def immSExtAddiur2 : ImmLeaf<i32, [{return Imm == 1 || Imm == -1 || - ((Imm % 4 == 0) && - Imm < 28 && Imm > 0);}]>; - -def immSExtAddius5 : ImmLeaf<i32, [{return Imm >= -8 && Imm <= 7;}]>; - -def immZExtAndi16 : ImmLeaf<i32, - [{return (Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 || - Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 || - Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535 );}]>; - -def immZExt2Shift : ImmLeaf<i32, [{return Imm >= 1 && Imm <= 8;}]>; - -def immLi16 : ImmLeaf<i32, [{return Imm >= -1 && Imm <= 126;}]>; - -def MicroMipsMemGPRMM16AsmOperand : AsmOperandClass { - let Name = "MicroMipsMem"; - let RenderMethod = "addMicroMipsMemOperands"; - let ParserMethod = "parseMemOperand"; - let PredicateMethod = "isMemWithGRPMM16Base"; -} - -// Define the classes of pointers used by microMIPS. -// The numbers must match those in MipsRegisterInfo::MipsPtrClass. -def ptr_gpr16mm_rc : PointerLikeRegClass<1>; -def ptr_sp_rc : PointerLikeRegClass<2>; -def ptr_gp_rc : PointerLikeRegClass<3>; - -class mem_mm_4_generic : Operand<i32> { - let PrintMethod = "printMemOperand"; - let MIOperandInfo = (ops ptr_gpr16mm_rc, simm4); - let OperandType = "OPERAND_MEMORY"; - let ParserMatchClass = MicroMipsMemGPRMM16AsmOperand; -} - -def mem_mm_4 : mem_mm_4_generic { - let EncoderMethod = "getMemEncodingMMImm4"; -} - -def mem_mm_4_lsl1 : mem_mm_4_generic { - let EncoderMethod = "getMemEncodingMMImm4Lsl1"; -} - -def mem_mm_4_lsl2 : mem_mm_4_generic { - let EncoderMethod = "getMemEncodingMMImm4Lsl2"; -} - -def MicroMipsMemSPAsmOperand : AsmOperandClass { - let Name = "MicroMipsMemSP"; - let RenderMethod = "addMemOperands"; - let ParserMethod = "parseMemOperand"; - let PredicateMethod = "isMemWithUimmWordAlignedOffsetSP<7>"; -} - -def MicroMipsMemGPAsmOperand : AsmOperandClass { - let Name = "MicroMipsMemGP"; - let RenderMethod = "addMemOperands"; - let ParserMethod = "parseMemOperand"; - let PredicateMethod = "isMemWithSimmWordAlignedOffsetGP<9>"; -} - -def mem_mm_sp_imm5_lsl2 : Operand<i32> { - let PrintMethod = "printMemOperand"; - let MIOperandInfo = (ops ptr_sp_rc:$base, simm5:$offset); - let OperandType = "OPERAND_MEMORY"; - let ParserMatchClass = MicroMipsMemSPAsmOperand; - let EncoderMethod = "getMemEncodingMMSPImm5Lsl2"; -} - -def mem_mm_gp_simm7_lsl2 : Operand<i32> { - let PrintMethod = "printMemOperand"; - let MIOperandInfo = (ops ptr_gp_rc:$base, simm7_lsl2:$offset); - let OperandType = "OPERAND_MEMORY"; - let ParserMatchClass = MicroMipsMemGPAsmOperand; - let EncoderMethod = "getMemEncodingMMGPImm7Lsl2"; -} - -def mem_mm_9 : Operand<i32> { - let PrintMethod = "printMemOperand"; - let MIOperandInfo = (ops ptr_rc, simm9); - let EncoderMethod = "getMemEncodingMMImm9"; - let ParserMatchClass = MipsMemSimm9AsmOperand; - let OperandType = "OPERAND_MEMORY"; -} - -def mem_mm_11 : Operand<i32> { - let PrintMethod = "printMemOperand"; - let MIOperandInfo = (ops GPR32, simm11); - let EncoderMethod = "getMemEncodingMMImm11"; - let ParserMatchClass = MipsMemSimm11AsmOperand; - let OperandType = "OPERAND_MEMORY"; -} - -def mem_mm_12 : Operand<i32> { - let PrintMethod = "printMemOperand"; - let MIOperandInfo = (ops ptr_rc, simm12); - let EncoderMethod = "getMemEncodingMMImm12"; - let ParserMatchClass = MipsMemAsmOperand; - let OperandType = "OPERAND_MEMORY"; -} - -def mem_mm_16 : Operand<i32> { - let PrintMethod = "printMemOperand"; - let MIOperandInfo = (ops ptr_rc, simm16); - let EncoderMethod = "getMemEncodingMMImm16"; - let DecoderMethod = "DecodeMemMMImm16"; - let ParserMatchClass = MipsMemSimm16AsmOperand; - let OperandType = "OPERAND_MEMORY"; -} - -def MipsMemUimm4AsmOperand : AsmOperandClass { - let Name = "MemOffsetUimm4"; - let SuperClasses = [MipsMemAsmOperand]; - let RenderMethod = "addMemOperands"; - let ParserMethod = "parseMemOperand"; - let PredicateMethod = "isMemWithUimmOffsetSP<6>"; -} - -def mem_mm_4sp : Operand<i32> { - let PrintMethod = "printMemOperand"; - let MIOperandInfo = (ops ptr_sp_rc, uimm8); - let EncoderMethod = "getMemEncodingMMImm4sp"; - let ParserMatchClass = MipsMemUimm4AsmOperand; - let OperandType = "OPERAND_MEMORY"; -} - -def jmptarget_mm : Operand<OtherVT> { - let EncoderMethod = "getJumpTargetOpValueMM"; -} - -def calltarget_mm : Operand<iPTR> { - let EncoderMethod = "getJumpTargetOpValueMM"; -} - -def brtarget7_mm : Operand<OtherVT> { - let EncoderMethod = "getBranchTarget7OpValueMM"; - let OperandType = "OPERAND_PCREL"; - let DecoderMethod = "DecodeBranchTarget7MM"; - let ParserMatchClass = MipsJumpTargetAsmOperand; -} - -def brtarget10_mm : Operand<OtherVT> { - let EncoderMethod = "getBranchTargetOpValueMMPC10"; - let OperandType = "OPERAND_PCREL"; - let DecoderMethod = "DecodeBranchTarget10MM"; - let ParserMatchClass = MipsJumpTargetAsmOperand; -} - -def brtarget_mm : Operand<OtherVT> { - let EncoderMethod = "getBranchTargetOpValueMM"; - let OperandType = "OPERAND_PCREL"; - let DecoderMethod = "DecodeBranchTargetMM"; - let ParserMatchClass = MipsJumpTargetAsmOperand; -} - -def simm23_lsl2 : Operand<i32> { - let EncoderMethod = "getSimm23Lsl2Encoding"; - let DecoderMethod = "DecodeSimm23Lsl2"; -} - -class CompactBranchMM<string opstr, DAGOperand opnd, PatFrag cond_op, - RegisterOperand RO> : - InstSE<(outs), (ins RO:$rs, opnd:$offset), - !strconcat(opstr, "\t$rs, $offset"), [], II_BCCZC, FrmI> { - let isBranch = 1; - let isTerminator = 1; - let hasDelaySlot = 0; - let Defs = [AT]; -} - -let canFoldAsLoad = 1 in -class LoadLeftRightMM<string opstr, SDNode OpNode, RegisterOperand RO, - Operand MemOpnd, InstrItinClass Itin> : - InstSE<(outs RO:$rt), (ins MemOpnd:$addr, RO:$src), - !strconcat(opstr, "\t$rt, $addr"), - [(set RO:$rt, (OpNode addrimm12:$addr, RO:$src))], - Itin, FrmI> { - let DecoderMethod = "DecodeMemMMImm12"; - string Constraints = "$src = $rt"; - let BaseOpcode = opstr; - bit mayLoad = 1; - bit mayStore = 0; -} - -class StoreLeftRightMM<string opstr, SDNode OpNode, RegisterOperand RO, - Operand MemOpnd, InstrItinClass Itin>: - InstSE<(outs), (ins RO:$rt, MemOpnd:$addr), - !strconcat(opstr, "\t$rt, $addr"), - [(OpNode RO:$rt, addrimm12:$addr)], Itin, FrmI> { - let DecoderMethod = "DecodeMemMMImm12"; - let BaseOpcode = opstr; - bit mayLoad = 0; - bit mayStore = 1; -} - -class MovePMM16<string opstr, RegisterOperand RO1, RegisterOperand RO2, - RegisterOperand RO3> : -MicroMipsInst16<(outs RO1:$rd1, RO2:$rd2), (ins RO3:$rs, RO3:$rt), - !strconcat(opstr, "\t$rd1, $rd2, $rs, $rt"), [], - NoItinerary, FrmR> { - let isReMaterializable = 1; - let isMoveReg = 1; - let DecoderMethod = "DecodeMovePOperands"; -} - -class StorePairMM<string opstr, ComplexPattern Addr = addr> - : InstSE<(outs), (ins GPR32Opnd:$rt, GPR32Opnd:$rt2, mem_simm12:$addr), - !strconcat(opstr, "\t$rt, $addr"), [], II_SWP, FrmI, opstr> { - let DecoderMethod = "DecodeMemMMImm12"; - let mayStore = 1; - let AsmMatchConverter = "ConvertXWPOperands"; -} - -class LoadPairMM<string opstr, ComplexPattern Addr = addr> - : InstSE<(outs GPR32Opnd:$rt, GPR32Opnd:$rt2), (ins mem_simm12:$addr), - !strconcat(opstr, "\t$rt, $addr"), [], II_LWP, FrmI, opstr> { - let DecoderMethod = "DecodeMemMMImm12"; - let mayLoad = 1; - let AsmMatchConverter = "ConvertXWPOperands"; -} - -class LLBaseMM<string opstr, RegisterOperand RO> : - InstSE<(outs RO:$rt), (ins mem_mm_12:$addr), - !strconcat(opstr, "\t$rt, $addr"), [], II_LL, FrmI> { - let DecoderMethod = "DecodeMemMMImm12"; - let mayLoad = 1; -} - -class LLEBaseMM<string opstr, RegisterOperand RO> : - InstSE<(outs RO:$rt), (ins mem_simm9:$addr), - !strconcat(opstr, "\t$rt, $addr"), [], II_LLE, FrmI> { - let DecoderMethod = "DecodeMemMMImm9"; - string BaseOpcode = opstr; - let mayLoad = 1; -} - -class SCBaseMM<string opstr, RegisterOperand RO> : - InstSE<(outs RO:$dst), (ins RO:$rt, mem_mm_12:$addr), - !strconcat(opstr, "\t$rt, $addr"), [], II_SC, FrmI> { - let DecoderMethod = "DecodeMemMMImm12"; - let mayStore = 1; - let Constraints = "$rt = $dst"; -} - -class SCEBaseMM<string opstr, RegisterOperand RO> : - InstSE<(outs RO:$dst), (ins RO:$rt, mem_simm9:$addr), - !strconcat(opstr, "\t$rt, $addr"), [], II_SCE, FrmI> { - let DecoderMethod = "DecodeMemMMImm9"; - string BaseOpcode = opstr; - let mayStore = 1; - let Constraints = "$rt = $dst"; -} - -class LoadMM<string opstr, DAGOperand RO, SDPatternOperator OpNode = null_frag, - InstrItinClass Itin = NoItinerary, DAGOperand MO = mem_mm_12> : - InstSE<(outs RO:$rt), (ins MO:$addr), - !strconcat(opstr, "\t$rt, $addr"), - [(set RO:$rt, (OpNode addrimm12:$addr))], Itin, FrmI, opstr> { - let DecoderMethod = "DecodeMemMMImm12"; - let canFoldAsLoad = 1; - let mayLoad = 1; -} - -class ArithRMM16<string opstr, RegisterOperand RO, bit isComm = 0, - InstrItinClass Itin = NoItinerary, - SDPatternOperator OpNode = null_frag> : - MicroMipsInst16<(outs RO:$rd), (ins RO:$rs, RO:$rt), - !strconcat(opstr, "\t$rd, $rs, $rt"), - [(set RO:$rd, (OpNode RO:$rs, RO:$rt))], Itin, FrmR> { - let isCommutable = isComm; -} - -class AndImmMM16<string opstr, RegisterOperand RO, - InstrItinClass Itin = NoItinerary> : - MicroMipsInst16<(outs RO:$rd), (ins RO:$rs, uimm4_andi:$imm), - !strconcat(opstr, "\t$rd, $rs, $imm"), [], Itin, FrmI>; - -class LogicRMM16<string opstr, RegisterOperand RO, - InstrItinClass Itin = NoItinerary, - SDPatternOperator OpNode = null_frag> : - MicroMipsInst16<(outs RO:$dst), (ins RO:$rs, RO:$rt), - !strconcat(opstr, "\t$rt, $rs"), - [(set RO:$dst, (OpNode RO:$rs, RO:$rt))], Itin, FrmR> { - let isCommutable = 1; - let Constraints = "$rt = $dst"; -} - -class NotMM16<string opstr, RegisterOperand RO> : - MicroMipsInst16<(outs RO:$rt), (ins RO:$rs), - !strconcat(opstr, "\t$rt, $rs"), - [(set RO:$rt, (not RO:$rs))], II_NOT, FrmR>; - -class ShiftIMM16<string opstr, Operand ImmOpnd, RegisterOperand RO, - InstrItinClass Itin = NoItinerary> : - MicroMipsInst16<(outs RO:$rd), (ins RO:$rt, ImmOpnd:$shamt), - !strconcat(opstr, "\t$rd, $rt, $shamt"), [], Itin, FrmR>; - -class LoadMM16<string opstr, DAGOperand RO, SDPatternOperator OpNode, - InstrItinClass Itin, Operand MemOpnd> : - MicroMipsInst16<(outs RO:$rt), (ins MemOpnd:$addr), - !strconcat(opstr, "\t$rt, $addr"), [], Itin, FrmI> { - let DecoderMethod = "DecodeMemMMImm4"; - let canFoldAsLoad = 1; - let mayLoad = 1; -} - -class StoreMM16<string opstr, DAGOperand RTOpnd, DAGOperand RO, - SDPatternOperator OpNode, InstrItinClass Itin, - Operand MemOpnd> : - MicroMipsInst16<(outs), (ins RTOpnd:$rt, MemOpnd:$addr), - !strconcat(opstr, "\t$rt, $addr"), [], Itin, FrmI> { - let DecoderMethod = "DecodeMemMMImm4"; - let mayStore = 1; -} - -class LoadSPMM16<string opstr, DAGOperand RO, InstrItinClass Itin, - Operand MemOpnd> : - MicroMipsInst16<(outs RO:$rt), (ins MemOpnd:$offset), - !strconcat(opstr, "\t$rt, $offset"), [], Itin, FrmI> { - let DecoderMethod = "DecodeMemMMSPImm5Lsl2"; - let canFoldAsLoad = 1; - let mayLoad = 1; -} - -class StoreSPMM16<string opstr, DAGOperand RO, InstrItinClass Itin, - Operand MemOpnd> : - MicroMipsInst16<(outs), (ins RO:$rt, MemOpnd:$offset), - !strconcat(opstr, "\t$rt, $offset"), [], Itin, FrmI> { - let DecoderMethod = "DecodeMemMMSPImm5Lsl2"; - let mayStore = 1; -} - -class LoadGPMM16<string opstr, DAGOperand RO, InstrItinClass Itin, - Operand MemOpnd> : - MicroMipsInst16<(outs RO:$rt), (ins MemOpnd:$offset), - !strconcat(opstr, "\t$rt, $offset"), [], Itin, FrmI> { - let DecoderMethod = "DecodeMemMMGPImm7Lsl2"; - let canFoldAsLoad = 1; - let mayLoad = 1; -} - -class AddImmUR2<string opstr, RegisterOperand RO> : - MicroMipsInst16<(outs RO:$rd), (ins RO:$rs, simm3_lsa2:$imm), - !strconcat(opstr, "\t$rd, $rs, $imm"), - [], II_ADDIU, FrmR> { - let isCommutable = 1; -} - -class AddImmUS5<string opstr, RegisterOperand RO> : - MicroMipsInst16<(outs RO:$dst), (ins RO:$rd, simm4:$imm), - !strconcat(opstr, "\t$rd, $imm"), [], II_ADDIU, FrmR> { - let Constraints = "$rd = $dst"; -} - -class AddImmUR1SP<string opstr, RegisterOperand RO> : - MicroMipsInst16<(outs RO:$rd), (ins uimm6_lsl2:$imm), - !strconcat(opstr, "\t$rd, $imm"), [], II_ADDIU, FrmR>; - -class AddImmUSP<string opstr> : - MicroMipsInst16<(outs), (ins simm9_addiusp:$imm), - !strconcat(opstr, "\t$imm"), [], II_ADDIU, FrmI>; - -class MoveFromHILOMM<string opstr, RegisterOperand RO, Register UseReg> : - MicroMipsInst16<(outs RO:$rd), (ins), !strconcat(opstr, "\t$rd"), - [], II_MFHI_MFLO, FrmR> { - let Uses = [UseReg]; - let hasSideEffects = 0; - let isMoveReg = 1; -} - -class MoveMM16<string opstr, RegisterOperand RO> - : MicroMipsInst16<(outs RO:$rd), (ins RO:$rs), - !strconcat(opstr, "\t$rd, $rs"), [], II_MOVE, FrmR> { - let isReMaterializable = 1; - let isMoveReg = 1; -} - -class LoadImmMM16<string opstr, Operand Od, RegisterOperand RO> : - MicroMipsInst16<(outs RO:$rd), (ins Od:$imm), - !strconcat(opstr, "\t$rd, $imm"), [], II_LI, FrmI> { - let isReMaterializable = 1; -} - -// 16-bit Jump and Link (Call) -class JumpLinkRegMM16<string opstr, RegisterOperand RO> : - MicroMipsInst16<(outs), (ins RO:$rs), !strconcat(opstr, "\t$rs"), - [(MipsJmpLink RO:$rs)], II_JALR, FrmR> { - let isCall = 1; - let hasDelaySlot = 1; - let Defs = [RA]; - let hasPostISelHook = 1; -} - -// 16-bit Jump Reg -class JumpRegMM16<string opstr, RegisterOperand RO> : - MicroMipsInst16<(outs), (ins RO:$rs), !strconcat(opstr, "\t$rs"), - [], II_JR, FrmR> { - let hasDelaySlot = 1; - let isBranch = 1; - let isIndirectBranch = 1; -} - -// Base class for JRADDIUSP instruction. -class JumpRAddiuStackMM16 : - MicroMipsInst16<(outs), (ins uimm5_lsl2:$imm), "jraddiusp\t$imm", - [], II_JRADDIUSP, FrmR> { - let isTerminator = 1; - let isBarrier = 1; - let isBranch = 1; - let isIndirectBranch = 1; -} - -// 16-bit Jump and Link (Call) - Short Delay Slot -class JumpLinkRegSMM16<string opstr, RegisterOperand RO> : - MicroMipsInst16<(outs), (ins RO:$rs), !strconcat(opstr, "\t$rs"), - [], II_JALRS, FrmR> { - let isCall = 1; - let hasDelaySlot = 1; - let Defs = [RA]; -} - -// 16-bit Jump Register Compact - No delay slot -class JumpRegCMM16<string opstr, RegisterOperand RO> : - MicroMipsInst16<(outs), (ins RO:$rs), !strconcat(opstr, "\t$rs"), - [], II_JRC, FrmR> { - let isTerminator = 1; - let isBarrier = 1; - let isBranch = 1; - let isIndirectBranch = 1; -} - -// Break16 and Sdbbp16 -class BrkSdbbp16MM<string opstr, InstrItinClass Itin> : - MicroMipsInst16<(outs), (ins uimm4:$code_), - !strconcat(opstr, "\t$code_"), - [], Itin, FrmOther>; - -class CBranchZeroMM<string opstr, DAGOperand opnd, RegisterOperand RO> : - MicroMipsInst16<(outs), (ins RO:$rs, opnd:$offset), - !strconcat(opstr, "\t$rs, $offset"), [], II_BCCZ, FrmI> { - let isBranch = 1; - let isTerminator = 1; - let hasDelaySlot = 1; - let Defs = [AT]; -} - -// MicroMIPS Jump and Link (Call) - Short Delay Slot -let isCall = 1, hasDelaySlot = 1, Defs = [RA] in { - class JumpLinkMM<string opstr, DAGOperand opnd> : - InstSE<(outs), (ins opnd:$target), !strconcat(opstr, "\t$target"), - [], II_JALS, FrmJ, opstr> { - let DecoderMethod = "DecodeJumpTargetMM"; - } - - class JumpLinkRegMM<string opstr, RegisterOperand RO>: - InstSE<(outs RO:$rd), (ins RO:$rs), !strconcat(opstr, "\t$rd, $rs"), - [], II_JALRS, FrmR>; - - class BranchCompareToZeroLinkMM<string opstr, DAGOperand opnd, - RegisterOperand RO> : - InstSE<(outs), (ins RO:$rs, opnd:$offset), - !strconcat(opstr, "\t$rs, $offset"), [], II_BCCZALS, FrmI, opstr>; -} - -class LoadWordIndexedScaledMM<string opstr, RegisterOperand RO, - SDPatternOperator OpNode = null_frag> : - InstSE<(outs RO:$rd), (ins PtrRC:$base, PtrRC:$index), - !strconcat(opstr, "\t$rd, ${index}(${base})"), [], II_LWXS, FrmFI>; - -class PrefetchIndexed<string opstr> : - InstSE<(outs), (ins PtrRC:$base, PtrRC:$index, uimm5:$hint), - !strconcat(opstr, "\t$hint, ${index}(${base})"), [], II_PREF, FrmOther>; - -class AddImmUPC<string opstr, RegisterOperand RO> : - InstSE<(outs RO:$rs), (ins simm23_lsl2:$imm), - !strconcat(opstr, "\t$rs, $imm"), [], II_ADDIU, FrmR>; - -/// A list of registers used by load/store multiple instructions. -def RegListAsmOperand : AsmOperandClass { - let Name = "RegList"; - let ParserMethod = "parseRegisterList"; -} - -def reglist : Operand<i32> { - let EncoderMethod = "getRegisterListOpValue"; - let ParserMatchClass = RegListAsmOperand; - let PrintMethod = "printRegisterList"; - let DecoderMethod = "DecodeRegListOperand"; -} - -def RegList16AsmOperand : AsmOperandClass { - let Name = "RegList16"; - let ParserMethod = "parseRegisterList"; - let PredicateMethod = "isRegList16"; - let RenderMethod = "addRegListOperands"; -} - -def reglist16 : Operand<i32> { - let EncoderMethod = "getRegisterListOpValue16"; - let DecoderMethod = "DecodeRegListOperand16"; - let PrintMethod = "printRegisterList"; - let ParserMatchClass = RegList16AsmOperand; -} - -class StoreMultMM<string opstr, - InstrItinClass Itin = NoItinerary, ComplexPattern Addr = addr> : - InstSE<(outs), (ins reglist:$rt, mem_mm_12:$addr), - !strconcat(opstr, "\t$rt, $addr"), [], Itin, FrmI, opstr> { - let DecoderMethod = "DecodeMemMMImm12"; - let mayStore = 1; -} - -class LoadMultMM<string opstr, - InstrItinClass Itin = NoItinerary, ComplexPattern Addr = addr> : - InstSE<(outs reglist:$rt), (ins mem_mm_12:$addr), - !strconcat(opstr, "\t$rt, $addr"), [], Itin, FrmI, opstr> { - let DecoderMethod = "DecodeMemMMImm12"; - let mayLoad = 1; -} - -class StoreMultMM16<string opstr, - InstrItinClass Itin = NoItinerary, - ComplexPattern Addr = addr> : - MicroMipsInst16<(outs), (ins reglist16:$rt, mem_mm_4sp:$addr), - !strconcat(opstr, "\t$rt, $addr"), [], Itin, FrmI> { - let DecoderMethod = "DecodeMemMMReglistImm4Lsl2"; - let mayStore = 1; -} - -class LoadMultMM16<string opstr, - InstrItinClass Itin = NoItinerary, - ComplexPattern Addr = addr> : - MicroMipsInst16<(outs reglist16:$rt), (ins mem_mm_4sp:$addr), - !strconcat(opstr, "\t$rt, $addr"), [], Itin, FrmI> { - let DecoderMethod = "DecodeMemMMReglistImm4Lsl2"; - let mayLoad = 1; -} - -class UncondBranchMM16<string opstr> : - MicroMipsInst16<(outs), (ins brtarget10_mm:$offset), - !strconcat(opstr, "\t$offset"), - [], II_B, FrmI> { - let isBranch = 1; - let isTerminator = 1; - let isBarrier = 1; - let hasDelaySlot = 1; - let Predicates = [RelocPIC, InMicroMips]; - let Defs = [AT]; -} - -class HypcallMM<string opstr> : - InstSE<(outs), (ins uimm10:$code_), - !strconcat(opstr, "\t$code_"), [], II_HYPCALL, FrmOther> { - let BaseOpcode = opstr; -} - -class TLBINVMM<string opstr, InstrItinClass Itin> : - InstSE<(outs), (ins), opstr, [], Itin, FrmOther> { - let BaseOpcode = opstr; -} - -class MfCop0MM<string opstr, RegisterOperand DstRC, - RegisterOperand SrcRC, InstrItinClass Itin> : - InstSE<(outs DstRC:$rt), (ins SrcRC:$rs, uimm3:$sel), - !strconcat(opstr, "\t$rt, $rs, $sel"), [], Itin, FrmR> { - let BaseOpcode = opstr; -} - -class MtCop0MM<string opstr, RegisterOperand DstRC, - RegisterOperand SrcRC, InstrItinClass Itin> : - InstSE<(outs DstRC:$rs), (ins SrcRC:$rt, uimm3:$sel), - !strconcat(opstr, "\t$rt, $rs, $sel"), [], Itin, FrmR> { - let BaseOpcode = opstr; -} - -let FastISelShouldIgnore = 1 in { - def ADDU16_MM : ArithRMM16<"addu16", GPRMM16Opnd, 1, II_ADDU, add>, - ARITH_FM_MM16<0>, ISA_MICROMIPS32_NOT_MIPS32R6; - def AND16_MM : LogicRMM16<"and16", GPRMM16Opnd, II_AND, and>, - LOGIC_FM_MM16<0x2>, ISA_MICROMIPS32_NOT_MIPS32R6; -} - -def ANDI16_MM : AndImmMM16<"andi16", GPRMM16Opnd, II_AND>, ANDI_FM_MM16<0x0b>, - ISA_MICROMIPS32_NOT_MIPS32R6; -def NOT16_MM : NotMM16<"not16", GPRMM16Opnd>, LOGIC_FM_MM16<0x0>, - ISA_MICROMIPS32_NOT_MIPS32R6; -let FastISelShouldIgnore = 1 in - def OR16_MM : LogicRMM16<"or16", GPRMM16Opnd, II_OR, or>, LOGIC_FM_MM16<0x3>, - ISA_MICROMIPS32_NOT_MIPS32R6; -def SLL16_MM : ShiftIMM16<"sll16", uimm3_shift, GPRMM16Opnd, II_SLL>, - SHIFT_FM_MM16<0>, ISA_MICROMIPS32_NOT_MIPS32R6; -def SRL16_MM : ShiftIMM16<"srl16", uimm3_shift, GPRMM16Opnd, II_SRL>, - SHIFT_FM_MM16<1>, ISA_MICROMIPS32_NOT_MIPS32R6; - -let FastISelShouldIgnore = 1 in { - def SUBU16_MM : ArithRMM16<"subu16", GPRMM16Opnd, 0, II_SUBU, sub>, - ARITH_FM_MM16<1>, ISA_MICROMIPS32_NOT_MIPS32R6; - def XOR16_MM : LogicRMM16<"xor16", GPRMM16Opnd, II_XOR, xor>, - LOGIC_FM_MM16<0x1>, ISA_MICROMIPS32_NOT_MIPS32R6; -} -def LBU16_MM : LoadMM16<"lbu16", GPRMM16Opnd, zextloadi8, II_LBU, - mem_mm_4>, LOAD_STORE_FM_MM16<0x02>, ISA_MICROMIPS; -def LHU16_MM : LoadMM16<"lhu16", GPRMM16Opnd, zextloadi16, II_LHU, - mem_mm_4_lsl1>, LOAD_STORE_FM_MM16<0x0a>, ISA_MICROMIPS; -def LW16_MM : LoadMM16<"lw16", GPRMM16Opnd, load, II_LW, mem_mm_4_lsl2>, - LOAD_STORE_FM_MM16<0x1a>, ISA_MICROMIPS; -def SB16_MM : StoreMM16<"sb16", GPRMM16OpndZero, GPRMM16Opnd, truncstorei8, - II_SB, mem_mm_4>, LOAD_STORE_FM_MM16<0x22>, - ISA_MICROMIPS32_NOT_MIPS32R6; -def SH16_MM : StoreMM16<"sh16", GPRMM16OpndZero, GPRMM16Opnd, truncstorei16, - II_SH, mem_mm_4_lsl1>, - LOAD_STORE_FM_MM16<0x2a>, ISA_MICROMIPS32_NOT_MIPS32R6; -def SW16_MM : StoreMM16<"sw16", GPRMM16OpndZero, GPRMM16Opnd, store, II_SW, - mem_mm_4_lsl2>, LOAD_STORE_FM_MM16<0x3a>, - ISA_MICROMIPS32_NOT_MIPS32R6; -def LWGP_MM : LoadGPMM16<"lw", GPRMM16Opnd, II_LW, mem_mm_gp_simm7_lsl2>, - LOAD_GP_FM_MM16<0x19>, ISA_MICROMIPS; -def LWSP_MM : LoadSPMM16<"lw", GPR32Opnd, II_LW, mem_mm_sp_imm5_lsl2>, - LOAD_STORE_SP_FM_MM16<0x12>, ISA_MICROMIPS; -def SWSP_MM : StoreSPMM16<"swsp", GPR32Opnd, II_SW, mem_mm_sp_imm5_lsl2>, - LOAD_STORE_SP_FM_MM16<0x32>, ISA_MICROMIPS32_NOT_MIPS32R6; -def ADDIUR1SP_MM : AddImmUR1SP<"addiur1sp", GPRMM16Opnd>, ADDIUR1SP_FM_MM16, - ISA_MICROMIPS; -def ADDIUR2_MM : AddImmUR2<"addiur2", GPRMM16Opnd>, ADDIUR2_FM_MM16, - ISA_MICROMIPS; -def ADDIUS5_MM : AddImmUS5<"addius5", GPR32Opnd>, ADDIUS5_FM_MM16, - ISA_MICROMIPS; -def ADDIUSP_MM : AddImmUSP<"addiusp">, ADDIUSP_FM_MM16, ISA_MICROMIPS; -def MFHI16_MM : MoveFromHILOMM<"mfhi16", GPR32Opnd, AC0>, - MFHILO_FM_MM16<0x10>, ISA_MICROMIPS32_NOT_MIPS32R6; -def MFLO16_MM : MoveFromHILOMM<"mflo16", GPR32Opnd, AC0>, - MFHILO_FM_MM16<0x12>, ISA_MICROMIPS32_NOT_MIPS32R6; -def MOVE16_MM : MoveMM16<"move", GPR32Opnd>, MOVE_FM_MM16<0x03>, - ISA_MICROMIPS32_NOT_MIPS32R6; -def MOVEP_MM : MovePMM16<"movep", GPRMM16OpndMovePPairFirst, - GPRMM16OpndMovePPairSecond, GPRMM16OpndMoveP>, - MOVEP_FM_MM16, ISA_MICROMIPS32_NOT_MIPS32R6; -def LI16_MM : LoadImmMM16<"li16", li16_imm, GPRMM16Opnd>, LI_FM_MM16, - IsAsCheapAsAMove, ISA_MICROMIPS32_NOT_MIPS32R6; -def JALR16_MM : JumpLinkRegMM16<"jalr", GPR32Opnd>, JALR_FM_MM16<0x0e>, - ISA_MICROMIPS32_NOT_MIPS32R6; -def JALRS16_MM : JumpLinkRegSMM16<"jalrs16", GPR32Opnd>, JALR_FM_MM16<0x0f>, - ISA_MICROMIPS32_NOT_MIPS32R6; -def JRC16_MM : JumpRegCMM16<"jrc", GPR32Opnd>, JALR_FM_MM16<0x0d>, - ISA_MICROMIPS32_NOT_MIPS32R6; -def JRADDIUSP : JumpRAddiuStackMM16, JRADDIUSP_FM_MM16<0x18>, - ISA_MICROMIPS32_NOT_MIPS32R6; -def JR16_MM : JumpRegMM16<"jr16", GPR32Opnd>, JALR_FM_MM16<0x0c>, - ISA_MICROMIPS32_NOT_MIPS32R6; -def BEQZ16_MM : CBranchZeroMM<"beqz16", brtarget7_mm, GPRMM16Opnd>, - BEQNEZ_FM_MM16<0x23>, ISA_MICROMIPS32_NOT_MIPS32R6; -def BNEZ16_MM : CBranchZeroMM<"bnez16", brtarget7_mm, GPRMM16Opnd>, - BEQNEZ_FM_MM16<0x2b>, ISA_MICROMIPS32_NOT_MIPS32R6; -def B16_MM : UncondBranchMM16<"b16">, B16_FM, ISA_MICROMIPS32_NOT_MIPS32R6; -def BREAK16_MM : BrkSdbbp16MM<"break16", II_BREAK>, BRKSDBBP16_FM_MM<0x28>, - ISA_MICROMIPS32_NOT_MIPS32R6; -def SDBBP16_MM : BrkSdbbp16MM<"sdbbp16", II_SDBBP>, BRKSDBBP16_FM_MM<0x2C>, - ISA_MICROMIPS32_NOT_MIPS32R6; - -class WaitMM<string opstr> : - InstSE<(outs), (ins uimm10:$code_), !strconcat(opstr, "\t$code_"), [], - II_WAIT, FrmOther, opstr>; - -let DecoderNamespace = "MicroMips" in { - /// Load and Store Instructions - multiple - def SWM16_MM : StoreMultMM16<"swm16", II_SWM>, LWM_FM_MM16<0x5>, - ISA_MICROMIPS32_NOT_MIPS32R6; - def LWM16_MM : LoadMultMM16<"lwm16", II_LWM>, LWM_FM_MM16<0x4>, - ISA_MICROMIPS32_NOT_MIPS32R6; - def CFC2_MM : InstSE<(outs GPR32Opnd:$rt), (ins COP2Opnd:$impl), - "cfc2\t$rt, $impl", [], II_CFC2, FrmFR, "cfc2">, - POOL32A_CFTC2_FM_MM<0b1100110100>, ISA_MICROMIPS; - def CTC2_MM : InstSE<(outs COP2Opnd:$impl), (ins GPR32Opnd:$rt), - "ctc2\t$rt, $impl", [], II_CTC2, FrmFR, "ctc2">, - POOL32A_CFTC2_FM_MM<0b1101110100>, ISA_MICROMIPS; - - /// Compact Branch Instructions - def BEQZC_MM : CompactBranchMM<"beqzc", brtarget_mm, seteq, GPR32Opnd>, - COMPACT_BRANCH_FM_MM<0x7>, ISA_MICROMIPS32_NOT_MIPS32R6; - def BNEZC_MM : CompactBranchMM<"bnezc", brtarget_mm, setne, GPR32Opnd>, - COMPACT_BRANCH_FM_MM<0x5>, ISA_MICROMIPS32_NOT_MIPS32R6; - - /// Arithmetic Instructions (ALU Immediate) - def ADDiu_MM : MMRel, ArithLogicI<"addiu", simm16, GPR32Opnd, II_ADDIU>, - ADDI_FM_MM<0xc>, ISA_MICROMIPS32_NOT_MIPS32R6; - def ADDi_MM : MMRel, ArithLogicI<"addi", simm16, GPR32Opnd, II_ADDI>, - ADDI_FM_MM<0x4>, ISA_MICROMIPS32_NOT_MIPS32R6; - def SLTi_MM : MMRel, SetCC_I<"slti", setlt, simm16, immSExt16, GPR32Opnd>, - SLTI_FM_MM<0x24>, ISA_MICROMIPS; - def SLTiu_MM : MMRel, SetCC_I<"sltiu", setult, simm16, immSExt16, GPR32Opnd>, - SLTI_FM_MM<0x2c>, ISA_MICROMIPS; - def ANDi_MM : MMRel, ArithLogicI<"andi", uimm16, GPR32Opnd, II_ANDI>, - ADDI_FM_MM<0x34>, ISA_MICROMIPS32_NOT_MIPS32R6; - def ORi_MM : MMRel, ArithLogicI<"ori", uimm16, GPR32Opnd, II_ORI, immZExt16, - or>, ADDI_FM_MM<0x14>, - ISA_MICROMIPS32_NOT_MIPS32R6; - def XORi_MM : MMRel, ArithLogicI<"xori", uimm16, GPR32Opnd, II_XORI, - immZExt16, xor>, ADDI_FM_MM<0x1c>, - ISA_MICROMIPS32_NOT_MIPS32R6; - def LUi_MM : MMRel, LoadUpper<"lui", GPR32Opnd, uimm16_relaxed>, LUI_FM_MM, - ISA_MICROMIPS32_NOT_MIPS32R6; - - def LEA_ADDiu_MM : MMRel, EffectiveAddress<"addiu", GPR32Opnd>, - LW_FM_MM<0xc>, ISA_MICROMIPS; - - /// Arithmetic Instructions (3-Operand, R-Type) - def ADDu_MM : MMRel, ArithLogicR<"addu", GPR32Opnd, 1, II_ADDU, add>, - ADD_FM_MM<0, 0x150>, ISA_MICROMIPS32_NOT_MIPS32R6; - def SUBu_MM : MMRel, ArithLogicR<"subu", GPR32Opnd, 0, II_SUBU, sub>, - ADD_FM_MM<0, 0x1d0>, ISA_MICROMIPS32_NOT_MIPS32R6; - let Defs = [HI0, LO0] in - def MUL_MM : MMRel, ArithLogicR<"mul", GPR32Opnd, 1, II_MUL, mul>, - ADD_FM_MM<0, 0x210>, ISA_MICROMIPS32_NOT_MIPS32R6; - def ADD_MM : MMRel, ArithLogicR<"add", GPR32Opnd, 1, II_ADD>, - ADD_FM_MM<0, 0x110>, ISA_MICROMIPS32_NOT_MIPS32R6; - def SUB_MM : MMRel, ArithLogicR<"sub", GPR32Opnd, 0, II_SUB>, - ADD_FM_MM<0, 0x190>, ISA_MICROMIPS32_NOT_MIPS32R6; - def SLT_MM : MMRel, SetCC_R<"slt", setlt, GPR32Opnd>, ADD_FM_MM<0, 0x350>, - ISA_MICROMIPS; - def SLTu_MM : MMRel, SetCC_R<"sltu", setult, GPR32Opnd>, - ADD_FM_MM<0, 0x390>, ISA_MICROMIPS; - def AND_MM : MMRel, ArithLogicR<"and", GPR32Opnd, 1, II_AND, and>, - ADD_FM_MM<0, 0x250>, ISA_MICROMIPS32_NOT_MIPS32R6; - def OR_MM : MMRel, ArithLogicR<"or", GPR32Opnd, 1, II_OR, or>, - ADD_FM_MM<0, 0x290>, ISA_MICROMIPS32_NOT_MIPS32R6; - def XOR_MM : MMRel, ArithLogicR<"xor", GPR32Opnd, 1, II_XOR, xor>, - ADD_FM_MM<0, 0x310>, ISA_MICROMIPS32_NOT_MIPS32R6; - def NOR_MM : MMRel, LogicNOR<"nor", GPR32Opnd>, ADD_FM_MM<0, 0x2d0>, - ISA_MICROMIPS32_NOT_MIPS32R6; - def MULT_MM : MMRel, Mult<"mult", II_MULT, GPR32Opnd, [HI0, LO0]>, - MULT_FM_MM<0x22c>, ISA_MICROMIPS32_NOT_MIPS32R6; - def MULTu_MM : MMRel, Mult<"multu", II_MULTU, GPR32Opnd, [HI0, LO0]>, - MULT_FM_MM<0x26c>, ISA_MICROMIPS32_NOT_MIPS32R6; - def SDIV_MM : MMRel, Div<"div", II_DIV, GPR32Opnd, [HI0, LO0]>, - MULT_FM_MM<0x2ac>, ISA_MICROMIPS32_NOT_MIPS32R6; - def UDIV_MM : MMRel, Div<"divu", II_DIVU, GPR32Opnd, [HI0, LO0]>, - MULT_FM_MM<0x2ec>, ISA_MICROMIPS32_NOT_MIPS32R6; - - /// Arithmetic Instructions with PC and Immediate - def ADDIUPC_MM : AddImmUPC<"addiupc", GPRMM16Opnd>, ADDIUPC_FM_MM, - ISA_MICROMIPS32_NOT_MIPS32R6; - - /// Shift Instructions - def SLL_MM : MMRel, shift_rotate_imm<"sll", uimm5, GPR32Opnd, II_SLL>, - SRA_FM_MM<0, 0>, ISA_MICROMIPS; - def SRL_MM : MMRel, shift_rotate_imm<"srl", uimm5, GPR32Opnd, II_SRL>, - SRA_FM_MM<0x40, 0>, ISA_MICROMIPS; - def SRA_MM : MMRel, shift_rotate_imm<"sra", uimm5, GPR32Opnd, II_SRA>, - SRA_FM_MM<0x80, 0>, ISA_MICROMIPS; - def SLLV_MM : MMRel, shift_rotate_reg<"sllv", GPR32Opnd, II_SLLV>, - SRLV_FM_MM<0x10, 0>, ISA_MICROMIPS; - def SRLV_MM : MMRel, shift_rotate_reg<"srlv", GPR32Opnd, II_SRLV>, - SRLV_FM_MM<0x50, 0>, ISA_MICROMIPS; - def SRAV_MM : MMRel, shift_rotate_reg<"srav", GPR32Opnd, II_SRAV>, - SRLV_FM_MM<0x90, 0>, ISA_MICROMIPS; - def ROTR_MM : MMRel, shift_rotate_imm<"rotr", uimm5, GPR32Opnd, II_ROTR>, - SRA_FM_MM<0xc0, 0>, ISA_MICROMIPS { - list<dag> Pattern = [(set GPR32Opnd:$rd, - (rotr GPR32Opnd:$rt, immZExt5:$shamt))]; - } - def ROTRV_MM : MMRel, shift_rotate_reg<"rotrv", GPR32Opnd, II_ROTRV>, - SRLV_FM_MM<0xd0, 0>, ISA_MICROMIPS { - list<dag> Pattern = [(set GPR32Opnd:$rd, - (rotr GPR32Opnd:$rt, GPR32Opnd:$rs))]; - } - - /// Load and Store Instructions - aligned - let DecoderMethod = "DecodeMemMMImm16" in { - def LB_MM : LoadMemory<"lb", GPR32Opnd, mem_mm_16, sextloadi8, II_LB>, - MMRel, LW_FM_MM<0x7>, ISA_MICROMIPS; - def LBu_MM : LoadMemory<"lbu", GPR32Opnd, mem_mm_16, zextloadi8, II_LBU>, - MMRel, LW_FM_MM<0x5>, ISA_MICROMIPS; - def LH_MM : LoadMemory<"lh", GPR32Opnd, mem_simmptr, sextloadi16, II_LH, - addrDefault>, MMRel, LW_FM_MM<0xf>, ISA_MICROMIPS; - def LHu_MM : LoadMemory<"lhu", GPR32Opnd, mem_simmptr, zextloadi16, II_LHU>, - MMRel, LW_FM_MM<0xd>, ISA_MICROMIPS; - def LW_MM : Load<"lw", GPR32Opnd, null_frag, II_LW>, MMRel, LW_FM_MM<0x3f>, - ISA_MICROMIPS; - def SB_MM : Store<"sb", GPR32Opnd, truncstorei8, II_SB>, MMRel, - LW_FM_MM<0x6>, ISA_MICROMIPS; - def SH_MM : Store<"sh", GPR32Opnd, truncstorei16, II_SH>, MMRel, - LW_FM_MM<0xe>, ISA_MICROMIPS; - def SW_MM : Store<"sw", GPR32Opnd, null_frag, II_SW>, MMRel, - LW_FM_MM<0x3e>, ISA_MICROMIPS; - } - - let DecoderMethod = "DecodeMemMMImm9" in { - def LBE_MM : MMRel, Load<"lbe", GPR32Opnd, null_frag, II_LBE>, - POOL32C_LHUE_FM_MM<0x18, 0x6, 0x4>, ISA_MICROMIPS, ASE_EVA; - def LBuE_MM : MMRel, Load<"lbue", GPR32Opnd, null_frag, II_LBUE>, - POOL32C_LHUE_FM_MM<0x18, 0x6, 0x0>, ISA_MICROMIPS, ASE_EVA; - def LHE_MM : MMRel, LoadMemory<"lhe", GPR32Opnd, mem_simm9, null_frag, - II_LHE>, - POOL32C_LHUE_FM_MM<0x18, 0x6, 0x5>, ISA_MICROMIPS, ASE_EVA; - def LHuE_MM : MMRel, LoadMemory<"lhue", GPR32Opnd, mem_simm9, null_frag, - II_LHUE>, - POOL32C_LHUE_FM_MM<0x18, 0x6, 0x1>, ISA_MICROMIPS, ASE_EVA; - def LWE_MM : MMRel, LoadMemory<"lwe", GPR32Opnd, mem_simm9, null_frag, - II_LWE>, - POOL32C_LHUE_FM_MM<0x18, 0x6, 0x7>, ISA_MICROMIPS, ASE_EVA; - def SBE_MM : MMRel, StoreMemory<"sbe", GPR32Opnd, mem_simm9, null_frag, - II_SBE>, - POOL32C_LHUE_FM_MM<0x18, 0xa, 0x4>, ISA_MICROMIPS, ASE_EVA; - def SHE_MM : MMRel, StoreMemory<"she", GPR32Opnd, mem_simm9, null_frag, - II_SHE>, - POOL32C_LHUE_FM_MM<0x18, 0xa, 0x5>, ISA_MICROMIPS, ASE_EVA; - def SWE_MM : MMRel, StoreMemory<"swe", GPR32Opnd, mem_simm9, null_frag, - II_SWE>, - POOL32C_LHUE_FM_MM<0x18, 0xa, 0x7>, ISA_MICROMIPS, ASE_EVA; - def LWLE_MM : MMRel, LoadLeftRightMM<"lwle", MipsLWL, GPR32Opnd, mem_mm_9, - II_LWLE>, - POOL32C_STEVA_LDEVA_FM_MM<0x6, 0x2>, - ISA_MICROMIPS32_NOT_MIPS32R6, ASE_EVA; - def LWRE_MM : MMRel, LoadLeftRightMM<"lwre", MipsLWR, GPR32Opnd, mem_mm_9, - II_LWRE>, - POOL32C_STEVA_LDEVA_FM_MM<0x6, 0x3>, - ISA_MICROMIPS32_NOT_MIPS32R6, ASE_EVA; - def SWLE_MM : MMRel, StoreLeftRightMM<"swle", MipsSWL, GPR32Opnd, mem_mm_9, - II_SWLE>, - POOL32C_STEVA_LDEVA_FM_MM<0xa, 0x0>, - ISA_MICROMIPS32_NOT_MIPS32R6, ASE_EVA; - def SWRE_MM : MMRel, StoreLeftRightMM<"swre", MipsSWR, GPR32Opnd, mem_mm_9, - II_SWRE>, - POOL32C_STEVA_LDEVA_FM_MM<0xa, 0x1>, - ISA_MICROMIPS32_NOT_MIPS32R6, ASE_EVA; - } - - def LWXS_MM : LoadWordIndexedScaledMM<"lwxs", GPR32Opnd>, LWXS_FM_MM<0x118>, - ISA_MICROMIPS; - - /// Load and Store Instructions - unaligned - def LWL_MM : MMRel, LoadLeftRightMM<"lwl", MipsLWL, GPR32Opnd, mem_mm_12, - II_LWL>, LWL_FM_MM<0x0>, - ISA_MICROMIPS32_NOT_MIPS32R6; - def LWR_MM : MMRel, LoadLeftRightMM<"lwr", MipsLWR, GPR32Opnd, mem_mm_12, - II_LWR>, LWL_FM_MM<0x1>, - ISA_MICROMIPS32_NOT_MIPS32R6; - def SWL_MM : MMRel, StoreLeftRightMM<"swl", MipsSWL, GPR32Opnd, mem_mm_12, - II_SWL>, LWL_FM_MM<0x8>, - ISA_MICROMIPS32_NOT_MIPS32R6; - def SWR_MM : MMRel, StoreLeftRightMM<"swr", MipsSWR, GPR32Opnd, mem_mm_12, - II_SWR>, LWL_FM_MM<0x9>, - ISA_MICROMIPS32_NOT_MIPS32R6; - - /// Load and Store Instructions - multiple - def SWM32_MM : StoreMultMM<"swm32", II_SWM>, LWM_FM_MM<0xd>, ISA_MICROMIPS; - def LWM32_MM : LoadMultMM<"lwm32", II_LWM>, LWM_FM_MM<0x5>, ISA_MICROMIPS; - - /// Load and Store Pair Instructions - def SWP_MM : StorePairMM<"swp">, LWM_FM_MM<0x9>, ISA_MICROMIPS; - def LWP_MM : LoadPairMM<"lwp">, LWM_FM_MM<0x1>, ISA_MICROMIPS; - - /// Load and Store multiple pseudo Instructions - class LoadWordMultMM<string instr_asm > : - MipsAsmPseudoInst<(outs reglist:$rt), (ins mem_mm_12:$addr), - !strconcat(instr_asm, "\t$rt, $addr")> ; - - class StoreWordMultMM<string instr_asm > : - MipsAsmPseudoInst<(outs), (ins reglist:$rt, mem_mm_12:$addr), - !strconcat(instr_asm, "\t$rt, $addr")> ; - - - def SWM_MM : StoreWordMultMM<"swm">, ISA_MICROMIPS; - def LWM_MM : LoadWordMultMM<"lwm">, ISA_MICROMIPS; - - /// Move Conditional - def MOVZ_I_MM : MMRel, CMov_I_I_FT<"movz", GPR32Opnd, GPR32Opnd, - II_MOVZ>, ADD_FM_MM<0, 0x58>, - ISA_MICROMIPS32_NOT_MIPS32R6; - def MOVN_I_MM : MMRel, CMov_I_I_FT<"movn", GPR32Opnd, GPR32Opnd, - II_MOVN>, ADD_FM_MM<0, 0x18>, - ISA_MICROMIPS32_NOT_MIPS32R6; - def MOVT_I_MM : MMRel, CMov_F_I_FT<"movt", GPR32Opnd, II_MOVT, MipsCMovFP_T>, - CMov_F_I_FM_MM<0x25>, ISA_MICROMIPS32_NOT_MIPS32R6; - def MOVF_I_MM : MMRel, CMov_F_I_FT<"movf", GPR32Opnd, II_MOVF, MipsCMovFP_F>, - CMov_F_I_FM_MM<0x5>, ISA_MICROMIPS32_NOT_MIPS32R6; - /// Move to/from HI/LO - def MTHI_MM : MMRel, MoveToLOHI<"mthi", GPR32Opnd, [HI0]>, - MTLO_FM_MM<0x0b5>, ISA_MICROMIPS32_NOT_MIPS32R6; - def MTLO_MM : MMRel, MoveToLOHI<"mtlo", GPR32Opnd, [LO0]>, - MTLO_FM_MM<0x0f5>, ISA_MICROMIPS32_NOT_MIPS32R6; - def MFHI_MM : MMRel, MoveFromLOHI<"mfhi", GPR32Opnd, AC0>, - MFLO_FM_MM<0x035>, ISA_MICROMIPS32_NOT_MIPS32R6; - def MFLO_MM : MMRel, MoveFromLOHI<"mflo", GPR32Opnd, AC0>, - MFLO_FM_MM<0x075>, ISA_MICROMIPS32_NOT_MIPS32R6; - - /// Multiply Add/Sub Instructions - def MADD_MM : MMRel, MArithR<"madd", II_MADD, 1>, MULT_FM_MM<0x32c>, - ISA_MICROMIPS32_NOT_MIPS32R6; - def MADDU_MM : MMRel, MArithR<"maddu", II_MADDU, 1>, MULT_FM_MM<0x36c>, - ISA_MICROMIPS32_NOT_MIPS32R6; - def MSUB_MM : MMRel, MArithR<"msub", II_MSUB>, MULT_FM_MM<0x3ac>, - ISA_MICROMIPS32_NOT_MIPS32R6; - def MSUBU_MM : MMRel, MArithR<"msubu", II_MSUBU>, MULT_FM_MM<0x3ec>, - ISA_MICROMIPS32_NOT_MIPS32R6; - - /// Count Leading - def CLZ_MM : MMRel, CountLeading0<"clz", GPR32Opnd, II_CLZ>, CLO_FM_MM<0x16c>, - ISA_MICROMIPS; - def CLO_MM : MMRel, CountLeading1<"clo", GPR32Opnd, II_CLO>, CLO_FM_MM<0x12c>, - ISA_MICROMIPS; - - /// Sign Ext In Register Instructions. - def SEB_MM : MMRel, SignExtInReg<"seb", i8, GPR32Opnd, II_SEB>, - SEB_FM_MM<0x0ac>, ISA_MICROMIPS; - def SEH_MM : MMRel, SignExtInReg<"seh", i16, GPR32Opnd, II_SEH>, - SEB_FM_MM<0x0ec>, ISA_MICROMIPS; - - /// Word Swap Bytes Within Halfwords - def WSBH_MM : MMRel, SubwordSwap<"wsbh", GPR32Opnd, II_WSBH>, - SEB_FM_MM<0x1ec>, ISA_MICROMIPS; - // TODO: Add '0 < pos+size <= 32' constraint check to ext instruction - def EXT_MM : MMRel, ExtBase<"ext", GPR32Opnd, uimm5, uimm5_plus1, immZExt5, - immZExt5Plus1, MipsExt>, EXT_FM_MM<0x2c>, - ISA_MICROMIPS32_NOT_MIPS32R6; - def INS_MM : MMRel, InsBase<"ins", GPR32Opnd, uimm5, uimm5_inssize_plus1, - immZExt5, immZExt5Plus1>, - EXT_FM_MM<0x0c>, ISA_MICROMIPS32_NOT_MIPS32R6; - - /// Jump Instructions - let DecoderMethod = "DecodeJumpTargetMM" in - def J_MM : MMRel, JumpFJ<jmptarget_mm, "j", br, bb, "j">, - J_FM_MM<0x35>, AdditionalRequires<[RelocNotPIC]>, - IsBranch, ISA_MICROMIPS32_NOT_MIPS32R6; - - let DecoderMethod = "DecodeJumpTargetMM" in { - def JAL_MM : MMRel, JumpLink<"jal", calltarget_mm>, J_FM_MM<0x3d>, - ISA_MICROMIPS32_NOT_MIPS32R6; - def JALX_MM : MMRel, JumpLink<"jalx", calltarget>, J_FM_MM<0x3c>, - ISA_MICROMIPS32_NOT_MIPS32R6; - } - def JR_MM : MMRel, IndirectBranch<"jr", GPR32Opnd>, JR_FM_MM<0x3c>, - ISA_MICROMIPS32_NOT_MIPS32R6; - def JALR_MM : JumpLinkReg<"jalr", GPR32Opnd>, JALR_FM_MM<0x03c>, - ISA_MICROMIPS32_NOT_MIPS32R6; - - /// Jump Instructions - Short Delay Slot - def JALS_MM : JumpLinkMM<"jals", calltarget_mm>, J_FM_MM<0x1d>, - ISA_MICROMIPS32_NOT_MIPS32R6; - def JALRS_MM : JumpLinkRegMM<"jalrs", GPR32Opnd>, JALR_FM_MM<0x13c>, - ISA_MICROMIPS32_NOT_MIPS32R6; - - /// Branch Instructions - def BEQ_MM : MMRel, CBranch<"beq", brtarget_mm, seteq, GPR32Opnd>, - BEQ_FM_MM<0x25>, ISA_MICROMIPS32_NOT_MIPS32R6; - def BNE_MM : MMRel, CBranch<"bne", brtarget_mm, setne, GPR32Opnd>, - BEQ_FM_MM<0x2d>, ISA_MICROMIPS32_NOT_MIPS32R6; - def BGEZ_MM : MMRel, CBranchZero<"bgez", brtarget_mm, setge, GPR32Opnd>, - BGEZ_FM_MM<0x2>, ISA_MICROMIPS32_NOT_MIPS32R6; - def BGTZ_MM : MMRel, CBranchZero<"bgtz", brtarget_mm, setgt, GPR32Opnd>, - BGEZ_FM_MM<0x6>, ISA_MICROMIPS32_NOT_MIPS32R6; - def BLEZ_MM : MMRel, CBranchZero<"blez", brtarget_mm, setle, GPR32Opnd>, - BGEZ_FM_MM<0x4>, ISA_MICROMIPS32_NOT_MIPS32R6; - def BLTZ_MM : MMRel, CBranchZero<"bltz", brtarget_mm, setlt, GPR32Opnd>, - BGEZ_FM_MM<0x0>, ISA_MICROMIPS32_NOT_MIPS32R6; - def BGEZAL_MM : MMRel, BGEZAL_FT<"bgezal", brtarget_mm, GPR32Opnd>, - BGEZAL_FM_MM<0x03>, ISA_MICROMIPS32_NOT_MIPS32R6; - def BLTZAL_MM : MMRel, BGEZAL_FT<"bltzal", brtarget_mm, GPR32Opnd>, - BGEZAL_FM_MM<0x01>, ISA_MICROMIPS32_NOT_MIPS32R6; - def BAL_BR_MM : BAL_BR_Pseudo<BGEZAL_MM, brtarget_mm>, - ISA_MICROMIPS32_NOT_MIPS32R6; - - /// Branch Instructions - Short Delay Slot - def BGEZALS_MM : BranchCompareToZeroLinkMM<"bgezals", brtarget_mm, - GPR32Opnd>, BGEZAL_FM_MM<0x13>, - ISA_MICROMIPS32_NOT_MIPS32R6; - def BLTZALS_MM : BranchCompareToZeroLinkMM<"bltzals", brtarget_mm, - GPR32Opnd>, BGEZAL_FM_MM<0x11>, - ISA_MICROMIPS32_NOT_MIPS32R6; - def B_MM : UncondBranch<BEQ_MM, brtarget_mm>, IsBranch, - ISA_MICROMIPS32_NOT_MIPS32R6; - - /// Control Instructions - def SYNC_MM : MMRel, SYNC_FT<"sync">, SYNC_FM_MM, ISA_MICROMIPS; - let DecoderMethod = "DecodeSyncI_MM" in - def SYNCI_MM : MMRel, SYNCI_FT<"synci", mem_mm_16>, SYNCI_FM_MM, - ISA_MICROMIPS32_NOT_MIPS32R6; - def BREAK_MM : MMRel, BRK_FT<"break">, BRK_FM_MM, ISA_MICROMIPS; - def SYSCALL_MM : MMRel, SYS_FT<"syscall", uimm10, II_SYSCALL>, SYS_FM_MM, - ISA_MICROMIPS; - def WAIT_MM : MMRel, WaitMM<"wait">, WAIT_FM_MM, ISA_MICROMIPS; - def ERET_MM : MMRel, ER_FT<"eret", II_ERET>, ER_FM_MM<0x3cd>, - ISA_MICROMIPS; - def DERET_MM : MMRel, ER_FT<"deret", II_DERET>, ER_FM_MM<0x38d>, - ISA_MICROMIPS; - def EI_MM : MMRel, DEI_FT<"ei", GPR32Opnd, II_EI>, EI_FM_MM<0x15d>, - ISA_MICROMIPS; - def DI_MM : MMRel, DEI_FT<"di", GPR32Opnd, II_DI>, EI_FM_MM<0x11d>, - ISA_MICROMIPS; - def TRAP_MM : TrapBase<BREAK_MM>, ISA_MICROMIPS; - - /// Trap Instructions - def TEQ_MM : MMRel, TEQ_FT<"teq", GPR32Opnd, uimm4, II_TEQ>, TEQ_FM_MM<0x0>, - ISA_MICROMIPS; - def TGE_MM : MMRel, TEQ_FT<"tge", GPR32Opnd, uimm4, II_TGE>, TEQ_FM_MM<0x08>, - ISA_MICROMIPS; - def TGEU_MM : MMRel, TEQ_FT<"tgeu", GPR32Opnd, uimm4, II_TGEU>, - TEQ_FM_MM<0x10>, ISA_MICROMIPS; - def TLT_MM : MMRel, TEQ_FT<"tlt", GPR32Opnd, uimm4, II_TLT>, TEQ_FM_MM<0x20>, - ISA_MICROMIPS; - def TLTU_MM : MMRel, TEQ_FT<"tltu", GPR32Opnd, uimm4, II_TLTU>, - TEQ_FM_MM<0x28>, ISA_MICROMIPS; - def TNE_MM : MMRel, TEQ_FT<"tne", GPR32Opnd, uimm4, II_TNE>, TEQ_FM_MM<0x30>, - ISA_MICROMIPS; - - def TEQI_MM : MMRel, TEQI_FT<"teqi", GPR32Opnd, II_TEQI>, TEQI_FM_MM<0x0e>, - ISA_MICROMIPS32_NOT_MIPS32R6; - def TGEI_MM : MMRel, TEQI_FT<"tgei", GPR32Opnd, II_TGEI>, TEQI_FM_MM<0x09>, - ISA_MICROMIPS32_NOT_MIPS32R6; - def TGEIU_MM : MMRel, TEQI_FT<"tgeiu", GPR32Opnd, II_TGEIU>, - TEQI_FM_MM<0x0b>, ISA_MICROMIPS32_NOT_MIPS32R6; - def TLTI_MM : MMRel, TEQI_FT<"tlti", GPR32Opnd, II_TLTI>, TEQI_FM_MM<0x08>, - ISA_MICROMIPS32_NOT_MIPS32R6; - def TLTIU_MM : MMRel, TEQI_FT<"tltiu", GPR32Opnd, II_TTLTIU>, - TEQI_FM_MM<0x0a>, ISA_MICROMIPS32_NOT_MIPS32R6; - def TNEI_MM : MMRel, TEQI_FT<"tnei", GPR32Opnd, II_TNEI>, TEQI_FM_MM<0x0c>, - ISA_MICROMIPS32_NOT_MIPS32R6; - - /// Load-linked, Store-conditional - def LL_MM : LLBaseMM<"ll", GPR32Opnd>, LL_FM_MM<0x3>, - ISA_MICROMIPS32_NOT_MIPS32R6; - def SC_MM : SCBaseMM<"sc", GPR32Opnd>, LL_FM_MM<0xb>, - ISA_MICROMIPS32_NOT_MIPS32R6; - - def LLE_MM : MMRel, LLEBaseMM<"lle", GPR32Opnd>, LLE_FM_MM<0x6>, - ISA_MICROMIPS, ASE_EVA; - def SCE_MM : MMRel, SCEBaseMM<"sce", GPR32Opnd>, LLE_FM_MM<0xA>, - ISA_MICROMIPS, ASE_EVA; - - let DecoderMethod = "DecodeCacheOpMM" in { - def CACHE_MM : MMRel, CacheOp<"cache", mem_mm_12, II_CACHE>, - CACHE_PREF_FM_MM<0x08, 0x6>, ISA_MICROMIPS32_NOT_MIPS32R6; - def PREF_MM : MMRel, CacheOp<"pref", mem_mm_12, II_PREF>, - CACHE_PREF_FM_MM<0x18, 0x2>, ISA_MICROMIPS32_NOT_MIPS32R6; - } - - let DecoderMethod = "DecodePrefeOpMM" in { - def PREFE_MM : MMRel, CacheOp<"prefe", mem_mm_9, II_PREFE>, - CACHE_PREFE_FM_MM<0x18, 0x2>, ISA_MICROMIPS, ASE_EVA; - def CACHEE_MM : MMRel, CacheOp<"cachee", mem_mm_9, II_CACHEE>, - CACHE_PREFE_FM_MM<0x18, 0x3>, ISA_MICROMIPS, ASE_EVA; - } - def SSNOP_MM : MMRel, Barrier<"ssnop", II_SSNOP>, BARRIER_FM_MM<0x1>, - ISA_MICROMIPS; - def EHB_MM : MMRel, Barrier<"ehb", II_EHB>, BARRIER_FM_MM<0x3>, - ISA_MICROMIPS; - def PAUSE_MM : MMRel, Barrier<"pause", II_PAUSE>, BARRIER_FM_MM<0x5>, - ISA_MICROMIPS; - - def TLBP_MM : MMRel, TLB<"tlbp", II_TLBP>, COP0_TLB_FM_MM<0x0d>, - ISA_MICROMIPS; - def TLBR_MM : MMRel, TLB<"tlbr", II_TLBR>, COP0_TLB_FM_MM<0x4d>, - ISA_MICROMIPS; - def TLBWI_MM : MMRel, TLB<"tlbwi", II_TLBWI>, COP0_TLB_FM_MM<0x8d>, - ISA_MICROMIPS; - def TLBWR_MM : MMRel, TLB<"tlbwr", II_TLBWR>, COP0_TLB_FM_MM<0xcd>, - ISA_MICROMIPS; - - def SDBBP_MM : MMRel, SYS_FT<"sdbbp", uimm10, II_SDBBP>, SDBBP_FM_MM, - ISA_MICROMIPS; - - def PREFX_MM : PrefetchIndexed<"prefx">, POOL32F_PREFX_FM_MM<0x15, 0x1A0>, - ISA_MICROMIPS32_NOT_MIPS32R6; -} - -let AdditionalPredicates = [NotDSP] in { - def PseudoMULT_MM : MultDivPseudo<MULT, ACC64, GPR32Opnd, MipsMult, II_MULT>, - ISA_MICROMIPS32_NOT_MIPS32R6; - def PseudoMULTu_MM : MultDivPseudo<MULTu, ACC64, GPR32Opnd, MipsMultu, II_MULTU>, - ISA_MICROMIPS32_NOT_MIPS32R6; - def PseudoMFHI_MM : PseudoMFLOHI<GPR32, ACC64, MipsMFHI>, - ISA_MICROMIPS32_NOT_MIPS32R6; - def PseudoMFLO_MM : PseudoMFLOHI<GPR32, ACC64, MipsMFLO>, - ISA_MICROMIPS32_NOT_MIPS32R6; - def PseudoMTLOHI_MM : PseudoMTLOHI<ACC64, GPR32>, - ISA_MICROMIPS32_NOT_MIPS32R6; - def PseudoMADD_MM : MAddSubPseudo<MADD, MipsMAdd, II_MADD>, - ISA_MICROMIPS32_NOT_MIPS32R6; - def PseudoMADDU_MM : MAddSubPseudo<MADDU, MipsMAddu, II_MADDU>, - ISA_MICROMIPS32_NOT_MIPS32R6; - def PseudoMSUB_MM : MAddSubPseudo<MSUB, MipsMSub, II_MSUB>, - ISA_MICROMIPS32_NOT_MIPS32R6; - def PseudoMSUBU_MM : MAddSubPseudo<MSUBU, MipsMSubu, II_MSUBU>, - ISA_MICROMIPS32_NOT_MIPS32R6; -} - -def TAILCALL_MM : TailCall<J_MM, jmptarget_mm>, - ISA_MICROMIPS32_NOT_MIPS32R6; - -def TAILCALLREG_MM : TailCallReg<JRC16_MM, GPR32Opnd>, - ISA_MICROMIPS32_NOT_MIPS32R6; - -def PseudoIndirectBranch_MM : PseudoIndirectBranchBase<JR_MM, GPR32Opnd>, - ISA_MICROMIPS32_NOT_MIPS32R6; - -let DecoderNamespace = "MicroMips" in { - def RDHWR_MM : MMRel, R6MMR6Rel, ReadHardware<GPR32Opnd, HWRegsOpnd>, - RDHWR_FM_MM, ISA_MICROMIPS32_NOT_MIPS32R6; - def LWU_MM : MMRel, LoadMM<"lwu", GPR32Opnd, zextloadi32, II_LWU, - mem_simm12>, LL_FM_MM<0xe>, - ISA_MICROMIPS32_NOT_MIPS32R6; - - def MFGC0_MM : MMRel, MfCop0MM<"mfgc0", GPR32Opnd, COP0Opnd, II_MFGC0>, - POOL32A_MFTC0_FM_MM<0b10011, 0b111100>, - ISA_MICROMIPS32R5, ASE_VIRT; - def MFHGC0_MM : MMRel, MfCop0MM<"mfhgc0", GPR32Opnd, COP0Opnd, II_MFHGC0>, - POOL32A_MFTC0_FM_MM<0b10011, 0b110100>, - ISA_MICROMIPS32R5, ASE_VIRT; - def MTGC0_MM : MMRel, MtCop0MM<"mtgc0", COP0Opnd, GPR32Opnd, II_MTGC0>, - POOL32A_MFTC0_FM_MM<0b11011, 0b111100>, - ISA_MICROMIPS32R5, ASE_VIRT; - def MTHGC0_MM : MMRel, MtCop0MM<"mthgc0", COP0Opnd, GPR32Opnd, II_MTHGC0>, - POOL32A_MFTC0_FM_MM<0b11011, 0b110100>, - ISA_MICROMIPS32R5, ASE_VIRT; - def HYPCALL_MM : MMRel, HypcallMM<"hypcall">, POOL32A_HYPCALL_FM_MM, - ISA_MICROMIPS32R5, ASE_VIRT; - def TLBGINV_MM : MMRel, TLBINVMM<"tlbginv", II_TLBGINV>, - POOL32A_TLBINV_FM_MM<0x105>, ISA_MICROMIPS32R5, ASE_VIRT; - def TLBGINVF_MM : MMRel, TLBINVMM<"tlbginvf", II_TLBGINVF>, - POOL32A_TLBINV_FM_MM<0x145>, ISA_MICROMIPS32R5, ASE_VIRT; - def TLBGP_MM : MMRel, TLBINVMM<"tlbgp", II_TLBGP>, - POOL32A_TLBINV_FM_MM<0x5>, ISA_MICROMIPS32R5, ASE_VIRT; - def TLBGR_MM : MMRel, TLBINVMM<"tlbgr", II_TLBGR>, - POOL32A_TLBINV_FM_MM<0x45>, ISA_MICROMIPS32R5, ASE_VIRT; - def TLBGWI_MM : MMRel, TLBINVMM<"tlbgwi", II_TLBGWI>, - POOL32A_TLBINV_FM_MM<0x85>, ISA_MICROMIPS32R5, ASE_VIRT; - def TLBGWR_MM : MMRel, TLBINVMM<"tlbgwr", II_TLBGWR>, - POOL32A_TLBINV_FM_MM<0xc5>, ISA_MICROMIPS32R5, ASE_VIRT; -} - -//===----------------------------------------------------------------------===// -// MicroMips arbitrary patterns that map to one or more instructions -//===----------------------------------------------------------------------===// - -defm : MipsHiLoRelocs<LUi_MM, ADDiu_MM, ZERO, GPR32Opnd>, ISA_MICROMIPS; - -def : MipsPat<(MipsGotHi tglobaladdr:$in), (LUi_MM tglobaladdr:$in)>, - ISA_MICROMIPS; -def : MipsPat<(MipsGotHi texternalsym:$in), (LUi_MM texternalsym:$in)>, - ISA_MICROMIPS; - -def : MipsPat<(MipsTlsHi tglobaltlsaddr:$in), (LUi_MM tglobaltlsaddr:$in)>, - ISA_MICROMIPS; - -// gp_rel relocs -def : MipsPat<(add GPR32:$gp, (MipsGPRel tglobaladdr:$in)), - (ADDiu_MM GPR32:$gp, tglobaladdr:$in)>, ISA_MICROMIPS; -def : MipsPat<(add GPR32:$gp, (MipsGPRel tconstpool:$in)), - (ADDiu_MM GPR32:$gp, tconstpool:$in)>, ISA_MICROMIPS; - -def : WrapperPat<tglobaladdr, ADDiu_MM, GPR32>, ISA_MICROMIPS; -def : WrapperPat<tconstpool, ADDiu_MM, GPR32>, ISA_MICROMIPS; -def : WrapperPat<texternalsym, ADDiu_MM, GPR32>, ISA_MICROMIPS; -def : WrapperPat<tblockaddress, ADDiu_MM, GPR32>, ISA_MICROMIPS; -def : WrapperPat<tjumptable, ADDiu_MM, GPR32>, ISA_MICROMIPS; -def : WrapperPat<tglobaltlsaddr, ADDiu_MM, GPR32>, ISA_MICROMIPS; - -def : MipsPat<(atomic_load_8 addr:$a), (LB_MM addr:$a)>, ISA_MICROMIPS; -def : MipsPat<(atomic_load_16 addr:$a), (LH_MM addr:$a)>, ISA_MICROMIPS; -def : MipsPat<(atomic_load_32 addr:$a), (LW_MM addr:$a)>, ISA_MICROMIPS; - -def : MipsPat<(i32 immLi16:$imm), - (LI16_MM immLi16:$imm)>, ISA_MICROMIPS; - -defm : MaterializeImms<i32, ZERO, ADDiu_MM, LUi_MM, ORi_MM>, ISA_MICROMIPS; - -def : MipsPat<(not GPRMM16:$in), - (NOT16_MM GPRMM16:$in)>, ISA_MICROMIPS; -def : MipsPat<(not GPR32:$in), - (NOR_MM GPR32Opnd:$in, ZERO)>, ISA_MICROMIPS; - -def : MipsPat<(add GPRMM16:$src, immSExtAddiur2:$imm), - (ADDIUR2_MM GPRMM16:$src, immSExtAddiur2:$imm)>, ISA_MICROMIPS; -def : MipsPat<(add GPR32:$src, immSExtAddius5:$imm), - (ADDIUS5_MM GPR32:$src, immSExtAddius5:$imm)>, ISA_MICROMIPS; -def : MipsPat<(add GPR32:$src, immSExt16:$imm), - (ADDiu_MM GPR32:$src, immSExt16:$imm)>, ISA_MICROMIPS; - -def : MipsPat<(and GPRMM16:$src, immZExtAndi16:$imm), - (ANDI16_MM GPRMM16:$src, immZExtAndi16:$imm)>, ISA_MICROMIPS; -def : MipsPat<(and GPR32:$src, immZExt16:$imm), - (ANDi_MM GPR32:$src, immZExt16:$imm)>, ISA_MICROMIPS; - -def : MipsPat<(shl GPRMM16:$src, immZExt2Shift:$imm), - (SLL16_MM GPRMM16:$src, immZExt2Shift:$imm)>, ISA_MICROMIPS; -def : MipsPat<(shl GPR32:$src, immZExt5:$imm), - (SLL_MM GPR32:$src, immZExt5:$imm)>, ISA_MICROMIPS; -def : MipsPat<(shl GPR32:$lhs, GPR32:$rhs), - (SLLV_MM GPR32:$lhs, GPR32:$rhs)>, ISA_MICROMIPS; - -def : MipsPat<(srl GPRMM16:$src, immZExt2Shift:$imm), - (SRL16_MM GPRMM16:$src, immZExt2Shift:$imm)>, ISA_MICROMIPS; -def : MipsPat<(srl GPR32:$src, immZExt5:$imm), - (SRL_MM GPR32:$src, immZExt5:$imm)>, ISA_MICROMIPS; -def : MipsPat<(srl GPR32:$lhs, GPR32:$rhs), - (SRLV_MM GPR32:$lhs, GPR32:$rhs)>, ISA_MICROMIPS; - -def : MipsPat<(sra GPR32:$src, immZExt5:$imm), - (SRA_MM GPR32:$src, immZExt5:$imm)>, ISA_MICROMIPS; -def : MipsPat<(sra GPR32:$lhs, GPR32:$rhs), - (SRAV_MM GPR32:$lhs, GPR32:$rhs)>, ISA_MICROMIPS; - -def : MipsPat<(store GPRMM16:$src, addrimm4lsl2:$addr), - (SW16_MM GPRMM16:$src, addrimm4lsl2:$addr)>, ISA_MICROMIPS; -def : MipsPat<(store GPR32:$src, addr:$addr), - (SW_MM GPR32:$src, addr:$addr)>, ISA_MICROMIPS; - -def : MipsPat<(load addrimm4lsl2:$addr), - (LW16_MM addrimm4lsl2:$addr)>, ISA_MICROMIPS; -def : MipsPat<(load addr:$addr), - (LW_MM addr:$addr)>, ISA_MICROMIPS; -def : MipsPat<(subc GPR32:$lhs, GPR32:$rhs), - (SUBu_MM GPR32:$lhs, GPR32:$rhs)>, ISA_MICROMIPS; - -def : MipsPat<(i32 (extloadi1 addr:$src)), (LBu_MM addr:$src)>, - ISA_MICROMIPS; - -def : MipsPat<(i32 (extloadi8 addr:$src)), (LBu_MM addr:$src)>, - ISA_MICROMIPS; - -def : MipsPat<(i32 (extloadi16 addr:$src)), (LHu_MM addr:$src)>, - ISA_MICROMIPS; - -let AddedComplexity = 40 in - def : MipsPat<(i32 (sextloadi16 addrRegImm:$a)), - (LH_MM addrRegImm:$a)>, ISA_MICROMIPS; - - -def : MipsPat<(bswap GPR32:$rt), (ROTR_MM (WSBH_MM GPR32:$rt), 16)>, - ISA_MICROMIPS; - -def : MipsPat<(MipsJmpLink (i32 texternalsym:$dst)), - (JAL_MM texternalsym:$dst)>, ISA_MICROMIPS32_NOT_MIPS32R6; -def : MipsPat<(MipsTailCall (iPTR tglobaladdr:$dst)), - (TAILCALL_MM tglobaladdr:$dst)>, ISA_MICROMIPS32_NOT_MIPS32R6; -def : MipsPat<(MipsTailCall (iPTR texternalsym:$dst)), - (TAILCALL_MM texternalsym:$dst)>, ISA_MICROMIPS32_NOT_MIPS32R6; - -defm : BrcondPats<GPR32, BEQ_MM, BEQ_MM, BNE_MM, SLT_MM, SLTu_MM, SLTi_MM, - SLTiu_MM, ZERO>, ISA_MICROMIPS32_NOT_MIPS32R6; - -def : MipsPat<(brcond (i32 (setlt i32:$lhs, 1)), bb:$dst), - (BLEZ_MM i32:$lhs, bb:$dst)>, ISA_MICROMIPS32_NOT_MIPS32R6; -def : MipsPat<(brcond (i32 (setgt i32:$lhs, -1)), bb:$dst), - (BGEZ_MM i32:$lhs, bb:$dst)>, ISA_MICROMIPS32_NOT_MIPS32R6; - -defm : SeteqPats<GPR32, SLTiu_MM, XOR_MM, SLTu_MM, ZERO>, ISA_MICROMIPS; -defm : SetlePats<GPR32, XORi_MM, SLT_MM, SLTu_MM>, ISA_MICROMIPS; -defm : SetgtPats<GPR32, SLT_MM, SLTu_MM>, ISA_MICROMIPS; -defm : SetgePats<GPR32, XORi_MM, SLT_MM, SLTu_MM>, ISA_MICROMIPS; -defm : SetgeImmPats<GPR32, XORi_MM, SLTi_MM, SLTiu_MM>, ISA_MICROMIPS; - -// Select patterns - -// Instantiation of conditional move patterns. -defm : MovzPats0<GPR32, GPR32, MOVZ_I_MM, SLT_MM, SLTu_MM, SLTi_MM, SLTiu_MM>, - ISA_MICROMIPS32_NOT_MIPS32R6; -defm : MovzPats1<GPR32, GPR32, MOVZ_I_MM, XOR_MM>, - ISA_MICROMIPS32_NOT_MIPS32R6; -defm : MovzPats2<GPR32, GPR32, MOVZ_I_MM, XORi_MM>, - ISA_MICROMIPS32_NOT_MIPS32R6; - - -defm : MovnPats<GPR32, GPR32, MOVN_I_MM, XOR_MM>, INSN_MIPS4_32_NOT_32R6_64R6; - -// Instantiation of conditional move patterns. -defm : MovzPats0<GPR32, GPR32, MOVZ_I_MM, SLT_MM, SLTu_MM, SLTi_MM, SLTiu_MM>, - ISA_MICROMIPS32_NOT_MIPS32R6; -defm : MovzPats1<GPR32, GPR32, MOVZ_I_MM, XOR_MM>, - ISA_MICROMIPS32_NOT_MIPS32R6; -defm : MovzPats2<GPR32, GPR32, MOVZ_I_MM, XORi_MM>, - ISA_MICROMIPS32_NOT_MIPS32R6; - -defm : MovnPats<GPR32, GPR32, MOVN_I_MM, XOR_MM>, ISA_MICROMIPS32_NOT_MIPS32R6; - -//===----------------------------------------------------------------------===// -// MicroMips instruction aliases -//===----------------------------------------------------------------------===// - -class UncondBranchMMPseudo<string opstr> : - MipsAsmPseudoInst<(outs), (ins brtarget_mm:$offset), - !strconcat(opstr, "\t$offset")>; - -def B_MM_Pseudo : UncondBranchMMPseudo<"b">, ISA_MICROMIPS; - -let EncodingPredicates = [InMicroMips] in { - def SDIV_MM_Pseudo : MultDivPseudo<SDIV_MM, ACC64, GPR32Opnd, MipsDivRem, - II_DIV, 0, 1, 1>, ISA_MIPS1_NOT_32R6_64R6; - def UDIV_MM_Pseudo : MultDivPseudo<UDIV_MM, ACC64, GPR32Opnd, MipsDivRemU, - II_DIVU, 0, 1, 1>, ISA_MIPS1_NOT_32R6_64R6; - - def : MipsInstAlias<"wait", (WAIT_MM 0x0), 1>, ISA_MICROMIPS; - def : MipsInstAlias<"nop", (SLL_MM ZERO, ZERO, 0), 1>, ISA_MICROMIPS; - def : MipsInstAlias<"nop", (MOVE16_MM ZERO, ZERO), 1>, ISA_MICROMIPS; - def : MipsInstAlias<"ei", (EI_MM ZERO), 1>, ISA_MICROMIPS; - def : MipsInstAlias<"di", (DI_MM ZERO), 1>, ISA_MICROMIPS; - def : MipsInstAlias<"neg $rt, $rs", - (SUB_MM GPR32Opnd:$rt, ZERO, GPR32Opnd:$rs), 1>, - ISA_MICROMIPS32_NOT_MIPS32R6; - def : MipsInstAlias<"neg $rt", - (SUB_MM GPR32Opnd:$rt, ZERO, GPR32Opnd:$rt), 1>, - ISA_MICROMIPS32_NOT_MIPS32R6; - def : MipsInstAlias<"negu $rt, $rs", - (SUBu_MM GPR32Opnd:$rt, ZERO, GPR32Opnd:$rs), 1>, - ISA_MICROMIPS32_NOT_MIPS32R6; - def : MipsInstAlias<"negu $rt", - (SUBu_MM GPR32Opnd:$rt, ZERO, GPR32Opnd:$rt), 1>, - ISA_MICROMIPS32_NOT_MIPS32R6; - def : MipsInstAlias<"teq $rs, $rt", - (TEQ_MM GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>; - def : MipsInstAlias<"tge $rs, $rt", - (TGE_MM GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>; - def : MipsInstAlias<"tgeu $rs, $rt", - (TGEU_MM GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>; - def : MipsInstAlias<"tlt $rs, $rt", - (TLT_MM GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>; - def : MipsInstAlias<"tltu $rs, $rt", - (TLTU_MM GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>; - def : MipsInstAlias<"tne $rs, $rt", - (TNE_MM GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>; - def : MipsInstAlias< - "sgt $rd, $rs, $rt", - (SLT_MM GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>; - def : MipsInstAlias< - "sgt $rs, $rt", - (SLT_MM GPR32Opnd:$rs, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>; - def : MipsInstAlias< - "sgtu $rd, $rs, $rt", - (SLTu_MM GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>; - def : MipsInstAlias< - "sgtu $rs, $rt", - (SLTu_MM GPR32Opnd:$rs, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>; - def : MipsInstAlias<"sll $rd, $rt, $rs", - (SLLV_MM GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>; - def : MipsInstAlias<"sra $rd, $rt, $rs", - (SRAV_MM GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>; - def : MipsInstAlias<"srl $rd, $rt, $rs", - (SRLV_MM GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>; - def : MipsInstAlias<"sll $rd, $rt", - (SLLV_MM GPR32Opnd:$rd, GPR32Opnd:$rd, GPR32Opnd:$rt), 0>; - def : MipsInstAlias<"sra $rd, $rt", - (SRAV_MM GPR32Opnd:$rd, GPR32Opnd:$rd, GPR32Opnd:$rt), 0>; - def : MipsInstAlias<"srl $rd, $rt", - (SRLV_MM GPR32Opnd:$rd, GPR32Opnd:$rd, GPR32Opnd:$rt), 0>; - def : MipsInstAlias<"sll $rd, $shamt", - (SLL_MM GPR32Opnd:$rd, GPR32Opnd:$rd, uimm5:$shamt), 0>; - def : MipsInstAlias<"sra $rd, $shamt", - (SRA_MM GPR32Opnd:$rd, GPR32Opnd:$rd, uimm5:$shamt), 0>; - def : MipsInstAlias<"srl $rd, $shamt", - (SRL_MM GPR32Opnd:$rd, GPR32Opnd:$rd, uimm5:$shamt), 0>; - def : MipsInstAlias<"rotr $rt, $imm", - (ROTR_MM GPR32Opnd:$rt, GPR32Opnd:$rt, uimm5:$imm), 0>; - def : MipsInstAlias<"syscall", (SYSCALL_MM 0), 1>, ISA_MICROMIPS; - - def : MipsInstAlias<"sync", (SYNC_MM 0), 1>, ISA_MICROMIPS; - - defm : OneOrTwoOperandMacroImmediateAlias<"add", ADDi_MM>, ISA_MICROMIPS; - - defm : OneOrTwoOperandMacroImmediateAlias<"addu", ADDiu_MM>, ISA_MICROMIPS; - - defm : OneOrTwoOperandMacroImmediateAlias<"and", ANDi_MM>, ISA_MICROMIPS; - - defm : OneOrTwoOperandMacroImmediateAlias<"or", ORi_MM>, ISA_MICROMIPS; - - defm : OneOrTwoOperandMacroImmediateAlias<"xor", XORi_MM>, ISA_MICROMIPS; - - defm : OneOrTwoOperandMacroImmediateAlias<"slt", SLTi_MM>, ISA_MICROMIPS; - - defm : OneOrTwoOperandMacroImmediateAlias<"sltu", SLTiu_MM>, ISA_MICROMIPS; - - def : MipsInstAlias<"not $rt, $rs", - (NOR_MM GPR32Opnd:$rt, GPR32Opnd:$rs, ZERO), 0>, - ISA_MICROMIPS32_NOT_MIPS32R6; - def : MipsInstAlias<"not $rt", - (NOR_MM GPR32Opnd:$rt, GPR32Opnd:$rt, ZERO), 0>, - ISA_MICROMIPS32_NOT_MIPS32R6; - def : MipsInstAlias<"bnez $rs,$offset", - (BNE_MM GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>, - ISA_MICROMIPS; - def : MipsInstAlias<"beqz $rs,$offset", - (BEQ_MM GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>, - ISA_MICROMIPS; - def : MipsInstAlias<"seh $rd", (SEH_MM GPR32Opnd:$rd, GPR32Opnd:$rd), 0>, - ISA_MICROMIPS; - def : MipsInstAlias<"seb $rd", (SEB_MM GPR32Opnd:$rd, GPR32Opnd:$rd), 0>, - ISA_MICROMIPS; - def : MipsInstAlias<"break", (BREAK_MM 0, 0), 1>, ISA_MICROMIPS; - def : MipsInstAlias<"break $imm", (BREAK_MM uimm10:$imm, 0), 1>, - ISA_MICROMIPS; - def : MipsInstAlias<"bal $offset", (BGEZAL_MM ZERO, brtarget_mm:$offset), 1>, - ISA_MICROMIPS32_NOT_MIPS32R6; - - def : MipsInstAlias<"j $rs", (JR_MM GPR32Opnd:$rs), 0>, - ISA_MICROMIPS32_NOT_MIPS32R6; -} -def : MipsInstAlias<"rdhwr $rt, $rs", - (RDHWR_MM GPR32Opnd:$rt, HWRegsOpnd:$rs, 0), 1>, - ISA_MICROMIPS32_NOT_MIPS32R6; - -def : MipsInstAlias<"hypcall", (HYPCALL_MM 0), 1>, - ISA_MICROMIPS32R5, ASE_VIRT; -def : MipsInstAlias<"mfgc0 $rt, $rs", - (MFGC0_MM GPR32Opnd:$rt, COP0Opnd:$rs, 0), 0>, - ISA_MICROMIPS32R5, ASE_VIRT; -def : MipsInstAlias<"mfhgc0 $rt, $rs", - (MFHGC0_MM GPR32Opnd:$rt, COP0Opnd:$rs, 0), 0>, - ISA_MICROMIPS32R5, ASE_VIRT; -def : MipsInstAlias<"mtgc0 $rt, $rs", - (MTGC0_MM COP0Opnd:$rs, GPR32Opnd:$rt, 0), 0>, - ISA_MICROMIPS32R5, ASE_VIRT; -def : MipsInstAlias<"mthgc0 $rt, $rs", - (MTHGC0_MM COP0Opnd:$rs, GPR32Opnd:$rt, 0), 0>, - ISA_MICROMIPS32R5, ASE_VIRT; -def : MipsInstAlias<"sw $rt, $offset", - (SWSP_MM GPR32Opnd:$rt, mem_mm_sp_imm5_lsl2:$offset), 1>, - ISA_MICROMIPS; diff --git a/contrib/llvm/lib/Target/Mips/MicroMipsSizeReduction.cpp b/contrib/llvm/lib/Target/Mips/MicroMipsSizeReduction.cpp deleted file mode 100644 index 70af95592aa5..000000000000 --- a/contrib/llvm/lib/Target/Mips/MicroMipsSizeReduction.cpp +++ /dev/null @@ -1,797 +0,0 @@ -//=== MicroMipsSizeReduction.cpp - MicroMips size reduction pass --------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -///\file -/// This pass is used to reduce the size of instructions where applicable. -/// -/// TODO: Implement microMIPS64 support. -//===----------------------------------------------------------------------===// -#include "Mips.h" -#include "MipsInstrInfo.h" -#include "MipsSubtarget.h" -#include "llvm/ADT/Statistic.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/Support/Debug.h" - -using namespace llvm; - -#define DEBUG_TYPE "micromips-reduce-size" -#define MICROMIPS_SIZE_REDUCE_NAME "MicroMips instruction size reduce pass" - -STATISTIC(NumReduced, "Number of instructions reduced (32-bit to 16-bit ones, " - "or two instructions into one"); - -namespace { - -/// Order of operands to transfer -// TODO: Will be extended when additional optimizations are added -enum OperandTransfer { - OT_NA, ///< Not applicable - OT_OperandsAll, ///< Transfer all operands - OT_Operands02, ///< Transfer operands 0 and 2 - OT_Operand2, ///< Transfer just operand 2 - OT_OperandsXOR, ///< Transfer operands for XOR16 - OT_OperandsLwp, ///< Transfer operands for LWP - OT_OperandsSwp, ///< Transfer operands for SWP - OT_OperandsMovep, ///< Transfer operands for MOVEP -}; - -/// Reduction type -// TODO: Will be extended when additional optimizations are added -enum ReduceType { - RT_TwoInstr, ///< Reduce two instructions into one instruction - RT_OneInstr ///< Reduce one instruction into a smaller instruction -}; - -// Information about immediate field restrictions -struct ImmField { - ImmField() : ImmFieldOperand(-1), Shift(0), LBound(0), HBound(0) {} - ImmField(uint8_t Shift, int16_t LBound, int16_t HBound, - int8_t ImmFieldOperand) - : ImmFieldOperand(ImmFieldOperand), Shift(Shift), LBound(LBound), - HBound(HBound) {} - int8_t ImmFieldOperand; // Immediate operand, -1 if it does not exist - uint8_t Shift; // Shift value - int16_t LBound; // Low bound of the immediate operand - int16_t HBound; // High bound of the immediate operand -}; - -/// Information about operands -// TODO: Will be extended when additional optimizations are added -struct OpInfo { - OpInfo(enum OperandTransfer TransferOperands) - : TransferOperands(TransferOperands) {} - OpInfo() : TransferOperands(OT_NA) {} - - enum OperandTransfer - TransferOperands; ///< Operands to transfer to the new instruction -}; - -// Information about opcodes -struct OpCodes { - OpCodes(unsigned WideOpc, unsigned NarrowOpc) - : WideOpc(WideOpc), NarrowOpc(NarrowOpc) {} - - unsigned WideOpc; ///< Wide opcode - unsigned NarrowOpc; ///< Narrow opcode -}; - -typedef struct ReduceEntryFunArgs ReduceEntryFunArgs; - -/// ReduceTable - A static table with information on mapping from wide -/// opcodes to narrow -struct ReduceEntry { - - enum ReduceType eRType; ///< Reduction type - bool (*ReduceFunction)( - ReduceEntryFunArgs *Arguments); ///< Pointer to reduce function - struct OpCodes Ops; ///< All relevant OpCodes - struct OpInfo OpInf; ///< Characteristics of operands - struct ImmField Imm; ///< Characteristics of immediate field - - ReduceEntry(enum ReduceType RType, struct OpCodes Op, - bool (*F)(ReduceEntryFunArgs *Arguments), struct OpInfo OpInf, - struct ImmField Imm) - : eRType(RType), ReduceFunction(F), Ops(Op), OpInf(OpInf), Imm(Imm) {} - - unsigned NarrowOpc() const { return Ops.NarrowOpc; } - unsigned WideOpc() const { return Ops.WideOpc; } - int16_t LBound() const { return Imm.LBound; } - int16_t HBound() const { return Imm.HBound; } - uint8_t Shift() const { return Imm.Shift; } - int8_t ImmField() const { return Imm.ImmFieldOperand; } - enum OperandTransfer TransferOperands() const { - return OpInf.TransferOperands; - } - enum ReduceType RType() const { return eRType; } - - // operator used by std::equal_range - bool operator<(const unsigned int r) const { return (WideOpc() < r); } - - // operator used by std::equal_range - friend bool operator<(const unsigned int r, const struct ReduceEntry &re) { - return (r < re.WideOpc()); - } -}; - -// Function arguments for ReduceFunction -struct ReduceEntryFunArgs { - MachineInstr *MI; // Instruction - const ReduceEntry &Entry; // Entry field - MachineBasicBlock::instr_iterator - &NextMII; // Iterator to next instruction in block - - ReduceEntryFunArgs(MachineInstr *argMI, const ReduceEntry &argEntry, - MachineBasicBlock::instr_iterator &argNextMII) - : MI(argMI), Entry(argEntry), NextMII(argNextMII) {} -}; - -typedef llvm::SmallVector<ReduceEntry, 32> ReduceEntryVector; - -class MicroMipsSizeReduce : public MachineFunctionPass { -public: - static char ID; - MicroMipsSizeReduce(); - - static const MipsInstrInfo *MipsII; - const MipsSubtarget *Subtarget; - - bool runOnMachineFunction(MachineFunction &MF) override; - - llvm::StringRef getPassName() const override { - return "microMIPS instruction size reduction pass"; - } - -private: - /// Reduces width of instructions in the specified basic block. - bool ReduceMBB(MachineBasicBlock &MBB); - - /// Attempts to reduce MI, returns true on success. - bool ReduceMI(const MachineBasicBlock::instr_iterator &MII, - MachineBasicBlock::instr_iterator &NextMII); - - // Attempts to reduce LW/SW instruction into LWSP/SWSP, - // returns true on success. - static bool ReduceXWtoXWSP(ReduceEntryFunArgs *Arguments); - - // Attempts to reduce two LW/SW instructions into LWP/SWP instruction, - // returns true on success. - static bool ReduceXWtoXWP(ReduceEntryFunArgs *Arguments); - - // Attempts to reduce LBU/LHU instruction into LBU16/LHU16, - // returns true on success. - static bool ReduceLXUtoLXU16(ReduceEntryFunArgs *Arguments); - - // Attempts to reduce SB/SH instruction into SB16/SH16, - // returns true on success. - static bool ReduceSXtoSX16(ReduceEntryFunArgs *Arguments); - - // Attempts to reduce two MOVE instructions into MOVEP instruction, - // returns true on success. - static bool ReduceMoveToMovep(ReduceEntryFunArgs *Arguments); - - // Attempts to reduce arithmetic instructions, returns true on success. - static bool ReduceArithmeticInstructions(ReduceEntryFunArgs *Arguments); - - // Attempts to reduce ADDIU into ADDIUSP instruction, - // returns true on success. - static bool ReduceADDIUToADDIUSP(ReduceEntryFunArgs *Arguments); - - // Attempts to reduce ADDIU into ADDIUR1SP instruction, - // returns true on success. - static bool ReduceADDIUToADDIUR1SP(ReduceEntryFunArgs *Arguments); - - // Attempts to reduce XOR into XOR16 instruction, - // returns true on success. - static bool ReduceXORtoXOR16(ReduceEntryFunArgs *Arguments); - - // Changes opcode of an instruction, replaces an instruction with a - // new one, or replaces two instructions with a new instruction - // depending on their order i.e. if these are consecutive forward - // or consecutive backward - static bool ReplaceInstruction(MachineInstr *MI, const ReduceEntry &Entry, - MachineInstr *MI2 = nullptr, - bool ConsecutiveForward = true); - - // Table with transformation rules for each instruction. - static ReduceEntryVector ReduceTable; -}; - -char MicroMipsSizeReduce::ID = 0; -const MipsInstrInfo *MicroMipsSizeReduce::MipsII; - -// This table must be sorted by WideOpc as a main criterion and -// ReduceType as a sub-criterion (when wide opcodes are the same). -ReduceEntryVector MicroMipsSizeReduce::ReduceTable = { - - // ReduceType, OpCodes, ReduceFunction, - // OpInfo(TransferOperands), - // ImmField(Shift, LBound, HBound, ImmFieldPosition) - {RT_OneInstr, OpCodes(Mips::ADDiu, Mips::ADDIUR1SP_MM), - ReduceADDIUToADDIUR1SP, OpInfo(OT_Operands02), ImmField(2, 0, 64, 2)}, - {RT_OneInstr, OpCodes(Mips::ADDiu, Mips::ADDIUSP_MM), ReduceADDIUToADDIUSP, - OpInfo(OT_Operand2), ImmField(0, 0, 0, 2)}, - {RT_OneInstr, OpCodes(Mips::ADDiu_MM, Mips::ADDIUR1SP_MM), - ReduceADDIUToADDIUR1SP, OpInfo(OT_Operands02), ImmField(2, 0, 64, 2)}, - {RT_OneInstr, OpCodes(Mips::ADDiu_MM, Mips::ADDIUSP_MM), - ReduceADDIUToADDIUSP, OpInfo(OT_Operand2), ImmField(0, 0, 0, 2)}, - {RT_OneInstr, OpCodes(Mips::ADDu, Mips::ADDU16_MM), - ReduceArithmeticInstructions, OpInfo(OT_OperandsAll), - ImmField(0, 0, 0, -1)}, - {RT_OneInstr, OpCodes(Mips::ADDu_MM, Mips::ADDU16_MM), - ReduceArithmeticInstructions, OpInfo(OT_OperandsAll), - ImmField(0, 0, 0, -1)}, - {RT_OneInstr, OpCodes(Mips::LBu, Mips::LBU16_MM), ReduceLXUtoLXU16, - OpInfo(OT_OperandsAll), ImmField(0, -1, 15, 2)}, - {RT_OneInstr, OpCodes(Mips::LBu_MM, Mips::LBU16_MM), ReduceLXUtoLXU16, - OpInfo(OT_OperandsAll), ImmField(0, -1, 15, 2)}, - {RT_OneInstr, OpCodes(Mips::LEA_ADDiu, Mips::ADDIUR1SP_MM), - ReduceADDIUToADDIUR1SP, OpInfo(OT_Operands02), ImmField(2, 0, 64, 2)}, - {RT_OneInstr, OpCodes(Mips::LEA_ADDiu_MM, Mips::ADDIUR1SP_MM), - ReduceADDIUToADDIUR1SP, OpInfo(OT_Operands02), ImmField(2, 0, 64, 2)}, - {RT_OneInstr, OpCodes(Mips::LHu, Mips::LHU16_MM), ReduceLXUtoLXU16, - OpInfo(OT_OperandsAll), ImmField(1, 0, 16, 2)}, - {RT_OneInstr, OpCodes(Mips::LHu_MM, Mips::LHU16_MM), ReduceLXUtoLXU16, - OpInfo(OT_OperandsAll), ImmField(1, 0, 16, 2)}, - {RT_TwoInstr, OpCodes(Mips::LW, Mips::LWP_MM), ReduceXWtoXWP, - OpInfo(OT_OperandsLwp), ImmField(0, -2048, 2048, 2)}, - {RT_OneInstr, OpCodes(Mips::LW, Mips::LWSP_MM), ReduceXWtoXWSP, - OpInfo(OT_OperandsAll), ImmField(2, 0, 32, 2)}, - {RT_TwoInstr, OpCodes(Mips::LW16_MM, Mips::LWP_MM), ReduceXWtoXWP, - OpInfo(OT_OperandsLwp), ImmField(0, -2048, 2048, 2)}, - {RT_TwoInstr, OpCodes(Mips::LW_MM, Mips::LWP_MM), ReduceXWtoXWP, - OpInfo(OT_OperandsLwp), ImmField(0, -2048, 2048, 2)}, - {RT_OneInstr, OpCodes(Mips::LW_MM, Mips::LWSP_MM), ReduceXWtoXWSP, - OpInfo(OT_OperandsAll), ImmField(2, 0, 32, 2)}, - {RT_TwoInstr, OpCodes(Mips::MOVE16_MM, Mips::MOVEP_MM), ReduceMoveToMovep, - OpInfo(OT_OperandsMovep), ImmField(0, 0, 0, -1)}, - {RT_OneInstr, OpCodes(Mips::SB, Mips::SB16_MM), ReduceSXtoSX16, - OpInfo(OT_OperandsAll), ImmField(0, 0, 16, 2)}, - {RT_OneInstr, OpCodes(Mips::SB_MM, Mips::SB16_MM), ReduceSXtoSX16, - OpInfo(OT_OperandsAll), ImmField(0, 0, 16, 2)}, - {RT_OneInstr, OpCodes(Mips::SH, Mips::SH16_MM), ReduceSXtoSX16, - OpInfo(OT_OperandsAll), ImmField(1, 0, 16, 2)}, - {RT_OneInstr, OpCodes(Mips::SH_MM, Mips::SH16_MM), ReduceSXtoSX16, - OpInfo(OT_OperandsAll), ImmField(1, 0, 16, 2)}, - {RT_OneInstr, OpCodes(Mips::SUBu, Mips::SUBU16_MM), - ReduceArithmeticInstructions, OpInfo(OT_OperandsAll), - ImmField(0, 0, 0, -1)}, - {RT_OneInstr, OpCodes(Mips::SUBu_MM, Mips::SUBU16_MM), - ReduceArithmeticInstructions, OpInfo(OT_OperandsAll), - ImmField(0, 0, 0, -1)}, - {RT_TwoInstr, OpCodes(Mips::SW, Mips::SWP_MM), ReduceXWtoXWP, - OpInfo(OT_OperandsSwp), ImmField(0, -2048, 2048, 2)}, - {RT_OneInstr, OpCodes(Mips::SW, Mips::SWSP_MM), ReduceXWtoXWSP, - OpInfo(OT_OperandsAll), ImmField(2, 0, 32, 2)}, - {RT_TwoInstr, OpCodes(Mips::SW16_MM, Mips::SWP_MM), ReduceXWtoXWP, - OpInfo(OT_OperandsSwp), ImmField(0, -2048, 2048, 2)}, - {RT_TwoInstr, OpCodes(Mips::SW_MM, Mips::SWP_MM), ReduceXWtoXWP, - OpInfo(OT_OperandsSwp), ImmField(0, -2048, 2048, 2)}, - {RT_OneInstr, OpCodes(Mips::SW_MM, Mips::SWSP_MM), ReduceXWtoXWSP, - OpInfo(OT_OperandsAll), ImmField(2, 0, 32, 2)}, - {RT_OneInstr, OpCodes(Mips::XOR, Mips::XOR16_MM), ReduceXORtoXOR16, - OpInfo(OT_OperandsXOR), ImmField(0, 0, 0, -1)}, - {RT_OneInstr, OpCodes(Mips::XOR_MM, Mips::XOR16_MM), ReduceXORtoXOR16, - OpInfo(OT_OperandsXOR), ImmField(0, 0, 0, -1)}}; -} // end anonymous namespace - -INITIALIZE_PASS(MicroMipsSizeReduce, DEBUG_TYPE, MICROMIPS_SIZE_REDUCE_NAME, - false, false) - -// Returns true if the machine operand MO is register SP. -static bool IsSP(const MachineOperand &MO) { - if (MO.isReg() && ((MO.getReg() == Mips::SP))) - return true; - return false; -} - -// Returns true if the machine operand MO is register $16, $17, or $2-$7. -static bool isMMThreeBitGPRegister(const MachineOperand &MO) { - if (MO.isReg() && Mips::GPRMM16RegClass.contains(MO.getReg())) - return true; - return false; -} - -// Returns true if the machine operand MO is register $0, $17, or $2-$7. -static bool isMMSourceRegister(const MachineOperand &MO) { - if (MO.isReg() && Mips::GPRMM16ZeroRegClass.contains(MO.getReg())) - return true; - return false; -} - -// Returns true if the operand Op is an immediate value -// and writes the immediate value into variable Imm. -static bool GetImm(MachineInstr *MI, unsigned Op, int64_t &Imm) { - - if (!MI->getOperand(Op).isImm()) - return false; - Imm = MI->getOperand(Op).getImm(); - return true; -} - -// Returns true if the value is a valid immediate for ADDIUSP. -static bool AddiuspImmValue(int64_t Value) { - int64_t Value2 = Value >> 2; - if (((Value & (int64_t)maskTrailingZeros<uint64_t>(2)) == Value) && - ((Value2 >= 2 && Value2 <= 257) || (Value2 >= -258 && Value2 <= -3))) - return true; - return false; -} - -// Returns true if the variable Value has the number of least-significant zero -// bits equal to Shift and if the shifted value is between the bounds. -static bool InRange(int64_t Value, unsigned short Shift, int LBound, - int HBound) { - int64_t Value2 = Value >> Shift; - if (((Value & (int64_t)maskTrailingZeros<uint64_t>(Shift)) == Value) && - (Value2 >= LBound) && (Value2 < HBound)) - return true; - return false; -} - -// Returns true if immediate operand is in range. -static bool ImmInRange(MachineInstr *MI, const ReduceEntry &Entry) { - - int64_t offset; - - if (!GetImm(MI, Entry.ImmField(), offset)) - return false; - - if (!InRange(offset, Entry.Shift(), Entry.LBound(), Entry.HBound())) - return false; - - return true; -} - -// Returns true if MI can be reduced to lwp/swp instruction -static bool CheckXWPInstr(MachineInstr *MI, bool ReduceToLwp, - const ReduceEntry &Entry) { - - if (ReduceToLwp && - !(MI->getOpcode() == Mips::LW || MI->getOpcode() == Mips::LW_MM || - MI->getOpcode() == Mips::LW16_MM)) - return false; - - if (!ReduceToLwp && - !(MI->getOpcode() == Mips::SW || MI->getOpcode() == Mips::SW_MM || - MI->getOpcode() == Mips::SW16_MM)) - return false; - - unsigned reg = MI->getOperand(0).getReg(); - if (reg == Mips::RA) - return false; - - if (!ImmInRange(MI, Entry)) - return false; - - if (ReduceToLwp && (MI->getOperand(0).getReg() == MI->getOperand(1).getReg())) - return false; - - return true; -} - -// Returns true if the registers Reg1 and Reg2 are consecutive -static bool ConsecutiveRegisters(unsigned Reg1, unsigned Reg2) { - static SmallVector<unsigned, 31> Registers = { - Mips::AT, Mips::V0, Mips::V1, Mips::A0, Mips::A1, Mips::A2, Mips::A3, - Mips::T0, Mips::T1, Mips::T2, Mips::T3, Mips::T4, Mips::T5, Mips::T6, - Mips::T7, Mips::S0, Mips::S1, Mips::S2, Mips::S3, Mips::S4, Mips::S5, - Mips::S6, Mips::S7, Mips::T8, Mips::T9, Mips::K0, Mips::K1, Mips::GP, - Mips::SP, Mips::FP, Mips::RA}; - - for (uint8_t i = 0; i < Registers.size() - 1; i++) { - if (Registers[i] == Reg1) { - if (Registers[i + 1] == Reg2) - return true; - else - return false; - } - } - return false; -} - -// Returns true if registers and offsets are consecutive -static bool ConsecutiveInstr(MachineInstr *MI1, MachineInstr *MI2) { - - int64_t Offset1, Offset2; - if (!GetImm(MI1, 2, Offset1)) - return false; - if (!GetImm(MI2, 2, Offset2)) - return false; - - unsigned Reg1 = MI1->getOperand(0).getReg(); - unsigned Reg2 = MI2->getOperand(0).getReg(); - - return ((Offset1 == (Offset2 - 4)) && (ConsecutiveRegisters(Reg1, Reg2))); -} - -MicroMipsSizeReduce::MicroMipsSizeReduce() : MachineFunctionPass(ID) {} - -bool MicroMipsSizeReduce::ReduceMI(const MachineBasicBlock::instr_iterator &MII, - MachineBasicBlock::instr_iterator &NextMII) { - - MachineInstr *MI = &*MII; - unsigned Opcode = MI->getOpcode(); - - // Search the table. - ReduceEntryVector::const_iterator Start = std::begin(ReduceTable); - ReduceEntryVector::const_iterator End = std::end(ReduceTable); - - std::pair<ReduceEntryVector::const_iterator, - ReduceEntryVector::const_iterator> - Range = std::equal_range(Start, End, Opcode); - - if (Range.first == Range.second) - return false; - - for (ReduceEntryVector::const_iterator Entry = Range.first; - Entry != Range.second; ++Entry) { - ReduceEntryFunArgs Arguments(&(*MII), *Entry, NextMII); - if (((*Entry).ReduceFunction)(&Arguments)) - return true; - } - return false; -} - -bool MicroMipsSizeReduce::ReduceXWtoXWSP(ReduceEntryFunArgs *Arguments) { - - MachineInstr *MI = Arguments->MI; - const ReduceEntry &Entry = Arguments->Entry; - - if (!ImmInRange(MI, Entry)) - return false; - - if (!IsSP(MI->getOperand(1))) - return false; - - return ReplaceInstruction(MI, Entry); -} - -bool MicroMipsSizeReduce::ReduceXWtoXWP(ReduceEntryFunArgs *Arguments) { - - const ReduceEntry &Entry = Arguments->Entry; - MachineBasicBlock::instr_iterator &NextMII = Arguments->NextMII; - const MachineBasicBlock::instr_iterator &E = - Arguments->MI->getParent()->instr_end(); - - if (NextMII == E) - return false; - - MachineInstr *MI1 = Arguments->MI; - MachineInstr *MI2 = &*NextMII; - - // ReduceToLwp = true/false - reduce to LWP/SWP instruction - bool ReduceToLwp = (MI1->getOpcode() == Mips::LW) || - (MI1->getOpcode() == Mips::LW_MM) || - (MI1->getOpcode() == Mips::LW16_MM); - - if (!CheckXWPInstr(MI1, ReduceToLwp, Entry)) - return false; - - if (!CheckXWPInstr(MI2, ReduceToLwp, Entry)) - return false; - - unsigned Reg1 = MI1->getOperand(1).getReg(); - unsigned Reg2 = MI2->getOperand(1).getReg(); - - if (Reg1 != Reg2) - return false; - - bool ConsecutiveForward = ConsecutiveInstr(MI1, MI2); - bool ConsecutiveBackward = ConsecutiveInstr(MI2, MI1); - - if (!(ConsecutiveForward || ConsecutiveBackward)) - return false; - - NextMII = std::next(NextMII); - return ReplaceInstruction(MI1, Entry, MI2, ConsecutiveForward); -} - -bool MicroMipsSizeReduce::ReduceArithmeticInstructions( - ReduceEntryFunArgs *Arguments) { - - MachineInstr *MI = Arguments->MI; - const ReduceEntry &Entry = Arguments->Entry; - - if (!isMMThreeBitGPRegister(MI->getOperand(0)) || - !isMMThreeBitGPRegister(MI->getOperand(1)) || - !isMMThreeBitGPRegister(MI->getOperand(2))) - return false; - - return ReplaceInstruction(MI, Entry); -} - -bool MicroMipsSizeReduce::ReduceADDIUToADDIUR1SP( - ReduceEntryFunArgs *Arguments) { - - MachineInstr *MI = Arguments->MI; - const ReduceEntry &Entry = Arguments->Entry; - - if (!ImmInRange(MI, Entry)) - return false; - - if (!isMMThreeBitGPRegister(MI->getOperand(0)) || !IsSP(MI->getOperand(1))) - return false; - - return ReplaceInstruction(MI, Entry); -} - -bool MicroMipsSizeReduce::ReduceADDIUToADDIUSP(ReduceEntryFunArgs *Arguments) { - - MachineInstr *MI = Arguments->MI; - const ReduceEntry &Entry = Arguments->Entry; - - int64_t ImmValue; - if (!GetImm(MI, Entry.ImmField(), ImmValue)) - return false; - - if (!AddiuspImmValue(ImmValue)) - return false; - - if (!IsSP(MI->getOperand(0)) || !IsSP(MI->getOperand(1))) - return false; - - return ReplaceInstruction(MI, Entry); -} - -bool MicroMipsSizeReduce::ReduceLXUtoLXU16(ReduceEntryFunArgs *Arguments) { - - MachineInstr *MI = Arguments->MI; - const ReduceEntry &Entry = Arguments->Entry; - - if (!ImmInRange(MI, Entry)) - return false; - - if (!isMMThreeBitGPRegister(MI->getOperand(0)) || - !isMMThreeBitGPRegister(MI->getOperand(1))) - return false; - - return ReplaceInstruction(MI, Entry); -} - -bool MicroMipsSizeReduce::ReduceSXtoSX16(ReduceEntryFunArgs *Arguments) { - - MachineInstr *MI = Arguments->MI; - const ReduceEntry &Entry = Arguments->Entry; - - if (!ImmInRange(MI, Entry)) - return false; - - if (!isMMSourceRegister(MI->getOperand(0)) || - !isMMThreeBitGPRegister(MI->getOperand(1))) - return false; - - return ReplaceInstruction(MI, Entry); -} - -// Returns true if Reg can be a source register -// of MOVEP instruction -static bool IsMovepSrcRegister(unsigned Reg) { - - if (Reg == Mips::ZERO || Reg == Mips::V0 || Reg == Mips::V1 || - Reg == Mips::S0 || Reg == Mips::S1 || Reg == Mips::S2 || - Reg == Mips::S3 || Reg == Mips::S4) - return true; - - return false; -} - -// Returns true if Reg can be a destination register -// of MOVEP instruction -static bool IsMovepDestinationReg(unsigned Reg) { - - if (Reg == Mips::A0 || Reg == Mips::A1 || Reg == Mips::A2 || - Reg == Mips::A3 || Reg == Mips::S5 || Reg == Mips::S6) - return true; - - return false; -} - -// Returns true if the registers can be a pair of destination -// registers in MOVEP instruction -static bool IsMovepDestinationRegPair(unsigned R0, unsigned R1) { - - if ((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) || - (R0 == Mips::A1 && R1 == Mips::A2) || - (R0 == Mips::A1 && R1 == Mips::A3) || - (R0 == Mips::A2 && R1 == Mips::A3)) - return true; - - return false; -} - -bool MicroMipsSizeReduce::ReduceMoveToMovep(ReduceEntryFunArgs *Arguments) { - - const ReduceEntry &Entry = Arguments->Entry; - MachineBasicBlock::instr_iterator &NextMII = Arguments->NextMII; - const MachineBasicBlock::instr_iterator &E = - Arguments->MI->getParent()->instr_end(); - - if (NextMII == E) - return false; - - MachineInstr *MI1 = Arguments->MI; - MachineInstr *MI2 = &*NextMII; - - unsigned RegDstMI1 = MI1->getOperand(0).getReg(); - unsigned RegSrcMI1 = MI1->getOperand(1).getReg(); - - if (!IsMovepSrcRegister(RegSrcMI1)) - return false; - - if (!IsMovepDestinationReg(RegDstMI1)) - return false; - - if (MI2->getOpcode() != Entry.WideOpc()) - return false; - - unsigned RegDstMI2 = MI2->getOperand(0).getReg(); - unsigned RegSrcMI2 = MI2->getOperand(1).getReg(); - - if (!IsMovepSrcRegister(RegSrcMI2)) - return false; - - bool ConsecutiveForward; - if (IsMovepDestinationRegPair(RegDstMI1, RegDstMI2)) { - ConsecutiveForward = true; - } else if (IsMovepDestinationRegPair(RegDstMI2, RegDstMI1)) { - ConsecutiveForward = false; - } else - return false; - - NextMII = std::next(NextMII); - return ReplaceInstruction(MI1, Entry, MI2, ConsecutiveForward); -} - -bool MicroMipsSizeReduce::ReduceXORtoXOR16(ReduceEntryFunArgs *Arguments) { - - MachineInstr *MI = Arguments->MI; - const ReduceEntry &Entry = Arguments->Entry; - - if (!isMMThreeBitGPRegister(MI->getOperand(0)) || - !isMMThreeBitGPRegister(MI->getOperand(1)) || - !isMMThreeBitGPRegister(MI->getOperand(2))) - return false; - - if (!(MI->getOperand(0).getReg() == MI->getOperand(2).getReg()) && - !(MI->getOperand(0).getReg() == MI->getOperand(1).getReg())) - return false; - - return ReplaceInstruction(MI, Entry); -} - -bool MicroMipsSizeReduce::ReduceMBB(MachineBasicBlock &MBB) { - bool Modified = false; - MachineBasicBlock::instr_iterator MII = MBB.instr_begin(), - E = MBB.instr_end(); - MachineBasicBlock::instr_iterator NextMII; - - // Iterate through the instructions in the basic block - for (; MII != E; MII = NextMII) { - NextMII = std::next(MII); - MachineInstr *MI = &*MII; - - // Don't reduce bundled instructions or pseudo operations - if (MI->isBundle() || MI->isTransient()) - continue; - - // Try to reduce 32-bit instruction into 16-bit instruction - Modified |= ReduceMI(MII, NextMII); - } - - return Modified; -} - -bool MicroMipsSizeReduce::ReplaceInstruction(MachineInstr *MI, - const ReduceEntry &Entry, - MachineInstr *MI2, - bool ConsecutiveForward) { - - enum OperandTransfer OpTransfer = Entry.TransferOperands(); - - LLVM_DEBUG(dbgs() << "Converting 32-bit: " << *MI); - ++NumReduced; - - if (OpTransfer == OT_OperandsAll) { - MI->setDesc(MipsII->get(Entry.NarrowOpc())); - LLVM_DEBUG(dbgs() << " to 16-bit: " << *MI); - return true; - } else { - MachineBasicBlock &MBB = *MI->getParent(); - const MCInstrDesc &NewMCID = MipsII->get(Entry.NarrowOpc()); - DebugLoc dl = MI->getDebugLoc(); - MachineInstrBuilder MIB = BuildMI(MBB, MI, dl, NewMCID); - switch (OpTransfer) { - case OT_Operand2: - MIB.add(MI->getOperand(2)); - break; - case OT_Operands02: { - MIB.add(MI->getOperand(0)); - MIB.add(MI->getOperand(2)); - break; - } - case OT_OperandsXOR: { - if (MI->getOperand(0).getReg() == MI->getOperand(2).getReg()) { - MIB.add(MI->getOperand(0)); - MIB.add(MI->getOperand(1)); - MIB.add(MI->getOperand(2)); - } else { - MIB.add(MI->getOperand(0)); - MIB.add(MI->getOperand(2)); - MIB.add(MI->getOperand(1)); - } - break; - } - case OT_OperandsMovep: - case OT_OperandsLwp: - case OT_OperandsSwp: { - if (ConsecutiveForward) { - MIB.add(MI->getOperand(0)); - MIB.add(MI2->getOperand(0)); - MIB.add(MI->getOperand(1)); - if (OpTransfer == OT_OperandsMovep) - MIB.add(MI2->getOperand(1)); - else - MIB.add(MI->getOperand(2)); - } else { // consecutive backward - MIB.add(MI2->getOperand(0)); - MIB.add(MI->getOperand(0)); - MIB.add(MI2->getOperand(1)); - if (OpTransfer == OT_OperandsMovep) - MIB.add(MI->getOperand(1)); - else - MIB.add(MI2->getOperand(2)); - } - - LLVM_DEBUG(dbgs() << "and converting 32-bit: " << *MI2 - << " to: " << *MIB); - - MBB.erase_instr(MI); - MBB.erase_instr(MI2); - return true; - } - default: - llvm_unreachable("Unknown operand transfer!"); - } - - // Transfer MI flags. - MIB.setMIFlags(MI->getFlags()); - - LLVM_DEBUG(dbgs() << " to 16-bit: " << *MIB); - MBB.erase_instr(MI); - return true; - } - return false; -} - -bool MicroMipsSizeReduce::runOnMachineFunction(MachineFunction &MF) { - - Subtarget = &static_cast<const MipsSubtarget &>(MF.getSubtarget()); - - // TODO: Add support for the subtarget microMIPS32R6. - if (!Subtarget->inMicroMipsMode() || !Subtarget->hasMips32r2() || - Subtarget->hasMips32r6()) - return false; - - MipsII = static_cast<const MipsInstrInfo *>(Subtarget->getInstrInfo()); - - bool Modified = false; - MachineFunction::iterator I = MF.begin(), E = MF.end(); - - for (; I != E; ++I) - Modified |= ReduceMBB(*I); - return Modified; -} - -/// Returns an instance of the MicroMips size reduction pass. -FunctionPass *llvm::createMicroMipsSizeReducePass() { - return new MicroMipsSizeReduce(); -} diff --git a/contrib/llvm/lib/Target/Mips/Mips.h b/contrib/llvm/lib/Target/Mips/Mips.h deleted file mode 100644 index b3faaab436f0..000000000000 --- a/contrib/llvm/lib/Target/Mips/Mips.h +++ /dev/null @@ -1,52 +0,0 @@ -//===-- Mips.h - Top-level interface for Mips representation ----*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains the entry points for global functions defined in -// the LLVM Mips back-end. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_MIPS_MIPS_H -#define LLVM_LIB_TARGET_MIPS_MIPS_H - -#include "MCTargetDesc/MipsMCTargetDesc.h" -#include "llvm/Target/TargetMachine.h" - -namespace llvm { - class MipsTargetMachine; - class ModulePass; - class FunctionPass; - class MipsRegisterBankInfo; - class MipsSubtarget; - class MipsTargetMachine; - class InstructionSelector; - class PassRegistry; - - ModulePass *createMipsOs16Pass(); - ModulePass *createMips16HardFloatPass(); - - FunctionPass *createMipsModuleISelDagPass(); - FunctionPass *createMipsOptimizePICCallPass(); - FunctionPass *createMipsDelaySlotFillerPass(); - FunctionPass *createMipsBranchExpansion(); - FunctionPass *createMipsConstantIslandPass(); - FunctionPass *createMicroMipsSizeReducePass(); - FunctionPass *createMipsExpandPseudoPass(); - FunctionPass *createMipsPreLegalizeCombiner(); - - InstructionSelector *createMipsInstructionSelector(const MipsTargetMachine &, - MipsSubtarget &, - MipsRegisterBankInfo &); - - void initializeMipsDelaySlotFillerPass(PassRegistry &); - void initializeMipsBranchExpansionPass(PassRegistry &); - void initializeMicroMipsSizeReducePass(PassRegistry &); - void initializeMipsPreLegalizerCombinerPass(PassRegistry&); -} // end namespace llvm; - -#endif diff --git a/contrib/llvm/lib/Target/Mips/Mips.td b/contrib/llvm/lib/Target/Mips/Mips.td deleted file mode 100644 index cac07c35d49f..000000000000 --- a/contrib/llvm/lib/Target/Mips/Mips.td +++ /dev/null @@ -1,264 +0,0 @@ -//===-- Mips.td - Describe the Mips Target Machine ---------*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// This is the top level entry point for the Mips target. -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// Target-independent interfaces -//===----------------------------------------------------------------------===// - -include "llvm/Target/Target.td" - -// The overall idea of the PredicateControl class is to chop the Predicates list -// into subsets that are usually overridden independently. This allows -// subclasses to partially override the predicates of their superclasses without -// having to re-add all the existing predicates. -class PredicateControl { - // Predicates for the encoding scheme in use such as HasStdEnc - list<Predicate> EncodingPredicates = []; - // Predicates for the GPR size such as IsGP64bit - list<Predicate> GPRPredicates = []; - // Predicates for the PTR size such as IsPTR64bit - list<Predicate> PTRPredicates = []; - // Predicates for the FGR size and layout such as IsFP64bit - list<Predicate> FGRPredicates = []; - // Predicates for the instruction group membership such as ISA's. - list<Predicate> InsnPredicates = []; - // Predicate for the ASE that an instruction belongs to. - list<Predicate> ASEPredicate = []; - // Predicate for marking the instruction as usable in hard-float mode only. - list<Predicate> HardFloatPredicate = []; - // Predicates for anything else - list<Predicate> AdditionalPredicates = []; - list<Predicate> Predicates = !listconcat(EncodingPredicates, - GPRPredicates, - PTRPredicates, - FGRPredicates, - InsnPredicates, - HardFloatPredicate, - ASEPredicate, - AdditionalPredicates); -} - -// Like Requires<> but for the AdditionalPredicates list -class AdditionalRequires<list<Predicate> preds> { - list<Predicate> AdditionalPredicates = preds; -} - -//===----------------------------------------------------------------------===// -// Register File, Calling Conv, Instruction Descriptions -//===----------------------------------------------------------------------===// - -include "MipsRegisterInfo.td" -include "MipsSchedule.td" -include "MipsInstrInfo.td" -include "MipsCallingConv.td" -include "MipsRegisterBanks.td" - -// Avoid forward declaration issues. -include "MipsScheduleP5600.td" -include "MipsScheduleGeneric.td" - -def MipsInstrInfo : InstrInfo; - -//===----------------------------------------------------------------------===// -// Mips Subtarget features // -//===----------------------------------------------------------------------===// - -def FeatureNoABICalls : SubtargetFeature<"noabicalls", "NoABICalls", "true", - "Disable SVR4-style position-independent code">; -def FeaturePTR64Bit : SubtargetFeature<"ptr64", "IsPTR64bit", "true", - "Pointers are 64-bit wide">; -def FeatureGP64Bit : SubtargetFeature<"gp64", "IsGP64bit", "true", - "General Purpose Registers are 64-bit wide">; -def FeatureFP64Bit : SubtargetFeature<"fp64", "IsFP64bit", "true", - "Support 64-bit FP registers">; -def FeatureFPXX : SubtargetFeature<"fpxx", "IsFPXX", "true", - "Support for FPXX">; -def FeatureNaN2008 : SubtargetFeature<"nan2008", "IsNaN2008bit", "true", - "IEEE 754-2008 NaN encoding">; -def FeatureAbs2008 : SubtargetFeature<"abs2008", "Abs2008", "true", - "Disable IEEE 754-2008 abs.fmt mode">; -def FeatureSingleFloat : SubtargetFeature<"single-float", "IsSingleFloat", - "true", "Only supports single precision float">; -def FeatureSoftFloat : SubtargetFeature<"soft-float", "IsSoftFloat", "true", - "Does not support floating point instructions">; -def FeatureNoOddSPReg : SubtargetFeature<"nooddspreg", "UseOddSPReg", "false", - "Disable odd numbered single-precision " - "registers">; -def FeatureVFPU : SubtargetFeature<"vfpu", "HasVFPU", - "true", "Enable vector FPU instructions">; -def FeatureMips1 : SubtargetFeature<"mips1", "MipsArchVersion", "Mips1", - "Mips I ISA Support [highly experimental]">; -def FeatureMips2 : SubtargetFeature<"mips2", "MipsArchVersion", "Mips2", - "Mips II ISA Support [highly experimental]", - [FeatureMips1]>; -def FeatureMips3_32 : SubtargetFeature<"mips3_32", "HasMips3_32", "true", - "Subset of MIPS-III that is also in MIPS32 " - "[highly experimental]">; -def FeatureMips3_32r2 : SubtargetFeature<"mips3_32r2", "HasMips3_32r2", "true", - "Subset of MIPS-III that is also in MIPS32r2 " - "[highly experimental]">; -def FeatureMips3 : SubtargetFeature<"mips3", "MipsArchVersion", "Mips3", - "MIPS III ISA Support [highly experimental]", - [FeatureMips2, FeatureMips3_32, - FeatureMips3_32r2, FeatureGP64Bit, - FeatureFP64Bit]>; -def FeatureMips4_32 : SubtargetFeature<"mips4_32", "HasMips4_32", "true", - "Subset of MIPS-IV that is also in MIPS32 " - "[highly experimental]">; -def FeatureMips4_32r2 : SubtargetFeature<"mips4_32r2", "HasMips4_32r2", "true", - "Subset of MIPS-IV that is also in MIPS32r2 " - "[highly experimental]">; -def FeatureMips4 : SubtargetFeature<"mips4", "MipsArchVersion", - "Mips4", "MIPS IV ISA Support", - [FeatureMips3, FeatureMips4_32, - FeatureMips4_32r2]>; -def FeatureMips5_32r2 : SubtargetFeature<"mips5_32r2", "HasMips5_32r2", "true", - "Subset of MIPS-V that is also in MIPS32r2 " - "[highly experimental]">; -def FeatureMips5 : SubtargetFeature<"mips5", "MipsArchVersion", "Mips5", - "MIPS V ISA Support [highly experimental]", - [FeatureMips4, FeatureMips5_32r2]>; -def FeatureMips32 : SubtargetFeature<"mips32", "MipsArchVersion", "Mips32", - "Mips32 ISA Support", - [FeatureMips2, FeatureMips3_32, - FeatureMips4_32]>; -def FeatureMips32r2 : SubtargetFeature<"mips32r2", "MipsArchVersion", - "Mips32r2", "Mips32r2 ISA Support", - [FeatureMips3_32r2, FeatureMips4_32r2, - FeatureMips5_32r2, FeatureMips32]>; -def FeatureMips32r3 : SubtargetFeature<"mips32r3", "MipsArchVersion", - "Mips32r3", "Mips32r3 ISA Support", - [FeatureMips32r2]>; -def FeatureMips32r5 : SubtargetFeature<"mips32r5", "MipsArchVersion", - "Mips32r5", "Mips32r5 ISA Support", - [FeatureMips32r3]>; -def FeatureMips32r6 : SubtargetFeature<"mips32r6", "MipsArchVersion", - "Mips32r6", - "Mips32r6 ISA Support [experimental]", - [FeatureMips32r5, FeatureFP64Bit, - FeatureNaN2008, FeatureAbs2008]>; -def FeatureMips64 : SubtargetFeature<"mips64", "MipsArchVersion", - "Mips64", "Mips64 ISA Support", - [FeatureMips5, FeatureMips32]>; -def FeatureMips64r2 : SubtargetFeature<"mips64r2", "MipsArchVersion", - "Mips64r2", "Mips64r2 ISA Support", - [FeatureMips64, FeatureMips32r2]>; -def FeatureMips64r3 : SubtargetFeature<"mips64r3", "MipsArchVersion", - "Mips64r3", "Mips64r3 ISA Support", - [FeatureMips64r2, FeatureMips32r3]>; -def FeatureMips64r5 : SubtargetFeature<"mips64r5", "MipsArchVersion", - "Mips64r5", "Mips64r5 ISA Support", - [FeatureMips64r3, FeatureMips32r5]>; -def FeatureMips64r6 : SubtargetFeature<"mips64r6", "MipsArchVersion", - "Mips64r6", - "Mips64r6 ISA Support [experimental]", - [FeatureMips32r6, FeatureMips64r5, - FeatureNaN2008, FeatureAbs2008]>; -def FeatureSym32 : SubtargetFeature<"sym32", "HasSym32", "true", - "Symbols are 32 bit on Mips64">; - -def FeatureMips16 : SubtargetFeature<"mips16", "InMips16Mode", "true", - "Mips16 mode">; - -def FeatureDSP : SubtargetFeature<"dsp", "HasDSP", "true", "Mips DSP ASE">; -def FeatureDSPR2 : SubtargetFeature<"dspr2", "HasDSPR2", "true", - "Mips DSP-R2 ASE", [FeatureDSP]>; -def FeatureDSPR3 - : SubtargetFeature<"dspr3", "HasDSPR3", "true", "Mips DSP-R3 ASE", - [ FeatureDSP, FeatureDSPR2 ]>; - -def FeatureMSA : SubtargetFeature<"msa", "HasMSA", "true", "Mips MSA ASE">; - -def FeatureEVA : SubtargetFeature<"eva", "HasEVA", "true", "Mips EVA ASE">; - -def FeatureCRC : SubtargetFeature<"crc", "HasCRC", "true", "Mips R6 CRC ASE">; - -def FeatureVirt : SubtargetFeature<"virt", "HasVirt", "true", - "Mips Virtualization ASE">; - -def FeatureGINV : SubtargetFeature<"ginv", "HasGINV", "true", - "Mips Global Invalidate ASE">; - -def FeatureMicroMips : SubtargetFeature<"micromips", "InMicroMipsMode", "true", - "microMips mode">; - -def FeatureCnMips : SubtargetFeature<"cnmips", "HasCnMips", - "true", "Octeon cnMIPS Support", - [FeatureMips64r2]>; - -def FeatureCnMipsP : SubtargetFeature<"cnmipsp", "HasCnMipsP", - "true", "Octeon+ cnMIPS Support", - [FeatureCnMips]>; - -def FeatureUseTCCInDIV : SubtargetFeature< - "use-tcc-in-div", - "UseTCCInDIV", "false", - "Force the assembler to use trapping">; - -def FeatureMadd4 : SubtargetFeature<"nomadd4", "DisableMadd4", "true", - "Disable 4-operand madd.fmt and related instructions">; - -def FeatureMT : SubtargetFeature<"mt", "HasMT", "true", "Mips MT ASE">; - -def FeatureLongCalls : SubtargetFeature<"long-calls", "UseLongCalls", "true", - "Disable use of the jal instruction">; - -def FeatureUseIndirectJumpsHazard : SubtargetFeature<"use-indirect-jump-hazard", - "UseIndirectJumpsHazard", - "true", "Use indirect jump" - " guards to prevent certain speculation based attacks">; -//===----------------------------------------------------------------------===// -// Mips processors supported. -//===----------------------------------------------------------------------===// - -def ImplP5600 : SubtargetFeature<"p5600", "ProcImpl", - "MipsSubtarget::CPU::P5600", - "The P5600 Processor", [FeatureMips32r5]>; - -class Proc<string Name, list<SubtargetFeature> Features> - : ProcessorModel<Name, MipsGenericModel, Features>; - -def : Proc<"mips1", [FeatureMips1]>; -def : Proc<"mips2", [FeatureMips2]>; -def : Proc<"mips32", [FeatureMips32]>; -def : Proc<"mips32r2", [FeatureMips32r2]>; -def : Proc<"mips32r3", [FeatureMips32r3]>; -def : Proc<"mips32r5", [FeatureMips32r5]>; -def : Proc<"mips32r6", [FeatureMips32r6]>; - -def : Proc<"mips3", [FeatureMips3]>; -def : Proc<"mips4", [FeatureMips4]>; -def : Proc<"mips5", [FeatureMips5]>; -def : Proc<"mips64", [FeatureMips64]>; -def : Proc<"mips64r2", [FeatureMips64r2]>; -def : Proc<"mips64r3", [FeatureMips64r3]>; -def : Proc<"mips64r5", [FeatureMips64r5]>; -def : Proc<"mips64r6", [FeatureMips64r6]>; -def : Proc<"octeon", [FeatureMips64r2, FeatureCnMips]>; -def : Proc<"octeon+", [FeatureMips64r2, FeatureCnMips, FeatureCnMipsP]>; -def : ProcessorModel<"p5600", MipsP5600Model, [ImplP5600]>; - -def MipsAsmParser : AsmParser { - let ShouldEmitMatchRegisterName = 0; -} - -def MipsAsmParserVariant : AsmParserVariant { - int Variant = 0; - - // Recognize hard coded registers. - string RegisterPrefix = "$"; -} - -def Mips : Target { - let InstructionSet = MipsInstrInfo; - let AssemblyParsers = [MipsAsmParser]; - let AssemblyParserVariants = [MipsAsmParserVariant]; - let AllowRegisterRenaming = 1; -} diff --git a/contrib/llvm/lib/Target/Mips/Mips16FrameLowering.cpp b/contrib/llvm/lib/Target/Mips/Mips16FrameLowering.cpp deleted file mode 100644 index 5a2a916a6b7a..000000000000 --- a/contrib/llvm/lib/Target/Mips/Mips16FrameLowering.cpp +++ /dev/null @@ -1,180 +0,0 @@ -//===- Mips16FrameLowering.cpp - Mips16 Frame Information -----------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains the Mips16 implementation of TargetFrameLowering class. -// -//===----------------------------------------------------------------------===// - -#include "Mips16FrameLowering.h" -#include "MCTargetDesc/MipsBaseInfo.h" -#include "Mips16InstrInfo.h" -#include "MipsInstrInfo.h" -#include "MipsRegisterInfo.h" -#include "MipsSubtarget.h" -#include "llvm/ADT/BitVector.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/MachineModuleInfo.h" -#include "llvm/IR/DebugLoc.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCDwarf.h" -#include "llvm/MC/MCRegisterInfo.h" -#include "llvm/MC/MachineLocation.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/CodeGen/TargetFrameLowering.h" -#include <cassert> -#include <cstdint> -#include <vector> - -using namespace llvm; - -Mips16FrameLowering::Mips16FrameLowering(const MipsSubtarget &STI) - : MipsFrameLowering(STI, STI.getStackAlignment()) {} - -void Mips16FrameLowering::emitPrologue(MachineFunction &MF, - MachineBasicBlock &MBB) const { - MachineFrameInfo &MFI = MF.getFrameInfo(); - const Mips16InstrInfo &TII = - *static_cast<const Mips16InstrInfo *>(STI.getInstrInfo()); - MachineBasicBlock::iterator MBBI = MBB.begin(); - - // Debug location must be unknown since the first debug location is used - // to determine the end of the prologue. - DebugLoc dl; - - uint64_t StackSize = MFI.getStackSize(); - - // No need to allocate space on the stack. - if (StackSize == 0 && !MFI.adjustsStack()) return; - - MachineModuleInfo &MMI = MF.getMMI(); - const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo(); - - // Adjust stack. - TII.makeFrame(Mips::SP, StackSize, MBB, MBBI); - - // emit ".cfi_def_cfa_offset StackSize" - unsigned CFIIndex = MF.addFrameInst( - MCCFIInstruction::createDefCfaOffset(nullptr, -StackSize)); - BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) - .addCFIIndex(CFIIndex); - - const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); - - if (!CSI.empty()) { - const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); - - for (std::vector<CalleeSavedInfo>::const_iterator I = CSI.begin(), - E = CSI.end(); I != E; ++I) { - int64_t Offset = MFI.getObjectOffset(I->getFrameIdx()); - unsigned Reg = I->getReg(); - unsigned DReg = MRI->getDwarfRegNum(Reg, true); - unsigned CFIIndex = MF.addFrameInst( - MCCFIInstruction::createOffset(nullptr, DReg, Offset)); - BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) - .addCFIIndex(CFIIndex); - } - } - if (hasFP(MF)) - BuildMI(MBB, MBBI, dl, TII.get(Mips::MoveR3216), Mips::S0) - .addReg(Mips::SP).setMIFlag(MachineInstr::FrameSetup); -} - -void Mips16FrameLowering::emitEpilogue(MachineFunction &MF, - MachineBasicBlock &MBB) const { - MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator(); - MachineFrameInfo &MFI = MF.getFrameInfo(); - const Mips16InstrInfo &TII = - *static_cast<const Mips16InstrInfo *>(STI.getInstrInfo()); - DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); - uint64_t StackSize = MFI.getStackSize(); - - if (!StackSize) - return; - - if (hasFP(MF)) - BuildMI(MBB, MBBI, dl, TII.get(Mips::Move32R16), Mips::SP) - .addReg(Mips::S0); - - // Adjust stack. - // assumes stacksize multiple of 8 - TII.restoreFrame(Mips::SP, StackSize, MBB, MBBI); -} - -bool Mips16FrameLowering:: -spillCalleeSavedRegisters(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - const std::vector<CalleeSavedInfo> &CSI, - const TargetRegisterInfo *TRI) const { - MachineFunction *MF = MBB.getParent(); - - // - // Registers RA, S0,S1 are the callee saved registers and they - // will be saved with the "save" instruction - // during emitPrologue - // - for (unsigned i = 0, e = CSI.size(); i != e; ++i) { - // Add the callee-saved register as live-in. Do not add if the register is - // RA and return address is taken, because it has already been added in - // method MipsTargetLowering::lowerRETURNADDR. - // It's killed at the spill, unless the register is RA and return address - // is taken. - unsigned Reg = CSI[i].getReg(); - bool IsRAAndRetAddrIsTaken = (Reg == Mips::RA) - && MF->getFrameInfo().isReturnAddressTaken(); - if (!IsRAAndRetAddrIsTaken) - MBB.addLiveIn(Reg); - } - - return true; -} - -bool Mips16FrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - std::vector<CalleeSavedInfo> &CSI, - const TargetRegisterInfo *TRI) const { - // - // Registers RA,S0,S1 are the callee saved registers and they will be restored - // with the restore instruction during emitEpilogue. - // We need to override this virtual function, otherwise llvm will try and - // restore the registers on it's on from the stack. - // - - return true; -} - -bool -Mips16FrameLowering::hasReservedCallFrame(const MachineFunction &MF) const { - const MachineFrameInfo &MFI = MF.getFrameInfo(); - // Reserve call frame if the size of the maximum call frame fits into 15-bit - // immediate field and there are no variable sized objects on the stack. - return isInt<15>(MFI.getMaxCallFrameSize()) && !MFI.hasVarSizedObjects(); -} - -void Mips16FrameLowering::determineCalleeSaves(MachineFunction &MF, - BitVector &SavedRegs, - RegScavenger *RS) const { - TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); - const Mips16InstrInfo &TII = - *static_cast<const Mips16InstrInfo *>(STI.getInstrInfo()); - const MipsRegisterInfo &RI = TII.getRegisterInfo(); - const BitVector Reserved = RI.getReservedRegs(MF); - bool SaveS2 = Reserved[Mips::S2]; - if (SaveS2) - SavedRegs.set(Mips::S2); - if (hasFP(MF)) - SavedRegs.set(Mips::S0); -} - -const MipsFrameLowering * -llvm::createMips16FrameLowering(const MipsSubtarget &ST) { - return new Mips16FrameLowering(ST); -} diff --git a/contrib/llvm/lib/Target/Mips/Mips16FrameLowering.h b/contrib/llvm/lib/Target/Mips/Mips16FrameLowering.h deleted file mode 100644 index 6b62453f8dfe..000000000000 --- a/contrib/llvm/lib/Target/Mips/Mips16FrameLowering.h +++ /dev/null @@ -1,46 +0,0 @@ -//===-- Mips16FrameLowering.h - Mips16 frame lowering ----------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_MIPS_MIPS16FRAMELOWERING_H -#define LLVM_LIB_TARGET_MIPS_MIPS16FRAMELOWERING_H - -#include "MipsFrameLowering.h" - -namespace llvm { -class Mips16FrameLowering : public MipsFrameLowering { -public: - explicit Mips16FrameLowering(const MipsSubtarget &STI); - - /// emitProlog/emitEpilog - These methods insert prolog and epilog code into - /// the function. - void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override; - void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override; - - bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - const std::vector<CalleeSavedInfo> &CSI, - const TargetRegisterInfo *TRI) const override; - - bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - std::vector<CalleeSavedInfo> &CSI, - const TargetRegisterInfo *TRI) const override; - - bool hasReservedCallFrame(const MachineFunction &MF) const override; - - void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, - RegScavenger *RS) const override; -}; - -} // End llvm namespace - -#endif diff --git a/contrib/llvm/lib/Target/Mips/Mips16HardFloat.cpp b/contrib/llvm/lib/Target/Mips/Mips16HardFloat.cpp deleted file mode 100644 index e9a3c7ec4b19..000000000000 --- a/contrib/llvm/lib/Target/Mips/Mips16HardFloat.cpp +++ /dev/null @@ -1,536 +0,0 @@ -//===- Mips16HardFloat.cpp for Mips16 Hard Float --------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines a pass needed for Mips16 Hard Float -// -//===----------------------------------------------------------------------===// - -#include "MipsTargetMachine.h" -#include "llvm/CodeGen/TargetPassConfig.h" -#include "llvm/IR/Module.h" -#include "llvm/IR/Value.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/raw_ostream.h" -#include <algorithm> -#include <string> - -using namespace llvm; - -#define DEBUG_TYPE "mips16-hard-float" - -namespace { - - class Mips16HardFloat : public ModulePass { - public: - static char ID; - - Mips16HardFloat() : ModulePass(ID) {} - - StringRef getPassName() const override { return "MIPS16 Hard Float Pass"; } - - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.addRequired<TargetPassConfig>(); - ModulePass::getAnalysisUsage(AU); - } - - bool runOnModule(Module &M) override; - }; - -} // end anonymous namespace - -static void EmitInlineAsm(LLVMContext &C, BasicBlock *BB, StringRef AsmText) { - std::vector<Type *> AsmArgTypes; - std::vector<Value *> AsmArgs; - - FunctionType *AsmFTy = - FunctionType::get(Type::getVoidTy(C), AsmArgTypes, false); - InlineAsm *IA = InlineAsm::get(AsmFTy, AsmText, "", true, - /* IsAlignStack */ false, InlineAsm::AD_ATT); - CallInst::Create(IA, AsmArgs, "", BB); -} - -char Mips16HardFloat::ID = 0; - -// -// Return types that matter for hard float are: -// float, double, complex float, and complex double -// -enum FPReturnVariant { - FRet, DRet, CFRet, CDRet, NoFPRet -}; - -// -// Determine which FP return type this function has -// -static FPReturnVariant whichFPReturnVariant(Type *T) { - switch (T->getTypeID()) { - case Type::FloatTyID: - return FRet; - case Type::DoubleTyID: - return DRet; - case Type::StructTyID: { - StructType *ST = cast<StructType>(T); - if (ST->getNumElements() != 2) - break; - if ((ST->getElementType(0)->isFloatTy()) && - (ST->getElementType(1)->isFloatTy())) - return CFRet; - if ((ST->getElementType(0)->isDoubleTy()) && - (ST->getElementType(1)->isDoubleTy())) - return CDRet; - break; - } - default: - break; - } - return NoFPRet; -} - -// Parameter type that matter are float, (float, float), (float, double), -// double, (double, double), (double, float) -enum FPParamVariant { - FSig, FFSig, FDSig, - DSig, DDSig, DFSig, NoSig -}; - -// which floating point parameter signature variant we are dealing with -using TypeID = Type::TypeID; -const Type::TypeID FloatTyID = Type::FloatTyID; -const Type::TypeID DoubleTyID = Type::DoubleTyID; - -static FPParamVariant whichFPParamVariantNeeded(Function &F) { - switch (F.arg_size()) { - case 0: - return NoSig; - case 1:{ - TypeID ArgTypeID = F.getFunctionType()->getParamType(0)->getTypeID(); - switch (ArgTypeID) { - case FloatTyID: - return FSig; - case DoubleTyID: - return DSig; - default: - return NoSig; - } - } - default: { - TypeID ArgTypeID0 = F.getFunctionType()->getParamType(0)->getTypeID(); - TypeID ArgTypeID1 = F.getFunctionType()->getParamType(1)->getTypeID(); - switch(ArgTypeID0) { - case FloatTyID: { - switch (ArgTypeID1) { - case FloatTyID: - return FFSig; - case DoubleTyID: - return FDSig; - default: - return FSig; - } - } - case DoubleTyID: { - switch (ArgTypeID1) { - case FloatTyID: - return DFSig; - case DoubleTyID: - return DDSig; - default: - return DSig; - } - } - default: - return NoSig; - } - } - } - llvm_unreachable("can't get here"); -} - -// Figure out if we need float point based on the function parameters. -// We need to move variables in and/or out of floating point -// registers because of the ABI -static bool needsFPStubFromParams(Function &F) { - if (F.arg_size() >=1) { - Type *ArgType = F.getFunctionType()->getParamType(0); - switch (ArgType->getTypeID()) { - case Type::FloatTyID: - case Type::DoubleTyID: - return true; - default: - break; - } - } - return false; -} - -static bool needsFPReturnHelper(Function &F) { - Type* RetType = F.getReturnType(); - return whichFPReturnVariant(RetType) != NoFPRet; -} - -static bool needsFPReturnHelper(FunctionType &FT) { - Type* RetType = FT.getReturnType(); - return whichFPReturnVariant(RetType) != NoFPRet; -} - -static bool needsFPHelperFromSig(Function &F) { - return needsFPStubFromParams(F) || needsFPReturnHelper(F); -} - -// We swap between FP and Integer registers to allow Mips16 and Mips32 to -// interoperate -static std::string swapFPIntParams(FPParamVariant PV, Module *M, bool LE, - bool ToFP) { - std::string MI = ToFP ? "mtc1 ": "mfc1 "; - std::string AsmText; - - switch (PV) { - case FSig: - AsmText += MI + "$$4, $$f12\n"; - break; - - case FFSig: - AsmText += MI + "$$4, $$f12\n"; - AsmText += MI + "$$5, $$f14\n"; - break; - - case FDSig: - AsmText += MI + "$$4, $$f12\n"; - if (LE) { - AsmText += MI + "$$6, $$f14\n"; - AsmText += MI + "$$7, $$f15\n"; - } else { - AsmText += MI + "$$7, $$f14\n"; - AsmText += MI + "$$6, $$f15\n"; - } - break; - - case DSig: - if (LE) { - AsmText += MI + "$$4, $$f12\n"; - AsmText += MI + "$$5, $$f13\n"; - } else { - AsmText += MI + "$$5, $$f12\n"; - AsmText += MI + "$$4, $$f13\n"; - } - break; - - case DDSig: - if (LE) { - AsmText += MI + "$$4, $$f12\n"; - AsmText += MI + "$$5, $$f13\n"; - AsmText += MI + "$$6, $$f14\n"; - AsmText += MI + "$$7, $$f15\n"; - } else { - AsmText += MI + "$$5, $$f12\n"; - AsmText += MI + "$$4, $$f13\n"; - AsmText += MI + "$$7, $$f14\n"; - AsmText += MI + "$$6, $$f15\n"; - } - break; - - case DFSig: - if (LE) { - AsmText += MI + "$$4, $$f12\n"; - AsmText += MI + "$$5, $$f13\n"; - } else { - AsmText += MI + "$$5, $$f12\n"; - AsmText += MI + "$$4, $$f13\n"; - } - AsmText += MI + "$$6, $$f14\n"; - break; - - case NoSig: - break; - } - - return AsmText; -} - -// Make sure that we know we already need a stub for this function. -// Having called needsFPHelperFromSig -static void assureFPCallStub(Function &F, Module *M, - const MipsTargetMachine &TM) { - // for now we only need them for static relocation - if (TM.isPositionIndependent()) - return; - LLVMContext &Context = M->getContext(); - bool LE = TM.isLittleEndian(); - std::string Name = F.getName(); - std::string SectionName = ".mips16.call.fp." + Name; - std::string StubName = "__call_stub_fp_" + Name; - // - // see if we already have the stub - // - Function *FStub = M->getFunction(StubName); - if (FStub && !FStub->isDeclaration()) return; - FStub = Function::Create(F.getFunctionType(), - Function::InternalLinkage, StubName, M); - FStub->addFnAttr("mips16_fp_stub"); - FStub->addFnAttr(Attribute::Naked); - FStub->addFnAttr(Attribute::NoInline); - FStub->addFnAttr(Attribute::NoUnwind); - FStub->addFnAttr("nomips16"); - FStub->setSection(SectionName); - BasicBlock *BB = BasicBlock::Create(Context, "entry", FStub); - FPReturnVariant RV = whichFPReturnVariant(FStub->getReturnType()); - FPParamVariant PV = whichFPParamVariantNeeded(F); - - std::string AsmText; - AsmText += ".set reorder\n"; - AsmText += swapFPIntParams(PV, M, LE, true); - if (RV != NoFPRet) { - AsmText += "move $$18, $$31\n"; - AsmText += "jal " + Name + "\n"; - } else { - AsmText += "lui $$25, %hi(" + Name + ")\n"; - AsmText += "addiu $$25, $$25, %lo(" + Name + ")\n"; - } - - switch (RV) { - case FRet: - AsmText += "mfc1 $$2, $$f0\n"; - break; - - case DRet: - if (LE) { - AsmText += "mfc1 $$2, $$f0\n"; - AsmText += "mfc1 $$3, $$f1\n"; - } else { - AsmText += "mfc1 $$3, $$f0\n"; - AsmText += "mfc1 $$2, $$f1\n"; - } - break; - - case CFRet: - if (LE) { - AsmText += "mfc1 $$2, $$f0\n"; - AsmText += "mfc1 $$3, $$f2\n"; - } else { - AsmText += "mfc1 $$3, $$f0\n"; - AsmText += "mfc1 $$3, $$f2\n"; - } - break; - - case CDRet: - if (LE) { - AsmText += "mfc1 $$4, $$f2\n"; - AsmText += "mfc1 $$5, $$f3\n"; - AsmText += "mfc1 $$2, $$f0\n"; - AsmText += "mfc1 $$3, $$f1\n"; - - } else { - AsmText += "mfc1 $$5, $$f2\n"; - AsmText += "mfc1 $$4, $$f3\n"; - AsmText += "mfc1 $$3, $$f0\n"; - AsmText += "mfc1 $$2, $$f1\n"; - } - break; - - case NoFPRet: - break; - } - - if (RV != NoFPRet) - AsmText += "jr $$18\n"; - else - AsmText += "jr $$25\n"; - EmitInlineAsm(Context, BB, AsmText); - - new UnreachableInst(Context, BB); -} - -// Functions that are llvm intrinsics and don't need helpers. -static const char *const IntrinsicInline[] = { - "fabs", "fabsf", - "llvm.ceil.f32", "llvm.ceil.f64", - "llvm.copysign.f32", "llvm.copysign.f64", - "llvm.cos.f32", "llvm.cos.f64", - "llvm.exp.f32", "llvm.exp.f64", - "llvm.exp2.f32", "llvm.exp2.f64", - "llvm.fabs.f32", "llvm.fabs.f64", - "llvm.floor.f32", "llvm.floor.f64", - "llvm.fma.f32", "llvm.fma.f64", - "llvm.log.f32", "llvm.log.f64", - "llvm.log10.f32", "llvm.log10.f64", - "llvm.nearbyint.f32", "llvm.nearbyint.f64", - "llvm.pow.f32", "llvm.pow.f64", - "llvm.powi.f32", "llvm.powi.f64", - "llvm.rint.f32", "llvm.rint.f64", - "llvm.round.f32", "llvm.round.f64", - "llvm.sin.f32", "llvm.sin.f64", - "llvm.sqrt.f32", "llvm.sqrt.f64", - "llvm.trunc.f32", "llvm.trunc.f64", -}; - -static bool isIntrinsicInline(Function *F) { - return std::binary_search(std::begin(IntrinsicInline), - std::end(IntrinsicInline), F->getName()); -} - -// Returns of float, double and complex need to be handled with a helper -// function. -static bool fixupFPReturnAndCall(Function &F, Module *M, - const MipsTargetMachine &TM) { - bool Modified = false; - LLVMContext &C = M->getContext(); - Type *MyVoid = Type::getVoidTy(C); - for (auto &BB: F) - for (auto &I: BB) { - if (const ReturnInst *RI = dyn_cast<ReturnInst>(&I)) { - Value *RVal = RI->getReturnValue(); - if (!RVal) continue; - // - // If there is a return value and it needs a helper function, - // figure out which one and add a call before the actual - // return to this helper. The purpose of the helper is to move - // floating point values from their soft float return mapping to - // where they would have been mapped to in floating point registers. - // - Type *T = RVal->getType(); - FPReturnVariant RV = whichFPReturnVariant(T); - if (RV == NoFPRet) continue; - static const char *const Helper[NoFPRet] = { - "__mips16_ret_sf", "__mips16_ret_df", "__mips16_ret_sc", - "__mips16_ret_dc" - }; - const char *Name = Helper[RV]; - AttributeList A; - Value *Params[] = {RVal}; - Modified = true; - // - // These helper functions have a different calling ABI so - // this __Mips16RetHelper indicates that so that later - // during call setup, the proper call lowering to the helper - // functions will take place. - // - A = A.addAttribute(C, AttributeList::FunctionIndex, - "__Mips16RetHelper"); - A = A.addAttribute(C, AttributeList::FunctionIndex, - Attribute::ReadNone); - A = A.addAttribute(C, AttributeList::FunctionIndex, - Attribute::NoInline); - FunctionCallee F = (M->getOrInsertFunction(Name, A, MyVoid, T)); - CallInst::Create(F, Params, "", &I); - } else if (const CallInst *CI = dyn_cast<CallInst>(&I)) { - FunctionType *FT = CI->getFunctionType(); - Function *F_ = CI->getCalledFunction(); - if (needsFPReturnHelper(*FT) && - !(F_ && isIntrinsicInline(F_))) { - Modified=true; - F.addFnAttr("saveS2"); - } - if (F_ && !isIntrinsicInline(F_)) { - // pic mode calls are handled by already defined - // helper functions - if (needsFPReturnHelper(*F_)) { - Modified=true; - F.addFnAttr("saveS2"); - } - if (!TM.isPositionIndependent()) { - if (needsFPHelperFromSig(*F_)) { - assureFPCallStub(*F_, M, TM); - Modified=true; - } - } - } - } - } - return Modified; -} - -static void createFPFnStub(Function *F, Module *M, FPParamVariant PV, - const MipsTargetMachine &TM) { - bool PicMode = TM.isPositionIndependent(); - bool LE = TM.isLittleEndian(); - LLVMContext &Context = M->getContext(); - std::string Name = F->getName(); - std::string SectionName = ".mips16.fn." + Name; - std::string StubName = "__fn_stub_" + Name; - std::string LocalName = "$$__fn_local_" + Name; - Function *FStub = Function::Create - (F->getFunctionType(), - Function::InternalLinkage, StubName, M); - FStub->addFnAttr("mips16_fp_stub"); - FStub->addFnAttr(Attribute::Naked); - FStub->addFnAttr(Attribute::NoUnwind); - FStub->addFnAttr(Attribute::NoInline); - FStub->addFnAttr("nomips16"); - FStub->setSection(SectionName); - BasicBlock *BB = BasicBlock::Create(Context, "entry", FStub); - - std::string AsmText; - if (PicMode) { - AsmText += ".set noreorder\n"; - AsmText += ".cpload $$25\n"; - AsmText += ".set reorder\n"; - AsmText += ".reloc 0, R_MIPS_NONE, " + Name + "\n"; - AsmText += "la $$25, " + LocalName + "\n"; - } else - AsmText += "la $$25, " + Name + "\n"; - AsmText += swapFPIntParams(PV, M, LE, false); - AsmText += "jr $$25\n"; - AsmText += LocalName + " = " + Name + "\n"; - EmitInlineAsm(Context, BB, AsmText); - - new UnreachableInst(FStub->getContext(), BB); -} - -// remove the use-soft-float attribute -static void removeUseSoftFloat(Function &F) { - AttrBuilder B; - LLVM_DEBUG(errs() << "removing -use-soft-float\n"); - B.addAttribute("use-soft-float", "false"); - F.removeAttributes(AttributeList::FunctionIndex, B); - if (F.hasFnAttribute("use-soft-float")) { - LLVM_DEBUG(errs() << "still has -use-soft-float\n"); - } - F.addAttributes(AttributeList::FunctionIndex, B); -} - -// This pass only makes sense when the underlying chip has floating point but -// we are compiling as mips16. -// For all mips16 functions (that are not stubs we have already generated), or -// declared via attributes as nomips16, we must: -// 1) fixup all returns of float, double, single and double complex -// by calling a helper function before the actual return. -// 2) generate helper functions (stubs) that can be called by mips32 -// functions that will move parameters passed normally passed in -// floating point -// registers the soft float equivalents. -// 3) in the case of static relocation, generate helper functions so that -// mips16 functions can call extern functions of unknown type (mips16 or -// mips32). -// 4) TBD. For pic, calls to extern functions of unknown type are handled by -// predefined helper functions in libc but this work is currently done -// during call lowering but it should be moved here in the future. -bool Mips16HardFloat::runOnModule(Module &M) { - auto &TM = static_cast<const MipsTargetMachine &>( - getAnalysis<TargetPassConfig>().getTM<TargetMachine>()); - LLVM_DEBUG(errs() << "Run on Module Mips16HardFloat\n"); - bool Modified = false; - for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { - if (F->hasFnAttribute("nomips16") && - F->hasFnAttribute("use-soft-float")) { - removeUseSoftFloat(*F); - continue; - } - if (F->isDeclaration() || F->hasFnAttribute("mips16_fp_stub") || - F->hasFnAttribute("nomips16")) continue; - Modified |= fixupFPReturnAndCall(*F, &M, TM); - FPParamVariant V = whichFPParamVariantNeeded(*F); - if (V != NoSig) { - Modified = true; - createFPFnStub(&*F, &M, V, TM); - } - } - return Modified; -} - -ModulePass *llvm::createMips16HardFloatPass() { - return new Mips16HardFloat(); -} diff --git a/contrib/llvm/lib/Target/Mips/Mips16HardFloatInfo.cpp b/contrib/llvm/lib/Target/Mips/Mips16HardFloatInfo.cpp deleted file mode 100644 index 8a02e8156175..000000000000 --- a/contrib/llvm/lib/Target/Mips/Mips16HardFloatInfo.cpp +++ /dev/null @@ -1,49 +0,0 @@ -//===---- Mips16HardFloatInfo.cpp for Mips16 Hard Float -----===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains the Mips16 implementation of Mips16HardFloatInfo -// namespace. -// -//===----------------------------------------------------------------------===// - -#include "Mips16HardFloatInfo.h" -#include <string.h> - -namespace llvm { - -namespace Mips16HardFloatInfo { - -const FuncNameSignature PredefinedFuncs[] = { - { "__floatdidf", { NoSig, DRet } }, - { "__floatdisf", { NoSig, FRet } }, - { "__floatundidf", { NoSig, DRet } }, - { "__fixsfdi", { FSig, NoFPRet } }, - { "__fixunsdfsi", { DSig, NoFPRet } }, - { "__fixunsdfdi", { DSig, NoFPRet } }, - { "__fixdfdi", { DSig, NoFPRet } }, - { "__fixunssfsi", { FSig, NoFPRet } }, - { "__fixunssfdi", { FSig, NoFPRet } }, - { "__floatundisf", { NoSig, FRet } }, - { nullptr, { NoSig, NoFPRet } } -}; - -// just do a search for now. there are very few of these special cases. -// -extern FuncSignature const *findFuncSignature(const char *name) { - const char *name_; - int i = 0; - while (PredefinedFuncs[i].Name) { - name_ = PredefinedFuncs[i].Name; - if (strcmp(name, name_) == 0) - return &PredefinedFuncs[i].Signature; - i++; - } - return nullptr; -} -} -} diff --git a/contrib/llvm/lib/Target/Mips/Mips16HardFloatInfo.h b/contrib/llvm/lib/Target/Mips/Mips16HardFloatInfo.h deleted file mode 100644 index b8c485b7e2e3..000000000000 --- a/contrib/llvm/lib/Target/Mips/Mips16HardFloatInfo.h +++ /dev/null @@ -1,49 +0,0 @@ -//===---- Mips16HardFloatInfo.h for Mips16 Hard Float --------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines some data structures relevant to the implementation of -// Mips16 hard float. -// -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_MIPS_MIPS16HARDFLOATINFO_H -#define LLVM_LIB_TARGET_MIPS_MIPS16HARDFLOATINFO_H - -namespace llvm { - -namespace Mips16HardFloatInfo { - -// Return types that matter for hard float are: -// float, double, complex float, and complex double -// -enum FPReturnVariant { FRet, DRet, CFRet, CDRet, NoFPRet }; - -// -// Parameter type that matter are float, (float, float), (float, double), -// double, (double, double), (double, float) -// -enum FPParamVariant { FSig, FFSig, FDSig, DSig, DDSig, DFSig, NoSig }; - -struct FuncSignature { - FPParamVariant ParamSig; - FPReturnVariant RetSig; -}; - -struct FuncNameSignature { - const char *Name; - FuncSignature Signature; -}; - -extern const FuncNameSignature PredefinedFuncs[]; - -extern FuncSignature const *findFuncSignature(const char *name); -} -} - -#endif diff --git a/contrib/llvm/lib/Target/Mips/Mips16ISelDAGToDAG.cpp b/contrib/llvm/lib/Target/Mips/Mips16ISelDAGToDAG.cpp deleted file mode 100644 index 3ab4f1e064da..000000000000 --- a/contrib/llvm/lib/Target/Mips/Mips16ISelDAGToDAG.cpp +++ /dev/null @@ -1,225 +0,0 @@ -//===-- Mips16ISelDAGToDAG.cpp - A Dag to Dag Inst Selector for Mips16 ----===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Subclass of MipsDAGToDAGISel specialized for mips16. -// -//===----------------------------------------------------------------------===// - -#include "Mips16ISelDAGToDAG.h" -#include "MCTargetDesc/MipsBaseInfo.h" -#include "Mips.h" -#include "MipsMachineFunction.h" -#include "MipsRegisterInfo.h" -#include "llvm/CodeGen/MachineConstantPool.h" -#include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/SelectionDAGNodes.h" -#include "llvm/IR/CFG.h" -#include "llvm/IR/GlobalValue.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/Intrinsics.h" -#include "llvm/IR/Type.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetMachine.h" -using namespace llvm; - -#define DEBUG_TYPE "mips-isel" - -bool Mips16DAGToDAGISel::runOnMachineFunction(MachineFunction &MF) { - Subtarget = &static_cast<const MipsSubtarget &>(MF.getSubtarget()); - if (!Subtarget->inMips16Mode()) - return false; - return MipsDAGToDAGISel::runOnMachineFunction(MF); -} -/// Select multiply instructions. -std::pair<SDNode *, SDNode *> -Mips16DAGToDAGISel::selectMULT(SDNode *N, unsigned Opc, const SDLoc &DL, EVT Ty, - bool HasLo, bool HasHi) { - SDNode *Lo = nullptr, *Hi = nullptr; - SDNode *Mul = CurDAG->getMachineNode(Opc, DL, MVT::Glue, N->getOperand(0), - N->getOperand(1)); - SDValue InFlag = SDValue(Mul, 0); - - if (HasLo) { - unsigned Opcode = Mips::Mflo16; - Lo = CurDAG->getMachineNode(Opcode, DL, Ty, MVT::Glue, InFlag); - InFlag = SDValue(Lo, 1); - } - if (HasHi) { - unsigned Opcode = Mips::Mfhi16; - Hi = CurDAG->getMachineNode(Opcode, DL, Ty, InFlag); - } - return std::make_pair(Lo, Hi); -} - -void Mips16DAGToDAGISel::initGlobalBaseReg(MachineFunction &MF) { - MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); - - if (!MipsFI->globalBaseRegSet()) - return; - - MachineBasicBlock &MBB = MF.front(); - MachineBasicBlock::iterator I = MBB.begin(); - MachineRegisterInfo &RegInfo = MF.getRegInfo(); - const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); - DebugLoc DL; - unsigned V0, V1, V2, GlobalBaseReg = MipsFI->getGlobalBaseReg(); - const TargetRegisterClass *RC = &Mips::CPU16RegsRegClass; - - V0 = RegInfo.createVirtualRegister(RC); - V1 = RegInfo.createVirtualRegister(RC); - V2 = RegInfo.createVirtualRegister(RC); - - - BuildMI(MBB, I, DL, TII.get(Mips::LiRxImmX16), V0) - .addExternalSymbol("_gp_disp", MipsII::MO_ABS_HI); - BuildMI(MBB, I, DL, TII.get(Mips::AddiuRxPcImmX16), V1) - .addExternalSymbol("_gp_disp", MipsII::MO_ABS_LO); - - BuildMI(MBB, I, DL, TII.get(Mips::SllX16), V2).addReg(V0).addImm(16); - BuildMI(MBB, I, DL, TII.get(Mips::AdduRxRyRz16), GlobalBaseReg) - .addReg(V1) - .addReg(V2); -} - -void Mips16DAGToDAGISel::processFunctionAfterISel(MachineFunction &MF) { - initGlobalBaseReg(MF); -} - -bool Mips16DAGToDAGISel::selectAddr(bool SPAllowed, SDValue Addr, SDValue &Base, - SDValue &Offset) { - SDLoc DL(Addr); - EVT ValTy = Addr.getValueType(); - - // if Address is FI, get the TargetFrameIndex. - if (SPAllowed) { - if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { - Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy); - Offset = CurDAG->getTargetConstant(0, DL, ValTy); - return true; - } - } - // on PIC code Load GA - if (Addr.getOpcode() == MipsISD::Wrapper) { - Base = Addr.getOperand(0); - Offset = Addr.getOperand(1); - return true; - } - if (!TM.isPositionIndependent()) { - if ((Addr.getOpcode() == ISD::TargetExternalSymbol || - Addr.getOpcode() == ISD::TargetGlobalAddress)) - return false; - } - // Addresses of the form FI+const or FI|const - if (CurDAG->isBaseWithConstantOffset(Addr)) { - ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)); - if (isInt<16>(CN->getSExtValue())) { - // If the first operand is a FI, get the TargetFI Node - if (SPAllowed) { - if (FrameIndexSDNode *FIN = - dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) { - Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy); - Offset = CurDAG->getTargetConstant(CN->getZExtValue(), DL, ValTy); - return true; - } - } - - Base = Addr.getOperand(0); - Offset = CurDAG->getTargetConstant(CN->getZExtValue(), DL, ValTy); - return true; - } - } - // Operand is a result from an ADD. - if (Addr.getOpcode() == ISD::ADD) { - // When loading from constant pools, load the lower address part in - // the instruction itself. Example, instead of: - // lui $2, %hi($CPI1_0) - // addiu $2, $2, %lo($CPI1_0) - // lwc1 $f0, 0($2) - // Generate: - // lui $2, %hi($CPI1_0) - // lwc1 $f0, %lo($CPI1_0)($2) - if (Addr.getOperand(1).getOpcode() == MipsISD::Lo || - Addr.getOperand(1).getOpcode() == MipsISD::GPRel) { - SDValue Opnd0 = Addr.getOperand(1).getOperand(0); - if (isa<ConstantPoolSDNode>(Opnd0) || isa<GlobalAddressSDNode>(Opnd0) || - isa<JumpTableSDNode>(Opnd0)) { - Base = Addr.getOperand(0); - Offset = Opnd0; - return true; - } - } - } - Base = Addr; - Offset = CurDAG->getTargetConstant(0, DL, ValTy); - return true; -} - -bool Mips16DAGToDAGISel::selectAddr16(SDValue Addr, SDValue &Base, - SDValue &Offset) { - return selectAddr(false, Addr, Base, Offset); -} - -bool Mips16DAGToDAGISel::selectAddr16SP(SDValue Addr, SDValue &Base, - SDValue &Offset) { - return selectAddr(true, Addr, Base, Offset); -} - -/// Select instructions not customized! Used for -/// expanded, promoted and normal instructions -bool Mips16DAGToDAGISel::trySelect(SDNode *Node) { - unsigned Opcode = Node->getOpcode(); - SDLoc DL(Node); - - /// - // Instruction Selection not handled by the auto-generated - // tablegen selection should be handled here. - /// - EVT NodeTy = Node->getValueType(0); - unsigned MultOpc; - - switch (Opcode) { - default: - break; - - /// Mul with two results - case ISD::SMUL_LOHI: - case ISD::UMUL_LOHI: { - MultOpc = (Opcode == ISD::UMUL_LOHI ? Mips::MultuRxRy16 : Mips::MultRxRy16); - std::pair<SDNode *, SDNode *> LoHi = - selectMULT(Node, MultOpc, DL, NodeTy, true, true); - if (!SDValue(Node, 0).use_empty()) - ReplaceUses(SDValue(Node, 0), SDValue(LoHi.first, 0)); - - if (!SDValue(Node, 1).use_empty()) - ReplaceUses(SDValue(Node, 1), SDValue(LoHi.second, 0)); - - CurDAG->RemoveDeadNode(Node); - return true; - } - - case ISD::MULHS: - case ISD::MULHU: { - MultOpc = (Opcode == ISD::MULHU ? Mips::MultuRxRy16 : Mips::MultRxRy16); - auto LoHi = selectMULT(Node, MultOpc, DL, NodeTy, false, true); - ReplaceNode(Node, LoHi.second); - return true; - } - } - - return false; -} - -FunctionPass *llvm::createMips16ISelDag(MipsTargetMachine &TM, - CodeGenOpt::Level OptLevel) { - return new Mips16DAGToDAGISel(TM, OptLevel); -} diff --git a/contrib/llvm/lib/Target/Mips/Mips16ISelDAGToDAG.h b/contrib/llvm/lib/Target/Mips/Mips16ISelDAGToDAG.h deleted file mode 100644 index 1ef194029f50..000000000000 --- a/contrib/llvm/lib/Target/Mips/Mips16ISelDAGToDAG.h +++ /dev/null @@ -1,54 +0,0 @@ -//===---- Mips16ISelDAGToDAG.h - A Dag to Dag Inst Selector for Mips ------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Subclass of MipsDAGToDAGISel specialized for mips16. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_MIPS_MIPS16ISELDAGTODAG_H -#define LLVM_LIB_TARGET_MIPS_MIPS16ISELDAGTODAG_H - -#include "MipsISelDAGToDAG.h" - -namespace llvm { - -class Mips16DAGToDAGISel : public MipsDAGToDAGISel { -public: - explicit Mips16DAGToDAGISel(MipsTargetMachine &TM, CodeGenOpt::Level OL) - : MipsDAGToDAGISel(TM, OL) {} - -private: - std::pair<SDNode *, SDNode *> selectMULT(SDNode *N, unsigned Opc, - const SDLoc &DL, EVT Ty, bool HasLo, - bool HasHi); - - bool runOnMachineFunction(MachineFunction &MF) override; - - bool selectAddr(bool SPAllowed, SDValue Addr, SDValue &Base, - SDValue &Offset); - bool selectAddr16(SDValue Addr, SDValue &Base, - SDValue &Offset) override; - bool selectAddr16SP(SDValue Addr, SDValue &Base, - SDValue &Offset) override; - - bool trySelect(SDNode *Node) override; - - void processFunctionAfterISel(MachineFunction &MF) override; - - // Insert instructions to initialize the global base register in the - // first MBB of the function. - void initGlobalBaseReg(MachineFunction &MF); - - void initMips16SPAliasReg(MachineFunction &MF); -}; - -FunctionPass *createMips16ISelDag(MipsTargetMachine &TM, - CodeGenOpt::Level OptLevel); -} - -#endif diff --git a/contrib/llvm/lib/Target/Mips/Mips16ISelLowering.cpp b/contrib/llvm/lib/Target/Mips/Mips16ISelLowering.cpp deleted file mode 100644 index 6d8e5aef2a3f..000000000000 --- a/contrib/llvm/lib/Target/Mips/Mips16ISelLowering.cpp +++ /dev/null @@ -1,790 +0,0 @@ -//===-- Mips16ISelLowering.h - Mips16 DAG Lowering Interface ----*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Subclass of MipsTargetLowering specialized for mips16. -// -//===----------------------------------------------------------------------===// -#include "Mips16ISelLowering.h" -#include "MCTargetDesc/MipsBaseInfo.h" -#include "Mips16HardFloatInfo.h" -#include "MipsMachineFunction.h" -#include "MipsRegisterInfo.h" -#include "MipsTargetMachine.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/TargetInstrInfo.h" -#include "llvm/Support/CommandLine.h" - -using namespace llvm; - -#define DEBUG_TYPE "mips-lower" - -static cl::opt<bool> DontExpandCondPseudos16( - "mips16-dont-expand-cond-pseudo", - cl::init(false), - cl::desc("Don't expand conditional move related " - "pseudos for Mips 16"), - cl::Hidden); - -namespace { -struct Mips16Libcall { - RTLIB::Libcall Libcall; - const char *Name; - - bool operator<(const Mips16Libcall &RHS) const { - return std::strcmp(Name, RHS.Name) < 0; - } -}; - -struct Mips16IntrinsicHelperType{ - const char* Name; - const char* Helper; - - bool operator<(const Mips16IntrinsicHelperType &RHS) const { - return std::strcmp(Name, RHS.Name) < 0; - } - bool operator==(const Mips16IntrinsicHelperType &RHS) const { - return std::strcmp(Name, RHS.Name) == 0; - } -}; -} - -// Libcalls for which no helper is generated. Sorted by name for binary search. -static const Mips16Libcall HardFloatLibCalls[] = { - { RTLIB::ADD_F64, "__mips16_adddf3" }, - { RTLIB::ADD_F32, "__mips16_addsf3" }, - { RTLIB::DIV_F64, "__mips16_divdf3" }, - { RTLIB::DIV_F32, "__mips16_divsf3" }, - { RTLIB::OEQ_F64, "__mips16_eqdf2" }, - { RTLIB::OEQ_F32, "__mips16_eqsf2" }, - { RTLIB::FPEXT_F32_F64, "__mips16_extendsfdf2" }, - { RTLIB::FPTOSINT_F64_I32, "__mips16_fix_truncdfsi" }, - { RTLIB::FPTOSINT_F32_I32, "__mips16_fix_truncsfsi" }, - { RTLIB::SINTTOFP_I32_F64, "__mips16_floatsidf" }, - { RTLIB::SINTTOFP_I32_F32, "__mips16_floatsisf" }, - { RTLIB::UINTTOFP_I32_F64, "__mips16_floatunsidf" }, - { RTLIB::UINTTOFP_I32_F32, "__mips16_floatunsisf" }, - { RTLIB::OGE_F64, "__mips16_gedf2" }, - { RTLIB::OGE_F32, "__mips16_gesf2" }, - { RTLIB::OGT_F64, "__mips16_gtdf2" }, - { RTLIB::OGT_F32, "__mips16_gtsf2" }, - { RTLIB::OLE_F64, "__mips16_ledf2" }, - { RTLIB::OLE_F32, "__mips16_lesf2" }, - { RTLIB::OLT_F64, "__mips16_ltdf2" }, - { RTLIB::OLT_F32, "__mips16_ltsf2" }, - { RTLIB::MUL_F64, "__mips16_muldf3" }, - { RTLIB::MUL_F32, "__mips16_mulsf3" }, - { RTLIB::UNE_F64, "__mips16_nedf2" }, - { RTLIB::UNE_F32, "__mips16_nesf2" }, - { RTLIB::UNKNOWN_LIBCALL, "__mips16_ret_dc" }, // No associated libcall. - { RTLIB::UNKNOWN_LIBCALL, "__mips16_ret_df" }, // No associated libcall. - { RTLIB::UNKNOWN_LIBCALL, "__mips16_ret_sc" }, // No associated libcall. - { RTLIB::UNKNOWN_LIBCALL, "__mips16_ret_sf" }, // No associated libcall. - { RTLIB::SUB_F64, "__mips16_subdf3" }, - { RTLIB::SUB_F32, "__mips16_subsf3" }, - { RTLIB::FPROUND_F64_F32, "__mips16_truncdfsf2" }, - { RTLIB::UO_F64, "__mips16_unorddf2" }, - { RTLIB::UO_F32, "__mips16_unordsf2" } -}; - -static const Mips16IntrinsicHelperType Mips16IntrinsicHelper[] = { - {"__fixunsdfsi", "__mips16_call_stub_2" }, - {"ceil", "__mips16_call_stub_df_2"}, - {"ceilf", "__mips16_call_stub_sf_1"}, - {"copysign", "__mips16_call_stub_df_10"}, - {"copysignf", "__mips16_call_stub_sf_5"}, - {"cos", "__mips16_call_stub_df_2"}, - {"cosf", "__mips16_call_stub_sf_1"}, - {"exp2", "__mips16_call_stub_df_2"}, - {"exp2f", "__mips16_call_stub_sf_1"}, - {"floor", "__mips16_call_stub_df_2"}, - {"floorf", "__mips16_call_stub_sf_1"}, - {"log2", "__mips16_call_stub_df_2"}, - {"log2f", "__mips16_call_stub_sf_1"}, - {"nearbyint", "__mips16_call_stub_df_2"}, - {"nearbyintf", "__mips16_call_stub_sf_1"}, - {"rint", "__mips16_call_stub_df_2"}, - {"rintf", "__mips16_call_stub_sf_1"}, - {"sin", "__mips16_call_stub_df_2"}, - {"sinf", "__mips16_call_stub_sf_1"}, - {"sqrt", "__mips16_call_stub_df_2"}, - {"sqrtf", "__mips16_call_stub_sf_1"}, - {"trunc", "__mips16_call_stub_df_2"}, - {"truncf", "__mips16_call_stub_sf_1"}, -}; - -Mips16TargetLowering::Mips16TargetLowering(const MipsTargetMachine &TM, - const MipsSubtarget &STI) - : MipsTargetLowering(TM, STI) { - - // Set up the register classes - addRegisterClass(MVT::i32, &Mips::CPU16RegsRegClass); - - if (!Subtarget.useSoftFloat()) - setMips16HardFloatLibCalls(); - - setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Expand); - setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i32, Expand); - setOperationAction(ISD::ATOMIC_SWAP, MVT::i32, Expand); - setOperationAction(ISD::ATOMIC_LOAD_ADD, MVT::i32, Expand); - setOperationAction(ISD::ATOMIC_LOAD_SUB, MVT::i32, Expand); - setOperationAction(ISD::ATOMIC_LOAD_AND, MVT::i32, Expand); - setOperationAction(ISD::ATOMIC_LOAD_OR, MVT::i32, Expand); - setOperationAction(ISD::ATOMIC_LOAD_XOR, MVT::i32, Expand); - setOperationAction(ISD::ATOMIC_LOAD_NAND, MVT::i32, Expand); - setOperationAction(ISD::ATOMIC_LOAD_MIN, MVT::i32, Expand); - setOperationAction(ISD::ATOMIC_LOAD_MAX, MVT::i32, Expand); - setOperationAction(ISD::ATOMIC_LOAD_UMIN, MVT::i32, Expand); - setOperationAction(ISD::ATOMIC_LOAD_UMAX, MVT::i32, Expand); - - setOperationAction(ISD::ROTR, MVT::i32, Expand); - setOperationAction(ISD::ROTR, MVT::i64, Expand); - setOperationAction(ISD::BSWAP, MVT::i32, Expand); - setOperationAction(ISD::BSWAP, MVT::i64, Expand); - - computeRegisterProperties(STI.getRegisterInfo()); -} - -const MipsTargetLowering * -llvm::createMips16TargetLowering(const MipsTargetMachine &TM, - const MipsSubtarget &STI) { - return new Mips16TargetLowering(TM, STI); -} - -bool Mips16TargetLowering::allowsMisalignedMemoryAccesses( - EVT VT, unsigned, unsigned, MachineMemOperand::Flags, bool *Fast) const { - return false; -} - -MachineBasicBlock * -Mips16TargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, - MachineBasicBlock *BB) const { - switch (MI.getOpcode()) { - default: - return MipsTargetLowering::EmitInstrWithCustomInserter(MI, BB); - case Mips::SelBeqZ: - return emitSel16(Mips::BeqzRxImm16, MI, BB); - case Mips::SelBneZ: - return emitSel16(Mips::BnezRxImm16, MI, BB); - case Mips::SelTBteqZCmpi: - return emitSeliT16(Mips::Bteqz16, Mips::CmpiRxImmX16, MI, BB); - case Mips::SelTBteqZSlti: - return emitSeliT16(Mips::Bteqz16, Mips::SltiRxImmX16, MI, BB); - case Mips::SelTBteqZSltiu: - return emitSeliT16(Mips::Bteqz16, Mips::SltiuRxImmX16, MI, BB); - case Mips::SelTBtneZCmpi: - return emitSeliT16(Mips::Btnez16, Mips::CmpiRxImmX16, MI, BB); - case Mips::SelTBtneZSlti: - return emitSeliT16(Mips::Btnez16, Mips::SltiRxImmX16, MI, BB); - case Mips::SelTBtneZSltiu: - return emitSeliT16(Mips::Btnez16, Mips::SltiuRxImmX16, MI, BB); - case Mips::SelTBteqZCmp: - return emitSelT16(Mips::Bteqz16, Mips::CmpRxRy16, MI, BB); - case Mips::SelTBteqZSlt: - return emitSelT16(Mips::Bteqz16, Mips::SltRxRy16, MI, BB); - case Mips::SelTBteqZSltu: - return emitSelT16(Mips::Bteqz16, Mips::SltuRxRy16, MI, BB); - case Mips::SelTBtneZCmp: - return emitSelT16(Mips::Btnez16, Mips::CmpRxRy16, MI, BB); - case Mips::SelTBtneZSlt: - return emitSelT16(Mips::Btnez16, Mips::SltRxRy16, MI, BB); - case Mips::SelTBtneZSltu: - return emitSelT16(Mips::Btnez16, Mips::SltuRxRy16, MI, BB); - case Mips::BteqzT8CmpX16: - return emitFEXT_T8I816_ins(Mips::Bteqz16, Mips::CmpRxRy16, MI, BB); - case Mips::BteqzT8SltX16: - return emitFEXT_T8I816_ins(Mips::Bteqz16, Mips::SltRxRy16, MI, BB); - case Mips::BteqzT8SltuX16: - // TBD: figure out a way to get this or remove the instruction - // altogether. - return emitFEXT_T8I816_ins(Mips::Bteqz16, Mips::SltuRxRy16, MI, BB); - case Mips::BtnezT8CmpX16: - return emitFEXT_T8I816_ins(Mips::Btnez16, Mips::CmpRxRy16, MI, BB); - case Mips::BtnezT8SltX16: - return emitFEXT_T8I816_ins(Mips::Btnez16, Mips::SltRxRy16, MI, BB); - case Mips::BtnezT8SltuX16: - // TBD: figure out a way to get this or remove the instruction - // altogether. - return emitFEXT_T8I816_ins(Mips::Btnez16, Mips::SltuRxRy16, MI, BB); - case Mips::BteqzT8CmpiX16: return emitFEXT_T8I8I16_ins( - Mips::Bteqz16, Mips::CmpiRxImm16, Mips::CmpiRxImmX16, false, MI, BB); - case Mips::BteqzT8SltiX16: return emitFEXT_T8I8I16_ins( - Mips::Bteqz16, Mips::SltiRxImm16, Mips::SltiRxImmX16, true, MI, BB); - case Mips::BteqzT8SltiuX16: return emitFEXT_T8I8I16_ins( - Mips::Bteqz16, Mips::SltiuRxImm16, Mips::SltiuRxImmX16, false, MI, BB); - case Mips::BtnezT8CmpiX16: return emitFEXT_T8I8I16_ins( - Mips::Btnez16, Mips::CmpiRxImm16, Mips::CmpiRxImmX16, false, MI, BB); - case Mips::BtnezT8SltiX16: return emitFEXT_T8I8I16_ins( - Mips::Btnez16, Mips::SltiRxImm16, Mips::SltiRxImmX16, true, MI, BB); - case Mips::BtnezT8SltiuX16: return emitFEXT_T8I8I16_ins( - Mips::Btnez16, Mips::SltiuRxImm16, Mips::SltiuRxImmX16, false, MI, BB); - break; - case Mips::SltCCRxRy16: - return emitFEXT_CCRX16_ins(Mips::SltRxRy16, MI, BB); - break; - case Mips::SltiCCRxImmX16: - return emitFEXT_CCRXI16_ins - (Mips::SltiRxImm16, Mips::SltiRxImmX16, MI, BB); - case Mips::SltiuCCRxImmX16: - return emitFEXT_CCRXI16_ins - (Mips::SltiuRxImm16, Mips::SltiuRxImmX16, MI, BB); - case Mips::SltuCCRxRy16: - return emitFEXT_CCRX16_ins - (Mips::SltuRxRy16, MI, BB); - } -} - -bool Mips16TargetLowering::isEligibleForTailCallOptimization( - const CCState &CCInfo, unsigned NextStackOffset, - const MipsFunctionInfo &FI) const { - // No tail call optimization for mips16. - return false; -} - -void Mips16TargetLowering::setMips16HardFloatLibCalls() { - for (unsigned I = 0; I != array_lengthof(HardFloatLibCalls); ++I) { - assert((I == 0 || HardFloatLibCalls[I - 1] < HardFloatLibCalls[I]) && - "Array not sorted!"); - if (HardFloatLibCalls[I].Libcall != RTLIB::UNKNOWN_LIBCALL) - setLibcallName(HardFloatLibCalls[I].Libcall, HardFloatLibCalls[I].Name); - } - - setLibcallName(RTLIB::O_F64, "__mips16_unorddf2"); - setLibcallName(RTLIB::O_F32, "__mips16_unordsf2"); -} - -// -// The Mips16 hard float is a crazy quilt inherited from gcc. I have a much -// cleaner way to do all of this but it will have to wait until the traditional -// gcc mechanism is completed. -// -// For Pic, in order for Mips16 code to call Mips32 code which according the abi -// have either arguments or returned values placed in floating point registers, -// we use a set of helper functions. (This includes functions which return type -// complex which on Mips are returned in a pair of floating point registers). -// -// This is an encoding that we inherited from gcc. -// In Mips traditional O32, N32 ABI, floating point numbers are passed in -// floating point argument registers 1,2 only when the first and optionally -// the second arguments are float (sf) or double (df). -// For Mips16 we are only concerned with the situations where floating point -// arguments are being passed in floating point registers by the ABI, because -// Mips16 mode code cannot execute floating point instructions to load those -// values and hence helper functions are needed. -// The possibilities are (), (sf), (sf, sf), (sf, df), (df), (df, sf), (df, df) -// the helper function suffixs for these are: -// 0, 1, 5, 9, 2, 6, 10 -// this suffix can then be calculated as follows: -// for a given argument Arg: -// Arg1x, Arg2x = 1 : Arg is sf -// 2 : Arg is df -// 0: Arg is neither sf or df -// So this stub is the string for number Arg1x + Arg2x*4. -// However not all numbers between 0 and 10 are possible, we check anyway and -// assert if the impossible exists. -// - -unsigned int Mips16TargetLowering::getMips16HelperFunctionStubNumber - (ArgListTy &Args) const { - unsigned int resultNum = 0; - if (Args.size() >= 1) { - Type *t = Args[0].Ty; - if (t->isFloatTy()) { - resultNum = 1; - } - else if (t->isDoubleTy()) { - resultNum = 2; - } - } - if (resultNum) { - if (Args.size() >=2) { - Type *t = Args[1].Ty; - if (t->isFloatTy()) { - resultNum += 4; - } - else if (t->isDoubleTy()) { - resultNum += 8; - } - } - } - return resultNum; -} - -// -// Prefixes are attached to stub numbers depending on the return type. -// return type: float sf_ -// double df_ -// single complex sc_ -// double complext dc_ -// others NO PREFIX -// -// -// The full name of a helper function is__mips16_call_stub + -// return type dependent prefix + stub number -// -// FIXME: This is something that probably should be in a different source file -// and perhaps done differently but my main purpose is to not waste runtime -// on something that we can enumerate in the source. Another possibility is -// to have a python script to generate these mapping tables. This will do -// for now. There are a whole series of helper function mapping arrays, one -// for each return type class as outlined above. There there are 11 possible -// entries. Ones with 0 are ones which should never be selected. -// -// All the arrays are similar except for ones which return neither -// sf, df, sc, dc, in which we only care about ones which have sf or df as a -// first parameter. -// -#define P_ "__mips16_call_stub_" -#define MAX_STUB_NUMBER 10 -#define T1 P "1", P "2", 0, 0, P "5", P "6", 0, 0, P "9", P "10" -#define T P "0" , T1 -#define P P_ -static char const * vMips16Helper[MAX_STUB_NUMBER+1] = - {nullptr, T1 }; -#undef P -#define P P_ "sf_" -static char const * sfMips16Helper[MAX_STUB_NUMBER+1] = - { T }; -#undef P -#define P P_ "df_" -static char const * dfMips16Helper[MAX_STUB_NUMBER+1] = - { T }; -#undef P -#define P P_ "sc_" -static char const * scMips16Helper[MAX_STUB_NUMBER+1] = - { T }; -#undef P -#define P P_ "dc_" -static char const * dcMips16Helper[MAX_STUB_NUMBER+1] = - { T }; -#undef P -#undef P_ - - -const char* Mips16TargetLowering:: - getMips16HelperFunction - (Type* RetTy, ArgListTy &Args, bool &needHelper) const { - const unsigned int stubNum = getMips16HelperFunctionStubNumber(Args); -#ifndef NDEBUG - const unsigned int maxStubNum = 10; - assert(stubNum <= maxStubNum); - const bool validStubNum[maxStubNum+1] = - {true, true, true, false, false, true, true, false, false, true, true}; - assert(validStubNum[stubNum]); -#endif - const char *result; - if (RetTy->isFloatTy()) { - result = sfMips16Helper[stubNum]; - } - else if (RetTy ->isDoubleTy()) { - result = dfMips16Helper[stubNum]; - } else if (StructType *SRetTy = dyn_cast<StructType>(RetTy)) { - // check if it's complex - if (SRetTy->getNumElements() == 2) { - if ((SRetTy->getElementType(0)->isFloatTy()) && - (SRetTy->getElementType(1)->isFloatTy())) { - result = scMips16Helper[stubNum]; - } else if ((SRetTy->getElementType(0)->isDoubleTy()) && - (SRetTy->getElementType(1)->isDoubleTy())) { - result = dcMips16Helper[stubNum]; - } else { - llvm_unreachable("Uncovered condition"); - } - } else { - llvm_unreachable("Uncovered condition"); - } - } else { - if (stubNum == 0) { - needHelper = false; - return ""; - } - result = vMips16Helper[stubNum]; - } - needHelper = true; - return result; -} - -void Mips16TargetLowering:: -getOpndList(SmallVectorImpl<SDValue> &Ops, - std::deque< std::pair<unsigned, SDValue> > &RegsToPass, - bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage, - bool IsCallReloc, CallLoweringInfo &CLI, SDValue Callee, - SDValue Chain) const { - SelectionDAG &DAG = CLI.DAG; - MachineFunction &MF = DAG.getMachineFunction(); - MipsFunctionInfo *FuncInfo = MF.getInfo<MipsFunctionInfo>(); - const char* Mips16HelperFunction = nullptr; - bool NeedMips16Helper = false; - - if (Subtarget.inMips16HardFloat()) { - // - // currently we don't have symbols tagged with the mips16 or mips32 - // qualifier so we will assume that we don't know what kind it is. - // and generate the helper - // - bool LookupHelper = true; - if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(CLI.Callee)) { - Mips16Libcall Find = { RTLIB::UNKNOWN_LIBCALL, S->getSymbol() }; - - if (std::binary_search(std::begin(HardFloatLibCalls), - std::end(HardFloatLibCalls), Find)) - LookupHelper = false; - else { - const char *Symbol = S->getSymbol(); - Mips16IntrinsicHelperType IntrinsicFind = { Symbol, "" }; - const Mips16HardFloatInfo::FuncSignature *Signature = - Mips16HardFloatInfo::findFuncSignature(Symbol); - if (!IsPICCall && (Signature && (FuncInfo->StubsNeeded.find(Symbol) == - FuncInfo->StubsNeeded.end()))) { - FuncInfo->StubsNeeded[Symbol] = Signature; - // - // S2 is normally saved if the stub is for a function which - // returns a float or double value and is not otherwise. This is - // because more work is required after the function the stub - // is calling completes, and so the stub cannot directly return - // and the stub has no stack space to store the return address so - // S2 is used for that purpose. - // In order to take advantage of not saving S2, we need to also - // optimize the call in the stub and this requires some further - // functionality in MipsAsmPrinter which we don't have yet. - // So for now we always save S2. The optimization will be done - // in a follow-on patch. - // - if (1 || (Signature->RetSig != Mips16HardFloatInfo::NoFPRet)) - FuncInfo->setSaveS2(); - } - // one more look at list of intrinsics - const Mips16IntrinsicHelperType *Helper = - llvm::lower_bound(Mips16IntrinsicHelper, IntrinsicFind); - if (Helper != std::end(Mips16IntrinsicHelper) && - *Helper == IntrinsicFind) { - Mips16HelperFunction = Helper->Helper; - NeedMips16Helper = true; - LookupHelper = false; - } - - } - } else if (GlobalAddressSDNode *G = - dyn_cast<GlobalAddressSDNode>(CLI.Callee)) { - Mips16Libcall Find = { RTLIB::UNKNOWN_LIBCALL, - G->getGlobal()->getName().data() }; - - if (std::binary_search(std::begin(HardFloatLibCalls), - std::end(HardFloatLibCalls), Find)) - LookupHelper = false; - } - if (LookupHelper) - Mips16HelperFunction = - getMips16HelperFunction(CLI.RetTy, CLI.getArgs(), NeedMips16Helper); - } - - SDValue JumpTarget = Callee; - - // T9 should contain the address of the callee function if - // -relocation-model=pic or it is an indirect call. - if (IsPICCall || !GlobalOrExternal) { - unsigned V0Reg = Mips::V0; - if (NeedMips16Helper) { - RegsToPass.push_front(std::make_pair(V0Reg, Callee)); - JumpTarget = DAG.getExternalSymbol(Mips16HelperFunction, - getPointerTy(DAG.getDataLayout())); - ExternalSymbolSDNode *S = cast<ExternalSymbolSDNode>(JumpTarget); - JumpTarget = getAddrGlobal(S, CLI.DL, JumpTarget.getValueType(), DAG, - MipsII::MO_GOT, Chain, - FuncInfo->callPtrInfo(S->getSymbol())); - } else - RegsToPass.push_front(std::make_pair((unsigned)Mips::T9, Callee)); - } - - Ops.push_back(JumpTarget); - - MipsTargetLowering::getOpndList(Ops, RegsToPass, IsPICCall, GlobalOrExternal, - InternalLinkage, IsCallReloc, CLI, Callee, - Chain); -} - -MachineBasicBlock * -Mips16TargetLowering::emitSel16(unsigned Opc, MachineInstr &MI, - MachineBasicBlock *BB) const { - if (DontExpandCondPseudos16) - return BB; - const TargetInstrInfo *TII = Subtarget.getInstrInfo(); - DebugLoc DL = MI.getDebugLoc(); - // To "insert" a SELECT_CC instruction, we actually have to insert the - // diamond control-flow pattern. The incoming instruction knows the - // destination vreg to set, the condition code register to branch on, the - // true/false values to select between, and a branch opcode to use. - const BasicBlock *LLVM_BB = BB->getBasicBlock(); - MachineFunction::iterator It = ++BB->getIterator(); - - // thisMBB: - // ... - // TrueVal = ... - // setcc r1, r2, r3 - // bNE r1, r0, copy1MBB - // fallthrough --> copy0MBB - MachineBasicBlock *thisMBB = BB; - MachineFunction *F = BB->getParent(); - MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB); - MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB); - F->insert(It, copy0MBB); - F->insert(It, sinkMBB); - - // Transfer the remainder of BB and its successor edges to sinkMBB. - sinkMBB->splice(sinkMBB->begin(), BB, - std::next(MachineBasicBlock::iterator(MI)), BB->end()); - sinkMBB->transferSuccessorsAndUpdatePHIs(BB); - - // Next, add the true and fallthrough blocks as its successors. - BB->addSuccessor(copy0MBB); - BB->addSuccessor(sinkMBB); - - BuildMI(BB, DL, TII->get(Opc)) - .addReg(MI.getOperand(3).getReg()) - .addMBB(sinkMBB); - - // copy0MBB: - // %FalseValue = ... - // # fallthrough to sinkMBB - BB = copy0MBB; - - // Update machine-CFG edges - BB->addSuccessor(sinkMBB); - - // sinkMBB: - // %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copy0MBB ] - // ... - BB = sinkMBB; - - BuildMI(*BB, BB->begin(), DL, TII->get(Mips::PHI), MI.getOperand(0).getReg()) - .addReg(MI.getOperand(1).getReg()) - .addMBB(thisMBB) - .addReg(MI.getOperand(2).getReg()) - .addMBB(copy0MBB); - - MI.eraseFromParent(); // The pseudo instruction is gone now. - return BB; -} - -MachineBasicBlock * -Mips16TargetLowering::emitSelT16(unsigned Opc1, unsigned Opc2, MachineInstr &MI, - MachineBasicBlock *BB) const { - if (DontExpandCondPseudos16) - return BB; - const TargetInstrInfo *TII = Subtarget.getInstrInfo(); - DebugLoc DL = MI.getDebugLoc(); - // To "insert" a SELECT_CC instruction, we actually have to insert the - // diamond control-flow pattern. The incoming instruction knows the - // destination vreg to set, the condition code register to branch on, the - // true/false values to select between, and a branch opcode to use. - const BasicBlock *LLVM_BB = BB->getBasicBlock(); - MachineFunction::iterator It = ++BB->getIterator(); - - // thisMBB: - // ... - // TrueVal = ... - // setcc r1, r2, r3 - // bNE r1, r0, copy1MBB - // fallthrough --> copy0MBB - MachineBasicBlock *thisMBB = BB; - MachineFunction *F = BB->getParent(); - MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB); - MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB); - F->insert(It, copy0MBB); - F->insert(It, sinkMBB); - - // Transfer the remainder of BB and its successor edges to sinkMBB. - sinkMBB->splice(sinkMBB->begin(), BB, - std::next(MachineBasicBlock::iterator(MI)), BB->end()); - sinkMBB->transferSuccessorsAndUpdatePHIs(BB); - - // Next, add the true and fallthrough blocks as its successors. - BB->addSuccessor(copy0MBB); - BB->addSuccessor(sinkMBB); - - BuildMI(BB, DL, TII->get(Opc2)) - .addReg(MI.getOperand(3).getReg()) - .addReg(MI.getOperand(4).getReg()); - BuildMI(BB, DL, TII->get(Opc1)).addMBB(sinkMBB); - - // copy0MBB: - // %FalseValue = ... - // # fallthrough to sinkMBB - BB = copy0MBB; - - // Update machine-CFG edges - BB->addSuccessor(sinkMBB); - - // sinkMBB: - // %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copy0MBB ] - // ... - BB = sinkMBB; - - BuildMI(*BB, BB->begin(), DL, TII->get(Mips::PHI), MI.getOperand(0).getReg()) - .addReg(MI.getOperand(1).getReg()) - .addMBB(thisMBB) - .addReg(MI.getOperand(2).getReg()) - .addMBB(copy0MBB); - - MI.eraseFromParent(); // The pseudo instruction is gone now. - return BB; - -} - -MachineBasicBlock * -Mips16TargetLowering::emitSeliT16(unsigned Opc1, unsigned Opc2, - MachineInstr &MI, - MachineBasicBlock *BB) const { - if (DontExpandCondPseudos16) - return BB; - const TargetInstrInfo *TII = Subtarget.getInstrInfo(); - DebugLoc DL = MI.getDebugLoc(); - // To "insert" a SELECT_CC instruction, we actually have to insert the - // diamond control-flow pattern. The incoming instruction knows the - // destination vreg to set, the condition code register to branch on, the - // true/false values to select between, and a branch opcode to use. - const BasicBlock *LLVM_BB = BB->getBasicBlock(); - MachineFunction::iterator It = ++BB->getIterator(); - - // thisMBB: - // ... - // TrueVal = ... - // setcc r1, r2, r3 - // bNE r1, r0, copy1MBB - // fallthrough --> copy0MBB - MachineBasicBlock *thisMBB = BB; - MachineFunction *F = BB->getParent(); - MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB); - MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB); - F->insert(It, copy0MBB); - F->insert(It, sinkMBB); - - // Transfer the remainder of BB and its successor edges to sinkMBB. - sinkMBB->splice(sinkMBB->begin(), BB, - std::next(MachineBasicBlock::iterator(MI)), BB->end()); - sinkMBB->transferSuccessorsAndUpdatePHIs(BB); - - // Next, add the true and fallthrough blocks as its successors. - BB->addSuccessor(copy0MBB); - BB->addSuccessor(sinkMBB); - - BuildMI(BB, DL, TII->get(Opc2)) - .addReg(MI.getOperand(3).getReg()) - .addImm(MI.getOperand(4).getImm()); - BuildMI(BB, DL, TII->get(Opc1)).addMBB(sinkMBB); - - // copy0MBB: - // %FalseValue = ... - // # fallthrough to sinkMBB - BB = copy0MBB; - - // Update machine-CFG edges - BB->addSuccessor(sinkMBB); - - // sinkMBB: - // %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copy0MBB ] - // ... - BB = sinkMBB; - - BuildMI(*BB, BB->begin(), DL, TII->get(Mips::PHI), MI.getOperand(0).getReg()) - .addReg(MI.getOperand(1).getReg()) - .addMBB(thisMBB) - .addReg(MI.getOperand(2).getReg()) - .addMBB(copy0MBB); - - MI.eraseFromParent(); // The pseudo instruction is gone now. - return BB; - -} - -MachineBasicBlock * -Mips16TargetLowering::emitFEXT_T8I816_ins(unsigned BtOpc, unsigned CmpOpc, - MachineInstr &MI, - MachineBasicBlock *BB) const { - if (DontExpandCondPseudos16) - return BB; - const TargetInstrInfo *TII = Subtarget.getInstrInfo(); - unsigned regX = MI.getOperand(0).getReg(); - unsigned regY = MI.getOperand(1).getReg(); - MachineBasicBlock *target = MI.getOperand(2).getMBB(); - BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(CmpOpc)) - .addReg(regX) - .addReg(regY); - BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(BtOpc)).addMBB(target); - MI.eraseFromParent(); // The pseudo instruction is gone now. - return BB; -} - -MachineBasicBlock *Mips16TargetLowering::emitFEXT_T8I8I16_ins( - unsigned BtOpc, unsigned CmpiOpc, unsigned CmpiXOpc, bool ImmSigned, - MachineInstr &MI, MachineBasicBlock *BB) const { - if (DontExpandCondPseudos16) - return BB; - const TargetInstrInfo *TII = Subtarget.getInstrInfo(); - unsigned regX = MI.getOperand(0).getReg(); - int64_t imm = MI.getOperand(1).getImm(); - MachineBasicBlock *target = MI.getOperand(2).getMBB(); - unsigned CmpOpc; - if (isUInt<8>(imm)) - CmpOpc = CmpiOpc; - else if ((!ImmSigned && isUInt<16>(imm)) || - (ImmSigned && isInt<16>(imm))) - CmpOpc = CmpiXOpc; - else - llvm_unreachable("immediate field not usable"); - BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(CmpOpc)).addReg(regX).addImm(imm); - BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(BtOpc)).addMBB(target); - MI.eraseFromParent(); // The pseudo instruction is gone now. - return BB; -} - -static unsigned Mips16WhichOp8uOr16simm - (unsigned shortOp, unsigned longOp, int64_t Imm) { - if (isUInt<8>(Imm)) - return shortOp; - else if (isInt<16>(Imm)) - return longOp; - else - llvm_unreachable("immediate field not usable"); -} - -MachineBasicBlock * -Mips16TargetLowering::emitFEXT_CCRX16_ins(unsigned SltOpc, MachineInstr &MI, - MachineBasicBlock *BB) const { - if (DontExpandCondPseudos16) - return BB; - const TargetInstrInfo *TII = Subtarget.getInstrInfo(); - unsigned CC = MI.getOperand(0).getReg(); - unsigned regX = MI.getOperand(1).getReg(); - unsigned regY = MI.getOperand(2).getReg(); - BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(SltOpc)) - .addReg(regX) - .addReg(regY); - BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(Mips::MoveR3216), CC) - .addReg(Mips::T8); - MI.eraseFromParent(); // The pseudo instruction is gone now. - return BB; -} - -MachineBasicBlock * -Mips16TargetLowering::emitFEXT_CCRXI16_ins(unsigned SltiOpc, unsigned SltiXOpc, - MachineInstr &MI, - MachineBasicBlock *BB) const { - if (DontExpandCondPseudos16) - return BB; - const TargetInstrInfo *TII = Subtarget.getInstrInfo(); - unsigned CC = MI.getOperand(0).getReg(); - unsigned regX = MI.getOperand(1).getReg(); - int64_t Imm = MI.getOperand(2).getImm(); - unsigned SltOpc = Mips16WhichOp8uOr16simm(SltiOpc, SltiXOpc, Imm); - BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(SltOpc)).addReg(regX).addImm(Imm); - BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(Mips::MoveR3216), CC) - .addReg(Mips::T8); - MI.eraseFromParent(); // The pseudo instruction is gone now. - return BB; - -} diff --git a/contrib/llvm/lib/Target/Mips/Mips16ISelLowering.h b/contrib/llvm/lib/Target/Mips/Mips16ISelLowering.h deleted file mode 100644 index 200249933577..000000000000 --- a/contrib/llvm/lib/Target/Mips/Mips16ISelLowering.h +++ /dev/null @@ -1,82 +0,0 @@ -//===-- Mips16ISelLowering.h - Mips16 DAG Lowering Interface ----*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Subclass of MipsTargetLowering specialized for mips16. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_MIPS_MIPS16ISELLOWERING_H -#define LLVM_LIB_TARGET_MIPS_MIPS16ISELLOWERING_H - -#include "MipsISelLowering.h" - -namespace llvm { - class Mips16TargetLowering : public MipsTargetLowering { - public: - explicit Mips16TargetLowering(const MipsTargetMachine &TM, - const MipsSubtarget &STI); - - bool allowsMisalignedMemoryAccesses(EVT VT, unsigned AddrSpace, - unsigned Align, - MachineMemOperand::Flags Flags, - bool *Fast) const override; - - MachineBasicBlock * - EmitInstrWithCustomInserter(MachineInstr &MI, - MachineBasicBlock *MBB) const override; - - private: - bool isEligibleForTailCallOptimization( - const CCState &CCInfo, unsigned NextStackOffset, - const MipsFunctionInfo &FI) const override; - - void setMips16HardFloatLibCalls(); - - unsigned int - getMips16HelperFunctionStubNumber(ArgListTy &Args) const; - - const char *getMips16HelperFunction - (Type* RetTy, ArgListTy &Args, bool &needHelper) const; - - void - getOpndList(SmallVectorImpl<SDValue> &Ops, - std::deque< std::pair<unsigned, SDValue> > &RegsToPass, - bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage, - bool IsCallReloc, CallLoweringInfo &CLI, SDValue Callee, - SDValue Chain) const override; - - MachineBasicBlock *emitSel16(unsigned Opc, MachineInstr &MI, - MachineBasicBlock *BB) const; - - MachineBasicBlock *emitSeliT16(unsigned Opc1, unsigned Opc2, - MachineInstr &MI, - MachineBasicBlock *BB) const; - - MachineBasicBlock *emitSelT16(unsigned Opc1, unsigned Opc2, - MachineInstr &MI, - MachineBasicBlock *BB) const; - - MachineBasicBlock *emitFEXT_T8I816_ins(unsigned BtOpc, unsigned CmpOpc, - MachineInstr &MI, - MachineBasicBlock *BB) const; - - MachineBasicBlock *emitFEXT_T8I8I16_ins(unsigned BtOpc, unsigned CmpiOpc, - unsigned CmpiXOpc, bool ImmSigned, - MachineInstr &MI, - MachineBasicBlock *BB) const; - - MachineBasicBlock *emitFEXT_CCRX16_ins(unsigned SltOpc, MachineInstr &MI, - MachineBasicBlock *BB) const; - - MachineBasicBlock *emitFEXT_CCRXI16_ins(unsigned SltiOpc, unsigned SltiXOpc, - MachineInstr &MI, - MachineBasicBlock *BB) const; - }; -} - -#endif diff --git a/contrib/llvm/lib/Target/Mips/Mips16InstrFormats.td b/contrib/llvm/lib/Target/Mips/Mips16InstrFormats.td deleted file mode 100644 index f4ac160c2ba5..000000000000 --- a/contrib/llvm/lib/Target/Mips/Mips16InstrFormats.td +++ /dev/null @@ -1,639 +0,0 @@ -//===- Mips16InstrFormats.td - Mips Instruction Formats ----*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// Describe MIPS instructions format -// -// CPU INSTRUCTION FORMATS -// -// funct or f Function field -// -// immediate 4-,5-,8- or 11-bit immediate, branch displacement, or -// or imm address displacement -// -// op 5-bit major operation code -// -// rx 3-bit source or destination register -// -// ry 3-bit source or destination register -// -// rz 3-bit source or destination register -// -// sa 3- or 5-bit shift amount -// -//===----------------------------------------------------------------------===// - - -// Base class for Mips 16 Format -// This class does not depend on the instruction size -// -class MipsInst16_Base<dag outs, dag ins, string asmstr, list<dag> pattern, - InstrItinClass itin>: Instruction -{ - - let Namespace = "Mips"; - - let OutOperandList = outs; - let InOperandList = ins; - - let AsmString = asmstr; - let Pattern = pattern; - let Itinerary = itin; - - let Predicates = [InMips16Mode]; -} - -// -// Generic Mips 16 Format -// -class MipsInst16<dag outs, dag ins, string asmstr, list<dag> pattern, - InstrItinClass itin>: - MipsInst16_Base<outs, ins, asmstr, pattern, itin> -{ - field bits<16> Inst; - bits<5> Opcode = 0; - - // Top 5 bits are the 'opcode' field - let Inst{15-11} = Opcode; - - let Size=2; - field bits<16> SoftFail = 0; -} - -// -// For 32 bit extended instruction forms. -// -class MipsInst16_32<dag outs, dag ins, string asmstr, list<dag> pattern, - InstrItinClass itin>: - MipsInst16_Base<outs, ins, asmstr, pattern, itin> -{ - field bits<32> Inst; - - let Size=4; - field bits<32> SoftFail = 0; -} - -class MipsInst16_EXTEND<dag outs, dag ins, string asmstr, list<dag> pattern, - InstrItinClass itin>: - MipsInst16_32<outs, ins, asmstr, pattern, itin> -{ - let Inst{31-27} = 0b11110; -} - - - -// Mips Pseudo Instructions Format -class MipsPseudo16<dag outs, dag ins, string asmstr, list<dag> pattern>: - MipsInst16<outs, ins, asmstr, pattern, IIPseudo> { - let isCodeGenOnly = 1; - let isPseudo = 1; -} - - -//===----------------------------------------------------------------------===// -// Format I instruction class in Mips : <|opcode|imm11|> -//===----------------------------------------------------------------------===// - -class FI16<bits<5> op, dag outs, dag ins, string asmstr, list<dag> pattern, - InstrItinClass itin>: - MipsInst16<outs, ins, asmstr, pattern, itin> -{ - bits<11> imm11; - - let Opcode = op; - - let Inst{10-0} = imm11; -} - -//===----------------------------------------------------------------------===// -// Format RI instruction class in Mips : <|opcode|rx|imm8|> -//===----------------------------------------------------------------------===// - -class FRI16<bits<5> op, dag outs, dag ins, string asmstr, - list<dag> pattern, InstrItinClass itin>: - MipsInst16<outs, ins, asmstr, pattern, itin> -{ - bits<3> rx; - bits<8> imm8; - - let Opcode = op; - - let Inst{10-8} = rx; - let Inst{7-0} = imm8; -} - -//===----------------------------------------------------------------------===// -// Format RR instruction class in Mips : <|opcode|rx|ry|funct|> -//===----------------------------------------------------------------------===// - -class FRR16<bits<5> _funct, dag outs, dag ins, string asmstr, - list<dag> pattern, InstrItinClass itin>: - MipsInst16<outs, ins, asmstr, pattern, itin> -{ - bits<3> rx; - bits<3> ry; - bits<5> funct; - - let Opcode = 0b11101; - let funct = _funct; - - let Inst{10-8} = rx; - let Inst{7-5} = ry; - let Inst{4-0} = funct; -} - -class FRRBreak16<dag outs, dag ins, string asmstr, - list<dag> pattern, InstrItinClass itin>: - MipsInst16<outs, ins, asmstr, pattern, itin> -{ - bits<6> Code; - bits<5> funct; - - let Opcode = 0b11101; - let funct = 0b00101; - - let Inst{10-5} = Code; - let Inst{4-0} = funct; -} - -// -// For conversion functions. -// -class FRR_SF16<bits<5> _funct, bits<3> _subfunct, dag outs, dag ins, - string asmstr, list<dag> pattern, InstrItinClass itin>: - MipsInst16<outs, ins, asmstr, pattern, itin> -{ - bits<3> rx; - bits<3> subfunct; - bits<5> funct; - - let Opcode = 0b11101; // RR - let funct = _funct; - let subfunct = _subfunct; - - let Inst{10-8} = rx; - let Inst{7-5} = subfunct; - let Inst{4-0} = funct; -} - -// -// just used for breakpoint (hardware and software) instructions. -// -class FC16<bits<5> _funct, dag outs, dag ins, string asmstr, - list<dag> pattern, InstrItinClass itin>: - MipsInst16<outs, ins, asmstr, pattern, itin> -{ - bits<6> _code; // code is a keyword in tablegen - bits<5> funct; - - let Opcode = 0b11101; // RR - let funct = _funct; - - let Inst{10-5} = _code; - let Inst{4-0} = funct; -} - -// -// J(AL)R(C) subformat -// -class FRR16_JALRC<bits<1> _nd, bits<1> _l, bits<1> r_a, - dag outs, dag ins, string asmstr, - list<dag> pattern, InstrItinClass itin>: - MipsInst16<outs, ins, asmstr, pattern, itin> -{ - bits<3> rx; - bits<1> nd; - bits<1> l; - bits<1> ra; - - let nd = _nd; - let l = _l; - let ra = r_a; - - let Opcode = 0b11101; - - let Inst{10-8} = rx; - let Inst{7} = nd; - let Inst{6} = l; - let Inst{5} = ra; - let Inst{4-0} = 0; -} - -//===----------------------------------------------------------------------===// -// Format RRI instruction class in Mips : <|opcode|rx|ry|imm5|> -//===----------------------------------------------------------------------===// - -class FRRI16<bits<5> op, dag outs, dag ins, string asmstr, - list<dag> pattern, InstrItinClass itin>: - MipsInst16<outs, ins, asmstr, pattern, itin> -{ - bits<3> rx; - bits<3> ry; - bits<5> imm5; - - let Opcode = op; - - - let Inst{10-8} = rx; - let Inst{7-5} = ry; - let Inst{4-0} = imm5; -} - -//===----------------------------------------------------------------------===// -// Format RRR instruction class in Mips : <|opcode|rx|ry|rz|f|> -//===----------------------------------------------------------------------===// - -class FRRR16<bits<2> _f, dag outs, dag ins, string asmstr, - list<dag> pattern, InstrItinClass itin>: - MipsInst16<outs, ins, asmstr, pattern, itin> -{ - bits<3> rx; - bits<3> ry; - bits<3> rz; - bits<2> f; - - let Opcode = 0b11100; - let f = _f; - - let Inst{10-8} = rx; - let Inst{7-5} = ry; - let Inst{4-2} = rz; - let Inst{1-0} = f; -} - -//===----------------------------------------------------------------------===// -// Format RRI-A instruction class in Mips : <|opcode|rx|ry|f|imm4|> -//===----------------------------------------------------------------------===// - -class FRRI_A16<bits<1> _f, dag outs, dag ins, string asmstr, - list<dag> pattern, InstrItinClass itin>: - MipsInst16<outs, ins, asmstr, pattern, itin> -{ - bits<3> rx; - bits<3> ry; - bits<1> f; - bits<4> imm4; - - let Opcode = 0b01000; - let f = _f; - - let Inst{10-8} = rx; - let Inst{7-5} = ry; - let Inst{4} = f; - let Inst{3-0} = imm4; -} - -//===----------------------------------------------------------------------===// -// Format Shift instruction class in Mips : <|opcode|rx|ry|sa|f|> -//===----------------------------------------------------------------------===// - -class FSHIFT16<bits<2> _f, dag outs, dag ins, string asmstr, - list<dag> pattern, InstrItinClass itin>: - MipsInst16<outs, ins, asmstr, pattern, itin> -{ - bits<3> rx; - bits<3> ry; - bits<3> sa; - bits<2> f; - - let Opcode = 0b00110; - let f = _f; - - let Inst{10-8} = rx; - let Inst{7-5} = ry; - let Inst{4-2} = sa; - let Inst{1-0} = f; -} - -//===----------------------------------------------------------------------===// -// Format i8 instruction class in Mips : <|opcode|funct|imm8> -//===----------------------------------------------------------------------===// - -class FI816<bits<3> _func, dag outs, dag ins, string asmstr, - list<dag> pattern, InstrItinClass itin>: - MipsInst16<outs, ins, asmstr, pattern, itin> -{ - bits<3> func; - bits<8> imm8; - - let Opcode = 0b01100; - let func = _func; - - let Inst{10-8} = func; - let Inst{7-0} = imm8; -} - -//===----------------------------------------------------------------------===// -// Format i8_MOVR32 instruction class in Mips : <|opcode|func|ry|r32> -//===----------------------------------------------------------------------===// - -class FI8_MOVR3216<dag outs, dag ins, string asmstr, - list<dag> pattern, InstrItinClass itin>: - MipsInst16<outs, ins, asmstr, pattern, itin> -{ - - bits<4> ry; - bits<4> r32; - - let Opcode = 0b01100; - - let Inst{10-8} = 0b111; - let Inst{7-4} = ry; - let Inst{3-0} = r32; - -} - - - -//===----------------------------------------------------------------------===// -// Format i8_MOV32R instruction class in Mips : <|opcode|func|r32|rz> -//===----------------------------------------------------------------------===// - -class FI8_MOV32R16<dag outs, dag ins, string asmstr, - list<dag> pattern, InstrItinClass itin>: - MipsInst16<outs, ins, asmstr, pattern, itin> -{ - - bits<3> func; - bits<5> r32; - bits<3> rz; - - - let Opcode = 0b01100; - - let Inst{10-8} = 0b101; - let Inst{7-5} = r32{2-0}; - let Inst{4-3} = r32{4-3}; - let Inst{2-0} = rz; - -} - -//===----------------------------------------------------------------------===// -// Format i8_SVRS instruction class in Mips : -// <|opcode|svrs|s|ra|s0|s1|framesize> -//===----------------------------------------------------------------------===// - -class FI8_SVRS16<bits<1> _s, dag outs, dag ins, string asmstr, - list<dag> pattern, InstrItinClass itin>: - MipsInst16<outs, ins, asmstr, pattern, itin> -{ - bits<1> s; - bits<1> ra = 0; - bits<1> s0 = 0; - bits<1> s1 = 0; - bits<4> framesize = 0; - - let s =_s; - let Opcode = 0b01100; - - let Inst{10-8} = 0b100; - let Inst{7} = s; - let Inst{6} = ra; - let Inst{5} = s0; - let Inst{4} = s1; - let Inst{3-0} = framesize; - -} - -//===----------------------------------------------------------------------===// -// Format JAL instruction class in Mips16 : -// <|opcode|svrs|s|ra|s0|s1|framesize> -//===----------------------------------------------------------------------===// - -class FJAL16<bits<1> _X, dag outs, dag ins, string asmstr, - list<dag> pattern, InstrItinClass itin>: - MipsInst16_32<outs, ins, asmstr, pattern, itin> -{ - bits<1> X; - bits<26> imm26; - - - let X = _X; - - let Inst{31-27} = 0b00011; - let Inst{26} = X; - let Inst{25-21} = imm26{20-16}; - let Inst{20-16} = imm26{25-21}; - let Inst{15-0} = imm26{15-0}; - -} - -//===----------------------------------------------------------------------===// -// Format EXT-I instruction class in Mips16 : -// <|EXTEND|imm10:5|imm15:11|op|0|0|0|0|0|0|imm4:0> -//===----------------------------------------------------------------------===// - -class FEXT_I16<bits<5> _eop, dag outs, dag ins, string asmstr, - list<dag> pattern, InstrItinClass itin>: - MipsInst16_EXTEND<outs, ins, asmstr, pattern, itin> -{ - bits<16> imm16; - bits<5> eop; - - let eop = _eop; - - let Inst{26-21} = imm16{10-5}; - let Inst{20-16} = imm16{15-11}; - let Inst{15-11} = eop; - let Inst{10-5} = 0; - let Inst{4-0} = imm16{4-0}; - -} - -//===----------------------------------------------------------------------===// -// Format ASMACRO instruction class in Mips16 : -// <EXTEND|select|p4|p3|RRR|p2|p1|p0> -//===----------------------------------------------------------------------===// - -class FASMACRO16<dag outs, dag ins, string asmstr, - list<dag> pattern, InstrItinClass itin>: - MipsInst16_EXTEND<outs, ins, asmstr, pattern, itin> -{ - bits<3> select; - bits<3> p4; - bits<5> p3; - bits<5> RRR = 0b11100; - bits<3> p2; - bits<3> p1; - bits<5> p0; - - - let Inst{26-24} = select; - let Inst{23-21} = p4; - let Inst{20-16} = p3; - let Inst{15-11} = RRR; - let Inst{10-8} = p2; - let Inst{7-5} = p1; - let Inst{4-0} = p0; - -} - - -//===----------------------------------------------------------------------===// -// Format EXT-RI instruction class in Mips16 : -// <|EXTEND|imm10:5|imm15:11|op|rx|0|0|0|imm4:0> -//===----------------------------------------------------------------------===// - -class FEXT_RI16<bits<5> _op, dag outs, dag ins, string asmstr, - list<dag> pattern, InstrItinClass itin>: - MipsInst16_EXTEND<outs, ins, asmstr, pattern, itin> -{ - bits<16> imm16; - bits<5> op; - bits<3> rx; - - let op = _op; - - let Inst{26-21} = imm16{10-5}; - let Inst{20-16} = imm16{15-11}; - let Inst{15-11} = op; - let Inst{10-8} = rx; - let Inst{7-5} = 0; - let Inst{4-0} = imm16{4-0}; - -} - -//===----------------------------------------------------------------------===// -// Format EXT-RRI instruction class in Mips16 : -// <|EXTEND|imm10:5|imm15:11|op|rx|ry|imm4:0> -//===----------------------------------------------------------------------===// - -class FEXT_RRI16<bits<5> _op, dag outs, dag ins, string asmstr, - list<dag> pattern, InstrItinClass itin>: - MipsInst16_EXTEND<outs, ins, asmstr, pattern, itin> -{ - bits<5> op; - bits<16> imm16; - bits<3> rx; - bits<3> ry; - - let op=_op; - - let Inst{26-21} = imm16{10-5}; - let Inst{20-16} = imm16{15-11}; - let Inst{15-11} = op; - let Inst{10-8} = rx; - let Inst{7-5} = ry; - let Inst{4-0} = imm16{4-0}; - -} - -//===----------------------------------------------------------------------===// -// Format EXT-RRI-A instruction class in Mips16 : -// <|EXTEND|imm10:4|imm14:11|RRI-A|rx|ry|f|imm3:0> -//===----------------------------------------------------------------------===// - -class FEXT_RRI_A16<bits<1> _f, dag outs, dag ins, string asmstr, - list<dag> pattern, InstrItinClass itin>: - MipsInst16_EXTEND<outs, ins, asmstr, pattern, itin> -{ - bits<15> imm15; - bits<3> rx; - bits<3> ry; - bits<1> f; - - let f = _f; - - let Inst{26-20} = imm15{10-4}; - let Inst{19-16} = imm15{14-11}; - let Inst{15-11} = 0b01000; - let Inst{10-8} = rx; - let Inst{7-5} = ry; - let Inst{4} = f; - let Inst{3-0} = imm15{3-0}; - -} - -//===----------------------------------------------------------------------===// -// Format EXT-SHIFT instruction class in Mips16 : -// <|EXTEND|sa 4:0|s5|0|SHIFT|rx|ry|0|f> -//===----------------------------------------------------------------------===// - -class FEXT_SHIFT16<bits<2> _f, dag outs, dag ins, string asmstr, - list<dag> pattern, InstrItinClass itin>: - MipsInst16_EXTEND<outs, ins, asmstr, pattern, itin> -{ - bits<6> sa6; - bits<3> rx; - bits<3> ry; - bits<2> f; - - let f = _f; - - let Inst{26-22} = sa6{4-0}; - let Inst{21} = sa6{5}; - let Inst{20-16} = 0; - let Inst{15-11} = 0b00110; - let Inst{10-8} = rx; - let Inst{7-5} = ry; - let Inst{4-2} = 0; - let Inst{1-0} = f; - -} - -//===----------------------------------------------------------------------===// -// Format EXT-I8 instruction class in Mips16 : -// <|EXTEND|imm10:5|imm15:11|I8|funct|0|imm4:0> -//===----------------------------------------------------------------------===// - -class FEXT_I816<bits<3> _funct, dag outs, dag ins, string asmstr, - list<dag> pattern, InstrItinClass itin>: - MipsInst16_EXTEND<outs, ins, asmstr, pattern, itin> -{ - bits<16> imm16; - bits<5> I8; - bits<3> funct; - - let funct = _funct; - let I8 = 0b00110; - - let Inst{26-21} = imm16{10-5}; - let Inst{20-16} = imm16{15-11}; - let Inst{15-11} = I8; - let Inst{10-8} = funct; - let Inst{7-5} = 0; - let Inst{4-0} = imm16{4-0}; - -} - -//===----------------------------------------------------------------------===// -// Format EXT-I8_SVRS instruction class in Mips16 : -// <|EXTEND|xsregs|framesize7:4|aregs|I8|SVRS|s|ra|s0|s1|framesize3:0> -//===----------------------------------------------------------------------===// - -class FEXT_I8_SVRS16<bits<1> s_, dag outs, dag ins, string asmstr, - list<dag> pattern, InstrItinClass itin>: - MipsInst16_EXTEND<outs, ins, asmstr, pattern, itin> -{ - bits<3> xsregs =0; - bits<8> framesize =0; - bits<3> aregs =0; - bits<5> I8 = 0b01100; - bits<3> SVRS = 0b100; - bits<1> s; - bits<1> ra = 0; - bits<1> s0 = 0; - bits<1> s1 = 0; - - let s= s_; - - let Inst{26-24} = xsregs; - let Inst{23-20} = framesize{7-4}; - let Inst{19} = 0; - let Inst{18-16} = aregs; - let Inst{15-11} = I8; - let Inst{10-8} = SVRS; - let Inst{7} = s; - let Inst{6} = ra; - let Inst{5} = s0; - let Inst{4} = s1; - let Inst{3-0} = framesize{3-0}; - - -} - diff --git a/contrib/llvm/lib/Target/Mips/Mips16InstrInfo.cpp b/contrib/llvm/lib/Target/Mips/Mips16InstrInfo.cpp deleted file mode 100644 index c234c309d760..000000000000 --- a/contrib/llvm/lib/Target/Mips/Mips16InstrInfo.cpp +++ /dev/null @@ -1,495 +0,0 @@ -//===- Mips16InstrInfo.cpp - Mips16 Instruction Information ---------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains the Mips16 implementation of the TargetInstrInfo class. -// -//===----------------------------------------------------------------------===// - -#include "Mips16InstrInfo.h" -#include "llvm/ADT/BitVector.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/MachineMemOperand.h" -#include "llvm/CodeGen/MachineOperand.h" -#include "llvm/CodeGen/RegisterScavenging.h" -#include "llvm/CodeGen/TargetRegisterInfo.h" -#include "llvm/IR/DebugLoc.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/raw_ostream.h" -#include <cassert> -#include <cctype> -#include <cstdint> -#include <cstdlib> -#include <cstring> -#include <iterator> -#include <vector> - -using namespace llvm; - -#define DEBUG_TYPE "mips16-instrinfo" - -Mips16InstrInfo::Mips16InstrInfo(const MipsSubtarget &STI) - : MipsInstrInfo(STI, Mips::Bimm16) {} - -const MipsRegisterInfo &Mips16InstrInfo::getRegisterInfo() const { - return RI; -} - -/// isLoadFromStackSlot - If the specified machine instruction is a direct -/// load from a stack slot, return the virtual or physical register number of -/// the destination along with the FrameIndex of the loaded stack slot. If -/// not, return 0. This predicate must return 0 if the instruction has -/// any side effects other than loading from the stack slot. -unsigned Mips16InstrInfo::isLoadFromStackSlot(const MachineInstr &MI, - int &FrameIndex) const { - return 0; -} - -/// isStoreToStackSlot - If the specified machine instruction is a direct -/// store to a stack slot, return the virtual or physical register number of -/// the source reg along with the FrameIndex of the loaded stack slot. If -/// not, return 0. This predicate must return 0 if the instruction has -/// any side effects other than storing to the stack slot. -unsigned Mips16InstrInfo::isStoreToStackSlot(const MachineInstr &MI, - int &FrameIndex) const { - return 0; -} - -void Mips16InstrInfo::copyPhysReg(MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, - const DebugLoc &DL, unsigned DestReg, - unsigned SrcReg, bool KillSrc) const { - unsigned Opc = 0; - - if (Mips::CPU16RegsRegClass.contains(DestReg) && - Mips::GPR32RegClass.contains(SrcReg)) - Opc = Mips::MoveR3216; - else if (Mips::GPR32RegClass.contains(DestReg) && - Mips::CPU16RegsRegClass.contains(SrcReg)) - Opc = Mips::Move32R16; - else if ((SrcReg == Mips::HI0) && - (Mips::CPU16RegsRegClass.contains(DestReg))) - Opc = Mips::Mfhi16, SrcReg = 0; - else if ((SrcReg == Mips::LO0) && - (Mips::CPU16RegsRegClass.contains(DestReg))) - Opc = Mips::Mflo16, SrcReg = 0; - - assert(Opc && "Cannot copy registers"); - - MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(Opc)); - - if (DestReg) - MIB.addReg(DestReg, RegState::Define); - - if (SrcReg) - MIB.addReg(SrcReg, getKillRegState(KillSrc)); -} - -bool Mips16InstrInfo::isCopyInstrImpl(const MachineInstr &MI, - const MachineOperand *&Src, - const MachineOperand *&Dest) const { - if (MI.isMoveReg()) { - Dest = &MI.getOperand(0); - Src = &MI.getOperand(1); - return true; - } - return false; -} - -void Mips16InstrInfo::storeRegToStack(MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, - unsigned SrcReg, bool isKill, int FI, - const TargetRegisterClass *RC, - const TargetRegisterInfo *TRI, - int64_t Offset) const { - DebugLoc DL; - if (I != MBB.end()) DL = I->getDebugLoc(); - MachineMemOperand *MMO = GetMemOperand(MBB, FI, MachineMemOperand::MOStore); - unsigned Opc = 0; - if (Mips::CPU16RegsRegClass.hasSubClassEq(RC)) - Opc = Mips::SwRxSpImmX16; - assert(Opc && "Register class not handled!"); - BuildMI(MBB, I, DL, get(Opc)).addReg(SrcReg, getKillRegState(isKill)). - addFrameIndex(FI).addImm(Offset) - .addMemOperand(MMO); -} - -void Mips16InstrInfo::loadRegFromStack(MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, - unsigned DestReg, int FI, - const TargetRegisterClass *RC, - const TargetRegisterInfo *TRI, - int64_t Offset) const { - DebugLoc DL; - if (I != MBB.end()) DL = I->getDebugLoc(); - MachineMemOperand *MMO = GetMemOperand(MBB, FI, MachineMemOperand::MOLoad); - unsigned Opc = 0; - - if (Mips::CPU16RegsRegClass.hasSubClassEq(RC)) - Opc = Mips::LwRxSpImmX16; - assert(Opc && "Register class not handled!"); - BuildMI(MBB, I, DL, get(Opc), DestReg).addFrameIndex(FI).addImm(Offset) - .addMemOperand(MMO); -} - -bool Mips16InstrInfo::expandPostRAPseudo(MachineInstr &MI) const { - MachineBasicBlock &MBB = *MI.getParent(); - switch (MI.getDesc().getOpcode()) { - default: - return false; - case Mips::RetRA16: - ExpandRetRA16(MBB, MI, Mips::JrcRa16); - break; - } - - MBB.erase(MI.getIterator()); - return true; -} - -/// GetOppositeBranchOpc - Return the inverse of the specified -/// opcode, e.g. turning BEQ to BNE. -unsigned Mips16InstrInfo::getOppositeBranchOpc(unsigned Opc) const { - switch (Opc) { - case Mips::BeqzRxImmX16: return Mips::BnezRxImmX16; - case Mips::BnezRxImmX16: return Mips::BeqzRxImmX16; - case Mips::BeqzRxImm16: return Mips::BnezRxImm16; - case Mips::BnezRxImm16: return Mips::BeqzRxImm16; - case Mips::BteqzT8CmpX16: return Mips::BtnezT8CmpX16; - case Mips::BteqzT8SltX16: return Mips::BtnezT8SltX16; - case Mips::BteqzT8SltiX16: return Mips::BtnezT8SltiX16; - case Mips::Btnez16: return Mips::Bteqz16; - case Mips::BtnezX16: return Mips::BteqzX16; - case Mips::BtnezT8CmpiX16: return Mips::BteqzT8CmpiX16; - case Mips::BtnezT8SltuX16: return Mips::BteqzT8SltuX16; - case Mips::BtnezT8SltiuX16: return Mips::BteqzT8SltiuX16; - case Mips::Bteqz16: return Mips::Btnez16; - case Mips::BteqzX16: return Mips::BtnezX16; - case Mips::BteqzT8CmpiX16: return Mips::BtnezT8CmpiX16; - case Mips::BteqzT8SltuX16: return Mips::BtnezT8SltuX16; - case Mips::BteqzT8SltiuX16: return Mips::BtnezT8SltiuX16; - case Mips::BtnezT8CmpX16: return Mips::BteqzT8CmpX16; - case Mips::BtnezT8SltX16: return Mips::BteqzT8SltX16; - case Mips::BtnezT8SltiX16: return Mips::BteqzT8SltiX16; - } - llvm_unreachable("Illegal opcode!"); -} - -static void addSaveRestoreRegs(MachineInstrBuilder &MIB, - const std::vector<CalleeSavedInfo> &CSI, - unsigned Flags = 0) { - for (unsigned i = 0, e = CSI.size(); i != e; ++i) { - // Add the callee-saved register as live-in. Do not add if the register is - // RA and return address is taken, because it has already been added in - // method MipsTargetLowering::lowerRETURNADDR. - // It's killed at the spill, unless the register is RA and return address - // is taken. - unsigned Reg = CSI[e-i-1].getReg(); - switch (Reg) { - case Mips::RA: - case Mips::S0: - case Mips::S1: - MIB.addReg(Reg, Flags); - break; - case Mips::S2: - break; - default: - llvm_unreachable("unexpected mips16 callee saved register"); - - } - } -} - -// Adjust SP by FrameSize bytes. Save RA, S0, S1 -void Mips16InstrInfo::makeFrame(unsigned SP, int64_t FrameSize, - MachineBasicBlock &MBB, - MachineBasicBlock::iterator I) const { - DebugLoc DL; - MachineFunction &MF = *MBB.getParent(); - MachineFrameInfo &MFI = MF.getFrameInfo(); - const BitVector Reserved = RI.getReservedRegs(MF); - bool SaveS2 = Reserved[Mips::S2]; - MachineInstrBuilder MIB; - unsigned Opc = ((FrameSize <= 128) && !SaveS2)? Mips::Save16:Mips::SaveX16; - MIB = BuildMI(MBB, I, DL, get(Opc)); - const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); - addSaveRestoreRegs(MIB, CSI); - if (SaveS2) - MIB.addReg(Mips::S2); - if (isUInt<11>(FrameSize)) - MIB.addImm(FrameSize); - else { - int Base = 2040; // should create template function like isUInt that - // returns largest possible n bit unsigned integer - int64_t Remainder = FrameSize - Base; - MIB.addImm(Base); - if (isInt<16>(-Remainder)) - BuildAddiuSpImm(MBB, I, -Remainder); - else - adjustStackPtrBig(SP, -Remainder, MBB, I, Mips::V0, Mips::V1); - } -} - -// Adjust SP by FrameSize bytes. Restore RA, S0, S1 -void Mips16InstrInfo::restoreFrame(unsigned SP, int64_t FrameSize, - MachineBasicBlock &MBB, - MachineBasicBlock::iterator I) const { - DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc(); - MachineFunction *MF = MBB.getParent(); - MachineFrameInfo &MFI = MF->getFrameInfo(); - const BitVector Reserved = RI.getReservedRegs(*MF); - bool SaveS2 = Reserved[Mips::S2]; - MachineInstrBuilder MIB; - unsigned Opc = ((FrameSize <= 128) && !SaveS2)? - Mips::Restore16:Mips::RestoreX16; - - if (!isUInt<11>(FrameSize)) { - unsigned Base = 2040; - int64_t Remainder = FrameSize - Base; - FrameSize = Base; // should create template function like isUInt that - // returns largest possible n bit unsigned integer - - if (isInt<16>(Remainder)) - BuildAddiuSpImm(MBB, I, Remainder); - else - adjustStackPtrBig(SP, Remainder, MBB, I, Mips::A0, Mips::A1); - } - MIB = BuildMI(MBB, I, DL, get(Opc)); - const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); - addSaveRestoreRegs(MIB, CSI, RegState::Define); - if (SaveS2) - MIB.addReg(Mips::S2, RegState::Define); - MIB.addImm(FrameSize); -} - -// Adjust SP by Amount bytes where bytes can be up to 32bit number. -// This can only be called at times that we know that there is at least one free -// register. -// This is clearly safe at prologue and epilogue. -void Mips16InstrInfo::adjustStackPtrBig(unsigned SP, int64_t Amount, - MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, - unsigned Reg1, unsigned Reg2) const { - DebugLoc DL; - // - // li reg1, constant - // move reg2, sp - // add reg1, reg1, reg2 - // move sp, reg1 - // - // - MachineInstrBuilder MIB1 = BuildMI(MBB, I, DL, get(Mips::LwConstant32), Reg1); - MIB1.addImm(Amount).addImm(-1); - MachineInstrBuilder MIB2 = BuildMI(MBB, I, DL, get(Mips::MoveR3216), Reg2); - MIB2.addReg(Mips::SP, RegState::Kill); - MachineInstrBuilder MIB3 = BuildMI(MBB, I, DL, get(Mips::AdduRxRyRz16), Reg1); - MIB3.addReg(Reg1); - MIB3.addReg(Reg2, RegState::Kill); - MachineInstrBuilder MIB4 = BuildMI(MBB, I, DL, get(Mips::Move32R16), - Mips::SP); - MIB4.addReg(Reg1, RegState::Kill); -} - -void Mips16InstrInfo::adjustStackPtrBigUnrestricted( - unsigned SP, int64_t Amount, MachineBasicBlock &MBB, - MachineBasicBlock::iterator I) const { - llvm_unreachable("adjust stack pointer amount exceeded"); -} - -/// Adjust SP by Amount bytes. -void Mips16InstrInfo::adjustStackPtr(unsigned SP, int64_t Amount, - MachineBasicBlock &MBB, - MachineBasicBlock::iterator I) const { - if (Amount == 0) - return; - - if (isInt<16>(Amount)) // need to change to addiu sp, ....and isInt<16> - BuildAddiuSpImm(MBB, I, Amount); - else - adjustStackPtrBigUnrestricted(SP, Amount, MBB, I); -} - -/// This function generates the sequence of instructions needed to get the -/// result of adding register REG and immediate IMM. -unsigned Mips16InstrInfo::loadImmediate(unsigned FrameReg, int64_t Imm, - MachineBasicBlock &MBB, - MachineBasicBlock::iterator II, - const DebugLoc &DL, - unsigned &NewImm) const { - // - // given original instruction is: - // Instr rx, T[offset] where offset is too big. - // - // lo = offset & 0xFFFF - // hi = ((offset >> 16) + (lo >> 15)) & 0xFFFF; - // - // let T = temporary register - // li T, hi - // shl T, 16 - // add T, Rx, T - // - RegScavenger rs; - int32_t lo = Imm & 0xFFFF; - NewImm = lo; - int Reg =0; - int SpReg = 0; - - rs.enterBasicBlock(MBB); - rs.forward(II); - // - // We need to know which registers can be used, in the case where there - // are not enough free registers. We exclude all registers that - // are used in the instruction that we are helping. - // // Consider all allocatable registers in the register class initially - BitVector Candidates = - RI.getAllocatableSet - (*II->getParent()->getParent(), &Mips::CPU16RegsRegClass); - // Exclude all the registers being used by the instruction. - for (unsigned i = 0, e = II->getNumOperands(); i != e; ++i) { - MachineOperand &MO = II->getOperand(i); - if (MO.isReg() && MO.getReg() != 0 && !MO.isDef() && - !TargetRegisterInfo::isVirtualRegister(MO.getReg())) - Candidates.reset(MO.getReg()); - } - - // If the same register was used and defined in an instruction, then - // it will not be in the list of candidates. - // - // we need to analyze the instruction that we are helping. - // we need to know if it defines register x but register x is not - // present as an operand of the instruction. this tells - // whether the register is live before the instruction. if it's not - // then we don't need to save it in case there are no free registers. - int DefReg = 0; - for (unsigned i = 0, e = II->getNumOperands(); i != e; ++i) { - MachineOperand &MO = II->getOperand(i); - if (MO.isReg() && MO.isDef()) { - DefReg = MO.getReg(); - break; - } - } - - BitVector Available = rs.getRegsAvailable(&Mips::CPU16RegsRegClass); - Available &= Candidates; - // - // we use T0 for the first register, if we need to save something away. - // we use T1 for the second register, if we need to save something away. - // - unsigned FirstRegSaved =0, SecondRegSaved=0; - unsigned FirstRegSavedTo = 0, SecondRegSavedTo = 0; - - Reg = Available.find_first(); - - if (Reg == -1) { - Reg = Candidates.find_first(); - Candidates.reset(Reg); - if (DefReg != Reg) { - FirstRegSaved = Reg; - FirstRegSavedTo = Mips::T0; - copyPhysReg(MBB, II, DL, FirstRegSavedTo, FirstRegSaved, true); - } - } - else - Available.reset(Reg); - BuildMI(MBB, II, DL, get(Mips::LwConstant32), Reg).addImm(Imm).addImm(-1); - NewImm = 0; - if (FrameReg == Mips::SP) { - SpReg = Available.find_first(); - if (SpReg == -1) { - SpReg = Candidates.find_first(); - // Candidates.reset(SpReg); // not really needed - if (DefReg!= SpReg) { - SecondRegSaved = SpReg; - SecondRegSavedTo = Mips::T1; - } - if (SecondRegSaved) - copyPhysReg(MBB, II, DL, SecondRegSavedTo, SecondRegSaved, true); - } - else - Available.reset(SpReg); - copyPhysReg(MBB, II, DL, SpReg, Mips::SP, false); - BuildMI(MBB, II, DL, get(Mips:: AdduRxRyRz16), Reg).addReg(SpReg, RegState::Kill) - .addReg(Reg); - } - else - BuildMI(MBB, II, DL, get(Mips:: AdduRxRyRz16), Reg).addReg(FrameReg) - .addReg(Reg, RegState::Kill); - if (FirstRegSaved || SecondRegSaved) { - II = std::next(II); - if (FirstRegSaved) - copyPhysReg(MBB, II, DL, FirstRegSaved, FirstRegSavedTo, true); - if (SecondRegSaved) - copyPhysReg(MBB, II, DL, SecondRegSaved, SecondRegSavedTo, true); - } - return Reg; -} - -unsigned Mips16InstrInfo::getAnalyzableBrOpc(unsigned Opc) const { - return (Opc == Mips::BeqzRxImmX16 || Opc == Mips::BimmX16 || - Opc == Mips::Bimm16 || - Opc == Mips::Bteqz16 || Opc == Mips::Btnez16 || - Opc == Mips::BeqzRxImm16 || Opc == Mips::BnezRxImm16 || - Opc == Mips::BnezRxImmX16 || Opc == Mips::BteqzX16 || - Opc == Mips::BteqzT8CmpX16 || Opc == Mips::BteqzT8CmpiX16 || - Opc == Mips::BteqzT8SltX16 || Opc == Mips::BteqzT8SltuX16 || - Opc == Mips::BteqzT8SltiX16 || Opc == Mips::BteqzT8SltiuX16 || - Opc == Mips::BtnezX16 || Opc == Mips::BtnezT8CmpX16 || - Opc == Mips::BtnezT8CmpiX16 || Opc == Mips::BtnezT8SltX16 || - Opc == Mips::BtnezT8SltuX16 || Opc == Mips::BtnezT8SltiX16 || - Opc == Mips::BtnezT8SltiuX16 ) ? Opc : 0; -} - -void Mips16InstrInfo::ExpandRetRA16(MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, - unsigned Opc) const { - BuildMI(MBB, I, I->getDebugLoc(), get(Opc)); -} - -const MCInstrDesc &Mips16InstrInfo::AddiuSpImm(int64_t Imm) const { - if (validSpImm8(Imm)) - return get(Mips::AddiuSpImm16); - else - return get(Mips::AddiuSpImmX16); -} - -void Mips16InstrInfo::BuildAddiuSpImm - (MachineBasicBlock &MBB, MachineBasicBlock::iterator I, int64_t Imm) const { - DebugLoc DL; - BuildMI(MBB, I, DL, AddiuSpImm(Imm)).addImm(Imm); -} - -const MipsInstrInfo *llvm::createMips16InstrInfo(const MipsSubtarget &STI) { - return new Mips16InstrInfo(STI); -} - -bool Mips16InstrInfo::validImmediate(unsigned Opcode, unsigned Reg, - int64_t Amount) { - switch (Opcode) { - case Mips::LbRxRyOffMemX16: - case Mips::LbuRxRyOffMemX16: - case Mips::LhRxRyOffMemX16: - case Mips::LhuRxRyOffMemX16: - case Mips::SbRxRyOffMemX16: - case Mips::ShRxRyOffMemX16: - case Mips::LwRxRyOffMemX16: - case Mips::SwRxRyOffMemX16: - case Mips::SwRxSpImmX16: - case Mips::LwRxSpImmX16: - return isInt<16>(Amount); - case Mips::AddiuRxRyOffMemX16: - if ((Reg == Mips::PC) || (Reg == Mips::SP)) - return isInt<16>(Amount); - return isInt<15>(Amount); - } - llvm_unreachable("unexpected Opcode in validImmediate"); -} diff --git a/contrib/llvm/lib/Target/Mips/Mips16InstrInfo.h b/contrib/llvm/lib/Target/Mips/Mips16InstrInfo.h deleted file mode 100644 index dadcaa3055b3..000000000000 --- a/contrib/llvm/lib/Target/Mips/Mips16InstrInfo.h +++ /dev/null @@ -1,131 +0,0 @@ -//===- Mips16InstrInfo.h - Mips16 Instruction Information -------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains the Mips16 implementation of the TargetInstrInfo class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_MIPS_MIPS16INSTRINFO_H -#define LLVM_LIB_TARGET_MIPS_MIPS16INSTRINFO_H - -#include "Mips16RegisterInfo.h" -#include "MipsInstrInfo.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/Support/MathExtras.h" -#include <cstdint> - -namespace llvm { - -class MCInstrDesc; -class MipsSubtarget; - -class Mips16InstrInfo : public MipsInstrInfo { - const Mips16RegisterInfo RI; - -public: - explicit Mips16InstrInfo(const MipsSubtarget &STI); - - const MipsRegisterInfo &getRegisterInfo() const override; - - /// isLoadFromStackSlot - If the specified machine instruction is a direct - /// load from a stack slot, return the virtual or physical register number of - /// the destination along with the FrameIndex of the loaded stack slot. If - /// not, return 0. This predicate must return 0 if the instruction has - /// any side effects other than loading from the stack slot. - unsigned isLoadFromStackSlot(const MachineInstr &MI, - int &FrameIndex) const override; - - /// isStoreToStackSlot - If the specified machine instruction is a direct - /// store to a stack slot, return the virtual or physical register number of - /// the source reg along with the FrameIndex of the loaded stack slot. If - /// not, return 0. This predicate must return 0 if the instruction has - /// any side effects other than storing to the stack slot. - unsigned isStoreToStackSlot(const MachineInstr &MI, - int &FrameIndex) const override; - - void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, - const DebugLoc &DL, unsigned DestReg, unsigned SrcReg, - bool KillSrc) const override; - - void storeRegToStack(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI, - unsigned SrcReg, bool isKill, int FrameIndex, - const TargetRegisterClass *RC, - const TargetRegisterInfo *TRI, - int64_t Offset) const override; - - void loadRegFromStack(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI, - unsigned DestReg, int FrameIndex, - const TargetRegisterClass *RC, - const TargetRegisterInfo *TRI, - int64_t Offset) const override; - - bool expandPostRAPseudo(MachineInstr &MI) const override; - - unsigned getOppositeBranchOpc(unsigned Opc) const override; - - // Adjust SP by FrameSize bytes. Save RA, S0, S1 - void makeFrame(unsigned SP, int64_t FrameSize, MachineBasicBlock &MBB, - MachineBasicBlock::iterator I) const; - - // Adjust SP by FrameSize bytes. Restore RA, S0, S1 - void restoreFrame(unsigned SP, int64_t FrameSize, MachineBasicBlock &MBB, - MachineBasicBlock::iterator I) const; - - /// Adjust SP by Amount bytes. - void adjustStackPtr(unsigned SP, int64_t Amount, MachineBasicBlock &MBB, - MachineBasicBlock::iterator I) const override; - - /// Emit a series of instructions to load an immediate. - // This is to adjust some FrameReg. We return the new register to be used - // in place of FrameReg and the adjusted immediate field (&NewImm) - unsigned loadImmediate(unsigned FrameReg, int64_t Imm, MachineBasicBlock &MBB, - MachineBasicBlock::iterator II, const DebugLoc &DL, - unsigned &NewImm) const; - - static bool validImmediate(unsigned Opcode, unsigned Reg, int64_t Amount); - - static bool validSpImm8(int offset) { - return ((offset & 7) == 0) && isInt<11>(offset); - } - - // build the proper one based on the Imm field - - const MCInstrDesc& AddiuSpImm(int64_t Imm) const; - - void BuildAddiuSpImm - (MachineBasicBlock &MBB, MachineBasicBlock::iterator I, int64_t Imm) const; - -protected: - /// If the specific machine instruction is a instruction that moves/copies - /// value from one register to another register return true along with - /// @Source machine operand and @Destination machine operand. - bool isCopyInstrImpl(const MachineInstr &MI, const MachineOperand *&Source, - const MachineOperand *&Destination) const override; - -private: - unsigned getAnalyzableBrOpc(unsigned Opc) const override; - - void ExpandRetRA16(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, - unsigned Opc) const; - - // Adjust SP by Amount bytes where bytes can be up to 32bit number. - void adjustStackPtrBig(unsigned SP, int64_t Amount, MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, - unsigned Reg1, unsigned Reg2) const; - - // Adjust SP by Amount bytes where bytes can be up to 32bit number. - void adjustStackPtrBigUnrestricted(unsigned SP, int64_t Amount, - MachineBasicBlock &MBB, - MachineBasicBlock::iterator I) const; -}; - -} // end namespace llvm - -#endif // LLVM_LIB_TARGET_MIPS_MIPS16INSTRINFO_H diff --git a/contrib/llvm/lib/Target/Mips/Mips16InstrInfo.td b/contrib/llvm/lib/Target/Mips/Mips16InstrInfo.td deleted file mode 100644 index 36b6c73d1008..000000000000 --- a/contrib/llvm/lib/Target/Mips/Mips16InstrInfo.td +++ /dev/null @@ -1,1910 +0,0 @@ -//===- Mips16InstrInfo.td - Target Description for Mips16 -*- tablegen -*-=// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file describes Mips16 instructions. -// -//===----------------------------------------------------------------------===// -// -// -// Mips Address -// -def addr16 : ComplexPattern<iPTR, 2, "selectAddr16", [frameindex]>; -def addr16sp : ComplexPattern<iPTR, 2, "selectAddr16SP", [frameindex]>; - -// -// Address operand -def mem16 : Operand<i32> { - let PrintMethod = "printMemOperand"; - let MIOperandInfo = (ops CPU16Regs, simm16); - let EncoderMethod = "getMemEncoding"; -} - -def mem16sp : Operand<i32> { - let PrintMethod = "printMemOperand"; - // This should be CPUSPReg but the MIPS16 subtarget isn't good enough at - // keeping the sp-relative load and the other varieties separate at the - // moment. This lie fixes the problem sufficiently well to fix the errors - // emitted by -verify-machineinstrs and the output ends up correct as long - // as we use an external assembler (which is already a requirement for MIPS16 - // for several other reasons). - let MIOperandInfo = (ops CPU16RegsPlusSP, simm16); - let EncoderMethod = "getMemEncoding"; -} - -def mem16_ea : Operand<i32> { - let PrintMethod = "printMemOperandEA"; - let MIOperandInfo = (ops CPU16RegsPlusSP, simm16); - let EncoderMethod = "getMemEncoding"; -} - -def pcrel16 : Operand<i32>; - -// -// I-type instruction format -// -// this is only used by bimm. the actual assembly value is a 12 bit signed -// number -// -class FI16_ins<bits<5> op, string asmstr, InstrItinClass itin>: - FI16<op, (outs), (ins brtarget:$imm16), - !strconcat(asmstr, "\t$imm16 # 16 bit inst"), [], itin>; - -// -// -// I8 instruction format -// - -class FI816_ins_base<bits<3> _func, string asmstr, - string asmstr2, InstrItinClass itin>: - FI816<_func, (outs), (ins simm16:$imm), !strconcat(asmstr, asmstr2), - [], itin>; - -class FI816_ins<bits<3> _func, string asmstr, - InstrItinClass itin>: - FI816_ins_base<_func, asmstr, "\t$imm # 16 bit inst", itin>; - -class FI816_SP_ins<bits<3> _func, string asmstr, - InstrItinClass itin>: - FI816_ins_base<_func, asmstr, "\t$$sp, $imm # 16 bit inst", itin>; - -// -// RI instruction format -// - - -class FRI16_ins_base<bits<5> op, string asmstr, string asmstr2, - InstrItinClass itin>: - FRI16<op, (outs CPU16Regs:$rx), (ins simm16:$imm), - !strconcat(asmstr, asmstr2), [], itin>; - -class FRI16_ins<bits<5> op, string asmstr, - InstrItinClass itin>: - FRI16_ins_base<op, asmstr, "\t$rx, $imm \t# 16 bit inst", itin>; - -class FRI16_TCP_ins<bits<5> _op, string asmstr, - InstrItinClass itin>: - FRI16<_op, (outs CPU16Regs:$rx), (ins pcrel16:$imm, i32imm:$size), - !strconcat(asmstr, "\t$rx, $imm\t# 16 bit inst"), [], itin>; - -class FRI16R_ins_base<bits<5> op, string asmstr, string asmstr2, - InstrItinClass itin>: - FRI16<op, (outs), (ins CPU16Regs:$rx, simm16:$imm), - !strconcat(asmstr, asmstr2), [], itin>; - -class FRI16R_ins<bits<5> op, string asmstr, - InstrItinClass itin>: - FRI16R_ins_base<op, asmstr, "\t$rx, $imm \t# 16 bit inst", itin>; - -class F2RI16_ins<bits<5> _op, string asmstr, - InstrItinClass itin>: - FRI16<_op, (outs CPU16Regs:$rx), (ins CPU16Regs:$rx_, simm16:$imm), - !strconcat(asmstr, "\t$rx, $imm\t# 16 bit inst"), [], itin> { - let Constraints = "$rx_ = $rx"; -} - -class FRI16_B_ins<bits<5> _op, string asmstr, - InstrItinClass itin>: - FRI16<_op, (outs), (ins CPU16Regs:$rx, brtarget:$imm), - !strconcat(asmstr, "\t$rx, $imm # 16 bit inst"), [], itin>; -// -// Compare a register and immediate and place result in CC -// Implicit use of T8 -// -// EXT-CCRR Instruction format -// -class FEXT_CCRXI16_ins<string asmstr>: - MipsPseudo16<(outs CPU16Regs:$cc), (ins CPU16Regs:$rx, simm16:$imm), - !strconcat(asmstr, "\t$rx, $imm\n\tmove\t$cc, $$t8"), []> { - let isCodeGenOnly=1; - let usesCustomInserter = 1; -} - -// JAL and JALX instruction format -// -class FJAL16_ins<bits<1> _X, string asmstr, - InstrItinClass itin>: - FJAL16<_X, (outs), (ins uimm26:$imm), - !strconcat(asmstr, "\t$imm\n\tnop"),[], - itin> { - let isCodeGenOnly=1; - let Size=6; -} - -class FJALB16_ins<bits<1> _X, string asmstr, - InstrItinClass itin>: - FJAL16<_X, (outs), (ins uimm26:$imm), - !strconcat(asmstr, "\t$imm\t# branch\n\tnop"),[], - itin> { - let isCodeGenOnly=1; - let Size=6; -} - -// -// EXT-I instruction format -// -class FEXT_I16_ins<bits<5> eop, string asmstr, InstrItinClass itin> : - FEXT_I16<eop, (outs), (ins brtarget:$imm16), - !strconcat(asmstr, "\t$imm16"),[], itin>; - -// -// EXT-I8 instruction format -// - -class FEXT_I816_ins_base<bits<3> _func, string asmstr, - string asmstr2, InstrItinClass itin>: - FEXT_I816<_func, (outs), (ins simm16:$imm), !strconcat(asmstr, asmstr2), - [], itin>; - -class FEXT_I816_ins<bits<3> _func, string asmstr, - InstrItinClass itin>: - FEXT_I816_ins_base<_func, asmstr, "\t$imm", itin>; - -class FEXT_I816_SP_ins<bits<3> _func, string asmstr, - InstrItinClass itin>: - FEXT_I816_ins_base<_func, asmstr, "\t$$sp, $imm", itin>; - -// -// Assembler formats in alphabetical order. -// Natural and pseudos are mixed together. -// -// Compare two registers and place result in CC -// Implicit use of T8 -// -// CC-RR Instruction format -// -class FCCRR16_ins<string asmstr> : - MipsPseudo16<(outs CPU16Regs:$cc), (ins CPU16Regs:$rx, CPU16Regs:$ry), - !strconcat(asmstr, "\t$rx, $ry\n\tmove\t$cc, $$t8"), []> { - let isCodeGenOnly=1; - let usesCustomInserter = 1; -} - -// -// EXT-RI instruction format -// - -class FEXT_RI16_ins_base<bits<5> _op, string asmstr, string asmstr2, - InstrItinClass itin>: - FEXT_RI16<_op, (outs CPU16Regs:$rx), (ins simm16:$imm), - !strconcat(asmstr, asmstr2), [], itin>; - -class FEXT_RI16_ins<bits<5> _op, string asmstr, - InstrItinClass itin>: - FEXT_RI16_ins_base<_op, asmstr, "\t$rx, $imm", itin>; - -class FEXT_RI16R_ins_base<bits<5> _op, string asmstr, string asmstr2, - InstrItinClass itin>: - FEXT_RI16<_op, (outs ), (ins CPU16Regs:$rx, simm16:$imm), - !strconcat(asmstr, asmstr2), [], itin>; - -class FEXT_RI16R_ins<bits<5> _op, string asmstr, - InstrItinClass itin>: - FEXT_RI16R_ins_base<_op, asmstr, "\t$rx, $imm", itin>; - -class FEXT_RI16_PC_ins<bits<5> _op, string asmstr, InstrItinClass itin>: - FEXT_RI16_ins_base<_op, asmstr, "\t$rx, $$pc, $imm", itin>; - -class FEXT_RI16_B_ins<bits<5> _op, string asmstr, - InstrItinClass itin>: - FEXT_RI16<_op, (outs), (ins CPU16Regs:$rx, brtarget:$imm), - !strconcat(asmstr, "\t$rx, $imm"), [], itin>; - -class FEXT_RI16_TCP_ins<bits<5> _op, string asmstr, - InstrItinClass itin>: - FEXT_RI16<_op, (outs CPU16Regs:$rx), (ins pcrel16:$imm, i32imm:$size), - !strconcat(asmstr, "\t$rx, $imm"), [], itin>; - -class FEXT_2RI16_ins<bits<5> _op, string asmstr, - InstrItinClass itin>: - FEXT_RI16<_op, (outs CPU16Regs:$rx), (ins CPU16Regs:$rx_, simm16:$imm), - !strconcat(asmstr, "\t$rx, $imm"), [], itin> { - let Constraints = "$rx_ = $rx"; -} - -// -// EXT-RRI instruction format -// - -class FEXT_RRI16_mem_ins<bits<5> op, string asmstr, Operand MemOpnd, - InstrItinClass itin>: - FEXT_RRI16<op, (outs CPU16Regs:$ry), (ins MemOpnd:$addr), - !strconcat(asmstr, "\t$ry, $addr"), [], itin>; - -class FEXT_RRI16_mem2_ins<bits<5> op, string asmstr, Operand MemOpnd, - InstrItinClass itin>: - FEXT_RRI16<op, (outs ), (ins CPU16Regs:$ry, MemOpnd:$addr), - !strconcat(asmstr, "\t$ry, $addr"), [], itin>; - -// -// -// EXT-RRI-A instruction format -// - -class FEXT_RRI_A16_mem_ins<bits<1> op, string asmstr, Operand MemOpnd, - InstrItinClass itin>: - FEXT_RRI_A16<op, (outs CPU16Regs:$ry), (ins MemOpnd:$addr), - !strconcat(asmstr, "\t$ry, $addr"), [], itin>; - -// -// EXT-SHIFT instruction format -// -class FEXT_SHIFT16_ins<bits<2> _f, string asmstr, InstrItinClass itin>: - FEXT_SHIFT16<_f, (outs CPU16Regs:$rx), (ins CPU16Regs:$ry, uimm5:$sa), - !strconcat(asmstr, "\t$rx, $ry, $sa"), [], itin>; - -// -// EXT-T8I8 -// -class FEXT_T8I816_ins<string asmstr, string asmstr2>: - MipsPseudo16<(outs), - (ins CPU16Regs:$rx, CPU16Regs:$ry, brtarget:$imm), - !strconcat(asmstr2, !strconcat("\t$rx, $ry\n\t", - !strconcat(asmstr, "\t$imm"))),[]> { - let isCodeGenOnly=1; - let usesCustomInserter = 1; -} - -// -// EXT-T8I8I -// -class FEXT_T8I8I16_ins<string asmstr, string asmstr2>: - MipsPseudo16<(outs), - (ins CPU16Regs:$rx, simm16:$imm, brtarget:$targ), - !strconcat(asmstr2, !strconcat("\t$rx, $imm\n\t", - !strconcat(asmstr, "\t$targ"))), []> { - let isCodeGenOnly=1; - let usesCustomInserter = 1; -} -// - - -// -// I8_MOVR32 instruction format (used only by the MOVR32 instructio -// -class FI8_MOVR3216_ins<string asmstr, InstrItinClass itin>: - FI8_MOVR3216<(outs CPU16Regs:$rz), (ins GPR32:$r32), - !strconcat(asmstr, "\t$rz, $r32"), [], itin>; - -// -// I8_MOV32R instruction format (used only by MOV32R instruction) -// - -class FI8_MOV32R16_ins<string asmstr, InstrItinClass itin>: - FI8_MOV32R16<(outs GPR32:$r32), (ins CPU16Regs:$rz), - !strconcat(asmstr, "\t$r32, $rz"), [], itin>; - -// -// This are pseudo formats for multiply -// This first one can be changed to non-pseudo now. -// -// MULT -// -class FMULT16_ins<string asmstr, InstrItinClass itin> : - MipsPseudo16<(outs), (ins CPU16Regs:$rx, CPU16Regs:$ry), - !strconcat(asmstr, "\t$rx, $ry"), []>; - -// -// MULT-LO -// -class FMULT16_LO_ins<string asmstr, InstrItinClass itin> : - MipsPseudo16<(outs CPU16Regs:$rz), (ins CPU16Regs:$rx, CPU16Regs:$ry), - !strconcat(asmstr, "\t$rx, $ry\n\tmflo\t$rz"), []> { - let isCodeGenOnly=1; -} - -// -// RR-type instruction format -// - -class FRR16_ins<bits<5> f, string asmstr, InstrItinClass itin> : - FRR16<f, (outs CPU16Regs:$rx), (ins CPU16Regs:$ry), - !strconcat(asmstr, "\t$rx, $ry"), [], itin> { -} - -class FRRBreakNull16_ins<string asmstr, InstrItinClass itin> : - FRRBreak16<(outs), (ins), asmstr, [], itin> { - let Code=0; -} - -class FRR16R_ins<bits<5> f, string asmstr, InstrItinClass itin> : - FRR16<f, (outs), (ins CPU16Regs:$rx, CPU16Regs:$ry), - !strconcat(asmstr, "\t$rx, $ry"), [], itin> { -} - -class FRRTR16_ins<string asmstr> : - MipsPseudo16<(outs CPU16Regs:$rz), (ins CPU16Regs:$rx, CPU16Regs:$ry), - !strconcat(asmstr, "\t$rx, $ry\n\tmove\t$rz, $$t8"), []> ; - -// -// maybe refactor but need a $zero as a dummy first parameter -// -class FRR16_div_ins<bits<5> f, string asmstr, InstrItinClass itin> : - FRR16<f, (outs ), (ins CPU16Regs:$rx, CPU16Regs:$ry), - !strconcat(asmstr, "\t$$zero, $rx, $ry"), [], itin> ; - -class FUnaryRR16_ins<bits<5> f, string asmstr, InstrItinClass itin> : - FRR16<f, (outs CPU16Regs:$rx), (ins CPU16Regs:$ry), - !strconcat(asmstr, "\t$rx, $ry"), [], itin> ; - - -class FRR16_M_ins<bits<5> f, string asmstr, - InstrItinClass itin> : - FRR16<f, (outs CPU16Regs:$rx), (ins), - !strconcat(asmstr, "\t$rx"), [], itin>; - -class FRxRxRy16_ins<bits<5> f, string asmstr, - InstrItinClass itin> : - FRR16<f, (outs CPU16Regs:$rz), (ins CPU16Regs:$rx, CPU16Regs:$ry), - !strconcat(asmstr, "\t$rz, $ry"), - [], itin> { - let Constraints = "$rx = $rz"; -} - -let rx=0 in -class FRR16_JALRC_RA_only_ins<bits<1> nd_, bits<1> l_, - string asmstr, InstrItinClass itin>: - FRR16_JALRC<nd_, l_, 1, (outs), (ins), !strconcat(asmstr, "\t$$ra"), - [], itin> ; - - -class FRR16_JALRC_ins<bits<1> nd, bits<1> l, bits<1> ra, - string asmstr, InstrItinClass itin>: - FRR16_JALRC<nd, l, ra, (outs), (ins CPU16Regs:$rx), - !strconcat(asmstr, "\t$rx"), [], itin> ; - -class FRR_SF16_ins - <bits<5> _funct, bits<3> _subfunc, - string asmstr, InstrItinClass itin>: - FRR_SF16<_funct, _subfunc, (outs CPU16Regs:$rx), (ins CPU16Regs:$rx_), - !strconcat(asmstr, "\t $rx"), - [], itin> { - let Constraints = "$rx_ = $rx"; - } -// -// RRR-type instruction format -// - -class FRRR16_ins<bits<2> _f, string asmstr, InstrItinClass itin> : - FRRR16<_f, (outs CPU16Regs:$rz), (ins CPU16Regs:$rx, CPU16Regs:$ry), - !strconcat(asmstr, "\t$rz, $rx, $ry"), [], itin>; - -// -// These Sel patterns support the generation of conditional move -// pseudo instructions. -// -// The nomenclature uses the components making up the pseudo and may -// be a bit counter intuitive when compared with the end result we seek. -// For example using a bqez in the example directly below results in the -// conditional move being done if the tested register is not zero. -// I considered in easier to check by keeping the pseudo consistent with -// it's components but it could have been done differently. -// -// The simplest case is when can test and operand directly and do the -// conditional move based on a simple mips16 conditional -// branch instruction. -// for example: -// if $op == beqz or bnez: -// -// $op1 $rt, .+4 -// move $rd, $rs -// -// if $op == beqz, then if $rt != 0, then the conditional assignment -// $rd = $rs is done. - -// if $op == bnez, then if $rt == 0, then the conditional assignment -// $rd = $rs is done. -// -// So this pseudo class only has one operand, i.e. op -// -class Sel<string op>: - MipsPseudo16<(outs CPU16Regs:$rd_), (ins CPU16Regs:$rd, CPU16Regs:$rs, - CPU16Regs:$rt), - !strconcat(op, "\t$rt, .+4\n\t\n\tmove $rd, $rs"), []> { - //let isCodeGenOnly=1; - let Constraints = "$rd = $rd_"; - let usesCustomInserter = 1; -} - -// -// The next two instruction classes allow for an operand which tests -// two operands and returns a value in register T8 and -//then does a conditional branch based on the value of T8 -// - -// op2 can be cmpi or slti/sltiu -// op1 can bteqz or btnez -// the operands for op2 are a register and a signed constant -// -// $op2 $t, $imm ;test register t and branch conditionally -// $op1 .+4 ;op1 is a conditional branch -// move $rd, $rs -// -// -class SeliT<string op1, string op2>: - MipsPseudo16<(outs CPU16Regs:$rd_), (ins CPU16Regs:$rd, CPU16Regs:$rs, - CPU16Regs:$rl, simm16:$imm), - !strconcat(op2, - !strconcat("\t$rl, $imm\n\t", - !strconcat(op1, "\t.+4\n\tmove $rd, $rs"))), []> { - let isCodeGenOnly=1; - let Constraints = "$rd = $rd_"; - let usesCustomInserter = 1; -} - -// -// op2 can be cmp or slt/sltu -// op1 can be bteqz or btnez -// the operands for op2 are two registers -// op1 is a conditional branch -// -// -// $op2 $rl, $rr ;test registers rl,rr -// $op1 .+4 ;op2 is a conditional branch -// move $rd, $rs -// -// -class SelT<string op1, string op2>: - MipsPseudo16<(outs CPU16Regs:$rd_), - (ins CPU16Regs:$rd, CPU16Regs:$rs, - CPU16Regs:$rl, CPU16Regs:$rr), - !strconcat(op2, - !strconcat("\t$rl, $rr\n\t", - !strconcat(op1, "\t.+4\n\tmove $rd, $rs"))), []> { - let isCodeGenOnly=1; - let Constraints = "$rd = $rd_"; - let usesCustomInserter = 1; -} - -// -// 32 bit constant -// -def Constant32 : MipsPseudo16<(outs), (ins simm32:$imm), "\t.word $imm", []>; - -def LwConstant32 : - MipsPseudo16<(outs CPU16Regs:$rx), (ins simm32:$imm, simm32:$constid), - "lw\t$rx, 1f\n\tb\t2f\n\t.align\t2\n1: \t.word\t$imm\n2:", []>; - -// -// Some general instruction class info -// -// - -class ArithLogic16Defs<bit isCom=0> { - bits<5> shamt = 0; - bit isCommutable = isCom; - bit isReMaterializable = 1; - bit hasSideEffects = 0; -} - -class branch16 { - bit isBranch = 1; - bit isTerminator = 1; - bit isBarrier = 1; -} - -class cbranch16 { - bit isBranch = 1; - bit isTerminator = 1; -} - -class MayLoad { - bit mayLoad = 1; -} - -class MayStore { - bit mayStore = 1; -} -// - - -// Format: ADDIU rx, immediate MIPS16e -// Purpose: Add Immediate Unsigned Word (2-Operand, Extended) -// To add a constant to a 32-bit integer. -// -def AddiuRxImmX16: FEXT_RI16_ins<0b01001, "addiu", IIM16Alu>; - -def AddiuRxRxImm16: F2RI16_ins<0b01001, "addiu", IIM16Alu>, - ArithLogic16Defs<0> { - let AddedComplexity = 5; -} -def AddiuRxRxImmX16: FEXT_2RI16_ins<0b01001, "addiu", IIM16Alu>, - ArithLogic16Defs<0> { - let isCodeGenOnly = 1; -} - -def AddiuRxRyOffMemX16: - FEXT_RRI_A16_mem_ins<0, "addiu", mem16_ea, IIM16Alu>; - -// - -// Format: ADDIU rx, pc, immediate MIPS16e -// Purpose: Add Immediate Unsigned Word (3-Operand, PC-Relative, Extended) -// To add a constant to the program counter. -// -def AddiuRxPcImmX16: FEXT_RI16_PC_ins<0b00001, "addiu", IIM16Alu>; - -// -// Format: ADDIU sp, immediate MIPS16e -// Purpose: Add Immediate Unsigned Word (2-Operand, SP-Relative, Extended) -// To add a constant to the stack pointer. -// -def AddiuSpImm16 - : FI816_SP_ins<0b011, "addiu", IIM16Alu> { - let Defs = [SP]; - let Uses = [SP]; - let AddedComplexity = 5; -} - -def AddiuSpImmX16 - : FEXT_I816_SP_ins<0b011, "addiu", IIM16Alu> { - let Defs = [SP]; - let Uses = [SP]; -} - -// -// Format: ADDU rz, rx, ry MIPS16e -// Purpose: Add Unsigned Word (3-Operand) -// To add 32-bit integers. -// - -def AdduRxRyRz16: FRRR16_ins<01, "addu", IIM16Alu>, ArithLogic16Defs<1>; - -// -// Format: AND rx, ry MIPS16e -// Purpose: AND -// To do a bitwise logical AND. - -def AndRxRxRy16: FRxRxRy16_ins<0b01100, "and", IIM16Alu>, ArithLogic16Defs<1>; - - -// -// Format: BEQZ rx, offset MIPS16e -// Purpose: Branch on Equal to Zero -// To test a GPR then do a PC-relative conditional branch. -// -def BeqzRxImm16: FRI16_B_ins<0b00100, "beqz", IIM16Alu>, cbranch16; - - -// -// Format: BEQZ rx, offset MIPS16e -// Purpose: Branch on Equal to Zero (Extended) -// To test a GPR then do a PC-relative conditional branch. -// -def BeqzRxImmX16: FEXT_RI16_B_ins<0b00100, "beqz", IIM16Alu>, cbranch16; - -// -// Format: B offset MIPS16e -// Purpose: Unconditional Branch (Extended) -// To do an unconditional PC-relative branch. -// - -def Bimm16: FI16_ins<0b00010, "b", IIM16Alu>, branch16; - -// Format: B offset MIPS16e -// Purpose: Unconditional Branch -// To do an unconditional PC-relative branch. -// -def BimmX16: FEXT_I16_ins<0b00010, "b", IIM16Alu>, branch16; - -// -// Format: BNEZ rx, offset MIPS16e -// Purpose: Branch on Not Equal to Zero -// To test a GPR then do a PC-relative conditional branch. -// -def BnezRxImm16: FRI16_B_ins<0b00101, "bnez", IIM16Alu>, cbranch16; - -// -// Format: BNEZ rx, offset MIPS16e -// Purpose: Branch on Not Equal to Zero (Extended) -// To test a GPR then do a PC-relative conditional branch. -// -def BnezRxImmX16: FEXT_RI16_B_ins<0b00101, "bnez", IIM16Alu>, cbranch16; - - -// -//Format: BREAK immediate -// Purpose: Breakpoint -// To cause a Breakpoint exception. - -def Break16: FRRBreakNull16_ins<"break 0", IIM16Alu>; -// -// Format: BTEQZ offset MIPS16e -// Purpose: Branch on T Equal to Zero (Extended) -// To test special register T then do a PC-relative conditional branch. -// -def Bteqz16: FI816_ins<0b000, "bteqz", IIM16Alu>, cbranch16 { - let Uses = [T8]; -} - -def BteqzX16: FEXT_I816_ins<0b000, "bteqz", IIM16Alu>, cbranch16 { - let Uses = [T8]; -} - -def BteqzT8CmpX16: FEXT_T8I816_ins<"bteqz", "cmp">, cbranch16; - -def BteqzT8CmpiX16: FEXT_T8I8I16_ins<"bteqz", "cmpi">, - cbranch16; - -def BteqzT8SltX16: FEXT_T8I816_ins<"bteqz", "slt">, cbranch16; - -def BteqzT8SltuX16: FEXT_T8I816_ins<"bteqz", "sltu">, cbranch16; - -def BteqzT8SltiX16: FEXT_T8I8I16_ins<"bteqz", "slti">, cbranch16; - -def BteqzT8SltiuX16: FEXT_T8I8I16_ins<"bteqz", "sltiu">, - cbranch16; - -// -// Format: BTNEZ offset MIPS16e -// Purpose: Branch on T Not Equal to Zero (Extended) -// To test special register T then do a PC-relative conditional branch. -// - -def Btnez16: FI816_ins<0b001, "btnez", IIM16Alu>, cbranch16 { - let Uses = [T8]; -} - -def BtnezX16: FEXT_I816_ins<0b001, "btnez", IIM16Alu> ,cbranch16 { - let Uses = [T8]; -} - -def BtnezT8CmpX16: FEXT_T8I816_ins<"btnez", "cmp">, cbranch16; - -def BtnezT8CmpiX16: FEXT_T8I8I16_ins<"btnez", "cmpi">, cbranch16; - -def BtnezT8SltX16: FEXT_T8I816_ins<"btnez", "slt">, cbranch16; - -def BtnezT8SltuX16: FEXT_T8I816_ins<"btnez", "sltu">, cbranch16; - -def BtnezT8SltiX16: FEXT_T8I8I16_ins<"btnez", "slti">, cbranch16; - -def BtnezT8SltiuX16: FEXT_T8I8I16_ins<"btnez", "sltiu">, - cbranch16; - -// -// Format: CMP rx, ry MIPS16e -// Purpose: Compare -// To compare the contents of two GPRs. -// -def CmpRxRy16: FRR16R_ins<0b01010, "cmp", IIM16Alu> { - let Defs = [T8]; -} - -// -// Format: CMPI rx, immediate MIPS16e -// Purpose: Compare Immediate -// To compare a constant with the contents of a GPR. -// -def CmpiRxImm16: FRI16R_ins<0b01110, "cmpi", IIM16Alu> { - let Defs = [T8]; -} - -// -// Format: CMPI rx, immediate MIPS16e -// Purpose: Compare Immediate (Extended) -// To compare a constant with the contents of a GPR. -// -def CmpiRxImmX16: FEXT_RI16R_ins<0b01110, "cmpi", IIM16Alu> { - let Defs = [T8]; -} - - -// -// Format: DIV rx, ry MIPS16e -// Purpose: Divide Word -// To divide 32-bit signed integers. -// -def DivRxRy16: FRR16_div_ins<0b11010, "div", IIM16Alu> { - let Defs = [HI0, LO0]; -} - -// -// Format: DIVU rx, ry MIPS16e -// Purpose: Divide Unsigned Word -// To divide 32-bit unsigned integers. -// -def DivuRxRy16: FRR16_div_ins<0b11011, "divu", IIM16Alu> { - let Defs = [HI0, LO0]; -} -// -// Format: JAL target MIPS16e -// Purpose: Jump and Link -// To execute a procedure call within the current 256 MB-aligned -// region and preserve the current ISA. -// - -def Jal16 : FJAL16_ins<0b0, "jal", IIM16Alu> { - let hasDelaySlot = 0; // not true, but we add the nop for now - let isCall=1; - let Defs = [RA]; -} - -def JalB16 : FJALB16_ins<0b0, "jal", IIM16Alu>, branch16 { - let hasDelaySlot = 0; // not true, but we add the nop for now - let isBranch=1; - let Defs = [RA]; -} - -// -// Format: JR ra MIPS16e -// Purpose: Jump Register Through Register ra -// To execute a branch to the instruction address in the return -// address register. -// - -def JrRa16: FRR16_JALRC_RA_only_ins<0, 0, "jr", IIM16Alu> { - let isBranch = 1; - let isIndirectBranch = 1; - let hasDelaySlot = 1; - let isTerminator=1; - let isBarrier=1; - let isReturn=1; -} - -def JrcRa16: FRR16_JALRC_RA_only_ins<1, 1, "jrc", IIM16Alu> { - let isBranch = 1; - let isIndirectBranch = 1; - let isTerminator=1; - let isBarrier=1; - let isReturn=1; -} - -def JrcRx16: FRR16_JALRC_ins<1, 1, 0, "jrc", IIM16Alu> { - let isBranch = 1; - let isIndirectBranch = 1; - let isTerminator=1; - let isBarrier=1; -} -// -// Format: LB ry, offset(rx) MIPS16e -// Purpose: Load Byte (Extended) -// To load a byte from memory as a signed value. -// -def LbRxRyOffMemX16: FEXT_RRI16_mem_ins<0b10011, "lb", mem16, II_LB>, MayLoad{ - let isCodeGenOnly = 1; -} - -// -// Format: LBU ry, offset(rx) MIPS16e -// Purpose: Load Byte Unsigned (Extended) -// To load a byte from memory as a unsigned value. -// -def LbuRxRyOffMemX16: - FEXT_RRI16_mem_ins<0b10100, "lbu", mem16, II_LBU>, MayLoad { - let isCodeGenOnly = 1; -} - -// -// Format: LH ry, offset(rx) MIPS16e -// Purpose: Load Halfword signed (Extended) -// To load a halfword from memory as a signed value. -// -def LhRxRyOffMemX16: FEXT_RRI16_mem_ins<0b10100, "lh", mem16, II_LH>, MayLoad{ - let isCodeGenOnly = 1; -} - -// -// Format: LHU ry, offset(rx) MIPS16e -// Purpose: Load Halfword unsigned (Extended) -// To load a halfword from memory as an unsigned value. -// -def LhuRxRyOffMemX16: - FEXT_RRI16_mem_ins<0b10100, "lhu", mem16, II_LHU>, MayLoad { - let isCodeGenOnly = 1; -} - -// -// Format: LI rx, immediate MIPS16e -// Purpose: Load Immediate -// To load a constant into a GPR. -// -def LiRxImm16: FRI16_ins<0b01101, "li", IIM16Alu>; - -// -// Format: LI rx, immediate MIPS16e -// Purpose: Load Immediate (Extended) -// To load a constant into a GPR. -// -def LiRxImmX16: FEXT_RI16_ins<0b01101, "li", IIM16Alu>; - -def LiRxImmAlignX16: FEXT_RI16_ins<0b01101, ".align 2\n\tli", IIM16Alu> { - let isCodeGenOnly = 1; -} - -// -// Format: LW ry, offset(rx) MIPS16e -// Purpose: Load Word (Extended) -// To load a word from memory as a signed value. -// -def LwRxRyOffMemX16: FEXT_RRI16_mem_ins<0b10011, "lw", mem16, II_LW>, MayLoad{ - let isCodeGenOnly = 1; -} - -// Format: LW rx, offset(sp) MIPS16e -// Purpose: Load Word (SP-Relative, Extended) -// To load an SP-relative word from memory as a signed value. -// -def LwRxSpImmX16: FEXT_RRI16_mem_ins<0b10010, "lw", mem16sp, II_LW>, MayLoad; - -def LwRxPcTcp16: FRI16_TCP_ins<0b10110, "lw", II_LW>, MayLoad; - -def LwRxPcTcpX16: FEXT_RI16_TCP_ins<0b10110, "lw", II_LW>, MayLoad; -// -// Format: MOVE r32, rz MIPS16e -// Purpose: Move -// To move the contents of a GPR to a GPR. -// -def Move32R16: FI8_MOV32R16_ins<"move", IIM16Alu>; - -// -// Format: MOVE ry, r32 MIPS16e -//Purpose: Move -// To move the contents of a GPR to a GPR. -// -def MoveR3216: FI8_MOVR3216_ins<"move", IIM16Alu> { - let isMoveReg = 1; -} - -// -// Format: MFHI rx MIPS16e -// Purpose: Move From HI Register -// To copy the special purpose HI register to a GPR. -// -def Mfhi16: FRR16_M_ins<0b10000, "mfhi", IIM16Alu> { - let Uses = [HI0]; - let hasSideEffects = 0; - let isMoveReg = 1; -} - -// -// Format: MFLO rx MIPS16e -// Purpose: Move From LO Register -// To copy the special purpose LO register to a GPR. -// -def Mflo16: FRR16_M_ins<0b10010, "mflo", IIM16Alu> { - let Uses = [LO0]; - let hasSideEffects = 0; - let isMoveReg = 0; -} - -// -// Pseudo Instruction for mult -// -def MultRxRy16: FMULT16_ins<"mult", IIM16Alu> { - let isCommutable = 1; - let hasSideEffects = 0; - let Defs = [HI0, LO0]; -} - -def MultuRxRy16: FMULT16_ins<"multu", IIM16Alu> { - let isCommutable = 1; - let hasSideEffects = 0; - let Defs = [HI0, LO0]; -} - -// -// Format: MULT rx, ry MIPS16e -// Purpose: Multiply Word -// To multiply 32-bit signed integers. -// -def MultRxRyRz16: FMULT16_LO_ins<"mult", IIM16Alu> { - let isCommutable = 1; - let hasSideEffects = 0; - let Defs = [HI0, LO0]; -} - -// -// Format: MULTU rx, ry MIPS16e -// Purpose: Multiply Unsigned Word -// To multiply 32-bit unsigned integers. -// -def MultuRxRyRz16: FMULT16_LO_ins<"multu", IIM16Alu> { - let isCommutable = 1; - let hasSideEffects = 0; - let Defs = [HI0, LO0]; -} - -// -// Format: NEG rx, ry MIPS16e -// Purpose: Negate -// To negate an integer value. -// -def NegRxRy16: FUnaryRR16_ins<0b11101, "neg", IIM16Alu>; - -// -// Format: NOT rx, ry MIPS16e -// Purpose: Not -// To complement an integer value -// -def NotRxRy16: FUnaryRR16_ins<0b01111, "not", IIM16Alu>; - -// -// Format: OR rx, ry MIPS16e -// Purpose: Or -// To do a bitwise logical OR. -// -def OrRxRxRy16: FRxRxRy16_ins<0b01101, "or", IIM16Alu>, ArithLogic16Defs<1>; - -// -// Format: RESTORE {ra,}{s0/s1/s0-1,}{framesize} -// (All args are optional) MIPS16e -// Purpose: Restore Registers and Deallocate Stack Frame -// To deallocate a stack frame before exit from a subroutine, -// restoring return address and static registers, and adjusting -// stack -// - -def Restore16: - FI8_SVRS16<0b1, (outs), (ins variable_ops), - "", [], II_RESTORE >, MayLoad { - let isCodeGenOnly = 1; - let Defs = [SP]; - let Uses = [SP]; -} - - -def RestoreX16: - FI8_SVRS16<0b1, (outs), (ins variable_ops), - "", [], II_RESTORE >, MayLoad { - let isCodeGenOnly = 1; - let Defs = [SP]; - let Uses = [SP]; -} - -// -// Format: SAVE {ra,}{s0/s1/s0-1,}{framesize} (All arguments are optional) -// MIPS16e -// Purpose: Save Registers and Set Up Stack Frame -// To set up a stack frame on entry to a subroutine, -// saving return address and static registers, and adjusting stack -// -def Save16: - FI8_SVRS16<0b1, (outs), (ins variable_ops), - "", [], II_SAVE >, MayStore { - let isCodeGenOnly = 1; - let Uses = [SP]; - let Defs = [SP]; -} - -def SaveX16: - FI8_SVRS16<0b1, (outs), (ins variable_ops), - "", [], II_SAVE >, MayStore { - let isCodeGenOnly = 1; - let Uses = [SP]; - let Defs = [SP]; -} -// -// Format: SB ry, offset(rx) MIPS16e -// Purpose: Store Byte (Extended) -// To store a byte to memory. -// -def SbRxRyOffMemX16: - FEXT_RRI16_mem2_ins<0b11000, "sb", mem16, II_SB>, MayStore; - -// -// Format: SEB rx MIPS16e -// Purpose: Sign-Extend Byte -// Sign-extend least significant byte in register rx. -// -def SebRx16 - : FRR_SF16_ins<0b10001, 0b100, "seb", IIM16Alu>; - -// -// Format: SEH rx MIPS16e -// Purpose: Sign-Extend Halfword -// Sign-extend least significant word in register rx. -// -def SehRx16 - : FRR_SF16_ins<0b10001, 0b101, "seh", IIM16Alu>; - -// -// The Sel(T) instructions are pseudos -// T means that they use T8 implicitly. -// -// -// Format: SelBeqZ rd, rs, rt -// Purpose: if rt==0, do nothing -// else rs = rt -// -def SelBeqZ: Sel<"beqz">; - -// -// Format: SelTBteqZCmp rd, rs, rl, rr -// Purpose: b = Cmp rl, rr. -// If b==0 then do nothing. -// if b!=0 then rd = rs -// -def SelTBteqZCmp: SelT<"bteqz", "cmp">; - -// -// Format: SelTBteqZCmpi rd, rs, rl, rr -// Purpose: b = Cmpi rl, imm. -// If b==0 then do nothing. -// if b!=0 then rd = rs -// -def SelTBteqZCmpi: SeliT<"bteqz", "cmpi">; - -// -// Format: SelTBteqZSlt rd, rs, rl, rr -// Purpose: b = Slt rl, rr. -// If b==0 then do nothing. -// if b!=0 then rd = rs -// -def SelTBteqZSlt: SelT<"bteqz", "slt">; - -// -// Format: SelTBteqZSlti rd, rs, rl, rr -// Purpose: b = Slti rl, imm. -// If b==0 then do nothing. -// if b!=0 then rd = rs -// -def SelTBteqZSlti: SeliT<"bteqz", "slti">; - -// -// Format: SelTBteqZSltu rd, rs, rl, rr -// Purpose: b = Sltu rl, rr. -// If b==0 then do nothing. -// if b!=0 then rd = rs -// -def SelTBteqZSltu: SelT<"bteqz", "sltu">; - -// -// Format: SelTBteqZSltiu rd, rs, rl, rr -// Purpose: b = Sltiu rl, imm. -// If b==0 then do nothing. -// if b!=0 then rd = rs -// -def SelTBteqZSltiu: SeliT<"bteqz", "sltiu">; - -// -// Format: SelBnez rd, rs, rt -// Purpose: if rt!=0, do nothing -// else rs = rt -// -def SelBneZ: Sel<"bnez">; - -// -// Format: SelTBtneZCmp rd, rs, rl, rr -// Purpose: b = Cmp rl, rr. -// If b!=0 then do nothing. -// if b0=0 then rd = rs -// -def SelTBtneZCmp: SelT<"btnez", "cmp">; - -// -// Format: SelTBtnezCmpi rd, rs, rl, rr -// Purpose: b = Cmpi rl, imm. -// If b!=0 then do nothing. -// if b==0 then rd = rs -// -def SelTBtneZCmpi: SeliT<"btnez", "cmpi">; - -// -// Format: SelTBtneZSlt rd, rs, rl, rr -// Purpose: b = Slt rl, rr. -// If b!=0 then do nothing. -// if b==0 then rd = rs -// -def SelTBtneZSlt: SelT<"btnez", "slt">; - -// -// Format: SelTBtneZSlti rd, rs, rl, rr -// Purpose: b = Slti rl, imm. -// If b!=0 then do nothing. -// if b==0 then rd = rs -// -def SelTBtneZSlti: SeliT<"btnez", "slti">; - -// -// Format: SelTBtneZSltu rd, rs, rl, rr -// Purpose: b = Sltu rl, rr. -// If b!=0 then do nothing. -// if b==0 then rd = rs -// -def SelTBtneZSltu: SelT<"btnez", "sltu">; - -// -// Format: SelTBtneZSltiu rd, rs, rl, rr -// Purpose: b = Slti rl, imm. -// If b!=0 then do nothing. -// if b==0 then rd = rs -// -def SelTBtneZSltiu: SeliT<"btnez", "sltiu">; -// -// -// Format: SH ry, offset(rx) MIPS16e -// Purpose: Store Halfword (Extended) -// To store a halfword to memory. -// -def ShRxRyOffMemX16: - FEXT_RRI16_mem2_ins<0b11001, "sh", mem16, II_SH>, MayStore; - -// -// Format: SLL rx, ry, sa MIPS16e -// Purpose: Shift Word Left Logical (Extended) -// To execute a left-shift of a word by a fixed number of bits-0 to 31 bits. -// -def SllX16: FEXT_SHIFT16_ins<0b00, "sll", IIM16Alu>; - -// -// Format: SLLV ry, rx MIPS16e -// Purpose: Shift Word Left Logical Variable -// To execute a left-shift of a word by a variable number of bits. -// -def SllvRxRy16 : FRxRxRy16_ins<0b00100, "sllv", IIM16Alu>; - -// Format: SLTI rx, immediate MIPS16e -// Purpose: Set on Less Than Immediate -// To record the result of a less-than comparison with a constant. -// -// -def SltiRxImm16: FRI16R_ins<0b01010, "slti", IIM16Alu> { - let Defs = [T8]; -} - -// -// Format: SLTI rx, immediate MIPS16e -// Purpose: Set on Less Than Immediate (Extended) -// To record the result of a less-than comparison with a constant. -// -// -def SltiRxImmX16: FEXT_RI16R_ins<0b01010, "slti", IIM16Alu> { - let Defs = [T8]; -} - -def SltiCCRxImmX16: FEXT_CCRXI16_ins<"slti">; - -// Format: SLTIU rx, immediate MIPS16e -// Purpose: Set on Less Than Immediate Unsigned -// To record the result of a less-than comparison with a constant. -// -// -def SltiuRxImm16: FRI16R_ins<0b01011, "sltiu", IIM16Alu> { - let Defs = [T8]; -} - -// -// Format: SLTI rx, immediate MIPS16e -// Purpose: Set on Less Than Immediate Unsigned (Extended) -// To record the result of a less-than comparison with a constant. -// -// -def SltiuRxImmX16: FEXT_RI16R_ins<0b01011, "sltiu", IIM16Alu> { - let Defs = [T8]; -} -// -// Format: SLTIU rx, immediate MIPS16e -// Purpose: Set on Less Than Immediate Unsigned (Extended) -// To record the result of a less-than comparison with a constant. -// -def SltiuCCRxImmX16: FEXT_CCRXI16_ins<"sltiu">; - -// -// Format: SLT rx, ry MIPS16e -// Purpose: Set on Less Than -// To record the result of a less-than comparison. -// -def SltRxRy16: FRR16R_ins<0b00010, "slt", IIM16Alu>{ - let Defs = [T8]; -} - -def SltCCRxRy16: FCCRR16_ins<"slt">; - -// Format: SLTU rx, ry MIPS16e -// Purpose: Set on Less Than Unsigned -// To record the result of an unsigned less-than comparison. -// -def SltuRxRy16: FRR16R_ins<0b00011, "sltu", IIM16Alu>{ - let Defs = [T8]; -} - -def SltuRxRyRz16: FRRTR16_ins<"sltu"> { - let isCodeGenOnly=1; - let Defs = [T8]; -} - - -def SltuCCRxRy16: FCCRR16_ins<"sltu">; -// -// Format: SRAV ry, rx MIPS16e -// Purpose: Shift Word Right Arithmetic Variable -// To execute an arithmetic right-shift of a word by a variable -// number of bits. -// -def SravRxRy16: FRxRxRy16_ins<0b00111, "srav", IIM16Alu>; - - -// -// Format: SRA rx, ry, sa MIPS16e -// Purpose: Shift Word Right Arithmetic (Extended) -// To execute an arithmetic right-shift of a word by a fixed -// number of bits-1 to 8 bits. -// -def SraX16: FEXT_SHIFT16_ins<0b11, "sra", IIM16Alu>; - - -// -// Format: SRLV ry, rx MIPS16e -// Purpose: Shift Word Right Logical Variable -// To execute a logical right-shift of a word by a variable -// number of bits. -// -def SrlvRxRy16: FRxRxRy16_ins<0b00110, "srlv", IIM16Alu>; - - -// -// Format: SRL rx, ry, sa MIPS16e -// Purpose: Shift Word Right Logical (Extended) -// To execute a logical right-shift of a word by a fixed -// number of bits-1 to 31 bits. -// -def SrlX16: FEXT_SHIFT16_ins<0b10, "srl", IIM16Alu>; - -// -// Format: SUBU rz, rx, ry MIPS16e -// Purpose: Subtract Unsigned Word -// To subtract 32-bit integers -// -def SubuRxRyRz16: FRRR16_ins<0b11, "subu", IIM16Alu>, ArithLogic16Defs<0>; - -// -// Format: SW ry, offset(rx) MIPS16e -// Purpose: Store Word (Extended) -// To store a word to memory. -// -def SwRxRyOffMemX16: FEXT_RRI16_mem2_ins<0b11011, "sw", mem16, II_SW>, MayStore; - -// -// Format: SW rx, offset(sp) MIPS16e -// Purpose: Store Word rx (SP-Relative) -// To store an SP-relative word to memory. -// -def SwRxSpImmX16: FEXT_RRI16_mem2_ins<0b11010, "sw", mem16sp, II_SW>, MayStore; - -// -// -// Format: XOR rx, ry MIPS16e -// Purpose: Xor -// To do a bitwise logical XOR. -// -def XorRxRxRy16: FRxRxRy16_ins<0b01110, "xor", IIM16Alu>, ArithLogic16Defs<1>; - -class Mips16Pat<dag pattern, dag result> : Pat<pattern, result> { - let Predicates = [InMips16Mode]; -} - -// Unary Arith/Logic -// -class ArithLogicU_pat<PatFrag OpNode, Instruction I> : - Mips16Pat<(OpNode CPU16Regs:$r), - (I CPU16Regs:$r)>; - -def: ArithLogicU_pat<not, NotRxRy16>; -def: ArithLogicU_pat<ineg, NegRxRy16>; - -class ArithLogic16_pat<SDNode OpNode, Instruction I> : - Mips16Pat<(OpNode CPU16Regs:$l, CPU16Regs:$r), - (I CPU16Regs:$l, CPU16Regs:$r)>; - -def: ArithLogic16_pat<add, AdduRxRyRz16>; -def: ArithLogic16_pat<and, AndRxRxRy16>; -def: ArithLogic16_pat<mul, MultRxRyRz16>; -def: ArithLogic16_pat<or, OrRxRxRy16>; -def: ArithLogic16_pat<sub, SubuRxRyRz16>; -def: ArithLogic16_pat<xor, XorRxRxRy16>; - -// Arithmetic and logical instructions with 2 register operands. - -class ArithLogicI16_pat<SDNode OpNode, PatFrag imm_type, Instruction I> : - Mips16Pat<(OpNode CPU16Regs:$in, imm_type:$imm), - (I CPU16Regs:$in, imm_type:$imm)>; - -def: ArithLogicI16_pat<add, immSExt8, AddiuRxRxImm16>; -def: ArithLogicI16_pat<add, immSExt16, AddiuRxRxImmX16>; -def: ArithLogicI16_pat<shl, immZExt5, SllX16>; -def: ArithLogicI16_pat<srl, immZExt5, SrlX16>; -def: ArithLogicI16_pat<sra, immZExt5, SraX16>; - -class shift_rotate_reg16_pat<SDNode OpNode, Instruction I> : - Mips16Pat<(OpNode CPU16Regs:$r, CPU16Regs:$ra), - (I CPU16Regs:$r, CPU16Regs:$ra)>; - -def: shift_rotate_reg16_pat<shl, SllvRxRy16>; -def: shift_rotate_reg16_pat<sra, SravRxRy16>; -def: shift_rotate_reg16_pat<srl, SrlvRxRy16>; - -class LoadM16_pat<PatFrag OpNode, Instruction I, ComplexPattern Addr> : - Mips16Pat<(OpNode Addr:$addr), (I Addr:$addr)>; - -def: LoadM16_pat<sextloadi8, LbRxRyOffMemX16, addr16>; -def: LoadM16_pat<zextloadi8, LbuRxRyOffMemX16, addr16>; -def: LoadM16_pat<sextloadi16, LhRxRyOffMemX16, addr16>; -def: LoadM16_pat<zextloadi16, LhuRxRyOffMemX16, addr16>; -def: LoadM16_pat<load, LwRxSpImmX16, addr16sp>; - -class StoreM16_pat<PatFrag OpNode, Instruction I, ComplexPattern Addr> : - Mips16Pat<(OpNode CPU16Regs:$r, Addr:$addr), (I CPU16Regs:$r, Addr:$addr)>; - -def: StoreM16_pat<truncstorei8, SbRxRyOffMemX16, addr16>; -def: StoreM16_pat<truncstorei16, ShRxRyOffMemX16, addr16>; -def: StoreM16_pat<store, SwRxSpImmX16, addr16sp>; - -// Unconditional branch -class UncondBranch16_pat<SDNode OpNode, Instruction I>: - Mips16Pat<(OpNode bb:$imm16), (I bb:$imm16)> { - let Predicates = [InMips16Mode]; - } - -def : Mips16Pat<(MipsJmpLink (i32 tglobaladdr:$dst)), - (Jal16 tglobaladdr:$dst)>; - -def : Mips16Pat<(MipsJmpLink (i32 texternalsym:$dst)), - (Jal16 texternalsym:$dst)>; - -// Indirect branch -def: Mips16Pat<(brind CPU16Regs:$rs), (JrcRx16 CPU16Regs:$rs)> { - // Ensure that the addition of MIPS32r6/MIPS64r6 support does not change - // MIPS16's behaviour. - let AddedComplexity = 1; -} - -// Jump and Link (Call) -let isCall=1, hasDelaySlot=0 in -def JumpLinkReg16: - FRR16_JALRC<0, 0, 0, (outs), (ins CPU16Regs:$rs), - "jalrc\t$rs", [(MipsJmpLink CPU16Regs:$rs)], II_JALRC> { - let Defs = [RA]; -} - -// Mips16 pseudos -let isReturn=1, isTerminator=1, hasDelaySlot=1, isBarrier=1, hasCtrlDep=1, - hasExtraSrcRegAllocReq = 1 in -def RetRA16 : MipsPseudo16<(outs), (ins), "", [(MipsRet)]>; - - -// setcc patterns - -class SetCC_R16<PatFrag cond_op, Instruction I>: - Mips16Pat<(cond_op CPU16Regs:$rx, CPU16Regs:$ry), - (I CPU16Regs:$rx, CPU16Regs:$ry)>; - -class SetCC_I16<PatFrag cond_op, PatLeaf imm_type, Instruction I>: - Mips16Pat<(cond_op CPU16Regs:$rx, imm_type:$imm16), - (I CPU16Regs:$rx, imm_type:$imm16)>; - - -def: Mips16Pat<(i32 addr16sp:$addr), (AddiuRxRyOffMemX16 addr16sp:$addr)>; - - -// Large (>16 bit) immediate loads -def : Mips16Pat<(i32 imm:$imm), (LwConstant32 imm:$imm, -1)>; - -// -// Some branch conditional patterns are not generated by llvm at this time. -// Some are for seemingly arbitrary reasons not used: i.e. with signed number -// comparison they are used and for unsigned a different pattern is used. -// I am pushing upstream from the full mips16 port and it seemed that I needed -// these earlier and the mips32 port has these but now I cannot create test -// cases that use these patterns. While I sort this all out I will leave these -// extra patterns commented out and if I can be sure they are really not used, -// I will delete the code. I don't want to check the code in uncommented without -// a valid test case. In some cases, the compiler is generating patterns with -// setcc instead and earlier I had implemented setcc first so may have masked -// the problem. The setcc variants are suboptimal for mips16 so I may wantto -// figure out how to enable the brcond patterns or else possibly new -// combinations of brcond and setcc. -// -// -// bcond-seteq -// -def: Mips16Pat - <(brcond (i32 (seteq CPU16Regs:$rx, CPU16Regs:$ry)), bb:$imm16), - (BteqzT8CmpX16 CPU16Regs:$rx, CPU16Regs:$ry, bb:$imm16) - >; - - -def: Mips16Pat - <(brcond (i32 (seteq CPU16Regs:$rx, immZExt16:$imm)), bb:$targ16), - (BteqzT8CmpiX16 CPU16Regs:$rx, immSExt16:$imm, bb:$targ16) - >; - -def: Mips16Pat - <(brcond (i32 (seteq CPU16Regs:$rx, 0)), bb:$targ16), - (BeqzRxImm16 CPU16Regs:$rx, bb:$targ16) - >; - -// -// bcond-setgt (do we need to have this pair of setlt, setgt??) -// -def: Mips16Pat - <(brcond (i32 (setgt CPU16Regs:$rx, CPU16Regs:$ry)), bb:$imm16), - (BtnezT8SltX16 CPU16Regs:$ry, CPU16Regs:$rx, bb:$imm16) - >; - -// -// bcond-setge -// -def: Mips16Pat - <(brcond (i32 (setge CPU16Regs:$rx, CPU16Regs:$ry)), bb:$imm16), - (BteqzT8SltX16 CPU16Regs:$rx, CPU16Regs:$ry, bb:$imm16) - >; - -// -// never called because compiler transforms a >= k to a > (k-1) -def: Mips16Pat - <(brcond (i32 (setge CPU16Regs:$rx, immSExt16:$imm)), bb:$imm16), - (BteqzT8SltiX16 CPU16Regs:$rx, immSExt16:$imm, bb:$imm16) - >; - -// -// bcond-setlt -// -def: Mips16Pat - <(brcond (i32 (setlt CPU16Regs:$rx, CPU16Regs:$ry)), bb:$imm16), - (BtnezT8SltX16 CPU16Regs:$rx, CPU16Regs:$ry, bb:$imm16) - >; - -def: Mips16Pat - <(brcond (i32 (setlt CPU16Regs:$rx, immSExt16:$imm)), bb:$imm16), - (BtnezT8SltiX16 CPU16Regs:$rx, immSExt16:$imm, bb:$imm16) - >; - -// -// bcond-setle -// -def: Mips16Pat - <(brcond (i32 (setle CPU16Regs:$rx, CPU16Regs:$ry)), bb:$imm16), - (BteqzT8SltX16 CPU16Regs:$ry, CPU16Regs:$rx, bb:$imm16) - >; - -// -// bcond-setne -// -def: Mips16Pat - <(brcond (i32 (setne CPU16Regs:$rx, CPU16Regs:$ry)), bb:$imm16), - (BtnezT8CmpX16 CPU16Regs:$rx, CPU16Regs:$ry, bb:$imm16) - >; - -def: Mips16Pat - <(brcond (i32 (setne CPU16Regs:$rx, immZExt16:$imm)), bb:$targ16), - (BtnezT8CmpiX16 CPU16Regs:$rx, immSExt16:$imm, bb:$targ16) - >; - -def: Mips16Pat - <(brcond (i32 (setne CPU16Regs:$rx, 0)), bb:$targ16), - (BnezRxImm16 CPU16Regs:$rx, bb:$targ16) - >; - -// -// This needs to be there but I forget which code will generate it -// -def: Mips16Pat - <(brcond CPU16Regs:$rx, bb:$targ16), - (BnezRxImm16 CPU16Regs:$rx, bb:$targ16) - >; - -// - -// -// bcond-setugt -// -//def: Mips16Pat -// <(brcond (i32 (setugt CPU16Regs:$rx, CPU16Regs:$ry)), bb:$imm16), -// (BtnezT8SltuX16 CPU16Regs:$ry, CPU16Regs:$rx, bb:$imm16) -// >; - -// -// bcond-setuge -// -//def: Mips16Pat -// <(brcond (i32 (setuge CPU16Regs:$rx, CPU16Regs:$ry)), bb:$imm16), -// (BteqzT8SltuX16 CPU16Regs:$rx, CPU16Regs:$ry, bb:$imm16) -// >; - - -// -// bcond-setult -// -//def: Mips16Pat -// <(brcond (i32 (setult CPU16Regs:$rx, CPU16Regs:$ry)), bb:$imm16), -// (BtnezT8SltuX16 CPU16Regs:$rx, CPU16Regs:$ry, bb:$imm16) -// >; - -def: UncondBranch16_pat<br, Bimm16>; - -// Small immediates -def: Mips16Pat<(i32 immSExt16:$in), - (AddiuRxRxImmX16 (MoveR3216 ZERO), immSExt16:$in)>; - -def: Mips16Pat<(i32 immZExt16:$in), (LiRxImmX16 immZExt16:$in)>; - -// -// MipsDivRem -// -def: Mips16Pat - <(MipsDivRem16 CPU16Regs:$rx, CPU16Regs:$ry), - (DivRxRy16 CPU16Regs:$rx, CPU16Regs:$ry)>; - -// -// MipsDivRemU -// -def: Mips16Pat - <(MipsDivRemU16 CPU16Regs:$rx, CPU16Regs:$ry), - (DivuRxRy16 CPU16Regs:$rx, CPU16Regs:$ry)>; - -// signed a,b -// x = (a>=b)?x:y -// -// if !(a < b) x = y -// -def : Mips16Pat<(select (i32 (setge CPU16Regs:$a, CPU16Regs:$b)), - CPU16Regs:$x, CPU16Regs:$y), - (SelTBteqZSlt CPU16Regs:$x, CPU16Regs:$y, - CPU16Regs:$a, CPU16Regs:$b)>; - -// signed a,b -// x = (a>b)?x:y -// -// if (b < a) x = y -// -def : Mips16Pat<(select (i32 (setgt CPU16Regs:$a, CPU16Regs:$b)), - CPU16Regs:$x, CPU16Regs:$y), - (SelTBtneZSlt CPU16Regs:$x, CPU16Regs:$y, - CPU16Regs:$b, CPU16Regs:$a)>; - -// unsigned a,b -// x = (a>=b)?x:y -// -// if !(a < b) x = y; -// -def : Mips16Pat< - (select (i32 (setuge CPU16Regs:$a, CPU16Regs:$b)), - CPU16Regs:$x, CPU16Regs:$y), - (SelTBteqZSltu CPU16Regs:$x, CPU16Regs:$y, - CPU16Regs:$a, CPU16Regs:$b)>; - -// unsigned a,b -// x = (a>b)?x:y -// -// if (b < a) x = y -// -def : Mips16Pat<(select (i32 (setugt CPU16Regs:$a, CPU16Regs:$b)), - CPU16Regs:$x, CPU16Regs:$y), - (SelTBtneZSltu CPU16Regs:$x, CPU16Regs:$y, - CPU16Regs:$b, CPU16Regs:$a)>; - -// signed -// x = (a >= k)?x:y -// due to an llvm optimization, i don't think that this will ever -// be used. This is transformed into x = (a > k-1)?x:y -// -// - -//def : Mips16Pat< -// (select (i32 (setge CPU16Regs:$lhs, immSExt16:$rhs)), -// CPU16Regs:$T, CPU16Regs:$F), -// (SelTBteqZSlti CPU16Regs:$T, CPU16Regs:$F, -// CPU16Regs:$lhs, immSExt16:$rhs)>; - -//def : Mips16Pat< -// (select (i32 (setuge CPU16Regs:$lhs, immSExt16:$rhs)), -// CPU16Regs:$T, CPU16Regs:$F), -// (SelTBteqZSltiu CPU16Regs:$T, CPU16Regs:$F, -// CPU16Regs:$lhs, immSExt16:$rhs)>; - -// signed -// x = (a < k)?x:y -// -// if !(a < k) x = y; -// -def : Mips16Pat< - (select (i32 (setlt CPU16Regs:$a, immSExt16:$b)), - CPU16Regs:$x, CPU16Regs:$y), - (SelTBtneZSlti CPU16Regs:$x, CPU16Regs:$y, - CPU16Regs:$a, immSExt16:$b)>; - - -// -// -// signed -// x = (a <= b)? x : y -// -// if (b < a) x = y -// -def : Mips16Pat<(select (i32 (setle CPU16Regs:$a, CPU16Regs:$b)), - CPU16Regs:$x, CPU16Regs:$y), - (SelTBteqZSlt CPU16Regs:$x, CPU16Regs:$y, - CPU16Regs:$b, CPU16Regs:$a)>; - -// -// unnsigned -// x = (a <= b)? x : y -// -// if (b < a) x = y -// -def : Mips16Pat<(select (i32 (setule CPU16Regs:$a, CPU16Regs:$b)), - CPU16Regs:$x, CPU16Regs:$y), - (SelTBteqZSltu CPU16Regs:$x, CPU16Regs:$y, - CPU16Regs:$b, CPU16Regs:$a)>; - -// -// signed/unsigned -// x = (a == b)? x : y -// -// if (a != b) x = y -// -def : Mips16Pat<(select (i32 (seteq CPU16Regs:$a, CPU16Regs:$b)), - CPU16Regs:$x, CPU16Regs:$y), - (SelTBteqZCmp CPU16Regs:$x, CPU16Regs:$y, - CPU16Regs:$b, CPU16Regs:$a)>; - -// -// signed/unsigned -// x = (a == 0)? x : y -// -// if (a != 0) x = y -// -def : Mips16Pat<(select (i32 (seteq CPU16Regs:$a, 0)), - CPU16Regs:$x, CPU16Regs:$y), - (SelBeqZ CPU16Regs:$x, CPU16Regs:$y, - CPU16Regs:$a)>; - - -// -// signed/unsigned -// x = (a == k)? x : y -// -// if (a != k) x = y -// -def : Mips16Pat<(select (i32 (seteq CPU16Regs:$a, immZExt16:$k)), - CPU16Regs:$x, CPU16Regs:$y), - (SelTBteqZCmpi CPU16Regs:$x, CPU16Regs:$y, - CPU16Regs:$a, immZExt16:$k)>; - - -// -// signed/unsigned -// x = (a != b)? x : y -// -// if (a == b) x = y -// -// -def : Mips16Pat<(select (i32 (setne CPU16Regs:$a, CPU16Regs:$b)), - CPU16Regs:$x, CPU16Regs:$y), - (SelTBtneZCmp CPU16Regs:$x, CPU16Regs:$y, - CPU16Regs:$b, CPU16Regs:$a)>; - -// -// signed/unsigned -// x = (a != 0)? x : y -// -// if (a == 0) x = y -// -def : Mips16Pat<(select (i32 (setne CPU16Regs:$a, 0)), - CPU16Regs:$x, CPU16Regs:$y), - (SelBneZ CPU16Regs:$x, CPU16Regs:$y, - CPU16Regs:$a)>; - -// signed/unsigned -// x = (a)? x : y -// -// if (!a) x = y -// -def : Mips16Pat<(select CPU16Regs:$a, - CPU16Regs:$x, CPU16Regs:$y), - (SelBneZ CPU16Regs:$x, CPU16Regs:$y, - CPU16Regs:$a)>; - - -// -// signed/unsigned -// x = (a != k)? x : y -// -// if (a == k) x = y -// -def : Mips16Pat<(select (i32 (setne CPU16Regs:$a, immZExt16:$k)), - CPU16Regs:$x, CPU16Regs:$y), - (SelTBtneZCmpi CPU16Regs:$x, CPU16Regs:$y, - CPU16Regs:$a, immZExt16:$k)>; - -// -// When writing C code to test setxx these patterns, -// some will be transformed into -// other things. So we test using C code but using -O3 and -O0 -// -// seteq -// -def : Mips16Pat - <(seteq CPU16Regs:$lhs,CPU16Regs:$rhs), - (SltiuCCRxImmX16 (XorRxRxRy16 CPU16Regs:$lhs, CPU16Regs:$rhs), 1)>; - -def : Mips16Pat - <(seteq CPU16Regs:$lhs, 0), - (SltiuCCRxImmX16 CPU16Regs:$lhs, 1)>; - - -// -// setge -// - -def: Mips16Pat - <(setge CPU16Regs:$lhs, CPU16Regs:$rhs), - (XorRxRxRy16 (SltCCRxRy16 CPU16Regs:$lhs, CPU16Regs:$rhs), - (LiRxImmX16 1))>; - -// -// For constants, llvm transforms this to: -// x > (k - 1) and then reverses the operands to use setlt. So this pattern -// is not used now by the compiler. (Presumably checking that k-1 does not -// overflow). The compiler never uses this at the current time, due to -// other optimizations. -// -//def: Mips16Pat -// <(setge CPU16Regs:$lhs, immSExt16:$rhs), -// (XorRxRxRy16 (SltiCCRxImmX16 CPU16Regs:$lhs, immSExt16:$rhs), -// (LiRxImmX16 1))>; - -// This catches the x >= -32768 case by transforming it to x > -32769 -// -def: Mips16Pat - <(setgt CPU16Regs:$lhs, -32769), - (XorRxRxRy16 (SltiCCRxImmX16 CPU16Regs:$lhs, -32768), - (LiRxImmX16 1))>; - -// -// setgt -// -// - -def: Mips16Pat - <(setgt CPU16Regs:$lhs, CPU16Regs:$rhs), - (SltCCRxRy16 CPU16Regs:$rhs, CPU16Regs:$lhs)>; - -// -// setle -// -def: Mips16Pat - <(setle CPU16Regs:$lhs, CPU16Regs:$rhs), - (XorRxRxRy16 (SltCCRxRy16 CPU16Regs:$rhs, CPU16Regs:$lhs), (LiRxImm16 1))>; - -// -// setlt -// -def: SetCC_R16<setlt, SltCCRxRy16>; - -def: SetCC_I16<setlt, immSExt16, SltiCCRxImmX16>; - -// -// setne -// -def : Mips16Pat - <(setne CPU16Regs:$lhs,CPU16Regs:$rhs), - (SltuCCRxRy16 (LiRxImmX16 0), - (XorRxRxRy16 CPU16Regs:$lhs, CPU16Regs:$rhs))>; - - -// -// setuge -// -def: Mips16Pat - <(setuge CPU16Regs:$lhs, CPU16Regs:$rhs), - (XorRxRxRy16 (SltuCCRxRy16 CPU16Regs:$lhs, CPU16Regs:$rhs), - (LiRxImmX16 1))>; - -// this pattern will never be used because the compiler will transform -// x >= k to x > (k - 1) and then use SLT -// -//def: Mips16Pat -// <(setuge CPU16Regs:$lhs, immZExt16:$rhs), -// (XorRxRxRy16 (SltiuCCRxImmX16 CPU16Regs:$lhs, immZExt16:$rhs), -// (LiRxImmX16 1))>; - -// -// setugt -// -def: Mips16Pat - <(setugt CPU16Regs:$lhs, CPU16Regs:$rhs), - (SltuCCRxRy16 CPU16Regs:$rhs, CPU16Regs:$lhs)>; - -// -// setule -// -def: Mips16Pat - <(setule CPU16Regs:$lhs, CPU16Regs:$rhs), - (XorRxRxRy16 (SltuCCRxRy16 CPU16Regs:$rhs, CPU16Regs:$lhs), (LiRxImmX16 1))>; - -// -// setult -// -def: SetCC_R16<setult, SltuCCRxRy16>; - -def: SetCC_I16<setult, immSExt16, SltiuCCRxImmX16>; - -def: Mips16Pat<(add CPU16Regs:$hi, (MipsLo tglobaladdr:$lo)), - (AddiuRxRxImmX16 CPU16Regs:$hi, tglobaladdr:$lo)>; - -// hi/lo relocs -def : Mips16Pat<(MipsHi tblockaddress:$in), - (SllX16 (LiRxImmX16 tblockaddress:$in), 16)>; -def : Mips16Pat<(MipsHi tglobaladdr:$in), - (SllX16 (LiRxImmX16 tglobaladdr:$in), 16)>; -def : Mips16Pat<(MipsHi tjumptable:$in), - (SllX16 (LiRxImmX16 tjumptable:$in), 16)>; - -def : Mips16Pat<(MipsLo tblockaddress:$in), (LiRxImmX16 tblockaddress:$in)>; - -def : Mips16Pat<(MipsTlsHi tglobaltlsaddr:$in), - (SllX16 (LiRxImmX16 tglobaltlsaddr:$in), 16)>; - -// wrapper_pic -class Wrapper16Pat<SDNode node, Instruction ADDiuOp, RegisterClass RC>: - Mips16Pat<(MipsWrapper RC:$gp, node:$in), - (ADDiuOp RC:$gp, node:$in)>; - - -def : Wrapper16Pat<tglobaladdr, AddiuRxRxImmX16, CPU16Regs>; -def : Wrapper16Pat<tglobaltlsaddr, AddiuRxRxImmX16, CPU16Regs>; - -def : Mips16Pat<(i32 (extloadi8 addr16:$src)), - (LbuRxRyOffMemX16 addr16:$src)>; -def : Mips16Pat<(i32 (extloadi16 addr16:$src)), - (LhuRxRyOffMemX16 addr16:$src)>; - -def: Mips16Pat<(trap), (Break16)>; - -def : Mips16Pat<(sext_inreg CPU16Regs:$val, i8), - (SebRx16 CPU16Regs:$val)>; - -def : Mips16Pat<(sext_inreg CPU16Regs:$val, i16), - (SehRx16 CPU16Regs:$val)>; - -def GotPrologue16: - MipsPseudo16< - (outs CPU16Regs:$rh, CPU16Regs:$rl), - (ins simm16:$immHi, simm16:$immLo), - "li\t$rh, $immHi\n\taddiu\t$rl, $$pc, $immLo\n ",[]> ; - -// An operand for the CONSTPOOL_ENTRY pseudo-instruction. -def cpinst_operand : Operand<i32> { - // let PrintMethod = "printCPInstOperand"; -} - -// CONSTPOOL_ENTRY - This instruction represents a floating constant pool in -// the function. The first operand is the ID# for this instruction, the second -// is the index into the MachineConstantPool that this is, the third is the -// size in bytes of this constant pool entry. -// -let hasSideEffects = 0, isNotDuplicable = 1 in -def CONSTPOOL_ENTRY : -MipsPseudo16<(outs), (ins cpinst_operand:$instid, cpinst_operand:$cpidx, - i32imm:$size), "foo", []>; - -// Instruction Aliases - -let EncodingPredicates = [InMips16Mode] in -def : MipsInstAlias<"nop", (Move32R16 ZERO, S0)>; diff --git a/contrib/llvm/lib/Target/Mips/Mips16RegisterInfo.cpp b/contrib/llvm/lib/Target/Mips/Mips16RegisterInfo.cpp deleted file mode 100644 index 5703f585a6a2..000000000000 --- a/contrib/llvm/lib/Target/Mips/Mips16RegisterInfo.cpp +++ /dev/null @@ -1,147 +0,0 @@ -//===-- Mips16RegisterInfo.cpp - MIPS16 Register Information --------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains the MIPS16 implementation of the TargetRegisterInfo class. -// -//===----------------------------------------------------------------------===// - -#include "Mips16RegisterInfo.h" -#include "Mips.h" -#include "Mips16InstrInfo.h" -#include "MipsInstrInfo.h" -#include "MipsMachineFunction.h" -#include "MipsSubtarget.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/TargetFrameLowering.h" -#include "llvm/CodeGen/TargetInstrInfo.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/DebugInfo.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/Type.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetOptions.h" - -using namespace llvm; - -#define DEBUG_TYPE "mips16-registerinfo" - -Mips16RegisterInfo::Mips16RegisterInfo() : MipsRegisterInfo() {} - -bool Mips16RegisterInfo::requiresRegisterScavenging - (const MachineFunction &MF) const { - return false; -} -bool Mips16RegisterInfo::requiresFrameIndexScavenging - (const MachineFunction &MF) const { - return false; -} - -bool Mips16RegisterInfo::useFPForScavengingIndex - (const MachineFunction &MF) const { - return false; -} - -bool Mips16RegisterInfo::saveScavengerRegister - (MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, - MachineBasicBlock::iterator &UseMI, - const TargetRegisterClass *RC, - unsigned Reg) const { - DebugLoc DL; - const TargetInstrInfo &TII = *MBB.getParent()->getSubtarget().getInstrInfo(); - TII.copyPhysReg(MBB, I, DL, Mips::T0, Reg, true); - TII.copyPhysReg(MBB, UseMI, DL, Reg, Mips::T0, true); - return true; -} - -const TargetRegisterClass * -Mips16RegisterInfo::intRegClass(unsigned Size) const { - assert(Size == 4); - return &Mips::CPU16RegsRegClass; -} - -void Mips16RegisterInfo::eliminateFI(MachineBasicBlock::iterator II, - unsigned OpNo, int FrameIndex, - uint64_t StackSize, - int64_t SPOffset) const { - MachineInstr &MI = *II; - MachineFunction &MF = *MI.getParent()->getParent(); - MachineFrameInfo &MFI = MF.getFrameInfo(); - - const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); - int MinCSFI = 0; - int MaxCSFI = -1; - - if (CSI.size()) { - MinCSFI = CSI[0].getFrameIdx(); - MaxCSFI = CSI[CSI.size() - 1].getFrameIdx(); - } - - // The following stack frame objects are always - // referenced relative to $sp: - // 1. Outgoing arguments. - // 2. Pointer to dynamically allocated stack space. - // 3. Locations for callee-saved registers. - // Everything else is referenced relative to whatever register - // getFrameRegister() returns. - unsigned FrameReg; - - if (FrameIndex >= MinCSFI && FrameIndex <= MaxCSFI) - FrameReg = Mips::SP; - else { - const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering(); - if (TFI->hasFP(MF)) { - FrameReg = Mips::S0; - } - else { - if ((MI.getNumOperands()> OpNo+2) && MI.getOperand(OpNo+2).isReg()) - FrameReg = MI.getOperand(OpNo+2).getReg(); - else - FrameReg = Mips::SP; - } - } - // Calculate final offset. - // - There is no need to change the offset if the frame object - // is one of the - // following: an outgoing argument, pointer to a dynamically allocated - // stack space or a $gp restore location, - // - If the frame object is any of the following, - // its offset must be adjusted - // by adding the size of the stack: - // incoming argument, callee-saved register location or local variable. - int64_t Offset; - bool IsKill = false; - Offset = SPOffset + (int64_t)StackSize; - Offset += MI.getOperand(OpNo + 1).getImm(); - - LLVM_DEBUG(errs() << "Offset : " << Offset << "\n" - << "<--------->\n"); - - if (!MI.isDebugValue() && - !Mips16InstrInfo::validImmediate(MI.getOpcode(), FrameReg, Offset)) { - MachineBasicBlock &MBB = *MI.getParent(); - DebugLoc DL = II->getDebugLoc(); - unsigned NewImm; - const Mips16InstrInfo &TII = - *static_cast<const Mips16InstrInfo *>(MF.getSubtarget().getInstrInfo()); - FrameReg = TII.loadImmediate(FrameReg, Offset, MBB, II, DL, NewImm); - Offset = SignExtend64<16>(NewImm); - IsKill = true; - } - MI.getOperand(OpNo).ChangeToRegister(FrameReg, false, false, IsKill); - MI.getOperand(OpNo + 1).ChangeToImmediate(Offset); - - -} diff --git a/contrib/llvm/lib/Target/Mips/Mips16RegisterInfo.h b/contrib/llvm/lib/Target/Mips/Mips16RegisterInfo.h deleted file mode 100644 index fca78b43f96b..000000000000 --- a/contrib/llvm/lib/Target/Mips/Mips16RegisterInfo.h +++ /dev/null @@ -1,47 +0,0 @@ -//===-- Mips16RegisterInfo.h - Mips16 Register Information ------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains the Mips16 implementation of the TargetRegisterInfo class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_MIPS_MIPS16REGISTERINFO_H -#define LLVM_LIB_TARGET_MIPS_MIPS16REGISTERINFO_H - -#include "MipsRegisterInfo.h" - -namespace llvm { -class Mips16InstrInfo; - -class Mips16RegisterInfo : public MipsRegisterInfo { -public: - Mips16RegisterInfo(); - - bool requiresRegisterScavenging(const MachineFunction &MF) const override; - - bool requiresFrameIndexScavenging(const MachineFunction &MF) const override; - - bool useFPForScavengingIndex(const MachineFunction &MF) const override; - - bool saveScavengerRegister(MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, - MachineBasicBlock::iterator &UseMI, - const TargetRegisterClass *RC, - unsigned Reg) const override; - - const TargetRegisterClass *intRegClass(unsigned Size) const override; - -private: - void eliminateFI(MachineBasicBlock::iterator II, unsigned OpNo, - int FrameIndex, uint64_t StackSize, - int64_t SPOffset) const override; -}; - -} // end namespace llvm - -#endif diff --git a/contrib/llvm/lib/Target/Mips/Mips32r6InstrFormats.td b/contrib/llvm/lib/Target/Mips/Mips32r6InstrFormats.td deleted file mode 100644 index ccb6d1df777a..000000000000 --- a/contrib/llvm/lib/Target/Mips/Mips32r6InstrFormats.td +++ /dev/null @@ -1,613 +0,0 @@ -//=- Mips32r6InstrFormats.td - Mips32r6 Instruction Formats -*- tablegen -*-==// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file describes Mips32r6 instruction formats. -// -//===----------------------------------------------------------------------===// - -class R6MMR6Rel; - -def MipsR62MicroMipsR6 : InstrMapping { - let FilterClass = "R6MMR6Rel"; - // Instructions with the same BaseOpcode and isNVStore values form a row. - let RowFields = ["BaseOpcode"]; - // Instructions with the same predicate sense form a column. - let ColFields = ["Arch"]; - // The key column is the unpredicated instructions. - let KeyCol = ["mipsr6"]; - // Value columns are PredSense=true and PredSense=false - let ValueCols = [["mipsr6"], ["micromipsr6"]]; -} - -class MipsR6Arch<string opstr> { - string Arch = "mipsr6"; - string BaseOpcode = opstr; -} - -class MipsR6Inst : MipsInst<(outs), (ins), "", [], NoItinerary, FrmOther> { - let DecoderNamespace = "Mips32r6_64r6"; - let EncodingPredicates = [HasStdEnc]; -} - -//===----------------------------------------------------------------------===// -// -// Field Values -// -//===----------------------------------------------------------------------===// - -class OPGROUP<bits<6> Val> { - bits<6> Value = Val; -} -def OPGROUP_COP0 : OPGROUP<0b010000>; -def OPGROUP_COP1 : OPGROUP<0b010001>; -def OPGROUP_COP2 : OPGROUP<0b010010>; -def OPGROUP_ADDI : OPGROUP<0b001000>; -def OPGROUP_AUI : OPGROUP<0b001111>; -def OPGROUP_BLEZ : OPGROUP<0b000110>; -def OPGROUP_BGTZ : OPGROUP<0b000111>; -def OPGROUP_BLEZL : OPGROUP<0b010110>; -def OPGROUP_BGTZL : OPGROUP<0b010111>; -def OPGROUP_DADDI : OPGROUP<0b011000>; -def OPGROUP_DAUI : OPGROUP<0b011101>; -def OPGROUP_PCREL : OPGROUP<0b111011>; -def OPGROUP_REGIMM : OPGROUP<0b000001>; -def OPGROUP_SPECIAL : OPGROUP<0b000000>; -// The spec occasionally names this value LL, LLD, SC, or SCD. -def OPGROUP_SPECIAL3 : OPGROUP<0b011111>; -// The spec names this constant LWC2, LDC2, SWC2, and SDC2 in different places. -def OPGROUP_COP2LDST : OPGROUP<0b010010>; - -class OPCODE2<bits<2> Val> { - bits<2> Value = Val; -} -def OPCODE2_ADDIUPC : OPCODE2<0b00>; -def OPCODE2_LWPC : OPCODE2<0b01>; -def OPCODE2_LWUPC : OPCODE2<0b10>; - -class OPCODE3<bits<3> Val> { - bits<3> Value = Val; -} -def OPCODE3_LDPC : OPCODE3<0b110>; - -class OPCODE5<bits<5> Val> { - bits<5> Value = Val; -} -def OPCODE5_ALUIPC : OPCODE5<0b11111>; -def OPCODE5_AUIPC : OPCODE5<0b11110>; -def OPCODE5_DAHI : OPCODE5<0b00110>; -def OPCODE5_DATI : OPCODE5<0b11110>; -def OPCODE5_BC1EQZ : OPCODE5<0b01001>; -def OPCODE5_BC1NEZ : OPCODE5<0b01101>; -def OPCODE5_BC2EQZ : OPCODE5<0b01001>; -def OPCODE5_BC2NEZ : OPCODE5<0b01101>; -def OPCODE5_BGEZAL : OPCODE5<0b10001>; -def OPCODE5_SIGRIE : OPCODE5<0b10111>; -// The next four constants are unnamed in the spec. These names are taken from -// the OPGROUP names they are used with. -def OPCODE5_LDC2 : OPCODE5<0b01110>; -def OPCODE5_LWC2 : OPCODE5<0b01010>; -def OPCODE5_SDC2 : OPCODE5<0b01111>; -def OPCODE5_SWC2 : OPCODE5<0b01011>; - -class OPCODE6<bits<6> Val> { - bits<6> Value = Val; -} -def OPCODE6_ALIGN : OPCODE6<0b100000>; -def OPCODE6_DALIGN : OPCODE6<0b100100>; -def OPCODE6_BITSWAP : OPCODE6<0b100000>; -def OPCODE6_DBITSWAP : OPCODE6<0b100100>; -def OPCODE6_JALR : OPCODE6<0b001001>; -def OPCODE6_CACHE : OPCODE6<0b100101>; -def OPCODE6_PREF : OPCODE6<0b110101>; -// The next four constants are unnamed in the spec. These names are taken from -// the OPGROUP names they are used with. -def OPCODE6_LL : OPCODE6<0b110110>; -def OPCODE6_LLD : OPCODE6<0b110111>; -def OPCODE6_SC : OPCODE6<0b100110>; -def OPCODE6_SCD : OPCODE6<0b100111>; -def OPCODE6_CLO : OPCODE6<0b010001>; -def OPCODE6_CLZ : OPCODE6<0b010000>; -def OPCODE6_DCLO : OPCODE6<0b010011>; -def OPCODE6_DCLZ : OPCODE6<0b010010>; -def OPCODE6_LSA : OPCODE6<0b000101>; -def OPCODE6_DLSA : OPCODE6<0b010101>; -def OPCODE6_SDBBP : OPCODE6<0b001110>; - -class FIELD_FMT<bits<5> Val> { - bits<5> Value = Val; -} -def FIELD_FMT_S : FIELD_FMT<0b10000>; -def FIELD_FMT_D : FIELD_FMT<0b10001>; - -class FIELD_CMP_COND<bits<5> Val> { - bits<5> Value = Val; -} -// Note: The CMP_COND_FMT names differ from the C_COND_FMT names. -def FIELD_CMP_COND_AF : FIELD_CMP_COND<0b00000>; -def FIELD_CMP_COND_UN : FIELD_CMP_COND<0b00001>; -def FIELD_CMP_COND_EQ : FIELD_CMP_COND<0b00010>; -def FIELD_CMP_COND_UEQ : FIELD_CMP_COND<0b00011>; -def FIELD_CMP_COND_LT : FIELD_CMP_COND<0b00100>; -def FIELD_CMP_COND_ULT : FIELD_CMP_COND<0b00101>; -def FIELD_CMP_COND_LE : FIELD_CMP_COND<0b00110>; -def FIELD_CMP_COND_ULE : FIELD_CMP_COND<0b00111>; -def FIELD_CMP_COND_SAF : FIELD_CMP_COND<0b01000>; -def FIELD_CMP_COND_SUN : FIELD_CMP_COND<0b01001>; -def FIELD_CMP_COND_SEQ : FIELD_CMP_COND<0b01010>; -def FIELD_CMP_COND_SUEQ : FIELD_CMP_COND<0b01011>; -def FIELD_CMP_COND_SLT : FIELD_CMP_COND<0b01100>; -def FIELD_CMP_COND_SULT : FIELD_CMP_COND<0b01101>; -def FIELD_CMP_COND_SLE : FIELD_CMP_COND<0b01110>; -def FIELD_CMP_COND_SULE : FIELD_CMP_COND<0b01111>; - -class FIELD_CMP_FORMAT<bits<5> Val> { - bits<5> Value = Val; -} -def FIELD_CMP_FORMAT_S : FIELD_CMP_FORMAT<0b10100>; -def FIELD_CMP_FORMAT_D : FIELD_CMP_FORMAT<0b10101>; - -//===----------------------------------------------------------------------===// -// -// Disambiguators -// -//===----------------------------------------------------------------------===// -// -// Some encodings are ambiguous except by comparing field values. - -class DecodeDisambiguates<string Name> { - string DecoderMethod = !strconcat("Decode", Name); -} - -class DecodeDisambiguatedBy<string Name> : DecodeDisambiguates<Name> { - string DecoderNamespace = "Mips32r6_64r6_Ambiguous"; -} - -//===----------------------------------------------------------------------===// -// -// Encoding Formats -// -//===----------------------------------------------------------------------===// - -class AUI_FM : MipsR6Inst { - bits<5> rs; - bits<5> rt; - bits<16> imm; - - bits<32> Inst; - - let Inst{31-26} = OPGROUP_AUI.Value; - let Inst{25-21} = rs; - let Inst{20-16} = rt; - let Inst{15-0} = imm; -} - -class DAUI_FM : AUI_FM { - let Inst{31-26} = OPGROUP_DAUI.Value; -} - -class BAL_FM : MipsR6Inst { - bits<16> offset; - - bits<32> Inst; - - let Inst{31-26} = OPGROUP_REGIMM.Value; - let Inst{25-21} = 0b00000; - let Inst{20-16} = OPCODE5_BGEZAL.Value; - let Inst{15-0} = offset; -} - -class COP0_EVP_DVP_FM<bits<1> sc> : MipsR6Inst { - bits<5> rt; - - bits<32> Inst; - - let Inst{31-26} = OPGROUP_COP0.Value; - let Inst{25-21} = 0b01011; - let Inst{20-16} = rt; - let Inst{15-11} = 0b00000; - let Inst{10-6} = 0b00000; - let Inst{5} = sc; - let Inst{4-3} = 0b00; - let Inst{2-0} = 0b100; -} - -class COP1_2R_FM<bits<6> funct, FIELD_FMT Format> : MipsR6Inst { - bits<5> fs; - bits<5> fd; - - bits<32> Inst; - - let Inst{31-26} = OPGROUP_COP1.Value; - let Inst{25-21} = Format.Value; - let Inst{20-16} = 0b00000; - let Inst{15-11} = fs; - let Inst{10-6} = fd; - let Inst{5-0} = funct; -} - -class COP1_3R_FM<bits<6> funct, FIELD_FMT Format> : MipsR6Inst { - bits<5> ft; - bits<5> fs; - bits<5> fd; - - bits<32> Inst; - - let Inst{31-26} = OPGROUP_COP1.Value; - let Inst{25-21} = Format.Value; - let Inst{20-16} = ft; - let Inst{15-11} = fs; - let Inst{10-6} = fd; - let Inst{5-0} = funct; -} - -class COP1_BCCZ_FM<OPCODE5 Operation> : MipsR6Inst { - bits<5> ft; - bits<16> offset; - - bits<32> Inst; - - let Inst{31-26} = OPGROUP_COP1.Value; - let Inst{25-21} = Operation.Value; - let Inst{20-16} = ft; - let Inst{15-0} = offset; -} - -class COP2_BCCZ_FM<OPCODE5 Operation> : MipsR6Inst { - bits<5> ct; - bits<16> offset; - - bits<32> Inst; - - let Inst{31-26} = OPGROUP_COP2.Value; - let Inst{25-21} = Operation.Value; - let Inst{20-16} = ct; - let Inst{15-0} = offset; -} - -class PCREL16_FM<OPCODE5 Operation> : MipsR6Inst { - bits<5> rs; - bits<16> imm; - - bits<32> Inst; - - let Inst{31-26} = OPGROUP_PCREL.Value; - let Inst{25-21} = rs; - let Inst{20-16} = Operation.Value; - let Inst{15-0} = imm; -} - -class PCREL19_FM<OPCODE2 Operation> : MipsR6Inst { - bits<5> rs; - bits<19> imm; - - bits<32> Inst; - - let Inst{31-26} = OPGROUP_PCREL.Value; - let Inst{25-21} = rs; - let Inst{20-19} = Operation.Value; - let Inst{18-0} = imm; -} - -class PCREL18_FM<OPCODE3 Operation> : MipsR6Inst { - bits<5> rs; - bits<18> imm; - - bits<32> Inst; - - let Inst{31-26} = OPGROUP_PCREL.Value; - let Inst{25-21} = rs; - let Inst{20-18} = Operation.Value; - let Inst{17-0} = imm; -} - -class SPECIAL3_2R_FM<OPCODE6 Operation> : MipsR6Inst { - bits<5> rd; - bits<5> rt; - - bits<32> Inst; - - let Inst{31-26} = OPGROUP_SPECIAL3.Value; - let Inst{25-21} = 0b00000; - let Inst{20-16} = rt; - let Inst{15-11} = rd; - let Inst{10-6} = 0b00000; - let Inst{5-0} = Operation.Value; -} - -class SPECIAL3_MEM_FM<OPCODE6 Operation> : MipsR6Inst { - bits<21> addr; - bits<5> hint; - bits<5> base = addr{20-16}; - bits<9> offset = addr{8-0}; - - bits<32> Inst; - - let Inst{31-26} = OPGROUP_SPECIAL3.Value; - let Inst{25-21} = base; - let Inst{20-16} = hint; - let Inst{15-7} = offset; - let Inst{6} = 0; - let Inst{5-0} = Operation.Value; -} - -class SPECIAL_2R_FM<OPCODE6 Operation> : MipsR6Inst { - bits<5> rd; - bits<5> rs; - - bits<32> Inst; - - let Inst{31-26} = OPGROUP_SPECIAL.Value; - let Inst{25-21} = rs; - let Inst{20-16} = 0b00000; - let Inst{15-11} = rd; - let Inst{10-6} = 0b00001; - let Inst{5-0} = Operation.Value; -} - -class SPECIAL_3R_FM<bits<5> mulop, bits<6> funct> : MipsR6Inst { - bits<5> rd; - bits<5> rs; - bits<5> rt; - - bits<32> Inst; - - let Inst{31-26} = OPGROUP_SPECIAL.Value; - let Inst{25-21} = rs; - let Inst{20-16} = rt; - let Inst{15-11} = rd; - let Inst{10-6} = mulop; - let Inst{5-0} = funct; -} - -class SPECIAL_SDBBP_FM : MipsR6Inst { - bits<20> code_; - - bits<32> Inst; - - let Inst{31-26} = OPGROUP_SPECIAL.Value; - let Inst{25-6} = code_; - let Inst{5-0} = OPCODE6_SDBBP.Value; -} - -// This class is ambiguous with other branches: -// BEQC/BNEC require that rs < rt && rs != 0 -class CMP_BRANCH_2R_OFF16_FM<OPGROUP funct> : MipsR6Inst { - bits<5> rs; - bits<5> rt; - bits<16> offset; - - bits<32> Inst; - - let Inst{31-26} = funct.Value; - let Inst{25-21} = rs; - let Inst{20-16} = rt; - let Inst{15-0} = offset; -} - -// This class is ambiguous with other branches: -// BLEZC/BGEZC/BEQZALC/BNEZALC/BGTZALC require that rs == 0 && rt != 0 -// The '1R_RT' in the name means 1 register in the rt field. -class CMP_BRANCH_1R_RT_OFF16_FM<OPGROUP funct> : MipsR6Inst { - bits<5> rt; - bits<16> offset; - - bits<32> Inst; - - let Inst{31-26} = funct.Value; - let Inst{25-21} = 0b00000; - let Inst{20-16} = rt; - let Inst{15-0} = offset; -} - -// This class is ambiguous with other branches: -// BLTZC/BGTZC/BLTZALC/BGEZALC require that rs == rt && rt != 0 -// The '1R_BOTH' in the name means 1 register in both the rs and rt fields. -class CMP_BRANCH_1R_BOTH_OFF16_FM<OPGROUP funct> : MipsR6Inst { - bits<5> rt; - bits<16> offset; - - bits<32> Inst; - - let Inst{31-26} = funct.Value; - let Inst{25-21} = rt; - let Inst{20-16} = rt; - let Inst{15-0} = offset; -} - -class CMP_BRANCH_OFF21_FM<bits<6> funct> : MipsR6Inst { - bits<5> rs; // rs != 0 - bits<21> offset; - - bits<32> Inst; - - let Inst{31-26} = funct; - let Inst{25-21} = rs; - let Inst{20-0} = offset; -} - -class JMP_IDX_COMPACT_FM<bits<6> funct> : MipsR6Inst { - bits<5> rt; - bits<16> offset; - - bits<32> Inst; - - let Inst{31-26} = funct; - let Inst{25-21} = 0b00000; - let Inst{20-16} = rt; - let Inst{15-0} = offset; -} - -class BRANCH_OFF26_FM<bits<6> funct> : MipsR6Inst { - bits<32> Inst; - bits<26> offset; - - let Inst{31-26} = funct; - let Inst{25-0} = offset; -} - -class SPECIAL3_ALIGN_FM<OPCODE6 Operation> : MipsR6Inst { - bits<5> rd; - bits<5> rs; - bits<5> rt; - bits<2> bp; - - bits<32> Inst; - - let Inst{31-26} = OPGROUP_SPECIAL3.Value; - let Inst{25-21} = rs; - let Inst{20-16} = rt; - let Inst{15-11} = rd; - let Inst{10-8} = 0b010; - let Inst{7-6} = bp; - let Inst{5-0} = Operation.Value; -} - -class SPECIAL3_DALIGN_FM<OPCODE6 Operation> : MipsR6Inst { - bits<5> rd; - bits<5> rs; - bits<5> rt; - bits<3> bp; - - bits<32> Inst; - - let Inst{31-26} = OPGROUP_SPECIAL3.Value; - let Inst{25-21} = rs; - let Inst{20-16} = rt; - let Inst{15-11} = rd; - let Inst{10-9} = 0b01; - let Inst{8-6} = bp; - let Inst{5-0} = Operation.Value; -} - -class SPECIAL3_LL_SC_FM<OPCODE6 Operation> : MipsR6Inst { - bits<5> rt; - bits<21> addr; - bits<5> base = addr{20-16}; - bits<9> offset = addr{8-0}; - - bits<32> Inst; - - let Inst{31-26} = OPGROUP_SPECIAL3.Value; - let Inst{25-21} = base; - let Inst{20-16} = rt; - let Inst{15-7} = offset; - let Inst{5-0} = Operation.Value; - - string DecoderMethod = "DecodeSpecial3LlSc"; -} - -class SPECIAL_LSA_FM<OPCODE6 Operation> : MipsR6Inst { - bits<5> rd; - bits<5> rs; - bits<5> rt; - bits<2> imm2; - - bits<32> Inst; - - let Inst{31-26} = OPGROUP_SPECIAL.Value; - let Inst{25-21} = rs; - let Inst{20-16} = rt; - let Inst{15-11} = rd; - let Inst{10-8} = 0b000; - let Inst{7-6} = imm2; - let Inst{5-0} = Operation.Value; -} - -class REGIMM_FM<OPCODE5 Operation> : MipsR6Inst { - bits<5> rs; - bits<16> imm; - - bits<32> Inst; - - let Inst{31-26} = OPGROUP_REGIMM.Value; - let Inst{25-21} = rs; - let Inst{20-16} = Operation.Value; - let Inst{15-0} = imm; -} - -class COP1_CMP_CONDN_FM<FIELD_CMP_FORMAT Format, - FIELD_CMP_COND Cond> : MipsR6Inst { - bits<5> fd; - bits<5> fs; - bits<5> ft; - - bits<32> Inst; - - let Inst{31-26} = OPGROUP_COP1.Value; - let Inst{25-21} = Format.Value; - let Inst{20-16} = ft; - let Inst{15-11} = fs; - let Inst{10-6} = fd; - let Inst{5} = 0; - let Inst{4-0} = Cond.Value; -} - -class JR_HB_R6_FM<OPCODE6 Operation> : MipsR6Inst { - bits<5> rs; - - bits<32> Inst; - - let Inst{31-26} = OPGROUP_SPECIAL.Value; - let Inst{25-21} = rs; - let Inst{20-16} = 0; - let Inst{15-11} = 0; - let Inst{10} = 1; - let Inst{9-6} = 0; - let Inst{5-0} = Operation.Value; -} - -class COP2LDST_FM<OPCODE5 Operation> : MipsR6Inst { - bits<5> rt; - bits<21> addr; - bits<5> base = addr{20-16}; - bits<11> offset = addr{10-0}; - - bits<32> Inst; - - let Inst{31-26} = OPGROUP_COP2LDST.Value; - let Inst{25-21} = Operation.Value; - let Inst{20-16} = rt; - let Inst{15-11} = base; - let Inst{10-0} = offset; -} - -class SPECIAL3_2R_SZ_CRC<bits<2> sz, bits<3> direction> : MipsR6Inst { - bits<5> rs; - bits<5> rt; - - let Inst{31-26} = OPGROUP_SPECIAL3.Value; - let Inst{25-21} = rs; - let Inst{20-16} = rt; - let Inst{15-11} = 0b00000; - let Inst{10-8} = direction; - let Inst{7-6} = sz; - let Inst{5-0} = 0b001111; - - string DecoderMethod = "DecodeCRC"; -} - -class SPECIAL3_GINV<bits<2> ginv> : MipsR6Inst { - bits<5> rs; - bits<2> type_; - - let Inst{31-26} = OPGROUP_SPECIAL3.Value; - let Inst{25-21} = rs; - let Inst{20-10} = 0x0; - let Inst{9-8} = type_; - let Inst{7-6} = ginv; - let Inst{5-0} = 0b111101; -} - -class SIGRIE_FM : MipsR6Inst { - bits<16> code_; - - let Inst{31-26} = OPGROUP_REGIMM.Value; - let Inst{25-21} = 0; - let Inst{20-16} = OPCODE5_SIGRIE.Value; - let Inst{15-0} = code_; -} diff --git a/contrib/llvm/lib/Target/Mips/Mips32r6InstrInfo.td b/contrib/llvm/lib/Target/Mips/Mips32r6InstrInfo.td deleted file mode 100644 index 2c3048411a5c..000000000000 --- a/contrib/llvm/lib/Target/Mips/Mips32r6InstrInfo.td +++ /dev/null @@ -1,1139 +0,0 @@ -//=- Mips32r6InstrInfo.td - Mips32r6 Instruction Information -*- tablegen -*-=// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file describes Mips32r6 instructions. -// -//===----------------------------------------------------------------------===// - -include "Mips32r6InstrFormats.td" - -//===----------------------------------------------------------------------===// -// -// Mips profiles and nodes -// -//===----------------------------------------------------------------------===// - -def SDT_MipsFSelect : SDTypeProfile<1, 3, [SDTCisFP<1>, - SDTCisSameAs<0,2>, - SDTCisSameAs<2,3>]>; - -def MipsFSelect : SDNode<"MipsISD::FSELECT", SDT_MipsFSelect>; - -//===----------------------------------------------------------------------===// -// -// Mips Operands -// -//===----------------------------------------------------------------------===// - -// Notes about removals/changes from MIPS32r6: -// Reencoded: jr -> jalr -// Reencoded: jr.hb -> jalr.hb - -def brtarget21 : Operand<OtherVT> { - let EncoderMethod = "getBranchTarget21OpValue"; - let OperandType = "OPERAND_PCREL"; - let DecoderMethod = "DecodeBranchTarget21"; - let ParserMatchClass = MipsJumpTargetAsmOperand; -} - -def brtarget26 : Operand<OtherVT> { - let EncoderMethod = "getBranchTarget26OpValue"; - let OperandType = "OPERAND_PCREL"; - let DecoderMethod = "DecodeBranchTarget26"; - let ParserMatchClass = MipsJumpTargetAsmOperand; -} - -def jmpoffset16 : Operand<OtherVT> { - let EncoderMethod = "getJumpOffset16OpValue"; - let ParserMatchClass = MipsJumpTargetAsmOperand; -} - -def calloffset16 : Operand<iPTR> { - let EncoderMethod = "getJumpOffset16OpValue"; - let ParserMatchClass = MipsJumpTargetAsmOperand; -} - -//===----------------------------------------------------------------------===// -// -// Instruction Encodings -// -//===----------------------------------------------------------------------===// - -class ADDIUPC_ENC : PCREL19_FM<OPCODE2_ADDIUPC>; -class ALIGN_ENC : SPECIAL3_ALIGN_FM<OPCODE6_ALIGN>; -class ALUIPC_ENC : PCREL16_FM<OPCODE5_ALUIPC>; -class AUI_ENC : AUI_FM; -class AUIPC_ENC : PCREL16_FM<OPCODE5_AUIPC>; - -class BAL_ENC : BAL_FM; -class BALC_ENC : BRANCH_OFF26_FM<0b111010>; -class BC_ENC : BRANCH_OFF26_FM<0b110010>; -class BEQC_ENC : CMP_BRANCH_2R_OFF16_FM<OPGROUP_ADDI>, - DecodeDisambiguates<"AddiGroupBranch">; -class BEQZALC_ENC : CMP_BRANCH_1R_RT_OFF16_FM<OPGROUP_ADDI>, - DecodeDisambiguatedBy<"DaddiGroupBranch">; -class BNEC_ENC : CMP_BRANCH_2R_OFF16_FM<OPGROUP_DADDI>, - DecodeDisambiguates<"DaddiGroupBranch">; -class BNEZALC_ENC : CMP_BRANCH_1R_RT_OFF16_FM<OPGROUP_DADDI>, - DecodeDisambiguatedBy<"DaddiGroupBranch">; - -class BLTZC_ENC : CMP_BRANCH_1R_BOTH_OFF16_FM<OPGROUP_BGTZL>, - DecodeDisambiguates<"BgtzlGroupBranch">; -class BGEC_ENC : CMP_BRANCH_2R_OFF16_FM<OPGROUP_BLEZL>, - DecodeDisambiguatedBy<"BlezlGroupBranch">; -class BGEUC_ENC : CMP_BRANCH_2R_OFF16_FM<OPGROUP_BLEZ>, - DecodeDisambiguatedBy<"BlezGroupBranch">; -class BGEZC_ENC : CMP_BRANCH_1R_BOTH_OFF16_FM<OPGROUP_BLEZL>, - DecodeDisambiguates<"BlezlGroupBranch">; -class BGTZALC_ENC : CMP_BRANCH_1R_RT_OFF16_FM<OPGROUP_BGTZ>, - DecodeDisambiguatedBy<"BgtzGroupBranch">; - -class BLTC_ENC : CMP_BRANCH_2R_OFF16_FM<OPGROUP_BGTZL>, - DecodeDisambiguatedBy<"BgtzlGroupBranch">; -class BLTUC_ENC : CMP_BRANCH_2R_OFF16_FM<OPGROUP_BGTZ>, - DecodeDisambiguatedBy<"BgtzGroupBranch">; - -class BLEZC_ENC : CMP_BRANCH_1R_RT_OFF16_FM<OPGROUP_BLEZL>, - DecodeDisambiguatedBy<"BlezlGroupBranch">; -class BLTZALC_ENC : CMP_BRANCH_1R_BOTH_OFF16_FM<OPGROUP_BGTZ>, - DecodeDisambiguates<"BgtzGroupBranch">; -class BGTZC_ENC : CMP_BRANCH_1R_RT_OFF16_FM<OPGROUP_BGTZL>, - DecodeDisambiguatedBy<"BgtzlGroupBranch">; - -class BEQZC_ENC : CMP_BRANCH_OFF21_FM<0b110110>; -class BGEZALC_ENC : CMP_BRANCH_1R_BOTH_OFF16_FM<OPGROUP_BLEZ>, - DecodeDisambiguates<"BlezGroupBranch">; -class BNEZC_ENC : CMP_BRANCH_OFF21_FM<0b111110>; - -class BC1EQZ_ENC : COP1_BCCZ_FM<OPCODE5_BC1EQZ>; -class BC1NEZ_ENC : COP1_BCCZ_FM<OPCODE5_BC1NEZ>; -class BC2EQZ_ENC : COP2_BCCZ_FM<OPCODE5_BC2EQZ>; -class BC2NEZ_ENC : COP2_BCCZ_FM<OPCODE5_BC2NEZ>; - -class DVP_ENC : COP0_EVP_DVP_FM<0b1>; -class EVP_ENC : COP0_EVP_DVP_FM<0b0>; - -class JIALC_ENC : JMP_IDX_COMPACT_FM<0b111110>; -class JIC_ENC : JMP_IDX_COMPACT_FM<0b110110>; -class JR_HB_R6_ENC : JR_HB_R6_FM<OPCODE6_JALR>; -class BITSWAP_ENC : SPECIAL3_2R_FM<OPCODE6_BITSWAP>; -class BLEZALC_ENC : CMP_BRANCH_1R_RT_OFF16_FM<OPGROUP_BLEZ>, - DecodeDisambiguatedBy<"BlezGroupBranch">; -class BNVC_ENC : CMP_BRANCH_2R_OFF16_FM<OPGROUP_DADDI>, - DecodeDisambiguatedBy<"DaddiGroupBranch">; -class BOVC_ENC : CMP_BRANCH_2R_OFF16_FM<OPGROUP_ADDI>, - DecodeDisambiguatedBy<"AddiGroupBranch">; -class DIV_ENC : SPECIAL_3R_FM<0b00010, 0b011010>; -class DIVU_ENC : SPECIAL_3R_FM<0b00010, 0b011011>; -class MOD_ENC : SPECIAL_3R_FM<0b00011, 0b011010>; -class MODU_ENC : SPECIAL_3R_FM<0b00011, 0b011011>; -class MUH_ENC : SPECIAL_3R_FM<0b00011, 0b011000>; -class MUHU_ENC : SPECIAL_3R_FM<0b00011, 0b011001>; -class MUL_R6_ENC : SPECIAL_3R_FM<0b00010, 0b011000>; -class MULU_ENC : SPECIAL_3R_FM<0b00010, 0b011001>; - -class MADDF_S_ENC : COP1_3R_FM<0b011000, FIELD_FMT_S>; -class MADDF_D_ENC : COP1_3R_FM<0b011000, FIELD_FMT_D>; -class MSUBF_S_ENC : COP1_3R_FM<0b011001, FIELD_FMT_S>; -class MSUBF_D_ENC : COP1_3R_FM<0b011001, FIELD_FMT_D>; - -class SEL_D_ENC : COP1_3R_FM<0b010000, FIELD_FMT_D>; -class SEL_S_ENC : COP1_3R_FM<0b010000, FIELD_FMT_S>; - -class SELEQZ_ENC : SPECIAL_3R_FM<0b00000, 0b110101>; -class SELNEZ_ENC : SPECIAL_3R_FM<0b00000, 0b110111>; - -class LWPC_ENC : PCREL19_FM<OPCODE2_LWPC>; - -class MAX_S_ENC : COP1_3R_FM<0b011101, FIELD_FMT_S>; -class MAX_D_ENC : COP1_3R_FM<0b011101, FIELD_FMT_D>; -class MIN_S_ENC : COP1_3R_FM<0b011100, FIELD_FMT_S>; -class MIN_D_ENC : COP1_3R_FM<0b011100, FIELD_FMT_D>; - -class MAXA_S_ENC : COP1_3R_FM<0b011111, FIELD_FMT_S>; -class MAXA_D_ENC : COP1_3R_FM<0b011111, FIELD_FMT_D>; -class MINA_S_ENC : COP1_3R_FM<0b011110, FIELD_FMT_S>; -class MINA_D_ENC : COP1_3R_FM<0b011110, FIELD_FMT_D>; - -class SELEQZ_S_ENC : COP1_3R_FM<0b010100, FIELD_FMT_S>; -class SELEQZ_D_ENC : COP1_3R_FM<0b010100, FIELD_FMT_D>; -class SELNEZ_S_ENC : COP1_3R_FM<0b010111, FIELD_FMT_S>; -class SELNEZ_D_ENC : COP1_3R_FM<0b010111, FIELD_FMT_D>; - -class RINT_S_ENC : COP1_2R_FM<0b011010, FIELD_FMT_S>; -class RINT_D_ENC : COP1_2R_FM<0b011010, FIELD_FMT_D>; -class CLASS_S_ENC : COP1_2R_FM<0b011011, FIELD_FMT_S>; -class CLASS_D_ENC : COP1_2R_FM<0b011011, FIELD_FMT_D>; - -class CACHE_ENC : SPECIAL3_MEM_FM<OPCODE6_CACHE>; -class PREF_ENC : SPECIAL3_MEM_FM<OPCODE6_PREF>; - -class LDC2_R6_ENC : COP2LDST_FM<OPCODE5_LDC2>; -class LWC2_R6_ENC : COP2LDST_FM<OPCODE5_LWC2>; -class SDC2_R6_ENC : COP2LDST_FM<OPCODE5_SDC2>; -class SWC2_R6_ENC : COP2LDST_FM<OPCODE5_SWC2>; - -class LSA_R6_ENC : SPECIAL_LSA_FM<OPCODE6_LSA>; - -class LL_R6_ENC : SPECIAL3_LL_SC_FM<OPCODE6_LL>; -class SC_R6_ENC : SPECIAL3_LL_SC_FM<OPCODE6_SC>; - -class CLO_R6_ENC : SPECIAL_2R_FM<OPCODE6_CLO>; -class CLZ_R6_ENC : SPECIAL_2R_FM<OPCODE6_CLZ>; - -class SDBBP_R6_ENC : SPECIAL_SDBBP_FM; - -class CRC32B_ENC : SPECIAL3_2R_SZ_CRC<0,0>; -class CRC32H_ENC : SPECIAL3_2R_SZ_CRC<1,0>; -class CRC32W_ENC : SPECIAL3_2R_SZ_CRC<2,0>; -class CRC32CB_ENC : SPECIAL3_2R_SZ_CRC<0,1>; -class CRC32CH_ENC : SPECIAL3_2R_SZ_CRC<1,1>; -class CRC32CW_ENC : SPECIAL3_2R_SZ_CRC<2,1>; - -class GINVI_ENC : SPECIAL3_GINV<0>; -class GINVT_ENC : SPECIAL3_GINV<2>; - -class SIGRIE_ENC : SIGRIE_FM; - -//===----------------------------------------------------------------------===// -// -// Instruction Multiclasses -// -//===----------------------------------------------------------------------===// - -class CMP_CONDN_DESC_BASE<string CondStr, string Typestr, - RegisterOperand FGROpnd, - InstrItinClass Itin, - SDPatternOperator Op = null_frag> { - dag OutOperandList = (outs FGRCCOpnd:$fd); - dag InOperandList = (ins FGROpnd:$fs, FGROpnd:$ft); - string AsmString = !strconcat("cmp.", CondStr, ".", Typestr, "\t$fd, $fs, $ft"); - list<dag> Pattern = [(set FGRCCOpnd:$fd, (Op FGROpnd:$fs, FGROpnd:$ft))]; - bit isCTI = 1; - InstrItinClass Itinerary = Itin; -} - -multiclass CMP_CC_M <FIELD_CMP_FORMAT Format, string Typestr, - RegisterOperand FGROpnd, InstrItinClass Itin>{ - let AdditionalPredicates = [NotInMicroMips] in { - def CMP_F_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_AF>, - CMP_CONDN_DESC_BASE<"af", Typestr, FGROpnd, Itin>, - MipsR6Arch<!strconcat("cmp.af.", Typestr)>, - ISA_MIPS32R6, HARDFLOAT; - def CMP_UN_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_UN>, - CMP_CONDN_DESC_BASE<"un", Typestr, FGROpnd, Itin, setuo>, - MipsR6Arch<!strconcat("cmp.un.", Typestr)>, - ISA_MIPS32R6, HARDFLOAT; - def CMP_EQ_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_EQ>, - CMP_CONDN_DESC_BASE<"eq", Typestr, FGROpnd, Itin, - setoeq>, - MipsR6Arch<!strconcat("cmp.eq.", Typestr)>, - ISA_MIPS32R6, HARDFLOAT; - def CMP_UEQ_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format, - FIELD_CMP_COND_UEQ>, - CMP_CONDN_DESC_BASE<"ueq", Typestr, FGROpnd, Itin, - setueq>, - MipsR6Arch<!strconcat("cmp.ueq.", Typestr)>, - ISA_MIPS32R6, HARDFLOAT; - def CMP_LT_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_LT>, - CMP_CONDN_DESC_BASE<"lt", Typestr, FGROpnd, Itin, - setolt>, - MipsR6Arch<!strconcat("cmp.lt.", Typestr)>, - ISA_MIPS32R6, HARDFLOAT; - def CMP_ULT_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format, - FIELD_CMP_COND_ULT>, - CMP_CONDN_DESC_BASE<"ult", Typestr, FGROpnd, Itin, - setult>, - MipsR6Arch<!strconcat("cmp.ult.", Typestr)>, - ISA_MIPS32R6, HARDFLOAT; - def CMP_LE_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_LE>, - CMP_CONDN_DESC_BASE<"le", Typestr, FGROpnd, Itin, - setole>, - MipsR6Arch<!strconcat("cmp.le.", Typestr)>, - ISA_MIPS32R6, HARDFLOAT; - def CMP_ULE_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format, - FIELD_CMP_COND_ULE>, - CMP_CONDN_DESC_BASE<"ule", Typestr, FGROpnd, Itin, - setule>, - MipsR6Arch<!strconcat("cmp.ule.", Typestr)>, - ISA_MIPS32R6, HARDFLOAT; - def CMP_SAF_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format, - FIELD_CMP_COND_SAF>, - CMP_CONDN_DESC_BASE<"saf", Typestr, FGROpnd, Itin>, - MipsR6Arch<!strconcat("cmp.saf.", Typestr)>, - ISA_MIPS32R6, HARDFLOAT; - def CMP_SUN_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format, - FIELD_CMP_COND_SUN>, - CMP_CONDN_DESC_BASE<"sun", Typestr, FGROpnd, Itin>, - MipsR6Arch<!strconcat("cmp.sun.", Typestr)>, - ISA_MIPS32R6, HARDFLOAT; - def CMP_SEQ_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format, - FIELD_CMP_COND_SEQ>, - CMP_CONDN_DESC_BASE<"seq", Typestr, FGROpnd, Itin>, - MipsR6Arch<!strconcat("cmp.seq.", Typestr)>, - ISA_MIPS32R6, HARDFLOAT; - def CMP_SUEQ_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format, - FIELD_CMP_COND_SUEQ>, - CMP_CONDN_DESC_BASE<"sueq", Typestr, FGROpnd, Itin>, - MipsR6Arch<!strconcat("cmp.sueq.", Typestr)>, - ISA_MIPS32R6, HARDFLOAT; - def CMP_SLT_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format, - FIELD_CMP_COND_SLT>, - CMP_CONDN_DESC_BASE<"slt", Typestr, FGROpnd, Itin>, - MipsR6Arch<!strconcat("cmp.slt.", Typestr)>, - ISA_MIPS32R6, HARDFLOAT; - def CMP_SULT_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format, - FIELD_CMP_COND_SULT>, - CMP_CONDN_DESC_BASE<"sult", Typestr, FGROpnd, Itin>, - MipsR6Arch<!strconcat("cmp.sult.", Typestr)>, - ISA_MIPS32R6, HARDFLOAT; - def CMP_SLE_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format, - FIELD_CMP_COND_SLE>, - CMP_CONDN_DESC_BASE<"sle", Typestr, FGROpnd, Itin>, - MipsR6Arch<!strconcat("cmp.sle.", Typestr)>, - ISA_MIPS32R6, HARDFLOAT; - def CMP_SULE_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format, - FIELD_CMP_COND_SULE>, - CMP_CONDN_DESC_BASE<"sule", Typestr, FGROpnd, Itin>, - MipsR6Arch<!strconcat("cmp.sule.", Typestr)>, - ISA_MIPS32R6, HARDFLOAT; - } -} - -//===----------------------------------------------------------------------===// -// -// Instruction Descriptions -// -//===----------------------------------------------------------------------===// - -class PCREL_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, - Operand ImmOpnd, InstrItinClass itin> - : MipsR6Arch<instr_asm> { - dag OutOperandList = (outs GPROpnd:$rs); - dag InOperandList = (ins ImmOpnd:$imm); - string AsmString = !strconcat(instr_asm, "\t$rs, $imm"); - list<dag> Pattern = []; - InstrItinClass Itinerary = itin; -} - -class ADDIUPC_DESC : PCREL_DESC_BASE<"addiupc", GPR32Opnd, simm19_lsl2, - II_ADDIUPC>; -class LWPC_DESC: PCREL_DESC_BASE<"lwpc", GPR32Opnd, simm19_lsl2, II_LWPC>; - -class ALIGN_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, - Operand ImmOpnd, InstrItinClass itin> - : MipsR6Arch<instr_asm> { - dag OutOperandList = (outs GPROpnd:$rd); - dag InOperandList = (ins GPROpnd:$rs, GPROpnd:$rt, ImmOpnd:$bp); - string AsmString = !strconcat(instr_asm, "\t$rd, $rs, $rt, $bp"); - list<dag> Pattern = []; - InstrItinClass Itinerary = itin; -} - -class ALIGN_DESC : ALIGN_DESC_BASE<"align", GPR32Opnd, uimm2, II_ALIGN>; - -class ALUIPC_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, - InstrItinClass itin = NoItinerary> - : MipsR6Arch<instr_asm> { - dag OutOperandList = (outs GPROpnd:$rs); - dag InOperandList = (ins simm16:$imm); - string AsmString = !strconcat(instr_asm, "\t$rs, $imm"); - list<dag> Pattern = []; - InstrItinClass Itinerary = itin; -} - -class ALUIPC_DESC : ALUIPC_DESC_BASE<"aluipc", GPR32Opnd, II_ALUIPC>; -class AUIPC_DESC : ALUIPC_DESC_BASE<"auipc", GPR32Opnd, II_AUIPC>; - -class AUI_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, - InstrItinClass itin = NoItinerary> - : MipsR6Arch<instr_asm> { - dag OutOperandList = (outs GPROpnd:$rt); - dag InOperandList = (ins GPROpnd:$rs, uimm16:$imm); - string AsmString = !strconcat(instr_asm, "\t$rt, $rs, $imm"); - list<dag> Pattern = []; - InstrItinClass Itinerary = itin; -} - -class AUI_DESC : AUI_DESC_BASE<"aui", GPR32Opnd, II_AUI>; - -class BRANCH_DESC_BASE { - bit isBranch = 1; - bit isTerminator = 1; - bit hasDelaySlot = 0; - bit isCTI = 1; -} - -class BC_DESC_BASE<string instr_asm, DAGOperand opnd> : BRANCH_DESC_BASE, - MipsR6Arch<instr_asm> { - dag InOperandList = (ins opnd:$offset); - dag OutOperandList = (outs); - string AsmString = !strconcat(instr_asm, "\t$offset"); - bit isBarrier = 1; - InstrItinClass Itinerary = II_BC; - bit isCTI = 1; -} - -class CMP_BC_DESC_BASE<string instr_asm, DAGOperand opnd, - RegisterOperand GPROpnd> : BRANCH_DESC_BASE, - MipsR6Arch<instr_asm> { - dag InOperandList = (ins GPROpnd:$rs, GPROpnd:$rt, opnd:$offset); - dag OutOperandList = (outs); - string AsmString = !strconcat(instr_asm, "\t$rs, $rt, $offset"); - list<Register> Defs = [AT]; - InstrItinClass Itinerary = II_BCCC; - bit hasForbiddenSlot = 1; - bit isCTI = 1; -} - -class CMP_CBR_EQNE_Z_DESC_BASE<string instr_asm, DAGOperand opnd, - RegisterOperand GPROpnd> - : BRANCH_DESC_BASE, MipsR6Arch<instr_asm> { - dag InOperandList = (ins GPROpnd:$rs, opnd:$offset); - dag OutOperandList = (outs); - string AsmString = !strconcat(instr_asm, "\t$rs, $offset"); - list<Register> Defs = [AT]; - InstrItinClass Itinerary = II_BCCZC; - bit hasForbiddenSlot = 1; - bit isCTI = 1; -} - -class CMP_CBR_RT_Z_DESC_BASE<string instr_asm, DAGOperand opnd, - RegisterOperand GPROpnd> - : BRANCH_DESC_BASE, MipsR6Arch<instr_asm> { - dag InOperandList = (ins GPROpnd:$rt, opnd:$offset); - dag OutOperandList = (outs); - string AsmString = !strconcat(instr_asm, "\t$rt, $offset"); - list<Register> Defs = [AT]; - InstrItinClass Itinerary = II_BCCZC; - bit hasForbiddenSlot = 1; - bit isCTI = 1; -} - -class BAL_DESC : BC_DESC_BASE<"bal", brtarget> { - bit isCall = 1; - bit hasDelaySlot = 1; - list<Register> Defs = [RA]; - bit isCTI = 1; -} - -class BALC_DESC : BC_DESC_BASE<"balc", brtarget26> { - bit isCall = 1; - list<Register> Defs = [RA]; - InstrItinClass Itinerary = II_BALC; - bit isCTI = 1; -} - -class BC_DESC : BC_DESC_BASE<"bc", brtarget26>; -class BGEC_DESC : CMP_BC_DESC_BASE<"bgec", brtarget, GPR32Opnd>; -class BGEUC_DESC : CMP_BC_DESC_BASE<"bgeuc", brtarget, GPR32Opnd>; -class BEQC_DESC : CMP_BC_DESC_BASE<"beqc", brtarget, GPR32Opnd>; -class BNEC_DESC : CMP_BC_DESC_BASE<"bnec", brtarget, GPR32Opnd>; - -class BLTC_DESC : CMP_BC_DESC_BASE<"bltc", brtarget, GPR32Opnd>; -class BLTUC_DESC : CMP_BC_DESC_BASE<"bltuc", brtarget, GPR32Opnd>; - -class BLTZC_DESC : CMP_CBR_RT_Z_DESC_BASE<"bltzc", brtarget, GPR32Opnd>; -class BGEZC_DESC : CMP_CBR_RT_Z_DESC_BASE<"bgezc", brtarget, GPR32Opnd>; - -class BLEZC_DESC : CMP_CBR_RT_Z_DESC_BASE<"blezc", brtarget, GPR32Opnd>; -class BGTZC_DESC : CMP_CBR_RT_Z_DESC_BASE<"bgtzc", brtarget, GPR32Opnd>; - -class BEQZC_DESC : CMP_CBR_EQNE_Z_DESC_BASE<"beqzc", brtarget21, GPR32Opnd>; -class BNEZC_DESC : CMP_CBR_EQNE_Z_DESC_BASE<"bnezc", brtarget21, GPR32Opnd>; - -class COP1_BCCZ_DESC_BASE<string instr_asm> : BRANCH_DESC_BASE { - dag InOperandList = (ins FGR64Opnd:$ft, brtarget:$offset); - dag OutOperandList = (outs); - string AsmString = instr_asm; - bit hasDelaySlot = 1; - InstrItinClass Itinerary = II_BC1CCZ; -} - -class BC1EQZ_DESC : COP1_BCCZ_DESC_BASE<"bc1eqz $ft, $offset">; -class BC1NEZ_DESC : COP1_BCCZ_DESC_BASE<"bc1nez $ft, $offset">; - -class COP2_BCCZ_DESC_BASE<string instr_asm> : BRANCH_DESC_BASE { - dag InOperandList = (ins COP2Opnd:$ct, brtarget:$offset); - dag OutOperandList = (outs); - string AsmString = instr_asm; - bit hasDelaySlot = 1; - bit isCTI = 1; - InstrItinClass Itinerary = II_BC2CCZ; -} - -class BC2EQZ_DESC : COP2_BCCZ_DESC_BASE<"bc2eqz $ct, $offset">; -class BC2NEZ_DESC : COP2_BCCZ_DESC_BASE<"bc2nez $ct, $offset">; - -class BOVC_DESC : CMP_BC_DESC_BASE<"bovc", brtarget, GPR32Opnd>; -class BNVC_DESC : CMP_BC_DESC_BASE<"bnvc", brtarget, GPR32Opnd>; - -class JMP_IDX_COMPACT_DESC_BASE<string opstr, DAGOperand opnd, - RegisterOperand GPROpnd, - InstrItinClass itin = NoItinerary> - : MipsR6Arch<opstr> { - dag InOperandList = (ins GPROpnd:$rt, opnd:$offset); - string AsmString = !strconcat(opstr, "\t$rt, $offset"); - list<dag> Pattern = []; - bit hasDelaySlot = 0; - InstrItinClass Itinerary = itin; - bit isCTI = 1; - bit isBranch = 1; - bit isIndirectBranch = 1; -} - -class JIALC_DESC : JMP_IDX_COMPACT_DESC_BASE<"jialc", calloffset16, - GPR32Opnd, II_JIALC> { - bit isCall = 1; - list<Register> Defs = [RA]; -} - -class JIC_DESC : JMP_IDX_COMPACT_DESC_BASE<"jic", jmpoffset16, - GPR32Opnd, II_JIALC> { - bit isBarrier = 1; - bit isTerminator = 1; - list<Register> Defs = [AT]; -} - -class JR_HB_R6_DESC : JR_HB_DESC_BASE<"jr.hb", GPR32Opnd> { - bit isBranch = 1; - bit isIndirectBranch = 1; - bit hasDelaySlot = 1; - bit isTerminator=1; - bit isBarrier=1; - bit isCTI = 1; - InstrItinClass Itinerary = II_JR_HB; -} - -class BITSWAP_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, - InstrItinClass itin> - : MipsR6Arch<instr_asm> { - dag OutOperandList = (outs GPROpnd:$rd); - dag InOperandList = (ins GPROpnd:$rt); - string AsmString = !strconcat(instr_asm, "\t$rd, $rt"); - list<dag> Pattern = []; - InstrItinClass Itinerary = itin; -} - -class BITSWAP_DESC : BITSWAP_DESC_BASE<"bitswap", GPR32Opnd, II_BITSWAP>; - -class DIVMOD_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, - InstrItinClass itin, - SDPatternOperator Op=null_frag> - : MipsR6Arch<instr_asm> { - dag OutOperandList = (outs GPROpnd:$rd); - dag InOperandList = (ins GPROpnd:$rs, GPROpnd:$rt); - string AsmString = !strconcat(instr_asm, "\t$rd, $rs, $rt"); - list<dag> Pattern = [(set GPROpnd:$rd, (Op GPROpnd:$rs, GPROpnd:$rt))]; - InstrItinClass Itinerary = itin; - // This instruction doesn't trap division by zero itself. We must insert - // teq instructions as well. - bit usesCustomInserter = 1; -} - -class DVPEVP_DESC_BASE<string instr_asm, InstrItinClass Itin> - : MipsR6Arch<instr_asm> { - dag OutOperandList = (outs GPR32Opnd:$rt); - dag InOperandList = (ins); - string AsmString = !strconcat(instr_asm, "\t$rt"); - list<dag> Pattern = []; - InstrItinClass Itinerary = Itin; - bit hasUnModeledSideEffects = 1; -} - -class DVP_DESC : DVPEVP_DESC_BASE<"dvp", II_DVP>; -class EVP_DESC : DVPEVP_DESC_BASE<"evp", II_EVP>; - -class DIV_DESC : DIVMOD_DESC_BASE<"div", GPR32Opnd, II_DIV, sdiv>; -class DIVU_DESC : DIVMOD_DESC_BASE<"divu", GPR32Opnd, II_DIVU, udiv>; -class MOD_DESC : DIVMOD_DESC_BASE<"mod", GPR32Opnd, II_MOD, srem>; -class MODU_DESC : DIVMOD_DESC_BASE<"modu", GPR32Opnd, II_MODU, urem>; - -class BEQZALC_DESC : CMP_CBR_RT_Z_DESC_BASE<"beqzalc", brtarget, GPR32Opnd> { - list<Register> Defs = [RA]; -} - -class BGEZALC_DESC : CMP_CBR_RT_Z_DESC_BASE<"bgezalc", brtarget, GPR32Opnd> { - list<Register> Defs = [RA]; -} - -class BGTZALC_DESC : CMP_CBR_RT_Z_DESC_BASE<"bgtzalc", brtarget, GPR32Opnd> { - list<Register> Defs = [RA]; -} - -class BLEZALC_DESC : CMP_CBR_RT_Z_DESC_BASE<"blezalc", brtarget, GPR32Opnd> { - list<Register> Defs = [RA]; -} - -class BLTZALC_DESC : CMP_CBR_RT_Z_DESC_BASE<"bltzalc", brtarget, GPR32Opnd> { - list<Register> Defs = [RA]; -} - -class BNEZALC_DESC : CMP_CBR_RT_Z_DESC_BASE<"bnezalc", brtarget, GPR32Opnd> { - list<Register> Defs = [RA]; -} - -class MUL_R6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, - InstrItinClass itin, - SDPatternOperator Op=null_frag> : MipsR6Arch<instr_asm> { - dag OutOperandList = (outs GPROpnd:$rd); - dag InOperandList = (ins GPROpnd:$rs, GPROpnd:$rt); - string AsmString = !strconcat(instr_asm, "\t$rd, $rs, $rt"); - list<dag> Pattern = [(set GPROpnd:$rd, (Op GPROpnd:$rs, GPROpnd:$rt))]; - InstrItinClass Itinerary = itin; -} - -class MUH_DESC : MUL_R6_DESC_BASE<"muh", GPR32Opnd, II_MUH, mulhs>; -class MUHU_DESC : MUL_R6_DESC_BASE<"muhu", GPR32Opnd, II_MUHU, mulhu>; -class MUL_R6_DESC : MUL_R6_DESC_BASE<"mul", GPR32Opnd, II_MUL, mul>; -class MULU_DESC : MUL_R6_DESC_BASE<"mulu", GPR32Opnd, II_MULU>; - -class COP1_SEL_DESC_BASE<string instr_asm, RegisterOperand FGROpnd, - InstrItinClass itin> { - dag OutOperandList = (outs FGROpnd:$fd); - dag InOperandList = (ins FGRCCOpnd:$fd_in, FGROpnd:$fs, FGROpnd:$ft); - string AsmString = !strconcat(instr_asm, "\t$fd, $fs, $ft"); - list<dag> Pattern = [(set FGROpnd:$fd, (select FGRCCOpnd:$fd_in, - FGROpnd:$ft, - FGROpnd:$fs))]; - string Constraints = "$fd_in = $fd"; - InstrItinClass Itinerary = itin; -} - -class COP1_SEL_D_DESC_BASE<string instr_asm, RegisterOperand FGROpnd, - InstrItinClass itin> { - dag OutOperandList = (outs FGROpnd:$fd); - dag InOperandList = (ins FGROpnd:$fd_in, FGROpnd:$fs, FGROpnd:$ft); - string AsmString = !strconcat(instr_asm, "\t$fd, $fs, $ft"); - list<dag> Pattern = [(set FGROpnd:$fd, (MipsFSelect FGROpnd:$fd_in, - FGROpnd:$ft, - FGROpnd:$fs))]; - string Constraints = "$fd_in = $fd"; - InstrItinClass Itinerary = itin; -} - -class SEL_D_DESC : COP1_SEL_D_DESC_BASE<"sel.d", FGR64Opnd, II_SEL_D>, - MipsR6Arch<"sel.d">; -class SEL_S_DESC : COP1_SEL_DESC_BASE<"sel.s", FGR32Opnd, II_SEL_S>, - MipsR6Arch<"sel.s">; - -class SELEQNE_Z_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> - : MipsR6Arch<instr_asm> { - dag OutOperandList = (outs GPROpnd:$rd); - dag InOperandList = (ins GPROpnd:$rs, GPROpnd:$rt); - string AsmString = !strconcat(instr_asm, "\t$rd, $rs, $rt"); - list<dag> Pattern = []; - InstrItinClass Itinerary = II_SELCCZ; -} - -class SELEQZ_DESC : SELEQNE_Z_DESC_BASE<"seleqz", GPR32Opnd>; -class SELNEZ_DESC : SELEQNE_Z_DESC_BASE<"selnez", GPR32Opnd>; - -class COP1_4R_DESC_BASE<string instr_asm, RegisterOperand FGROpnd, - InstrItinClass itin = NoItinerary> { - dag OutOperandList = (outs FGROpnd:$fd); - dag InOperandList = (ins FGROpnd:$fd_in, FGROpnd:$fs, FGROpnd:$ft); - string AsmString = !strconcat(instr_asm, "\t$fd, $fs, $ft"); - list<dag> Pattern = []; - string Constraints = "$fd_in = $fd"; - InstrItinClass Itinerary = itin; -} - -class MADDF_S_DESC : COP1_4R_DESC_BASE<"maddf.s", FGR32Opnd, II_MADDF_S>; -class MADDF_D_DESC : COP1_4R_DESC_BASE<"maddf.d", FGR64Opnd, II_MADDF_D>; -class MSUBF_S_DESC : COP1_4R_DESC_BASE<"msubf.s", FGR32Opnd, II_MSUBF_S>; -class MSUBF_D_DESC : COP1_4R_DESC_BASE<"msubf.d", FGR64Opnd, II_MSUBF_D>; - -class MAX_MIN_DESC_BASE<string instr_asm, RegisterOperand FGROpnd, - InstrItinClass itin> { - dag OutOperandList = (outs FGROpnd:$fd); - dag InOperandList = (ins FGROpnd:$fs, FGROpnd:$ft); - string AsmString = !strconcat(instr_asm, "\t$fd, $fs, $ft"); - list<dag> Pattern = []; - InstrItinClass Itinerary = itin; -} - -class MAX_S_DESC : MAX_MIN_DESC_BASE<"max.s", FGR32Opnd, II_MAX_S>; -class MAX_D_DESC : MAX_MIN_DESC_BASE<"max.d", FGR64Opnd, II_MAX_D>; -class MIN_S_DESC : MAX_MIN_DESC_BASE<"min.s", FGR32Opnd, II_MIN_S>; -class MIN_D_DESC : MAX_MIN_DESC_BASE<"min.d", FGR64Opnd, II_MIN_D>; - -class MAXA_S_DESC : MAX_MIN_DESC_BASE<"maxa.s", FGR32Opnd, II_MAX_S>; -class MAXA_D_DESC : MAX_MIN_DESC_BASE<"maxa.d", FGR64Opnd, II_MAX_D>; -class MINA_S_DESC : MAX_MIN_DESC_BASE<"mina.s", FGR32Opnd, II_MIN_D>; -class MINA_D_DESC : MAX_MIN_DESC_BASE<"mina.d", FGR64Opnd, II_MIN_S>; - -class SELEQNEZ_DESC_BASE<string instr_asm, RegisterOperand FGROpnd, - InstrItinClass itin> { - dag OutOperandList = (outs FGROpnd:$fd); - dag InOperandList = (ins FGROpnd:$fs, FGROpnd:$ft); - string AsmString = !strconcat(instr_asm, "\t$fd, $fs, $ft"); - list<dag> Pattern = []; - InstrItinClass Itinerary = itin; -} - -class SELEQZ_S_DESC : SELEQNEZ_DESC_BASE<"seleqz.s", FGR32Opnd, II_SELCCZ_S>, - MipsR6Arch<"seleqz.s">; -class SELEQZ_D_DESC : SELEQNEZ_DESC_BASE<"seleqz.d", FGR64Opnd, II_SELCCZ_D>, - MipsR6Arch<"seleqz.d">; -class SELNEZ_S_DESC : SELEQNEZ_DESC_BASE<"selnez.s", FGR32Opnd, II_SELCCZ_S>, - MipsR6Arch<"selnez.s">; -class SELNEZ_D_DESC : SELEQNEZ_DESC_BASE<"selnez.d", FGR64Opnd, II_SELCCZ_D>, - MipsR6Arch<"selnez.d">; - -class CLASS_RINT_DESC_BASE<string instr_asm, RegisterOperand FGROpnd, - InstrItinClass itin> { - dag OutOperandList = (outs FGROpnd:$fd); - dag InOperandList = (ins FGROpnd:$fs); - string AsmString = !strconcat(instr_asm, "\t$fd, $fs"); - list<dag> Pattern = []; - InstrItinClass Itinerary = itin; -} - -class RINT_S_DESC : CLASS_RINT_DESC_BASE<"rint.s", FGR32Opnd, II_RINT_S>; -class RINT_D_DESC : CLASS_RINT_DESC_BASE<"rint.d", FGR64Opnd, II_RINT_D>; -class CLASS_S_DESC : CLASS_RINT_DESC_BASE<"class.s", FGR32Opnd, II_CLASS_S>; -class CLASS_D_DESC : CLASS_RINT_DESC_BASE<"class.d", FGR64Opnd, II_CLASS_D>; - -class CACHE_HINT_DESC<string instr_asm, Operand MemOpnd, - RegisterOperand GPROpnd, InstrItinClass itin> - : MipsR6Arch<instr_asm> { - dag OutOperandList = (outs); - dag InOperandList = (ins MemOpnd:$addr, uimm5:$hint); - string AsmString = !strconcat(instr_asm, "\t$hint, $addr"); - list<dag> Pattern = []; - string DecoderMethod = "DecodeCacheeOp_CacheOpR6"; - InstrItinClass Itinerary = itin; -} - -class CACHE_DESC : CACHE_HINT_DESC<"cache", mem_simm9, GPR32Opnd, II_CACHE>; -class PREF_DESC : CACHE_HINT_DESC<"pref", mem_simm9, GPR32Opnd, II_PREF>; - -class COP2LD_DESC_BASE<string instr_asm, RegisterOperand COPOpnd, - InstrItinClass itin> { - dag OutOperandList = (outs COPOpnd:$rt); - dag InOperandList = (ins mem_simm11:$addr); - string AsmString = !strconcat(instr_asm, "\t$rt, $addr"); - list<dag> Pattern = []; - bit mayLoad = 1; - string DecoderMethod = "DecodeFMemCop2R6"; - InstrItinClass Itinerary = itin; -} - -class LDC2_R6_DESC : COP2LD_DESC_BASE<"ldc2", COP2Opnd, II_LDC2>; -class LWC2_R6_DESC : COP2LD_DESC_BASE<"lwc2", COP2Opnd, II_LWC2>; - -class COP2ST_DESC_BASE<string instr_asm, RegisterOperand COPOpnd, - InstrItinClass itin> { - dag OutOperandList = (outs); - dag InOperandList = (ins COPOpnd:$rt, mem_simm11:$addr); - string AsmString = !strconcat(instr_asm, "\t$rt, $addr"); - list<dag> Pattern = []; - bit mayStore = 1; - string DecoderMethod = "DecodeFMemCop2R6"; - InstrItinClass Itinerary = itin; -} - -class SDC2_R6_DESC : COP2ST_DESC_BASE<"sdc2", COP2Opnd, II_SDC2>; -class SWC2_R6_DESC : COP2ST_DESC_BASE<"swc2", COP2Opnd, II_SWC2>; - -class LSA_R6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, - Operand ImmOpnd, InstrItinClass itin> - : MipsR6Arch<instr_asm> { - dag OutOperandList = (outs GPROpnd:$rd); - dag InOperandList = (ins GPROpnd:$rs, GPROpnd:$rt, ImmOpnd:$imm2); - string AsmString = !strconcat(instr_asm, "\t$rd, $rs, $rt, $imm2"); - list<dag> Pattern = []; - InstrItinClass Itinerary = itin; -} - -class LSA_R6_DESC : LSA_R6_DESC_BASE<"lsa", GPR32Opnd, uimm2_plus1, II_LSA>; - -class LL_R6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, - Operand MemOpnd, InstrItinClass itin> - : MipsR6Arch<instr_asm> { - dag OutOperandList = (outs GPROpnd:$rt); - dag InOperandList = (ins MemOpnd:$addr); - string AsmString = !strconcat(instr_asm, "\t$rt, $addr"); - list<dag> Pattern = []; - bit mayLoad = 1; - InstrItinClass Itinerary = itin; -} - -class LL_R6_DESC : LL_R6_DESC_BASE<"ll", GPR32Opnd, mem_simm9, II_LL>; - -class SC_R6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, - InstrItinClass itin> { - dag OutOperandList = (outs GPROpnd:$dst); - dag InOperandList = (ins GPROpnd:$rt, mem_simm9:$addr); - string AsmString = !strconcat(instr_asm, "\t$rt, $addr"); - list<dag> Pattern = []; - bit mayStore = 1; - string Constraints = "$rt = $dst"; - InstrItinClass Itinerary = itin; -} - -class SC_R6_DESC : SC_R6_DESC_BASE<"sc", GPR32Opnd, II_SC>; - -class CLO_CLZ_R6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, - InstrItinClass itin> - : MipsR6Arch<instr_asm> { - dag OutOperandList = (outs GPROpnd:$rd); - dag InOperandList = (ins GPROpnd:$rs); - string AsmString = !strconcat(instr_asm, "\t$rd, $rs"); - InstrItinClass Itinerary = itin; -} - -class CLO_R6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, - InstrItinClass itin> : - CLO_CLZ_R6_DESC_BASE<instr_asm, GPROpnd, itin> { - list<dag> Pattern = [(set GPROpnd:$rd, (ctlz (not GPROpnd:$rs)))]; -} - -class CLZ_R6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, - InstrItinClass itin> : - CLO_CLZ_R6_DESC_BASE<instr_asm, GPROpnd, itin> { - list<dag> Pattern = [(set GPROpnd:$rd, (ctlz GPROpnd:$rs))]; -} - -class CLO_R6_DESC : CLO_R6_DESC_BASE<"clo", GPR32Opnd, II_CLO>; -class CLZ_R6_DESC : CLZ_R6_DESC_BASE<"clz", GPR32Opnd, II_CLZ>; - -class SDBBP_R6_DESC { - dag OutOperandList = (outs); - dag InOperandList = (ins uimm20:$code_); - string AsmString = "sdbbp\t$code_"; - list<dag> Pattern = []; - bit isCTI = 1; - InstrItinClass Itinerary = II_SDBBP; -} - -class CRC_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, - InstrItinClass itin> : MipsR6Arch<instr_asm> { - dag OutOperandList = (outs GPROpnd:$rd); - dag InOperandList = (ins GPROpnd:$rs, GPROpnd:$rt); - string AsmString = !strconcat(instr_asm, "\t$rd, $rs, $rt"); - list<dag> Pattern = []; - InstrItinClass Itinerary = itin; -} - -class CRC32B_DESC : CRC_DESC_BASE<"crc32b", GPR32Opnd, II_CRC32B>; -class CRC32H_DESC : CRC_DESC_BASE<"crc32h", GPR32Opnd, II_CRC32H>; -class CRC32W_DESC : CRC_DESC_BASE<"crc32w", GPR32Opnd, II_CRC32W>; -class CRC32CB_DESC : CRC_DESC_BASE<"crc32cb", GPR32Opnd, II_CRC32CB>; -class CRC32CH_DESC : CRC_DESC_BASE<"crc32ch", GPR32Opnd, II_CRC32CH>; -class CRC32CW_DESC : CRC_DESC_BASE<"crc32cw", GPR32Opnd, II_CRC32CW>; - -class GINV_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, - InstrItinClass itin> : MipsR6Arch<instr_asm> { - dag OutOperandList = (outs); - dag InOperandList = (ins GPROpnd:$rs, uimm2:$type_); - string AsmString = !strconcat(instr_asm, "\t$rs, $type_"); - list<dag> Pattern = []; - InstrItinClass Itinerary = itin; - bit hasSideEffects = 1; -} - -class GINVI_DESC : GINV_DESC_BASE<"ginvi", GPR32Opnd, II_GINVI> { - dag InOperandList = (ins GPR32Opnd:$rs); - string AsmString = "ginvi\t$rs"; -} -class GINVT_DESC : GINV_DESC_BASE<"ginvt", GPR32Opnd, II_GINVT>; - -class SIGRIE_DESC { - dag OutOperandList = (outs); - dag InOperandList = (ins uimm16:$code_); - string AsmString = "sigrie\t$code_"; - list<dag> Pattern = []; - InstrItinClass Itinerary = II_SIGRIE; -} - -//===----------------------------------------------------------------------===// -// -// Instruction Definitions -// -//===----------------------------------------------------------------------===// - -def ADDIUPC : R6MMR6Rel, ADDIUPC_ENC, ADDIUPC_DESC, ISA_MIPS32R6; -def ALIGN : R6MMR6Rel, ALIGN_ENC, ALIGN_DESC, ISA_MIPS32R6; -def ALUIPC : R6MMR6Rel, ALUIPC_ENC, ALUIPC_DESC, ISA_MIPS32R6; -def AUI : R6MMR6Rel, AUI_ENC, AUI_DESC, ISA_MIPS32R6; -def AUIPC : R6MMR6Rel, AUIPC_ENC, AUIPC_DESC, ISA_MIPS32R6; -def BAL : BAL_ENC, BAL_DESC, ISA_MIPS32R6; -def BALC : R6MMR6Rel, BALC_ENC, BALC_DESC, ISA_MIPS32R6; -let AdditionalPredicates = [NotInMicroMips] in { - def BC1EQZ : BC1EQZ_ENC, BC1EQZ_DESC, ISA_MIPS32R6, HARDFLOAT; - def BC1NEZ : BC1NEZ_ENC, BC1NEZ_DESC, ISA_MIPS32R6, HARDFLOAT; - def BC2EQZ : BC2EQZ_ENC, BC2EQZ_DESC, ISA_MIPS32R6; - def BC2NEZ : BC2NEZ_ENC, BC2NEZ_DESC, ISA_MIPS32R6; - def BC : R6MMR6Rel, BC_ENC, BC_DESC, ISA_MIPS32R6; - def BEQC : R6MMR6Rel, BEQC_ENC, BEQC_DESC, ISA_MIPS32R6; - def BEQZALC : R6MMR6Rel, BEQZALC_ENC, BEQZALC_DESC, ISA_MIPS32R6; - def BEQZC : R6MMR6Rel, BEQZC_ENC, BEQZC_DESC, ISA_MIPS32R6; - def BGEC : R6MMR6Rel, BGEC_ENC, BGEC_DESC, ISA_MIPS32R6; - def BGEUC : R6MMR6Rel, BGEUC_ENC, BGEUC_DESC, ISA_MIPS32R6; - def BGEZALC : R6MMR6Rel, BGEZALC_ENC, BGEZALC_DESC, ISA_MIPS32R6; - def BGEZC : R6MMR6Rel, BGEZC_ENC, BGEZC_DESC, ISA_MIPS32R6; - def BGTZALC : R6MMR6Rel, BGTZALC_ENC, BGTZALC_DESC, ISA_MIPS32R6; - def BGTZC : R6MMR6Rel, BGTZC_ENC, BGTZC_DESC, ISA_MIPS32R6; -} -def BITSWAP : R6MMR6Rel, BITSWAP_ENC, BITSWAP_DESC, ISA_MIPS32R6; -let AdditionalPredicates = [NotInMicroMips] in { - def BLEZALC : R6MMR6Rel, BLEZALC_ENC, BLEZALC_DESC, ISA_MIPS32R6; - def BLEZC : R6MMR6Rel, BLEZC_ENC, BLEZC_DESC, ISA_MIPS32R6; - def BLTC : R6MMR6Rel, BLTC_ENC, BLTC_DESC, ISA_MIPS32R6; - def BLTUC : R6MMR6Rel, BLTUC_ENC, BLTUC_DESC, ISA_MIPS32R6; - def BLTZALC : R6MMR6Rel, BLTZALC_ENC, BLTZALC_DESC, ISA_MIPS32R6; - def BLTZC : R6MMR6Rel, BLTZC_ENC, BLTZC_DESC, ISA_MIPS32R6; - def BNEC : R6MMR6Rel, BNEC_ENC, BNEC_DESC, ISA_MIPS32R6; - def BNEZALC : R6MMR6Rel, BNEZALC_ENC, BNEZALC_DESC, ISA_MIPS32R6; - def BNEZC : R6MMR6Rel, BNEZC_ENC, BNEZC_DESC, ISA_MIPS32R6; - def BNVC : R6MMR6Rel, BNVC_ENC, BNVC_DESC, ISA_MIPS32R6; - def BOVC : R6MMR6Rel, BOVC_ENC, BOVC_DESC, ISA_MIPS32R6; - def CACHE_R6 : R6MMR6Rel, CACHE_ENC, CACHE_DESC, ISA_MIPS32R6; - def CLASS_D : CLASS_D_ENC, CLASS_D_DESC, ISA_MIPS32R6, HARDFLOAT; - def CLASS_S : CLASS_S_ENC, CLASS_S_DESC, ISA_MIPS32R6, HARDFLOAT; -} -def CLO_R6 : R6MMR6Rel, CLO_R6_ENC, CLO_R6_DESC, ISA_MIPS32R6; -def CLZ_R6 : R6MMR6Rel, CLZ_R6_ENC, CLZ_R6_DESC, ISA_MIPS32R6; -defm S : CMP_CC_M<FIELD_CMP_FORMAT_S, "s", FGR32Opnd, II_CMP_CC_S>; -defm D : CMP_CC_M<FIELD_CMP_FORMAT_D, "d", FGR64Opnd, II_CMP_CC_D>; -let AdditionalPredicates = [NotInMicroMips] in { - def DIV : R6MMR6Rel, DIV_ENC, DIV_DESC, ISA_MIPS32R6; - def DIVU : R6MMR6Rel, DIVU_ENC, DIVU_DESC, ISA_MIPS32R6; -} - -def DVP : R6MMR6Rel, DVP_ENC, DVP_DESC, ISA_MIPS32R6; -def EVP : R6MMR6Rel, EVP_ENC, EVP_DESC, ISA_MIPS32R6; - -def JIALC : R6MMR6Rel, JIALC_ENC, JIALC_DESC, ISA_MIPS32R6; -def JIC : R6MMR6Rel, JIC_ENC, JIC_DESC, ISA_MIPS32R6; -def JR_HB_R6 : JR_HB_R6_ENC, JR_HB_R6_DESC, ISA_MIPS32R6; -let AdditionalPredicates = [NotInMicroMips] in { - def LDC2_R6 : LDC2_R6_ENC, LDC2_R6_DESC, ISA_MIPS32R6; - def LL_R6 : LL_R6_ENC, LL_R6_DESC, PTR_32, ISA_MIPS32R6; -} -def LSA_R6 : R6MMR6Rel, LSA_R6_ENC, LSA_R6_DESC, ISA_MIPS32R6; -let AdditionalPredicates = [NotInMicroMips] in { - def LWC2_R6 : LWC2_R6_ENC, LWC2_R6_DESC, ISA_MIPS32R6; -} -def LWPC : R6MMR6Rel, LWPC_ENC, LWPC_DESC, ISA_MIPS32R6; -let AdditionalPredicates = [NotInMicroMips] in { - def MADDF_S : MADDF_S_ENC, MADDF_S_DESC, ISA_MIPS32R6, HARDFLOAT; - def MADDF_D : MADDF_D_ENC, MADDF_D_DESC, ISA_MIPS32R6, HARDFLOAT; - def MAXA_D : MAXA_D_ENC, MAXA_D_DESC, ISA_MIPS32R6, HARDFLOAT; - def MAXA_S : MAXA_S_ENC, MAXA_S_DESC, ISA_MIPS32R6, HARDFLOAT; - def MAX_D : MAX_D_ENC, MAX_D_DESC, ISA_MIPS32R6, HARDFLOAT; - def MAX_S : MAX_S_ENC, MAX_S_DESC, ISA_MIPS32R6, HARDFLOAT; - def MINA_D : MINA_D_ENC, MINA_D_DESC, ISA_MIPS32R6, HARDFLOAT; - def MINA_S : MINA_S_ENC, MINA_S_DESC, ISA_MIPS32R6, HARDFLOAT; - def MIN_D : MIN_D_ENC, MIN_D_DESC, ISA_MIPS32R6, HARDFLOAT; - def MIN_S : MIN_S_ENC, MIN_S_DESC, ISA_MIPS32R6, HARDFLOAT; - - def MOD : R6MMR6Rel, MOD_ENC, MOD_DESC, ISA_MIPS32R6; - def MODU : R6MMR6Rel, MODU_ENC, MODU_DESC, ISA_MIPS32R6; - - def MSUBF_S : MSUBF_S_ENC, MSUBF_S_DESC, ISA_MIPS32R6, HARDFLOAT; - def MSUBF_D : MSUBF_D_ENC, MSUBF_D_DESC, ISA_MIPS32R6, HARDFLOAT; - - def MUH : R6MMR6Rel, MUH_ENC, MUH_DESC, ISA_MIPS32R6; - def MUHU : R6MMR6Rel, MUHU_ENC, MUHU_DESC, ISA_MIPS32R6; - def MUL_R6 : R6MMR6Rel, MUL_R6_ENC, MUL_R6_DESC, ISA_MIPS32R6; - def MULU : R6MMR6Rel, MULU_ENC, MULU_DESC, ISA_MIPS32R6; -} -def NAL; // BAL with rd=0 -let AdditionalPredicates = [NotInMicroMips] in { - def PREF_R6 : R6MMR6Rel, PREF_ENC, PREF_DESC, ISA_MIPS32R6; - def RINT_D : RINT_D_ENC, RINT_D_DESC, ISA_MIPS32R6, HARDFLOAT; - def RINT_S : RINT_S_ENC, RINT_S_DESC, ISA_MIPS32R6, HARDFLOAT; - def SC_R6 : SC_R6_ENC, SC_R6_DESC, PTR_32, ISA_MIPS32R6; - def SDBBP_R6 : SDBBP_R6_ENC, SDBBP_R6_DESC, ISA_MIPS32R6; - def SELEQZ : R6MMR6Rel, SELEQZ_ENC, SELEQZ_DESC, ISA_MIPS32R6, GPR_32; - def SELNEZ : R6MMR6Rel, SELNEZ_ENC, SELNEZ_DESC, ISA_MIPS32R6, GPR_32; - def SELEQZ_D : R6MMR6Rel, SELEQZ_D_ENC, SELEQZ_D_DESC, ISA_MIPS32R6, - HARDFLOAT; - def SELEQZ_S : R6MMR6Rel, SELEQZ_S_ENC, SELEQZ_S_DESC, ISA_MIPS32R6, - HARDFLOAT; - def SELNEZ_D : R6MMR6Rel, SELNEZ_D_ENC, SELNEZ_D_DESC, ISA_MIPS32R6, - HARDFLOAT; - def SELNEZ_S : R6MMR6Rel, SELNEZ_S_ENC, SELNEZ_S_DESC, ISA_MIPS32R6, - HARDFLOAT; - def SEL_D : R6MMR6Rel, SEL_D_ENC, SEL_D_DESC, ISA_MIPS32R6, HARDFLOAT; - def SEL_S : R6MMR6Rel, SEL_S_ENC, SEL_S_DESC, ISA_MIPS32R6, HARDFLOAT; - def SDC2_R6 : SDC2_R6_ENC, SDC2_R6_DESC, ISA_MIPS32R6; - def SWC2_R6 : SWC2_R6_ENC, SWC2_R6_DESC, ISA_MIPS32R6; - def SIGRIE : SIGRIE_ENC, SIGRIE_DESC, ISA_MIPS32R6; -} - -let AdditionalPredicates = [NotInMicroMips] in { - def CRC32B : R6MMR6Rel, CRC32B_ENC, CRC32B_DESC, ISA_MIPS32R6, ASE_CRC; - def CRC32H : R6MMR6Rel, CRC32H_ENC, CRC32H_DESC, ISA_MIPS32R6, ASE_CRC; - def CRC32W : R6MMR6Rel, CRC32W_ENC, CRC32W_DESC, ISA_MIPS32R6, ASE_CRC; - def CRC32CB : R6MMR6Rel, CRC32CB_ENC, CRC32CB_DESC, ISA_MIPS32R6, ASE_CRC; - def CRC32CH : R6MMR6Rel, CRC32CH_ENC, CRC32CH_DESC, ISA_MIPS32R6, ASE_CRC; - def CRC32CW : R6MMR6Rel, CRC32CW_ENC, CRC32CW_DESC, ISA_MIPS32R6, ASE_CRC; -} - -let AdditionalPredicates = [NotInMicroMips] in { - def GINVI : R6MMR6Rel, GINVI_ENC, GINVI_DESC, ISA_MIPS32R6, ASE_GINV; - def GINVT : R6MMR6Rel, GINVT_ENC, GINVT_DESC, ISA_MIPS32R6, ASE_GINV; -} - -//===----------------------------------------------------------------------===// -// -// Instruction Aliases -// -//===----------------------------------------------------------------------===// - -def : MipsInstAlias<"dvp", (DVP ZERO), 0>, ISA_MIPS32R6; -def : MipsInstAlias<"evp", (EVP ZERO), 0>, ISA_MIPS32R6; - -let AdditionalPredicates = [NotInMicroMips] in { -def : MipsInstAlias<"sdbbp", (SDBBP_R6 0)>, ISA_MIPS32R6; -def : MipsInstAlias<"sigrie", (SIGRIE 0)>, ISA_MIPS32R6; -def : MipsInstAlias<"jr $rs", (JALR ZERO, GPR32Opnd:$rs), 1>, ISA_MIPS32R6, GPR_32; -} - -def : MipsInstAlias<"jrc $rs", (JIC GPR32Opnd:$rs, 0), 1>, ISA_MIPS32R6, GPR_32; - -let AdditionalPredicates = [NotInMicroMips] in { -def : MipsInstAlias<"jalrc $rs", (JIALC GPR32Opnd:$rs, 0), 1>, ISA_MIPS32R6, GPR_32; -} - -def : MipsInstAlias<"div $rs, $rt", (DIV GPR32Opnd:$rs, GPR32Opnd:$rs, - GPR32Opnd:$rt)>, ISA_MIPS32R6; -def : MipsInstAlias<"divu $rs, $rt", (DIVU GPR32Opnd:$rs, GPR32Opnd:$rs, - GPR32Opnd:$rt)>, ISA_MIPS32R6; - -def : MipsInstAlias<"lapc $rd, $imm", - (ADDIUPC GPR32Opnd:$rd, simm19_lsl2:$imm)>, ISA_MIPS32R6; - -//===----------------------------------------------------------------------===// -// -// Patterns and Pseudo Instructions -// -//===----------------------------------------------------------------------===// - -// comparisons supported via another comparison -multiclass Cmp_Pats<ValueType VT, Instruction NOROp, Register ZEROReg> { -def : MipsPat<(setone VT:$lhs, VT:$rhs), - (NOROp (!cast<Instruction>("CMP_UEQ_"#NAME) VT:$lhs, VT:$rhs), ZEROReg)>; -def : MipsPat<(seto VT:$lhs, VT:$rhs), - (NOROp (!cast<Instruction>("CMP_UN_"#NAME) VT:$lhs, VT:$rhs), ZEROReg)>; -def : MipsPat<(setune VT:$lhs, VT:$rhs), - (NOROp (!cast<Instruction>("CMP_EQ_"#NAME) VT:$lhs, VT:$rhs), ZEROReg)>; -def : MipsPat<(seteq VT:$lhs, VT:$rhs), - (!cast<Instruction>("CMP_EQ_"#NAME) VT:$lhs, VT:$rhs)>; -def : MipsPat<(setgt VT:$lhs, VT:$rhs), - (!cast<Instruction>("CMP_LE_"#NAME) VT:$rhs, VT:$lhs)>; -def : MipsPat<(setge VT:$lhs, VT:$rhs), - (!cast<Instruction>("CMP_LT_"#NAME) VT:$rhs, VT:$lhs)>; -def : MipsPat<(setlt VT:$lhs, VT:$rhs), - (!cast<Instruction>("CMP_LT_"#NAME) VT:$lhs, VT:$rhs)>; -def : MipsPat<(setle VT:$lhs, VT:$rhs), - (!cast<Instruction>("CMP_LE_"#NAME) VT:$lhs, VT:$rhs)>; -def : MipsPat<(setne VT:$lhs, VT:$rhs), - (NOROp (!cast<Instruction>("CMP_EQ_"#NAME) VT:$lhs, VT:$rhs), ZEROReg)>; -} - -let AdditionalPredicates = [NotInMicroMips] in { - defm S : Cmp_Pats<f32, NOR, ZERO>, ISA_MIPS32R6; - defm D : Cmp_Pats<f64, NOR, ZERO>, ISA_MIPS32R6; -} - -// i32 selects -multiclass SelectInt_Pats<ValueType RC, Instruction OROp, Instruction XORiOp, - Instruction SLTiOp, Instruction SLTiuOp, - Instruction SELEQZOp, Instruction SELNEZOp, - SDPatternOperator imm_type, ValueType Opg> { -// reg, immz -def : MipsPat<(select (Opg (seteq RC:$cond, immz)), RC:$t, RC:$f), - (OROp (SELEQZOp RC:$t, RC:$cond), (SELNEZOp RC:$f, RC:$cond))>; -def : MipsPat<(select (Opg (setne RC:$cond, immz)), RC:$t, RC:$f), - (OROp (SELNEZOp RC:$t, RC:$cond), (SELEQZOp RC:$f, RC:$cond))>; - -// reg, immZExt16[_64] -def : MipsPat<(select (Opg (seteq RC:$cond, imm_type:$imm)), RC:$t, RC:$f), - (OROp (SELEQZOp RC:$t, (XORiOp RC:$cond, imm_type:$imm)), - (SELNEZOp RC:$f, (XORiOp RC:$cond, imm_type:$imm)))>; -def : MipsPat<(select (Opg (setne RC:$cond, imm_type:$imm)), RC:$t, RC:$f), - (OROp (SELNEZOp RC:$t, (XORiOp RC:$cond, imm_type:$imm)), - (SELEQZOp RC:$f, (XORiOp RC:$cond, imm_type:$imm)))>; - -// reg, immSExt16Plus1 -def : MipsPat<(select (Opg (setgt RC:$cond, immSExt16Plus1:$imm)), RC:$t, RC:$f), - (OROp (SELEQZOp RC:$t, (SLTiOp RC:$cond, (Plus1 imm:$imm))), - (SELNEZOp RC:$f, (SLTiOp RC:$cond, (Plus1 imm:$imm))))>; -def : MipsPat<(select (Opg (setugt RC:$cond, immSExt16Plus1:$imm)), RC:$t, RC:$f), - (OROp (SELEQZOp RC:$t, (SLTiuOp RC:$cond, (Plus1 imm:$imm))), - (SELNEZOp RC:$f, (SLTiuOp RC:$cond, (Plus1 imm:$imm))))>; - -def : MipsPat<(select (Opg (seteq RC:$cond, immz)), RC:$t, immz), - (SELEQZOp RC:$t, RC:$cond)>; -def : MipsPat<(select (Opg (setne RC:$cond, immz)), RC:$t, immz), - (SELNEZOp RC:$t, RC:$cond)>; -def : MipsPat<(select (Opg (seteq RC:$cond, immz)), immz, RC:$f), - (SELNEZOp RC:$f, RC:$cond)>; -def : MipsPat<(select (Opg (setne RC:$cond, immz)), immz, RC:$f), - (SELEQZOp RC:$f, RC:$cond)>; -} - -let AdditionalPredicates = [NotInMicroMips] in { -defm : SelectInt_Pats<i32, OR, XORi, SLTi, SLTiu, SELEQZ, SELNEZ, - immZExt16, i32>, ISA_MIPS32R6; - -def : MipsPat<(select i32:$cond, i32:$t, i32:$f), - (OR (SELNEZ i32:$t, i32:$cond), - (SELEQZ i32:$f, i32:$cond))>, - ISA_MIPS32R6; -def : MipsPat<(select i32:$cond, i32:$t, immz), - (SELNEZ i32:$t, i32:$cond)>, - ISA_MIPS32R6; -def : MipsPat<(select i32:$cond, immz, i32:$f), - (SELEQZ i32:$f, i32:$cond)>, - ISA_MIPS32R6; -} - -// Pseudo instructions -let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, hasDelaySlot = 1, - hasExtraSrcRegAllocReq = 1, isCTI = 1, Defs = [AT], hasPostISelHook = 1 in { - class TailCallRegR6<Instruction JumpInst, Register RT, RegisterOperand RO> : - PseudoSE<(outs), (ins RO:$rs), [(MipsTailCall RO:$rs)], II_JR>, - PseudoInstExpansion<(JumpInst RT:$rt, RO:$rs)>; -} - -class PseudoIndirectBranchBaseR6<Instruction JumpInst, Register RT, - RegisterOperand RO> : - MipsPseudo<(outs), (ins RO:$rs), [(brind RO:$rs)], - II_IndirectBranchPseudo>, - PseudoInstExpansion<(JumpInst RT:$rt, RO:$rs)> { - 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 TAILCALLR6REG : TailCallRegR6<JALR, ZERO, GPR32Opnd>, ISA_MIPS32R6; - def PseudoIndirectBranchR6 : PseudoIndirectBranchBaseR6<JALR, ZERO, - GPR32Opnd>, - ISA_MIPS32R6; -} - -let AdditionalPredicates = [NotInMips16Mode, NotInMicroMips, - UseIndirectJumpsHazard] in { - def TAILCALLHBR6REG : TailCallReg<JR_HB_R6, GPR32Opnd>, ISA_MIPS32R6; - def PseudoIndrectHazardBranchR6 : PseudoIndirectBranchBase<JR_HB_R6, - GPR32Opnd>, - ISA_MIPS32R6; -} - diff --git a/contrib/llvm/lib/Target/Mips/Mips64InstrInfo.td b/contrib/llvm/lib/Target/Mips/Mips64InstrInfo.td deleted file mode 100644 index 1a89d7e30637..000000000000 --- a/contrib/llvm/lib/Target/Mips/Mips64InstrInfo.td +++ /dev/null @@ -1,1205 +0,0 @@ -//===- Mips64InstrInfo.td - Mips64 Instruction Information -*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file describes Mips64 instructions. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// Mips Operand, Complex Patterns and Transformations Definitions. -//===----------------------------------------------------------------------===// - -// shamt must fit in 6 bits. -def immZExt6 : ImmLeaf<i32, [{return Imm == (Imm & 0x3f);}]>; - -// Node immediate fits as 10-bit sign extended on target immediate. -// e.g. seqi, snei -def immSExt10_64 : PatLeaf<(i64 imm), - [{ return isInt<10>(N->getSExtValue()); }]>; - -def immZExt16_64 : PatLeaf<(i64 imm), - [{ return isUInt<16>(N->getZExtValue()); }]>; - -def immZExt5_64 : ImmLeaf<i64, [{ return Imm == (Imm & 0x1f); }]>; - -// Transformation function: get log2 of low 32 bits of immediate -def Log2LO : SDNodeXForm<imm, [{ - return getImm(N, Log2_64((unsigned) N->getZExtValue())); -}]>; - -// Transformation function: get log2 of high 32 bits of immediate -def Log2HI : SDNodeXForm<imm, [{ - return getImm(N, Log2_64((unsigned) (N->getZExtValue() >> 32))); -}]>; - -// Predicate: True if immediate is a power of 2 and fits 32 bits -def PowerOf2LO : PatLeaf<(imm), [{ - if (N->getValueType(0) == MVT::i64) { - uint64_t Imm = N->getZExtValue(); - return isPowerOf2_64(Imm) && (Imm & 0xffffffff) == Imm; - } - else - return false; -}]>; - -// Predicate: True if immediate is a power of 2 and exceeds 32 bits -def PowerOf2HI : PatLeaf<(imm), [{ - if (N->getValueType(0) == MVT::i64) { - uint64_t Imm = N->getZExtValue(); - return isPowerOf2_64(Imm) && (Imm & 0xffffffff00000000) == Imm; - } - else - 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 -//===----------------------------------------------------------------------===// -let usesCustomInserter = 1 in { - def ATOMIC_LOAD_ADD_I64 : Atomic2Ops<atomic_load_add_64, GPR64>; - def ATOMIC_LOAD_SUB_I64 : Atomic2Ops<atomic_load_sub_64, GPR64>; - def ATOMIC_LOAD_AND_I64 : Atomic2Ops<atomic_load_and_64, GPR64>; - def ATOMIC_LOAD_OR_I64 : Atomic2Ops<atomic_load_or_64, GPR64>; - def ATOMIC_LOAD_XOR_I64 : Atomic2Ops<atomic_load_xor_64, GPR64>; - def ATOMIC_LOAD_NAND_I64 : Atomic2Ops<atomic_load_nand_64, GPR64>; - def ATOMIC_SWAP_I64 : Atomic2Ops<atomic_swap_64, GPR64>; - 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 { - def LOAD_ACC128 : Load<"", ACC128>; - def STORE_ACC128 : Store<"", ACC128>; -} - -//===----------------------------------------------------------------------===// -// Instruction definition -//===----------------------------------------------------------------------===// -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; -} - -let isCodeGenOnly = 1 in { -def SLTi64 : SetCC_I<"slti", setlt, simm16_64, immSExt16, GPR64Opnd>, - SLTI_FM<0xa>, GPR_64; -def SLTiu64 : SetCC_I<"sltiu", setult, simm16_64, immSExt16, GPR64Opnd>, - SLTI_FM<0xb>, GPR_64; -def ANDi64 : ArithLogicI<"andi", uimm16_64, GPR64Opnd, II_AND, immZExt16, and>, - ADDI_FM<0xc>, GPR_64; -def ORi64 : ArithLogicI<"ori", uimm16_64, GPR64Opnd, II_OR, immZExt16, or>, - ADDI_FM<0xd>, GPR_64; -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; -} - -/// 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; -} - -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; -} - -/// Shift Instructions -let AdditionalPredicates = [NotInMicroMips] in { - 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>, - SRA_FM<0x3a, 0>, ISA_MIPS3; - 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; - -// 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; -} - -/// 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; -} - - - -/// 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 LDL : LoadLeftRight<"ldl", MipsLDL, GPR64Opnd, II_LDL>, LW_FM<0x1a>, - ISA_MIPS3_NOT_32R6_64R6; -def LDR : LoadLeftRight<"ldr", MipsLDR, GPR64Opnd, II_LDR>, LW_FM<0x1b>, - ISA_MIPS3_NOT_32R6_64R6; -def SDL : StoreLeftRight<"sdl", MipsSDL, GPR64Opnd, II_SDL>, LW_FM<0x2c>, - ISA_MIPS3_NOT_32R6_64R6; -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 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, PTR_64; - -/// 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>, - PTR_64; -} -let AdditionalPredicates = [NotInMicroMips], - DecoderNamespace = "Mips64" in { - def JR_HB64 : JR_HB_DESC<GPR64Opnd>, JR_HB_ENC, ISA_MIPS64_NOT_64R6; - def JALR_HB64 : JALR_HB_DESC<GPR64Opnd>, JALR_HB_ENC, ISA_MIPS64R2; -} -def PseudoReturn64 : PseudoReturnBase<GPR64Opnd>, GPR_64; - -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; -} - -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, PTR_64; -} - -/// 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 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 PseudoDSDIV : MultDivPseudo<DSDIV, ACC128, GPR64Opnd, MipsDivRem, - II_DDIV, 0, 1, 1>, ISA_MIPS3_NOT_32R6_64R6; -def PseudoDUDIV : MultDivPseudo<DUDIV, ACC128, GPR64Opnd, MipsDivRemU, - II_DDIVU, 0, 1, 1>, ISA_MIPS3_NOT_32R6_64R6; - -let isCodeGenOnly = 1 in { -def MTHI64 : MoveToLOHI<"mthi", GPR64Opnd, [HI0_64]>, MTLO_FM<0x11>, - ISA_MIPS3_NOT_32R6_64R6; -def MTLO64 : MoveToLOHI<"mtlo", GPR64Opnd, [LO0_64]>, MTLO_FM<0x13>, - ISA_MIPS3_NOT_32R6_64R6; -def MFHI64 : MoveFromLOHI<"mfhi", GPR64Opnd, AC0_64>, MFLO_FM<0x10>, - ISA_MIPS3_NOT_32R6_64R6; -def MFLO64 : MoveFromLOHI<"mflo", GPR64Opnd, AC0_64>, MFLO_FM<0x12>, - ISA_MIPS3_NOT_32R6_64R6; -def PseudoMFHI64 : PseudoMFLOHI<GPR64, ACC128, MipsMFHI>, - ISA_MIPS3_NOT_32R6_64R6; -def PseudoMFLO64 : PseudoMFLOHI<GPR64, ACC128, MipsMFLO>, - ISA_MIPS3_NOT_32R6_64R6; -def PseudoMTLOHI64 : PseudoMTLOHI<ACC128, GPR64>, ISA_MIPS3_NOT_32R6_64R6; - -/// Sign Ext In Register Instructions. -def SEB64 : SignExtInReg<"seb", i8, GPR64Opnd, II_SEB>, SEB_FM<0x10, 0x20>, - ISA_MIPS32R2, GPR_64; -def SEH64 : SignExtInReg<"seh", i16, GPR64Opnd, II_SEH>, SEB_FM<0x18, 0x20>, - ISA_MIPS32R2, GPR_64; -} - -/// Count Leading -let AdditionalPredicates = [NotInMicroMips] in { - def DCLZ : CountLeading0<"dclz", GPR64Opnd, II_DCLZ>, CLO_FM<0x24>, - ISA_MIPS64_NOT_64R6, GPR_64; - def DCLO : CountLeading1<"dclo", GPR64Opnd, II_DCLO>, CLO_FM<0x25>, - ISA_MIPS64_NOT_64R6, GPR_64; - -/// 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 LEA_ADDiu64 : EffectiveAddress<"daddiu", GPR64Opnd>, LW_FM<0x19>, - GPR_64; -} - -let isCodeGenOnly = 1 in -def RDHWR64 : ReadHardware<GPR64Opnd, HWRegsOpnd>, RDHWR_FM, GPR_64; - -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; - } -} - -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; -} - -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; - } -} - -// 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 { - bit hasNoSchedulingInfo = 1; -} -// Expands to: addiu $dst, %highest/%higher/%hi/%lo($tgt) -def LONG_BRANCH_DADDiu2Op : - PseudoSE<(outs GPR64Opnd:$dst), (ins GPR64Opnd:$src, brtarget:$tgt), []>, - GPR_64 { - bit hasNoSchedulingInfo = 1; -} -// 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 { - bit hasNoSchedulingInfo = 1; -} - -// Cavium Octeon cnMIPS instructions -let DecoderNamespace = "CnMips", - // FIXME: The lack of HasStdEnc is probably a bug - EncodingPredicates = []<Predicate> in { - -class Count1s<string opstr, RegisterOperand RO>: - InstSE<(outs RO:$rd), (ins RO:$rs), !strconcat(opstr, "\t$rd, $rs"), - [(set RO:$rd, (ctpop RO:$rs))], II_POP, FrmR, opstr> { - 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> { - let TwoOperandAliasConstraint = "$rt = $rs"; -} - -class SetCC64_R<string opstr, PatFrag cond_op> : - InstSE<(outs GPR64Opnd:$rd), (ins GPR64Opnd:$rs, GPR64Opnd:$rt), - !strconcat(opstr, "\t$rd, $rs, $rt"), - [(set GPR64Opnd:$rd, (zext (cond_op GPR64Opnd:$rs, - GPR64Opnd:$rt)))], - II_SEQ_SNE, FrmR, opstr> { - let TwoOperandAliasConstraint = "$rd = $rs"; -} - -class SetCC64_I<string opstr, PatFrag cond_op>: - InstSE<(outs GPR64Opnd:$rt), (ins GPR64Opnd:$rs, simm10_64:$imm10), - !strconcat(opstr, "\t$rt, $rs, $imm10"), - [(set GPR64Opnd:$rt, (zext (cond_op GPR64Opnd:$rs, - immSExt10_64:$imm10)))], - II_SEQI_SNEI, FrmI, opstr> { - let TwoOperandAliasConstraint = "$rt = $rs"; -} - -class CBranchBitNum<string opstr, DAGOperand opnd, PatFrag cond_op, - RegisterOperand RO, Operand ImmOp, bits<64> shift = 1> : - InstSE<(outs), (ins RO:$rs, ImmOp:$p, opnd:$offset), - !strconcat(opstr, "\t$rs, $p, $offset"), - [(brcond (i32 (cond_op (and RO:$rs, (shl shift, immZExt5_64:$p)), 0)), - bb:$offset)], II_BBIT, FrmI, opstr> { - let isBranch = 1; - let isTerminator = 1; - let hasDelaySlot = 1; - let Defs = [AT]; -} - -class MFC2OP<string asmstr, RegisterOperand RO, InstrItinClass itin> : - InstSE<(outs RO:$rt, uimm16:$imm16), (ins), - !strconcat(asmstr, "\t$rt, $imm16"), [], itin, FrmFR>; - -// Unsigned Byte Add -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))]; -} - -// Branch on Bit Clear /+32 -def BBIT0 : CBranchBitNum<"bbit0", brtarget, seteq, GPR64Opnd, - uimm5_64_report_uimm6>, BBIT_FM<0x32>, ASE_CNMIPS; -def BBIT032: CBranchBitNum<"bbit032", brtarget, seteq, GPR64Opnd, uimm5_64, - 0x100000000>, BBIT_FM<0x36>, ASE_CNMIPS; - -// Branch on Bit Set /+32 -def BBIT1 : CBranchBitNum<"bbit1", brtarget, setne, GPR64Opnd, - uimm5_64_report_uimm6>, BBIT_FM<0x3a>, ASE_CNMIPS; -def BBIT132: CBranchBitNum<"bbit132", brtarget, setne, GPR64Opnd, uimm5_64, - 0x100000000>, BBIT_FM<0x3e>, ASE_CNMIPS; - -// Multiply Doubleword to GPR -def DMUL : ArithLogicR<"dmul", GPR64Opnd, 1, II_DMUL, mul>, - ADD_FM<0x1c, 0x03>, ASE_CNMIPS { - let Defs = [HI0, LO0, P0, P1, P2]; -} - -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; - } -} - -// 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; - -// 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; - -// 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; - -// 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]; -} - -// 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]; -} - -// 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]; -} - -// 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; -} - -// Cavium Octeon+ cnMIPS instructions -let DecoderNamespace = "CnMipsP", - // FIXME: The lack of HasStdEnc is probably a bug - EncodingPredicates = []<Predicate> in { - -class Saa<string opstr>: - InstSE<(outs), (ins GPR64Opnd:$rt, GPR64Opnd:$rs), - !strconcat(opstr, "\t$rt, (${rs})"), [], NoItinerary, FrmR, opstr>; - -def SAA : Saa<"saa">, SAA_FM<0x18>, ASE_CNMIPSP; -def SAAD : Saa<"saad">, SAA_FM<0x19>, ASE_CNMIPSP; - -def SaaAddr : MipsAsmPseudoInst<(outs), (ins GPR64Opnd:$rt, mem:$addr), - "saa\t$rt, $addr">, ASE_CNMIPSP; -def SaadAddr : MipsAsmPseudoInst<(outs), (ins GPR64Opnd:$rt, mem:$addr), - "saad\t$rt, $addr">, ASE_CNMIPSP; -} - -} - -/// Move between CPU and coprocessor registers -let DecoderNamespace = "Mips64" in { -def DMFC0 : MFC3OP<"dmfc0", GPR64Opnd, COP0Opnd, II_DMFC0>, - MFC3OP_FM<0x10, 1, 0>, ISA_MIPS3, GPR_64; -def DMTC0 : MTC3OP<"dmtc0", COP0Opnd, GPR64Opnd, II_DMTC0>, - MFC3OP_FM<0x10, 5, 0>, ISA_MIPS3, GPR_64; -def DMFC2 : MFC3OP<"dmfc2", GPR64Opnd, COP2Opnd, II_DMFC2>, - MFC3OP_FM<0x12, 1, 0>, ISA_MIPS3, GPR_64; -def DMTC2 : MTC3OP<"dmtc2", COP2Opnd, GPR64Opnd, II_DMTC2>, - MFC3OP_FM<0x12, 5, 0>, ISA_MIPS3, GPR_64; -} - -/// 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>, PTR_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; - -// 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; -} - -// 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; -def : MipsPat<(brcond (i32 (setgt i64:$lhs, -1)), bb:$dst), - (BGEZ64 i64:$lhs, bb:$dst)>, ISA_MIPS3, GPR_64; - -// 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; -} -// 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; -def : MipsPat<(i32 (trunc GPR64:$src)), - (SLL (EXTRACT_SUBREG GPR64:$src, sub_32), 0)>, ISA_MIPS3, GPR_64; - -// 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; -def : MipsPat<(srl GPR64:$rt, (i32 (trunc GPR64:$rs))), - (DSRLV GPR64:$rt, (EXTRACT_SUBREG GPR64:$rs, sub_32))>, - ISA_MIPS3, GPR_64; -def : MipsPat<(sra GPR64:$rt, (i32 (trunc GPR64:$rs))), - (DSRAV GPR64:$rt, (EXTRACT_SUBREG GPR64:$rs, sub_32))>, - ISA_MIPS3, GPR_64; -def : MipsPat<(rotr GPR64:$rt, (i32 (trunc GPR64:$rs))), - (DROTRV GPR64:$rt, (EXTRACT_SUBREG GPR64:$rs, sub_32))>, - ISA_MIPS3, GPR_64; - -// 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; -} - -// Sign extend in register -def : MipsPat<(i64 (sext_inreg GPR64:$src, i32)), - (SLL64_64 GPR64:$src)>, ISA_MIPS3, GPR_64; - -// bswap MipsPattern -def : MipsPat<(bswap GPR64:$rt), (DSHD (DSBH GPR64:$rt))>, ISA_MIPS64R2; - -// Carry pattern -let AdditionalPredicates = [NotInMicroMips] in { - def : MipsPat<(subc GPR64:$lhs, GPR64:$rhs), - (DSUBu GPR64:$lhs, GPR64:$rhs)>, ISA_MIPS3, GPR_64; - def : MipsPat<(addc GPR64:$lhs, GPR64:$rhs), - (DADDu GPR64:$lhs, GPR64:$rhs)>, ISA_MIPS3, ASE_NOT_DSP, GPR_64; - def : MipsPat<(addc GPR64:$lhs, immSExt16:$imm), - (DADDiu GPR64:$lhs, imm:$imm)>, ISA_MIPS3, ASE_NOT_DSP, GPR_64; -} - -// Octeon bbit0/bbit1 MipsPattern -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; -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; -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; -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; - -// 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; - -// 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_MIPS32_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)>; - -//===----------------------------------------------------------------------===// -// 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<"dsubi $rs, $rt, $imm", - (DADDi GPR64Opnd:$rs, GPR64Opnd:$rt, - InvertedImOperand64:$imm), - 0>, ISA_MIPS3_NOT_32R6_64R6; -def : MipsInstAlias<"dsubi $rs, $imm", - (DADDi GPR64Opnd:$rs, GPR64Opnd:$rs, - InvertedImOperand64:$imm), - 0>, ISA_MIPS3_NOT_32R6_64R6; -def : MipsInstAlias<"dsub $rs, $rt, $imm", - (DADDi GPR64Opnd:$rs, GPR64Opnd:$rt, - InvertedImOperand64:$imm), - 0>, ISA_MIPS3_NOT_32R6_64R6; -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<"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; -// 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<"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; - -// cnMIPS Aliases. - -// bbit* with $p 32-63 converted to bbit*32 with $p 0-31 -def : MipsInstAlias<"bbit0 $rs, $p, $offset", - (BBIT032 GPR64Opnd:$rs, uimm5_plus32_normalize_64:$p, - brtarget:$offset), 0>, - ASE_CNMIPS; -def : MipsInstAlias<"bbit1 $rs, $p, $offset", - (BBIT132 GPR64Opnd:$rs, uimm5_plus32_normalize_64:$p, - brtarget:$offset), 0>, - ASE_CNMIPS; - -// exts with $pos 32-63 in converted to exts32 with $pos 0-31 -def : MipsInstAlias<"exts $rt, $rs, $pos, $lenm1", - (EXTS32 GPR64Opnd:$rt, GPR64Opnd:$rs, - uimm5_plus32_normalize:$pos, uimm5:$lenm1), 0>, - ASE_MIPS64_CNMIPS; -def : MipsInstAlias<"exts $rt, $pos, $lenm1", - (EXTS32 GPR64Opnd:$rt, GPR64Opnd:$rt, - uimm5_plus32_normalize:$pos, uimm5:$lenm1), 0>, - ASE_MIPS64_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; -def : MipsInstAlias<"cins $rt, $pos, $lenm1", - (CINS32 GPR64Opnd:$rt, GPR64Opnd:$rt, - uimm5_plus32_normalize:$pos, uimm5:$lenm1), 0>, - ASE_MIPS64_CNMIPS; - -//===----------------------------------------------------------------------===// -// Assembler Pseudo Instructions -//===----------------------------------------------------------------------===// - -class LoadImmediate64<string instr_asm, Operand Od, RegisterOperand RO> : - MipsAsmPseudoInst<(outs RO:$rt), (ins Od:$imm64), - !strconcat(instr_asm, "\t$rt, $imm64")> ; -def LoadImm64 : LoadImmediate64<"dli", imm64, GPR64Opnd>; - -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 SGEImm64 : MipsAsmPseudoInst<(outs GPR64Opnd:$rd), - (ins GPR64Opnd:$rs, imm64:$imm), - "sge\t$rd, $rs, $imm">, GPR_64; -def : MipsInstAlias<"sge $rs, $imm", (SGEImm64 GPR64Opnd:$rs, - GPR64Opnd:$rs, - imm64:$imm), 0>, GPR_64; - -def SGEUImm64 : MipsAsmPseudoInst<(outs GPR64Opnd:$rd), - (ins GPR64Opnd:$rs, imm64:$imm), - "sgeu\t$rd, $rs, $imm">, GPR_64; -def : MipsInstAlias<"sgeu $rs, $imm", (SGEUImm64 GPR64Opnd:$rs, - GPR64Opnd:$rs, - imm64:$imm), 0>, GPR_64; - -def SGTImm64 : MipsAsmPseudoInst<(outs GPR64Opnd:$rd), - (ins GPR64Opnd:$rs, imm64:$imm), - "sgt\t$rd, $rs, $imm">, GPR_64; -def : MipsInstAlias<"sgt $rs, $imm", (SGTImm64 GPR64Opnd:$rs, - GPR64Opnd:$rs, - imm64:$imm), 0>, GPR_64; - -def SGTUImm64 : MipsAsmPseudoInst<(outs GPR64Opnd:$rd), - (ins GPR64Opnd:$rs, imm64:$imm), - "sgtu\t$rd, $rs, $imm">, GPR_64; -def : MipsInstAlias<"sgtu $rs, $imm", (SGTUImm64 GPR64Opnd:$rs, - GPR64Opnd:$rs, - imm64:$imm), 0>, GPR_64; - -def : MipsInstAlias<"rdhwr $rt, $rs", - (RDHWR64 GPR64Opnd:$rt, HWRegsOpnd:$rs, 0), 1>, GPR_64; diff --git a/contrib/llvm/lib/Target/Mips/Mips64r6InstrInfo.td b/contrib/llvm/lib/Target/Mips/Mips64r6InstrInfo.td deleted file mode 100644 index d746bb61f824..000000000000 --- a/contrib/llvm/lib/Target/Mips/Mips64r6InstrInfo.td +++ /dev/null @@ -1,339 +0,0 @@ -//=- Mips64r6InstrInfo.td - Mips64r6 Instruction Information -*- tablegen -*-=// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file describes Mips64r6 instructions. -// -//===----------------------------------------------------------------------===// - -// Notes about removals/changes from MIPS32r6: -// Reencoded: dclo, dclz - -//===----------------------------------------------------------------------===// -// -// Instruction Encodings -// -//===----------------------------------------------------------------------===// - -class DALIGN_ENC : SPECIAL3_DALIGN_FM<OPCODE6_DALIGN>; -class DAUI_ENC : DAUI_FM; -class DAHI_ENC : REGIMM_FM<OPCODE5_DAHI>; -class DATI_ENC : REGIMM_FM<OPCODE5_DATI>; -class DBITSWAP_ENC : SPECIAL3_2R_FM<OPCODE6_DBITSWAP>; -class DCLO_R6_ENC : SPECIAL_2R_FM<OPCODE6_DCLO>; -class DCLZ_R6_ENC : SPECIAL_2R_FM<OPCODE6_DCLZ>; -class DDIV_ENC : SPECIAL_3R_FM<0b00010, 0b011110>; -class DDIVU_ENC : SPECIAL_3R_FM<0b00010, 0b011111>; -class DLSA_R6_ENC : SPECIAL_LSA_FM<OPCODE6_DLSA>; -class DMOD_ENC : SPECIAL_3R_FM<0b00011, 0b011110>; -class DMODU_ENC : SPECIAL_3R_FM<0b00011, 0b011111>; -class DMUH_ENC : SPECIAL_3R_FM<0b00011, 0b011100>; -class DMUHU_ENC : SPECIAL_3R_FM<0b00011, 0b011101>; -class DMUL_R6_ENC : SPECIAL_3R_FM<0b00010, 0b011100>; -class DMULU_ENC : SPECIAL_3R_FM<0b00010, 0b011101>; -class LDPC_ENC : PCREL18_FM<OPCODE3_LDPC>; -class LWUPC_ENC : PCREL19_FM<OPCODE2_LWUPC>; -class LLD_R6_ENC : SPECIAL3_LL_SC_FM<OPCODE6_LLD>; -class SCD_R6_ENC : SPECIAL3_LL_SC_FM<OPCODE6_SCD>; -class CRC32D_ENC : SPECIAL3_2R_SZ_CRC<3,0>; -class CRC32CD_ENC : SPECIAL3_2R_SZ_CRC<3,1>; - -//===----------------------------------------------------------------------===// -// -// Instruction Descriptions -// -//===----------------------------------------------------------------------===// - -class AHI_ATI_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, InstrItinClass itin> { - dag OutOperandList = (outs GPROpnd:$rs); - dag InOperandList = (ins GPROpnd:$rt, uimm16_altrelaxed:$imm); - string AsmString = !strconcat(instr_asm, "\t$rs, $rt, $imm"); - string Constraints = "$rs = $rt"; - InstrItinClass Itinerary = itin; -} - -class DALIGN_DESC : ALIGN_DESC_BASE<"dalign", GPR64Opnd, uimm3, II_DALIGN>; -class DAHI_DESC : AHI_ATI_DESC_BASE<"dahi", GPR64Opnd, II_DAHI>; -class DATI_DESC : AHI_ATI_DESC_BASE<"dati", GPR64Opnd, II_DATI>; -class DAUI_DESC : AUI_DESC_BASE<"daui", GPR64Opnd, II_DAUI>; -class DBITSWAP_DESC : BITSWAP_DESC_BASE<"dbitswap", GPR64Opnd, II_DBITSWAP>; -class DCLO_R6_DESC : CLO_R6_DESC_BASE<"dclo", GPR64Opnd, II_DCLO>; -class DCLZ_R6_DESC : CLZ_R6_DESC_BASE<"dclz", GPR64Opnd, II_DCLZ>; -class DDIV_DESC : DIVMOD_DESC_BASE<"ddiv", GPR64Opnd, II_DDIV, sdiv>; -class DDIVU_DESC : DIVMOD_DESC_BASE<"ddivu", GPR64Opnd, II_DDIVU, udiv>; -class DLSA_R6_DESC : LSA_R6_DESC_BASE<"dlsa", GPR64Opnd, uimm2_plus1, II_DLSA>; -class DMOD_DESC : DIVMOD_DESC_BASE<"dmod", GPR64Opnd, II_DMOD, srem>; -class DMODU_DESC : DIVMOD_DESC_BASE<"dmodu", GPR64Opnd, II_DMODU, urem>; -class DMUH_DESC : MUL_R6_DESC_BASE<"dmuh", GPR64Opnd, II_DMUH, mulhs>; -class DMUHU_DESC : MUL_R6_DESC_BASE<"dmuhu", GPR64Opnd, II_DMUHU, mulhu>; -class DMUL_R6_DESC : MUL_R6_DESC_BASE<"dmul", GPR64Opnd, II_DMUL, mul>; -class DMULU_DESC : MUL_R6_DESC_BASE<"dmulu", GPR64Opnd, II_DMUL>; -class LDPC_DESC : PCREL_DESC_BASE<"ldpc", GPR64Opnd, simm18_lsl3, II_LDPC>; -class LWUPC_DESC : PCREL_DESC_BASE<"lwupc", GPR32Opnd, simm19_lsl2, II_LWUPC>; -class LLD_R6_DESC : LL_R6_DESC_BASE<"lld", GPR64Opnd, mem_simmptr, II_LLD>; -class SCD_R6_DESC : SC_R6_DESC_BASE<"scd", GPR64Opnd, II_SCD>; -class SELEQZ64_DESC : SELEQNE_Z_DESC_BASE<"seleqz", GPR64Opnd>; -class SELNEZ64_DESC : SELEQNE_Z_DESC_BASE<"selnez", GPR64Opnd>; - -class BGEC64_DESC : CMP_BC_DESC_BASE<"bgec", brtarget, GPR64Opnd>; -class BGEUC64_DESC : CMP_BC_DESC_BASE<"bgeuc", brtarget, GPR64Opnd>; -class BEQC64_DESC : CMP_BC_DESC_BASE<"beqc", brtarget, GPR64Opnd>; -class BNEC64_DESC : CMP_BC_DESC_BASE<"bnec", brtarget, GPR64Opnd>; -class BLTC64_DESC : CMP_BC_DESC_BASE<"bltc", brtarget, GPR64Opnd>; -class BLTUC64_DESC : CMP_BC_DESC_BASE<"bltuc", brtarget, GPR64Opnd>; -class BLTZC64_DESC : CMP_CBR_RT_Z_DESC_BASE<"bltzc", brtarget, GPR64Opnd>; -class BGEZC64_DESC : CMP_CBR_RT_Z_DESC_BASE<"bgezc", brtarget, GPR64Opnd>; -class BLEZC64_DESC : CMP_CBR_RT_Z_DESC_BASE<"blezc", brtarget, GPR64Opnd>; -class BGTZC64_DESC : CMP_CBR_RT_Z_DESC_BASE<"bgtzc", brtarget, GPR64Opnd>; -class BEQZC64_DESC : CMP_CBR_EQNE_Z_DESC_BASE<"beqzc", brtarget21, GPR64Opnd>; -class BNEZC64_DESC : CMP_CBR_EQNE_Z_DESC_BASE<"bnezc", brtarget21, GPR64Opnd>; - -class JIALC64_DESC : JMP_IDX_COMPACT_DESC_BASE<"jialc", calloffset16, - GPR64Opnd, II_JIALC> { - bit isCall = 1; - list<Register> Defs = [RA]; -} - -class JIC64_DESC : JMP_IDX_COMPACT_DESC_BASE<"jic", jmpoffset16, GPR64Opnd, - II_JIC> { - bit isBarrier = 1; - bit isTerminator = 1; - list<Register> Defs = [AT]; -} - -class LL64_R6_DESC : LL_R6_DESC_BASE<"ll", GPR32Opnd, mem_simm9, II_LL>; -class SC64_R6_DESC : SC_R6_DESC_BASE<"sc", GPR32Opnd, II_SC>; - -class JR_HB64_R6_DESC : JR_HB_DESC_BASE<"jr.hb", GPR64Opnd> { - bit isBranch = 1; - bit isIndirectBranch = 1; - bit hasDelaySlot = 1; - bit isTerminator=1; - bit isBarrier=1; - bit isCTI = 1; - InstrItinClass Itinerary = II_JR_HB; -} - -class CRC32D_DESC : CRC_DESC_BASE<"crc32d", GPR32Opnd, II_CRC32D>; -class CRC32CD_DESC : CRC_DESC_BASE<"crc32cd", GPR32Opnd, II_CRC32CD>; - -//===----------------------------------------------------------------------===// -// -// Instruction Definitions -// -//===----------------------------------------------------------------------===// - -let AdditionalPredicates = [NotInMicroMips] in { - let DecoderMethod = "DecodeDAHIDATI" in { - def DATI : DATI_ENC, DATI_DESC, ISA_MIPS64R6; - def DAHI : DAHI_ENC, DAHI_DESC, ISA_MIPS64R6; - } - def DAUI : DAUI_ENC, DAUI_DESC, ISA_MIPS64R6; - def DALIGN : DALIGN_ENC, DALIGN_DESC, ISA_MIPS64R6; - def DBITSWAP : DBITSWAP_ENC, DBITSWAP_DESC, ISA_MIPS64R6; - def DCLO_R6 : DCLO_R6_ENC, DCLO_R6_DESC, ISA_MIPS64R6; - def DCLZ_R6 : DCLZ_R6_ENC, DCLZ_R6_DESC, ISA_MIPS64R6; - def DDIV : DDIV_ENC, DDIV_DESC, ISA_MIPS64R6; - def DDIVU : DDIVU_ENC, DDIVU_DESC, ISA_MIPS64R6; - def DMOD : DMOD_ENC, DMOD_DESC, ISA_MIPS64R6; - def DMODU : DMODU_ENC, DMODU_DESC, ISA_MIPS64R6; - def DLSA_R6 : DLSA_R6_ENC, DLSA_R6_DESC, ISA_MIPS64R6; - def DMUH: DMUH_ENC, DMUH_DESC, ISA_MIPS64R6; - def DMUHU: DMUHU_ENC, DMUHU_DESC, ISA_MIPS64R6; - def DMUL_R6: DMUL_R6_ENC, DMUL_R6_DESC, ISA_MIPS64R6; - def DMULU: DMULU_ENC, DMULU_DESC, ISA_MIPS64R6; - def LLD_R6 : LLD_R6_ENC, LLD_R6_DESC, ISA_MIPS64R6; -} -def LDPC: LDPC_ENC, LDPC_DESC, ISA_MIPS64R6; -def LWUPC : LWUPC_ENC, LWUPC_DESC, ISA_MIPS64R6; -def SCD_R6 : SCD_R6_ENC, SCD_R6_DESC, ISA_MIPS32R6; -let DecoderNamespace = "Mips32r6_64r6_GP64" in { - def SELEQZ64 : SELEQZ_ENC, SELEQZ64_DESC, ISA_MIPS32R6, GPR_64; - def SELNEZ64 : SELNEZ_ENC, SELNEZ64_DESC, ISA_MIPS32R6, GPR_64; - def JR_HB64_R6 : JR_HB_R6_ENC, JR_HB64_R6_DESC, ISA_MIPS32R6; -} -let AdditionalPredicates = [NotInMicroMips], - DecoderNamespace = "Mips32r6_64r6_PTR64" in { - def LL64_R6 : LL_R6_ENC, LL64_R6_DESC, PTR_64, ISA_MIPS64R6; - def SC64_R6 : SC_R6_ENC, SC64_R6_DESC, PTR_64, ISA_MIPS64R6; -} - -let DecoderNamespace = "Mips32r6_64r6_GP64" in { -// Jump and Branch Instructions -def JIALC64 : JIALC_ENC, JIALC64_DESC, ISA_MIPS64R6, GPR_64; -def JIC64 : JIC_ENC, JIC64_DESC, ISA_MIPS64R6, GPR_64; - -def BEQC64 : BEQC_ENC, BEQC64_DESC, ISA_MIPS64R6, GPR_64; -def BEQZC64 : BEQZC_ENC, BEQZC64_DESC, ISA_MIPS64R6, GPR_64; -def BGEC64 : BGEC_ENC, BGEC64_DESC, ISA_MIPS64R6, GPR_64; -def BGEUC64 : BGEUC_ENC, BGEUC64_DESC, ISA_MIPS64R6, GPR_64; -def BGTZC64 : BGTZC_ENC, BGTZC64_DESC, ISA_MIPS64R6, GPR_64; -def BLEZC64 : BLEZC_ENC, BLEZC64_DESC, ISA_MIPS64R6, GPR_64; -def BLTC64 : BLTC_ENC, BLTC64_DESC, ISA_MIPS64R6, GPR_64; -def BLTUC64 : BLTUC_ENC, BLTUC64_DESC, ISA_MIPS64R6, GPR_64; -def BNEC64 : BNEC_ENC, BNEC64_DESC, ISA_MIPS64R6, GPR_64; -def BNEZC64 : BNEZC_ENC, BNEZC64_DESC, ISA_MIPS64R6, GPR_64; -} -let DecoderNamespace = "Mips32r6_64r6_BranchZero" in { -def BLTZC64 : BLTZC_ENC, BLTZC64_DESC, ISA_MIPS64R6, GPR_64; -def BGEZC64 : BGEZC_ENC, BGEZC64_DESC, ISA_MIPS64R6, GPR_64; -} -let AdditionalPredicates = [NotInMicroMips] in { - def CRC32D : R6MMR6Rel, CRC32D_ENC, CRC32D_DESC, ISA_MIPS64R6, ASE_CRC; - def CRC32CD : R6MMR6Rel, CRC32CD_ENC, CRC32CD_DESC, ISA_MIPS64R6, ASE_CRC; -} - -//===----------------------------------------------------------------------===// -// -// Instruction Aliases -// -//===----------------------------------------------------------------------===// - -def : MipsInstAlias<"jr $rs", (JALR64 ZERO_64, GPR64Opnd:$rs), 1>, ISA_MIPS64R6; - -def : MipsInstAlias<"jrc $rs", (JIC64 GPR64Opnd:$rs, 0), 1>, ISA_MIPS64R6; - -def : MipsInstAlias<"jalrc $rs", (JIALC64 GPR64Opnd:$rs, 0), 1>, ISA_MIPS64R6; -//===----------------------------------------------------------------------===// -// -// Patterns and Pseudo Instructions -// -//===----------------------------------------------------------------------===// - -// i64 selects -def : MipsPat<(select i64:$cond, i64:$t, i64:$f), - (OR64 (SELNEZ64 i64:$t, i64:$cond), - (SELEQZ64 i64:$f, i64:$cond))>, - ISA_MIPS64R6; -def : MipsPat<(select (i32 (seteq i64:$cond, immz)), i64:$t, i64:$f), - (OR64 (SELEQZ64 i64:$t, i64:$cond), - (SELNEZ64 i64:$f, i64:$cond))>, - ISA_MIPS64R6; -def : MipsPat<(select (i32 (setne i64:$cond, immz)), i64:$t, i64:$f), - (OR64 (SELNEZ64 i64:$t, i64:$cond), - (SELEQZ64 i64:$f, i64:$cond))>, - ISA_MIPS64R6; -def : MipsPat<(select (i32 (seteq i64:$cond, immZExt16_64:$imm)), i64:$t, i64:$f), - (OR64 (SELEQZ64 i64:$t, (XORi64 i64:$cond, immZExt16_64:$imm)), - (SELNEZ64 i64:$f, (XORi64 i64:$cond, immZExt16_64:$imm)))>, - ISA_MIPS64R6; -def : MipsPat<(select (i32 (setne i64:$cond, immZExt16_64:$imm)), i64:$t, i64:$f), - (OR64 (SELNEZ64 i64:$t, (XORi64 i64:$cond, immZExt16_64:$imm)), - (SELEQZ64 i64:$f, (XORi64 i64:$cond, immZExt16_64:$imm)))>, - ISA_MIPS64R6; -def : MipsPat< - (select (i32 (setgt i64:$cond, immSExt16Plus1:$imm)), i64:$t, i64:$f), - (OR64 (SELEQZ64 i64:$t, - (SUBREG_TO_REG (i64 0), (SLTi64 i64:$cond, (Plus1 imm:$imm)), - sub_32)), - (SELNEZ64 i64:$f, - (SUBREG_TO_REG (i64 0), (SLTi64 i64:$cond, (Plus1 imm:$imm)), - sub_32)))>, - ISA_MIPS64R6; -def : MipsPat< - (select (i32 (setugt i64:$cond, immSExt16Plus1:$imm)), i64:$t, i64:$f), - (OR64 (SELEQZ64 i64:$t, - (SUBREG_TO_REG (i64 0), (SLTiu64 i64:$cond, (Plus1 imm:$imm)), - sub_32)), - (SELNEZ64 i64:$f, - (SUBREG_TO_REG (i64 0), (SLTiu64 i64:$cond, (Plus1 imm:$imm)), - sub_32)))>, - ISA_MIPS64R6; - -def : MipsPat<(select (i32 (setne i64:$cond, immz)), i64:$t, immz), - (SELNEZ64 i64:$t, i64:$cond)>, ISA_MIPS64R6; -def : MipsPat<(select (i32 (seteq i64:$cond, immz)), i64:$t, immz), - (SELEQZ64 i64:$t, i64:$cond)>, ISA_MIPS64R6; -def : MipsPat<(select (i32 (setne i64:$cond, immz)), immz, i64:$f), - (SELEQZ64 i64:$f, i64:$cond)>, ISA_MIPS64R6; -def : MipsPat<(select (i32 (seteq i64:$cond, immz)), immz, i64:$f), - (SELNEZ64 i64:$f, i64:$cond)>, ISA_MIPS64R6; - -// i64 selects from an i32 comparison -// One complicating factor here is that bits 32-63 of an i32 are undefined. -// FIXME: Ideally, setcc would always produce an i64 on MIPS64 targets. -// This would allow us to remove the sign-extensions here. -def : MipsPat<(select i32:$cond, i64:$t, i64:$f), - (OR64 (SELNEZ64 i64:$t, (SLL64_32 i32:$cond)), - (SELEQZ64 i64:$f, (SLL64_32 i32:$cond)))>, - ISA_MIPS64R6; -def : MipsPat<(select (i32 (seteq i32:$cond, immz)), i64:$t, i64:$f), - (OR64 (SELEQZ64 i64:$t, (SLL64_32 i32:$cond)), - (SELNEZ64 i64:$f, (SLL64_32 i32:$cond)))>, - ISA_MIPS64R6; -def : MipsPat<(select (i32 (setne i32:$cond, immz)), i64:$t, i64:$f), - (OR64 (SELNEZ64 i64:$t, (SLL64_32 i32:$cond)), - (SELEQZ64 i64:$f, (SLL64_32 i32:$cond)))>, - ISA_MIPS64R6; -def : MipsPat<(select (i32 (seteq i32:$cond, immZExt16:$imm)), i64:$t, i64:$f), - (OR64 (SELEQZ64 i64:$t, (SLL64_32 (XORi i32:$cond, - immZExt16:$imm))), - (SELNEZ64 i64:$f, (SLL64_32 (XORi i32:$cond, - immZExt16:$imm))))>, - ISA_MIPS64R6; -def : MipsPat<(select (i32 (setne i32:$cond, immZExt16:$imm)), i64:$t, i64:$f), - (OR64 (SELNEZ64 i64:$t, (SLL64_32 (XORi i32:$cond, - immZExt16:$imm))), - (SELEQZ64 i64:$f, (SLL64_32 (XORi i32:$cond, - immZExt16:$imm))))>, - ISA_MIPS64R6; - -def : MipsPat<(select i32:$cond, i64:$t, immz), - (SELNEZ64 i64:$t, (SLL64_32 i32:$cond))>, - ISA_MIPS64R6; -def : MipsPat<(select (i32 (setne i32:$cond, immz)), i64:$t, immz), - (SELNEZ64 i64:$t, (SLL64_32 i32:$cond))>, - ISA_MIPS64R6; -def : MipsPat<(select (i32 (seteq i32:$cond, immz)), i64:$t, immz), - (SELEQZ64 i64:$t, (SLL64_32 i32:$cond))>, - ISA_MIPS64R6; -def : MipsPat<(select i32:$cond, immz, i64:$f), - (SELEQZ64 i64:$f, (SLL64_32 i32:$cond))>, - ISA_MIPS64R6; -def : MipsPat<(select (i32 (setne i32:$cond, immz)), immz, i64:$f), - (SELEQZ64 i64:$f, (SLL64_32 i32:$cond))>, - ISA_MIPS64R6; -def : MipsPat<(select (i32 (seteq i32:$cond, immz)), immz, i64:$f), - (SELNEZ64 i64:$f, (SLL64_32 i32:$cond))>, - ISA_MIPS64R6; - -// Patterns used for matching away redundant sign extensions. -// MIPS32 arithmetic instructions sign extend their result implicitly. -def : MipsPat<(i64 (sext (i32 (mul GPR32:$src, GPR32:$src2)))), - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), - (MUL_R6 GPR32:$src, GPR32:$src2), sub_32)>, ISA_MIPS64R6; -def : MipsPat<(i64 (sext (i32 (sdiv GPR32:$src, GPR32:$src2)))), - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), - (DIV GPR32:$src, GPR32:$src2), sub_32)>, ISA_MIPS64R6; -def : MipsPat<(i64 (sext (i32 (udiv GPR32:$src, GPR32:$src2)))), - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), - (DIVU GPR32:$src, GPR32:$src2), sub_32)>, ISA_MIPS64R6; -def : MipsPat<(i64 (sext (i32 (srem GPR32:$src, GPR32:$src2)))), - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), - (MOD GPR32:$src, GPR32:$src2), sub_32)>, ISA_MIPS64R6; -def : MipsPat<(i64 (sext (i32 (urem GPR32:$src, GPR32:$src2)))), - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), - (MODU GPR32:$src, GPR32:$src2), sub_32)>, ISA_MIPS64R6; - -// Pseudo instructions - -let AdditionalPredicates = [NotInMips16Mode, NotInMicroMips, - NoIndirectJumpGuards] in { - def TAILCALL64R6REG : TailCallRegR6<JALR64, ZERO_64, GPR64Opnd>, ISA_MIPS64R6; - def PseudoIndirectBranch64R6 : PseudoIndirectBranchBaseR6<JALR64, ZERO_64, - GPR64Opnd>, - ISA_MIPS64R6; -} - -let AdditionalPredicates = [NotInMips16Mode, NotInMicroMips, - UseIndirectJumpsHazard] in { - def TAILCALLHB64R6REG : TailCallReg<JR_HB64_R6, GPR64Opnd>, - ISA_MIPS64R6; - def PseudoIndrectHazardBranch64R6 : PseudoIndirectBranchBase<JR_HB64_R6, - GPR64Opnd>, - ISA_MIPS64R6; -} diff --git a/contrib/llvm/lib/Target/Mips/MipsAnalyzeImmediate.cpp b/contrib/llvm/lib/Target/Mips/MipsAnalyzeImmediate.cpp deleted file mode 100644 index ae2b83c414db..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsAnalyzeImmediate.cpp +++ /dev/null @@ -1,157 +0,0 @@ -//===- MipsAnalyzeImmediate.cpp - Analyze Immediates ----------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "MipsAnalyzeImmediate.h" -#include "Mips.h" -#include "llvm/Support/MathExtras.h" -#include <cassert> -#include <cstdint> -#include <iterator> - -using namespace llvm; - -MipsAnalyzeImmediate::Inst::Inst(unsigned O, unsigned I) : Opc(O), ImmOpnd(I) {} - -// Add I to the instruction sequences. -void MipsAnalyzeImmediate::AddInstr(InstSeqLs &SeqLs, const Inst &I) { - // Add an instruction seqeunce consisting of just I. - if (SeqLs.empty()) { - SeqLs.push_back(InstSeq(1, I)); - return; - } - - for (InstSeqLs::iterator Iter = SeqLs.begin(); Iter != SeqLs.end(); ++Iter) - Iter->push_back(I); -} - -void MipsAnalyzeImmediate::GetInstSeqLsADDiu(uint64_t Imm, unsigned RemSize, - InstSeqLs &SeqLs) { - GetInstSeqLs((Imm + 0x8000ULL) & 0xffffffffffff0000ULL, RemSize, SeqLs); - AddInstr(SeqLs, Inst(ADDiu, Imm & 0xffffULL)); -} - -void MipsAnalyzeImmediate::GetInstSeqLsORi(uint64_t Imm, unsigned RemSize, - InstSeqLs &SeqLs) { - GetInstSeqLs(Imm & 0xffffffffffff0000ULL, RemSize, SeqLs); - AddInstr(SeqLs, Inst(ORi, Imm & 0xffffULL)); -} - -void MipsAnalyzeImmediate::GetInstSeqLsSLL(uint64_t Imm, unsigned RemSize, - InstSeqLs &SeqLs) { - unsigned Shamt = countTrailingZeros(Imm); - GetInstSeqLs(Imm >> Shamt, RemSize - Shamt, SeqLs); - AddInstr(SeqLs, Inst(SLL, Shamt)); -} - -void MipsAnalyzeImmediate::GetInstSeqLs(uint64_t Imm, unsigned RemSize, - InstSeqLs &SeqLs) { - uint64_t MaskedImm = Imm & (0xffffffffffffffffULL >> (64 - Size)); - - // Do nothing if Imm is 0. - if (!MaskedImm) - return; - - // A single ADDiu will do if RemSize <= 16. - if (RemSize <= 16) { - AddInstr(SeqLs, Inst(ADDiu, MaskedImm)); - return; - } - - // Shift if the lower 16-bit is cleared. - if (!(Imm & 0xffff)) { - GetInstSeqLsSLL(Imm, RemSize, SeqLs); - return; - } - - GetInstSeqLsADDiu(Imm, RemSize, SeqLs); - - // If bit 15 is cleared, it doesn't make a difference whether the last - // instruction is an ADDiu or ORi. In that case, do not call GetInstSeqLsORi. - if (Imm & 0x8000) { - InstSeqLs SeqLsORi; - GetInstSeqLsORi(Imm, RemSize, SeqLsORi); - SeqLs.append(std::make_move_iterator(SeqLsORi.begin()), - std::make_move_iterator(SeqLsORi.end())); - } -} - -// Replace a ADDiu & SLL pair with a LUi. -// e.g. the following two instructions -// ADDiu 0x0111 -// SLL 18 -// are replaced with -// LUi 0x444 -void MipsAnalyzeImmediate::ReplaceADDiuSLLWithLUi(InstSeq &Seq) { - // Check if the first two instructions are ADDiu and SLL and the shift amount - // is at least 16. - if ((Seq.size() < 2) || (Seq[0].Opc != ADDiu) || - (Seq[1].Opc != SLL) || (Seq[1].ImmOpnd < 16)) - return; - - // Sign-extend and shift operand of ADDiu and see if it still fits in 16-bit. - int64_t Imm = SignExtend64<16>(Seq[0].ImmOpnd); - int64_t ShiftedImm = (uint64_t)Imm << (Seq[1].ImmOpnd - 16); - - if (!isInt<16>(ShiftedImm)) - return; - - // Replace the first instruction and erase the second. - Seq[0].Opc = LUi; - Seq[0].ImmOpnd = (unsigned)(ShiftedImm & 0xffff); - Seq.erase(Seq.begin() + 1); -} - -void MipsAnalyzeImmediate::GetShortestSeq(InstSeqLs &SeqLs, InstSeq &Insts) { - InstSeqLs::iterator ShortestSeq = SeqLs.end(); - // The length of an instruction sequence is at most 7. - unsigned ShortestLength = 8; - - for (InstSeqLs::iterator S = SeqLs.begin(); S != SeqLs.end(); ++S) { - ReplaceADDiuSLLWithLUi(*S); - assert(S->size() <= 7); - - if (S->size() < ShortestLength) { - ShortestSeq = S; - ShortestLength = S->size(); - } - } - - Insts.clear(); - Insts.append(ShortestSeq->begin(), ShortestSeq->end()); -} - -const MipsAnalyzeImmediate::InstSeq -&MipsAnalyzeImmediate::Analyze(uint64_t Imm, unsigned Size, - bool LastInstrIsADDiu) { - this->Size = Size; - - if (Size == 32) { - ADDiu = Mips::ADDiu; - ORi = Mips::ORi; - SLL = Mips::SLL; - LUi = Mips::LUi; - } else { - ADDiu = Mips::DADDiu; - ORi = Mips::ORi64; - SLL = Mips::DSLL; - LUi = Mips::LUi64; - } - - InstSeqLs SeqLs; - - // Get the list of instruction sequences. - if (LastInstrIsADDiu | !Imm) - GetInstSeqLsADDiu(Imm, Size, SeqLs); - else - GetInstSeqLs(Imm, Size, SeqLs); - - // Set Insts to the shortest instruction sequence. - GetShortestSeq(SeqLs, Insts); - - return Insts; -} diff --git a/contrib/llvm/lib/Target/Mips/MipsAnalyzeImmediate.h b/contrib/llvm/lib/Target/Mips/MipsAnalyzeImmediate.h deleted file mode 100644 index 018b9d824526..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsAnalyzeImmediate.h +++ /dev/null @@ -1,66 +0,0 @@ -//===- MipsAnalyzeImmediate.h - Analyze Immediates -------------*- C++ -*--===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_MIPS_MIPSANALYZEIMMEDIATE_H -#define LLVM_LIB_TARGET_MIPS_MIPSANALYZEIMMEDIATE_H - -#include "llvm/ADT/SmallVector.h" -#include <cstdint> - -namespace llvm { - - class MipsAnalyzeImmediate { - public: - struct Inst { - unsigned Opc, ImmOpnd; - - Inst(unsigned Opc, unsigned ImmOpnd); - }; - using InstSeq = SmallVector<Inst, 7>; - - /// Analyze - Get an instruction sequence to load immediate Imm. The last - /// instruction in the sequence must be an ADDiu if LastInstrIsADDiu is - /// true; - const InstSeq &Analyze(uint64_t Imm, unsigned Size, bool LastInstrIsADDiu); - - private: - using InstSeqLs = SmallVector<InstSeq, 5>; - - /// AddInstr - Add I to all instruction sequences in SeqLs. - void AddInstr(InstSeqLs &SeqLs, const Inst &I); - - /// GetInstSeqLsADDiu - Get instruction sequences which end with an ADDiu to - /// load immediate Imm - void GetInstSeqLsADDiu(uint64_t Imm, unsigned RemSize, InstSeqLs &SeqLs); - - /// GetInstSeqLsORi - Get instrutcion sequences which end with an ORi to - /// load immediate Imm - void GetInstSeqLsORi(uint64_t Imm, unsigned RemSize, InstSeqLs &SeqLs); - - /// GetInstSeqLsSLL - Get instruction sequences which end with a SLL to - /// load immediate Imm - void GetInstSeqLsSLL(uint64_t Imm, unsigned RemSize, InstSeqLs &SeqLs); - - /// GetInstSeqLs - Get instruction sequences to load immediate Imm. - void GetInstSeqLs(uint64_t Imm, unsigned RemSize, InstSeqLs &SeqLs); - - /// ReplaceADDiuSLLWithLUi - Replace an ADDiu & SLL pair with a LUi. - void ReplaceADDiuSLLWithLUi(InstSeq &Seq); - - /// GetShortestSeq - Find the shortest instruction sequence in SeqLs and - /// return it in Insts. - void GetShortestSeq(InstSeqLs &SeqLs, InstSeq &Insts); - - unsigned Size; - unsigned ADDiu, ORi, SLL, LUi; - InstSeq Insts; - }; - -} // end namespace llvm - -#endif // LLVM_LIB_TARGET_MIPS_MIPSANALYZEIMMEDIATE_H diff --git a/contrib/llvm/lib/Target/Mips/MipsAsmPrinter.cpp b/contrib/llvm/lib/Target/Mips/MipsAsmPrinter.cpp deleted file mode 100644 index db83fe49cec0..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsAsmPrinter.cpp +++ /dev/null @@ -1,1304 +0,0 @@ -//===- MipsAsmPrinter.cpp - Mips LLVM Assembly Printer --------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains a printer that converts from our internal representation -// of machine-dependent LLVM code to GAS-format MIPS assembly language. -// -//===----------------------------------------------------------------------===// - -#include "MipsAsmPrinter.h" -#include "MCTargetDesc/MipsABIInfo.h" -#include "MCTargetDesc/MipsBaseInfo.h" -#include "MCTargetDesc/MipsInstPrinter.h" -#include "MCTargetDesc/MipsMCNaCl.h" -#include "MCTargetDesc/MipsMCTargetDesc.h" -#include "Mips.h" -#include "MipsMCInstLower.h" -#include "MipsMachineFunction.h" -#include "MipsSubtarget.h" -#include "MipsTargetMachine.h" -#include "MipsTargetStreamer.h" -#include "TargetInfo/MipsTargetInfo.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Triple.h" -#include "llvm/ADT/Twine.h" -#include "llvm/BinaryFormat/ELF.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/MachineConstantPool.h" -#include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/CodeGen/MachineJumpTableInfo.h" -#include "llvm/CodeGen/MachineOperand.h" -#include "llvm/CodeGen/TargetRegisterInfo.h" -#include "llvm/CodeGen/TargetSubtargetInfo.h" -#include "llvm/IR/Attributes.h" -#include "llvm/IR/BasicBlock.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/InlineAsm.h" -#include "llvm/IR/Instructions.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCInst.h" -#include "llvm/MC/MCInstBuilder.h" -#include "llvm/MC/MCObjectFileInfo.h" -#include "llvm/MC/MCSectionELF.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/MC/MCSymbolELF.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/TargetRegistry.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetMachine.h" -#include <cassert> -#include <cstdint> -#include <map> -#include <memory> -#include <string> -#include <vector> - -using namespace llvm; - -#define DEBUG_TYPE "mips-asm-printer" - -extern cl::opt<bool> EmitJalrReloc; - -MipsTargetStreamer &MipsAsmPrinter::getTargetStreamer() const { - return static_cast<MipsTargetStreamer &>(*OutStreamer->getTargetStreamer()); -} - -bool MipsAsmPrinter::runOnMachineFunction(MachineFunction &MF) { - Subtarget = &MF.getSubtarget<MipsSubtarget>(); - - MipsFI = MF.getInfo<MipsFunctionInfo>(); - if (Subtarget->inMips16Mode()) - for (std::map< - const char *, - const Mips16HardFloatInfo::FuncSignature *>::const_iterator - it = MipsFI->StubsNeeded.begin(); - it != MipsFI->StubsNeeded.end(); ++it) { - const char *Symbol = it->first; - const Mips16HardFloatInfo::FuncSignature *Signature = it->second; - if (StubsNeeded.find(Symbol) == StubsNeeded.end()) - StubsNeeded[Symbol] = Signature; - } - MCP = MF.getConstantPool(); - - // In NaCl, all indirect jump targets must be aligned to bundle size. - if (Subtarget->isTargetNaCl()) - NaClAlignIndirectJumpTargets(MF); - - AsmPrinter::runOnMachineFunction(MF); - - emitXRayTable(); - - return true; -} - -bool MipsAsmPrinter::lowerOperand(const MachineOperand &MO, MCOperand &MCOp) { - MCOp = MCInstLowering.LowerOperand(MO); - return MCOp.isValid(); -} - -#include "MipsGenMCPseudoLowering.inc" - -// Lower PseudoReturn/PseudoIndirectBranch/PseudoIndirectBranch64 to JR, JR_MM, -// JALR, or JALR64 as appropriate for the target. -void MipsAsmPrinter::emitPseudoIndirectBranch(MCStreamer &OutStreamer, - const MachineInstr *MI) { - bool HasLinkReg = false; - bool InMicroMipsMode = Subtarget->inMicroMipsMode(); - MCInst TmpInst0; - - if (Subtarget->hasMips64r6()) { - // MIPS64r6 should use (JALR64 ZERO_64, $rs) - TmpInst0.setOpcode(Mips::JALR64); - HasLinkReg = true; - } else if (Subtarget->hasMips32r6()) { - // MIPS32r6 should use (JALR ZERO, $rs) - if (InMicroMipsMode) - TmpInst0.setOpcode(Mips::JRC16_MMR6); - else { - TmpInst0.setOpcode(Mips::JALR); - HasLinkReg = true; - } - } else if (Subtarget->inMicroMipsMode()) - // microMIPS should use (JR_MM $rs) - TmpInst0.setOpcode(Mips::JR_MM); - else { - // Everything else should use (JR $rs) - TmpInst0.setOpcode(Mips::JR); - } - - MCOperand MCOp; - - if (HasLinkReg) { - unsigned ZeroReg = Subtarget->isGP64bit() ? Mips::ZERO_64 : Mips::ZERO; - TmpInst0.addOperand(MCOperand::createReg(ZeroReg)); - } - - lowerOperand(MI->getOperand(0), MCOp); - TmpInst0.addOperand(MCOp); - - EmitToStreamer(OutStreamer, TmpInst0); -} - -// If there is an MO_JALR operand, insert: -// -// .reloc tmplabel, R_{MICRO}MIPS_JALR, symbol -// tmplabel: -// -// This is an optimization hint for the linker which may then replace -// an indirect call with a direct branch. -static void emitDirectiveRelocJalr(const MachineInstr &MI, - MCContext &OutContext, - TargetMachine &TM, - MCStreamer &OutStreamer, - const MipsSubtarget &Subtarget) { - for (unsigned int I = MI.getDesc().getNumOperands(), E = MI.getNumOperands(); - I < E; ++I) { - MachineOperand MO = MI.getOperand(I); - if (MO.isMCSymbol() && (MO.getTargetFlags() & MipsII::MO_JALR)) { - MCSymbol *Callee = MO.getMCSymbol(); - if (Callee && !Callee->getName().empty()) { - MCSymbol *OffsetLabel = OutContext.createTempSymbol(); - const MCExpr *OffsetExpr = - MCSymbolRefExpr::create(OffsetLabel, OutContext); - const MCExpr *CaleeExpr = - MCSymbolRefExpr::create(Callee, OutContext); - OutStreamer.EmitRelocDirective - (*OffsetExpr, - Subtarget.inMicroMipsMode() ? "R_MICROMIPS_JALR" : "R_MIPS_JALR", - CaleeExpr, SMLoc(), *TM.getMCSubtargetInfo()); - OutStreamer.EmitLabel(OffsetLabel); - return; - } - } - } -} - -void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) { - MipsTargetStreamer &TS = getTargetStreamer(); - unsigned Opc = MI->getOpcode(); - TS.forbidModuleDirective(); - - if (MI->isDebugValue()) { - SmallString<128> Str; - raw_svector_ostream OS(Str); - - PrintDebugValueComment(MI, OS); - return; - } - if (MI->isDebugLabel()) - return; - - // If we just ended a constant pool, mark it as such. - if (InConstantPool && Opc != Mips::CONSTPOOL_ENTRY) { - OutStreamer->EmitDataRegion(MCDR_DataRegionEnd); - InConstantPool = false; - } - if (Opc == Mips::CONSTPOOL_ENTRY) { - // CONSTPOOL_ENTRY - This instruction represents a floating - // constant pool in the function. The first operand is the ID# - // for this instruction, the second is the index into the - // MachineConstantPool that this is, the third is the size in - // bytes of this constant pool entry. - // The required alignment is specified on the basic block holding this MI. - // - unsigned LabelId = (unsigned)MI->getOperand(0).getImm(); - unsigned CPIdx = (unsigned)MI->getOperand(1).getIndex(); - - // If this is the first entry of the pool, mark it. - if (!InConstantPool) { - OutStreamer->EmitDataRegion(MCDR_DataRegion); - InConstantPool = true; - } - - OutStreamer->EmitLabel(GetCPISymbol(LabelId)); - - const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx]; - if (MCPE.isMachineConstantPoolEntry()) - EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal); - else - EmitGlobalConstant(MF->getDataLayout(), MCPE.Val.ConstVal); - return; - } - - switch (Opc) { - case Mips::PATCHABLE_FUNCTION_ENTER: - LowerPATCHABLE_FUNCTION_ENTER(*MI); - return; - case Mips::PATCHABLE_FUNCTION_EXIT: - LowerPATCHABLE_FUNCTION_EXIT(*MI); - return; - case Mips::PATCHABLE_TAIL_CALL: - LowerPATCHABLE_TAIL_CALL(*MI); - return; - } - - if (EmitJalrReloc && - (MI->isReturn() || MI->isCall() || MI->isIndirectBranch())) { - emitDirectiveRelocJalr(*MI, OutContext, TM, *OutStreamer, *Subtarget); - } - - MachineBasicBlock::const_instr_iterator I = MI->getIterator(); - MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end(); - - do { - // Do any auto-generated pseudo lowerings. - if (emitPseudoExpansionLowering(*OutStreamer, &*I)) - continue; - - if (I->getOpcode() == Mips::PseudoReturn || - I->getOpcode() == Mips::PseudoReturn64 || - I->getOpcode() == Mips::PseudoIndirectBranch || - I->getOpcode() == Mips::PseudoIndirectBranch64 || - I->getOpcode() == Mips::TAILCALLREG || - I->getOpcode() == Mips::TAILCALLREG64) { - emitPseudoIndirectBranch(*OutStreamer, &*I); - continue; - } - - // The inMips16Mode() test is not permanent. - // Some instructions are marked as pseudo right now which - // would make the test fail for the wrong reason but - // that will be fixed soon. We need this here because we are - // removing another test for this situation downstream in the - // callchain. - // - if (I->isPseudo() && !Subtarget->inMips16Mode() - && !isLongBranchPseudo(I->getOpcode())) - llvm_unreachable("Pseudo opcode found in EmitInstruction()"); - - MCInst TmpInst0; - MCInstLowering.Lower(&*I, TmpInst0); - EmitToStreamer(*OutStreamer, TmpInst0); - } while ((++I != E) && I->isInsideBundle()); // Delay slot check -} - -//===----------------------------------------------------------------------===// -// -// Mips Asm Directives -// -// -- Frame directive "frame Stackpointer, Stacksize, RARegister" -// Describe the stack frame. -// -// -- Mask directives "(f)mask bitmask, offset" -// Tells the assembler which registers are saved and where. -// bitmask - contain a little endian bitset indicating which registers are -// saved on function prologue (e.g. with a 0x80000000 mask, the -// assembler knows the register 31 (RA) is saved at prologue. -// offset - the position before stack pointer subtraction indicating where -// the first saved register on prologue is located. (e.g. with a -// -// Consider the following function prologue: -// -// .frame $fp,48,$ra -// .mask 0xc0000000,-8 -// addiu $sp, $sp, -48 -// sw $ra, 40($sp) -// sw $fp, 36($sp) -// -// With a 0xc0000000 mask, the assembler knows the register 31 (RA) and -// 30 (FP) are saved at prologue. As the save order on prologue is from -// left to right, RA is saved first. A -8 offset means that after the -// stack pointer subtration, the first register in the mask (RA) will be -// saved at address 48-8=40. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// Mask directives -//===----------------------------------------------------------------------===// - -// Create a bitmask with all callee saved registers for CPU or Floating Point -// registers. For CPU registers consider RA, GP and FP for saving if necessary. -void MipsAsmPrinter::printSavedRegsBitmask() { - // CPU and FPU Saved Registers Bitmasks - unsigned CPUBitmask = 0, FPUBitmask = 0; - int CPUTopSavedRegOff, FPUTopSavedRegOff; - - // Set the CPU and FPU Bitmasks - const MachineFrameInfo &MFI = MF->getFrameInfo(); - const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo(); - const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); - // size of stack area to which FP callee-saved regs are saved. - unsigned CPURegSize = TRI->getRegSizeInBits(Mips::GPR32RegClass) / 8; - unsigned FGR32RegSize = TRI->getRegSizeInBits(Mips::FGR32RegClass) / 8; - unsigned AFGR64RegSize = TRI->getRegSizeInBits(Mips::AFGR64RegClass) / 8; - bool HasAFGR64Reg = false; - unsigned CSFPRegsSize = 0; - - for (const auto &I : CSI) { - unsigned Reg = I.getReg(); - unsigned RegNum = TRI->getEncodingValue(Reg); - - // If it's a floating point register, set the FPU Bitmask. - // If it's a general purpose register, set the CPU Bitmask. - if (Mips::FGR32RegClass.contains(Reg)) { - FPUBitmask |= (1 << RegNum); - CSFPRegsSize += FGR32RegSize; - } else if (Mips::AFGR64RegClass.contains(Reg)) { - FPUBitmask |= (3 << RegNum); - CSFPRegsSize += AFGR64RegSize; - HasAFGR64Reg = true; - } else if (Mips::GPR32RegClass.contains(Reg)) - CPUBitmask |= (1 << RegNum); - } - - // FP Regs are saved right below where the virtual frame pointer points to. - FPUTopSavedRegOff = FPUBitmask ? - (HasAFGR64Reg ? -AFGR64RegSize : -FGR32RegSize) : 0; - - // CPU Regs are saved below FP Regs. - CPUTopSavedRegOff = CPUBitmask ? -CSFPRegsSize - CPURegSize : 0; - - MipsTargetStreamer &TS = getTargetStreamer(); - // Print CPUBitmask - TS.emitMask(CPUBitmask, CPUTopSavedRegOff); - - // Print FPUBitmask - TS.emitFMask(FPUBitmask, FPUTopSavedRegOff); -} - -//===----------------------------------------------------------------------===// -// Frame and Set directives -//===----------------------------------------------------------------------===// - -/// Frame Directive -void MipsAsmPrinter::emitFrameDirective() { - const TargetRegisterInfo &RI = *MF->getSubtarget().getRegisterInfo(); - - unsigned stackReg = RI.getFrameRegister(*MF); - unsigned returnReg = RI.getRARegister(); - unsigned stackSize = MF->getFrameInfo().getStackSize(); - - getTargetStreamer().emitFrame(stackReg, stackSize, returnReg); -} - -/// Emit Set directives. -const char *MipsAsmPrinter::getCurrentABIString() const { - switch (static_cast<MipsTargetMachine &>(TM).getABI().GetEnumValue()) { - case MipsABIInfo::ABI::O32: return "abi32"; - case MipsABIInfo::ABI::N32: return "abiN32"; - case MipsABIInfo::ABI::N64: return "abi64"; - default: llvm_unreachable("Unknown Mips ABI"); - } -} - -void MipsAsmPrinter::EmitFunctionEntryLabel() { - MipsTargetStreamer &TS = getTargetStreamer(); - - // NaCl sandboxing requires that indirect call instructions are masked. - // This means that function entry points should be bundle-aligned. - if (Subtarget->isTargetNaCl()) - EmitAlignment(std::max(MF->getAlignment(), MIPS_NACL_BUNDLE_ALIGN)); - - if (Subtarget->inMicroMipsMode()) { - TS.emitDirectiveSetMicroMips(); - TS.setUsesMicroMips(); - TS.updateABIInfo(*Subtarget); - } else - TS.emitDirectiveSetNoMicroMips(); - - if (Subtarget->inMips16Mode()) - TS.emitDirectiveSetMips16(); - else - TS.emitDirectiveSetNoMips16(); - - TS.emitDirectiveEnt(*CurrentFnSym); - OutStreamer->EmitLabel(CurrentFnSym); -} - -/// EmitFunctionBodyStart - Targets can override this to emit stuff before -/// the first basic block in the function. -void MipsAsmPrinter::EmitFunctionBodyStart() { - MipsTargetStreamer &TS = getTargetStreamer(); - - MCInstLowering.Initialize(&MF->getContext()); - - bool IsNakedFunction = MF->getFunction().hasFnAttribute(Attribute::Naked); - if (!IsNakedFunction) - emitFrameDirective(); - - if (!IsNakedFunction) - printSavedRegsBitmask(); - - if (!Subtarget->inMips16Mode()) { - TS.emitDirectiveSetNoReorder(); - TS.emitDirectiveSetNoMacro(); - TS.emitDirectiveSetNoAt(); - } -} - -/// EmitFunctionBodyEnd - Targets can override this to emit stuff after -/// the last basic block in the function. -void MipsAsmPrinter::EmitFunctionBodyEnd() { - MipsTargetStreamer &TS = getTargetStreamer(); - - // There are instruction for this macros, but they must - // always be at the function end, and we can't emit and - // break with BB logic. - if (!Subtarget->inMips16Mode()) { - TS.emitDirectiveSetAt(); - TS.emitDirectiveSetMacro(); - TS.emitDirectiveSetReorder(); - } - TS.emitDirectiveEnd(CurrentFnSym->getName()); - // Make sure to terminate any constant pools that were at the end - // of the function. - if (!InConstantPool) - return; - InConstantPool = false; - OutStreamer->EmitDataRegion(MCDR_DataRegionEnd); -} - -void MipsAsmPrinter::EmitBasicBlockEnd(const MachineBasicBlock &MBB) { - AsmPrinter::EmitBasicBlockEnd(MBB); - MipsTargetStreamer &TS = getTargetStreamer(); - if (MBB.empty()) - TS.emitDirectiveInsn(); -} - -/// isBlockOnlyReachableByFallthough - Return true if the basic block has -/// exactly one predecessor and the control transfer mechanism between -/// the predecessor and this block is a fall-through. -bool MipsAsmPrinter::isBlockOnlyReachableByFallthrough(const MachineBasicBlock* - MBB) const { - // The predecessor has to be immediately before this block. - const MachineBasicBlock *Pred = *MBB->pred_begin(); - - // If the predecessor is a switch statement, assume a jump table - // implementation, so it is not a fall through. - if (const BasicBlock *bb = Pred->getBasicBlock()) - if (isa<SwitchInst>(bb->getTerminator())) - return false; - - // If this is a landing pad, it isn't a fall through. If it has no preds, - // then nothing falls through to it. - if (MBB->isEHPad() || MBB->pred_empty()) - return false; - - // If there isn't exactly one predecessor, it can't be a fall through. - MachineBasicBlock::const_pred_iterator PI = MBB->pred_begin(), PI2 = PI; - ++PI2; - - if (PI2 != MBB->pred_end()) - return false; - - // The predecessor has to be immediately before this block. - if (!Pred->isLayoutSuccessor(MBB)) - return false; - - // If the block is completely empty, then it definitely does fall through. - if (Pred->empty()) - return true; - - // Otherwise, check the last instruction. - // Check if the last terminator is an unconditional branch. - MachineBasicBlock::const_iterator I = Pred->end(); - while (I != Pred->begin() && !(--I)->isTerminator()) ; - - return !I->isBarrier(); -} - -// Print out an operand for an inline asm expression. -bool MipsAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, - const char *ExtraCode, raw_ostream &O) { - // Does this asm operand have a single letter operand modifier? - if (ExtraCode && ExtraCode[0]) { - if (ExtraCode[1] != 0) return true; // Unknown modifier. - - const MachineOperand &MO = MI->getOperand(OpNum); - switch (ExtraCode[0]) { - default: - // See if this is a generic print operand - return AsmPrinter::PrintAsmOperand(MI, OpNum, ExtraCode, O); - case 'X': // hex const int - if ((MO.getType()) != MachineOperand::MO_Immediate) - return true; - O << "0x" << Twine::utohexstr(MO.getImm()); - return false; - case 'x': // hex const int (low 16 bits) - if ((MO.getType()) != MachineOperand::MO_Immediate) - return true; - O << "0x" << Twine::utohexstr(MO.getImm() & 0xffff); - return false; - case 'd': // decimal const int - if ((MO.getType()) != MachineOperand::MO_Immediate) - return true; - O << MO.getImm(); - return false; - case 'm': // decimal const int minus 1 - if ((MO.getType()) != MachineOperand::MO_Immediate) - return true; - O << MO.getImm() - 1; - return false; - case 'y': // exact log2 - if ((MO.getType()) != MachineOperand::MO_Immediate) - return true; - if (!isPowerOf2_64(MO.getImm())) - return true; - O << Log2_64(MO.getImm()); - return false; - case 'z': - // $0 if zero, regular printing otherwise - if (MO.getType() == MachineOperand::MO_Immediate && MO.getImm() == 0) { - O << "$0"; - return false; - } - // If not, call printOperand as normal. - break; - case 'D': // Second part of a double word register operand - case 'L': // Low order register of a double word register operand - case 'M': // High order register of a double word register operand - { - if (OpNum == 0) - return true; - const MachineOperand &FlagsOP = MI->getOperand(OpNum - 1); - if (!FlagsOP.isImm()) - return true; - unsigned Flags = FlagsOP.getImm(); - unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags); - // Number of registers represented by this operand. We are looking - // for 2 for 32 bit mode and 1 for 64 bit mode. - if (NumVals != 2) { - if (Subtarget->isGP64bit() && NumVals == 1 && MO.isReg()) { - unsigned Reg = MO.getReg(); - O << '$' << MipsInstPrinter::getRegisterName(Reg); - return false; - } - return true; - } - - unsigned RegOp = OpNum; - if (!Subtarget->isGP64bit()){ - // Endianness reverses which register holds the high or low value - // between M and L. - switch(ExtraCode[0]) { - case 'M': - RegOp = (Subtarget->isLittle()) ? OpNum + 1 : OpNum; - break; - case 'L': - RegOp = (Subtarget->isLittle()) ? OpNum : OpNum + 1; - break; - case 'D': // Always the second part - RegOp = OpNum + 1; - } - if (RegOp >= MI->getNumOperands()) - return true; - const MachineOperand &MO = MI->getOperand(RegOp); - if (!MO.isReg()) - return true; - unsigned Reg = MO.getReg(); - O << '$' << MipsInstPrinter::getRegisterName(Reg); - return false; - } - break; - } - case 'w': - // Print MSA registers for the 'f' constraint - // In LLVM, the 'w' modifier doesn't need to do anything. - // We can just call printOperand as normal. - break; - } - } - - printOperand(MI, OpNum, O); - return false; -} - -bool MipsAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, - unsigned OpNum, - const char *ExtraCode, - raw_ostream &O) { - assert(OpNum + 1 < MI->getNumOperands() && "Insufficient operands"); - const MachineOperand &BaseMO = MI->getOperand(OpNum); - const MachineOperand &OffsetMO = MI->getOperand(OpNum + 1); - assert(BaseMO.isReg() && "Unexpected base pointer for inline asm memory operand."); - assert(OffsetMO.isImm() && "Unexpected offset for inline asm memory operand."); - int Offset = OffsetMO.getImm(); - - // Currently we are expecting either no ExtraCode or 'D','M','L'. - if (ExtraCode) { - switch (ExtraCode[0]) { - case 'D': - Offset += 4; - break; - case 'M': - if (Subtarget->isLittle()) - Offset += 4; - break; - case 'L': - if (!Subtarget->isLittle()) - Offset += 4; - break; - default: - return true; // Unknown modifier. - } - } - - O << Offset << "($" << MipsInstPrinter::getRegisterName(BaseMO.getReg()) - << ")"; - - return false; -} - -void MipsAsmPrinter::printOperand(const MachineInstr *MI, int opNum, - raw_ostream &O) { - const MachineOperand &MO = MI->getOperand(opNum); - bool closeP = false; - - if (MO.getTargetFlags()) - closeP = true; - - switch(MO.getTargetFlags()) { - case MipsII::MO_GPREL: O << "%gp_rel("; break; - case MipsII::MO_GOT_CALL: O << "%call16("; break; - case MipsII::MO_GOT: O << "%got("; break; - case MipsII::MO_ABS_HI: O << "%hi("; break; - case MipsII::MO_ABS_LO: O << "%lo("; break; - case MipsII::MO_HIGHER: O << "%higher("; break; - case MipsII::MO_HIGHEST: O << "%highest(("; break; - case MipsII::MO_TLSGD: O << "%tlsgd("; break; - case MipsII::MO_GOTTPREL: O << "%gottprel("; break; - case MipsII::MO_TPREL_HI: O << "%tprel_hi("; break; - case MipsII::MO_TPREL_LO: O << "%tprel_lo("; break; - case MipsII::MO_GPOFF_HI: O << "%hi(%neg(%gp_rel("; break; - case MipsII::MO_GPOFF_LO: O << "%lo(%neg(%gp_rel("; break; - case MipsII::MO_GOT_DISP: O << "%got_disp("; break; - case MipsII::MO_GOT_PAGE: O << "%got_page("; break; - case MipsII::MO_GOT_OFST: O << "%got_ofst("; break; - } - - switch (MO.getType()) { - case MachineOperand::MO_Register: - O << '$' - << StringRef(MipsInstPrinter::getRegisterName(MO.getReg())).lower(); - break; - - case MachineOperand::MO_Immediate: - O << MO.getImm(); - break; - - case MachineOperand::MO_MachineBasicBlock: - MO.getMBB()->getSymbol()->print(O, MAI); - return; - - case MachineOperand::MO_GlobalAddress: - PrintSymbolOperand(MO, O); - break; - - case MachineOperand::MO_BlockAddress: { - MCSymbol *BA = GetBlockAddressSymbol(MO.getBlockAddress()); - O << BA->getName(); - break; - } - - case MachineOperand::MO_ConstantPoolIndex: - O << getDataLayout().getPrivateGlobalPrefix() << "CPI" - << getFunctionNumber() << "_" << MO.getIndex(); - if (MO.getOffset()) - O << "+" << MO.getOffset(); - break; - - default: - llvm_unreachable("<unknown operand type>"); - } - - if (closeP) O << ")"; -} - -void MipsAsmPrinter:: -printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O) { - // Load/Store memory operands -- imm($reg) - // If PIC target the target is loaded as the - // pattern lw $25,%call16($28) - - // opNum can be invalid if instruction has reglist as operand. - // MemOperand is always last operand of instruction (base + offset). - switch (MI->getOpcode()) { - default: - break; - case Mips::SWM32_MM: - case Mips::LWM32_MM: - opNum = MI->getNumOperands() - 2; - break; - } - - printOperand(MI, opNum+1, O); - O << "("; - printOperand(MI, opNum, O); - O << ")"; -} - -void MipsAsmPrinter:: -printMemOperandEA(const MachineInstr *MI, int opNum, raw_ostream &O) { - // when using stack locations for not load/store instructions - // print the same way as all normal 3 operand instructions. - printOperand(MI, opNum, O); - O << ", "; - printOperand(MI, opNum+1, O); -} - -void MipsAsmPrinter:: -printFCCOperand(const MachineInstr *MI, int opNum, raw_ostream &O, - const char *Modifier) { - const MachineOperand &MO = MI->getOperand(opNum); - O << Mips::MipsFCCToString((Mips::CondCode)MO.getImm()); -} - -void MipsAsmPrinter:: -printRegisterList(const MachineInstr *MI, int opNum, raw_ostream &O) { - for (int i = opNum, e = MI->getNumOperands(); i != e; ++i) { - if (i != opNum) O << ", "; - printOperand(MI, i, O); - } -} - -void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) { - MipsTargetStreamer &TS = getTargetStreamer(); - - // MipsTargetStreamer has an initialization order problem when emitting an - // object file directly (see MipsTargetELFStreamer for full details). Work - // around it by re-initializing the PIC state here. - TS.setPic(OutContext.getObjectFileInfo()->isPositionIndependent()); - - // Compute MIPS architecture attributes based on the default subtarget - // that we'd have constructed. Module level directives aren't LTO - // clean anyhow. - // FIXME: For ifunc related functions we could iterate over and look - // for a feature string that doesn't match the default one. - const Triple &TT = TM.getTargetTriple(); - StringRef CPU = MIPS_MC::selectMipsCPU(TT, TM.getTargetCPU()); - StringRef FS = TM.getTargetFeatureString(); - const MipsTargetMachine &MTM = static_cast<const MipsTargetMachine &>(TM); - const MipsSubtarget STI(TT, CPU, FS, MTM.isLittleEndian(), MTM, 0); - - bool IsABICalls = STI.isABICalls(); - const MipsABIInfo &ABI = MTM.getABI(); - if (IsABICalls) { - TS.emitDirectiveAbiCalls(); - // FIXME: This condition should be a lot more complicated that it is here. - // Ideally it should test for properties of the ABI and not the ABI - // itself. - // For the moment, I'm only correcting enough to make MIPS-IV work. - if (!isPositionIndependent() && STI.hasSym32()) - TS.emitDirectiveOptionPic0(); - } - - // Tell the assembler which ABI we are using - std::string SectionName = std::string(".mdebug.") + getCurrentABIString(); - OutStreamer->SwitchSection( - OutContext.getELFSection(SectionName, ELF::SHT_PROGBITS, 0)); - - // NaN: At the moment we only support: - // 1. .nan legacy (default) - // 2. .nan 2008 - STI.isNaN2008() ? TS.emitDirectiveNaN2008() - : TS.emitDirectiveNaNLegacy(); - - // TODO: handle O64 ABI - - TS.updateABIInfo(STI); - - // We should always emit a '.module fp=...' but binutils 2.24 does not accept - // it. We therefore emit it when it contradicts the ABI defaults (-mfpxx or - // -mfp64) and omit it otherwise. - if ((ABI.IsO32() && (STI.isABI_FPXX() || STI.isFP64bit())) || - STI.useSoftFloat()) - TS.emitDirectiveModuleFP(); - - // We should always emit a '.module [no]oddspreg' but binutils 2.24 does not - // accept it. We therefore emit it when it contradicts the default or an - // option has changed the default (i.e. FPXX) and omit it otherwise. - if (ABI.IsO32() && (!STI.useOddSPReg() || STI.isABI_FPXX())) - TS.emitDirectiveModuleOddSPReg(); -} - -void MipsAsmPrinter::emitInlineAsmStart() const { - MipsTargetStreamer &TS = getTargetStreamer(); - - // GCC's choice of assembler options for inline assembly code ('at', 'macro' - // and 'reorder') is different from LLVM's choice for generated code ('noat', - // 'nomacro' and 'noreorder'). - // In order to maintain compatibility with inline assembly code which depends - // on GCC's assembler options being used, we have to switch to those options - // for the duration of the inline assembly block and then switch back. - TS.emitDirectiveSetPush(); - TS.emitDirectiveSetAt(); - TS.emitDirectiveSetMacro(); - TS.emitDirectiveSetReorder(); - OutStreamer->AddBlankLine(); -} - -void MipsAsmPrinter::emitInlineAsmEnd(const MCSubtargetInfo &StartInfo, - const MCSubtargetInfo *EndInfo) const { - OutStreamer->AddBlankLine(); - getTargetStreamer().emitDirectiveSetPop(); -} - -void MipsAsmPrinter::EmitJal(const MCSubtargetInfo &STI, MCSymbol *Symbol) { - MCInst I; - I.setOpcode(Mips::JAL); - I.addOperand( - MCOperand::createExpr(MCSymbolRefExpr::create(Symbol, OutContext))); - OutStreamer->EmitInstruction(I, STI); -} - -void MipsAsmPrinter::EmitInstrReg(const MCSubtargetInfo &STI, unsigned Opcode, - unsigned Reg) { - MCInst I; - I.setOpcode(Opcode); - I.addOperand(MCOperand::createReg(Reg)); - OutStreamer->EmitInstruction(I, STI); -} - -void MipsAsmPrinter::EmitInstrRegReg(const MCSubtargetInfo &STI, - unsigned Opcode, unsigned Reg1, - unsigned Reg2) { - MCInst I; - // - // Because of the current td files for Mips32, the operands for MTC1 - // appear backwards from their normal assembly order. It's not a trivial - // change to fix this in the td file so we adjust for it here. - // - if (Opcode == Mips::MTC1) { - unsigned Temp = Reg1; - Reg1 = Reg2; - Reg2 = Temp; - } - I.setOpcode(Opcode); - I.addOperand(MCOperand::createReg(Reg1)); - I.addOperand(MCOperand::createReg(Reg2)); - OutStreamer->EmitInstruction(I, STI); -} - -void MipsAsmPrinter::EmitInstrRegRegReg(const MCSubtargetInfo &STI, - unsigned Opcode, unsigned Reg1, - unsigned Reg2, unsigned Reg3) { - MCInst I; - I.setOpcode(Opcode); - I.addOperand(MCOperand::createReg(Reg1)); - I.addOperand(MCOperand::createReg(Reg2)); - I.addOperand(MCOperand::createReg(Reg3)); - OutStreamer->EmitInstruction(I, STI); -} - -void MipsAsmPrinter::EmitMovFPIntPair(const MCSubtargetInfo &STI, - unsigned MovOpc, unsigned Reg1, - unsigned Reg2, unsigned FPReg1, - unsigned FPReg2, bool LE) { - if (!LE) { - unsigned temp = Reg1; - Reg1 = Reg2; - Reg2 = temp; - } - EmitInstrRegReg(STI, MovOpc, Reg1, FPReg1); - EmitInstrRegReg(STI, MovOpc, Reg2, FPReg2); -} - -void MipsAsmPrinter::EmitSwapFPIntParams(const MCSubtargetInfo &STI, - Mips16HardFloatInfo::FPParamVariant PV, - bool LE, bool ToFP) { - using namespace Mips16HardFloatInfo; - - unsigned MovOpc = ToFP ? Mips::MTC1 : Mips::MFC1; - switch (PV) { - case FSig: - EmitInstrRegReg(STI, MovOpc, Mips::A0, Mips::F12); - break; - case FFSig: - EmitMovFPIntPair(STI, MovOpc, Mips::A0, Mips::A1, Mips::F12, Mips::F14, LE); - break; - case FDSig: - EmitInstrRegReg(STI, MovOpc, Mips::A0, Mips::F12); - EmitMovFPIntPair(STI, MovOpc, Mips::A2, Mips::A3, Mips::F14, Mips::F15, LE); - break; - case DSig: - EmitMovFPIntPair(STI, MovOpc, Mips::A0, Mips::A1, Mips::F12, Mips::F13, LE); - break; - case DDSig: - EmitMovFPIntPair(STI, MovOpc, Mips::A0, Mips::A1, Mips::F12, Mips::F13, LE); - EmitMovFPIntPair(STI, MovOpc, Mips::A2, Mips::A3, Mips::F14, Mips::F15, LE); - break; - case DFSig: - EmitMovFPIntPair(STI, MovOpc, Mips::A0, Mips::A1, Mips::F12, Mips::F13, LE); - EmitInstrRegReg(STI, MovOpc, Mips::A2, Mips::F14); - break; - case NoSig: - return; - } -} - -void MipsAsmPrinter::EmitSwapFPIntRetval( - const MCSubtargetInfo &STI, Mips16HardFloatInfo::FPReturnVariant RV, - bool LE) { - using namespace Mips16HardFloatInfo; - - unsigned MovOpc = Mips::MFC1; - switch (RV) { - case FRet: - EmitInstrRegReg(STI, MovOpc, Mips::V0, Mips::F0); - break; - case DRet: - EmitMovFPIntPair(STI, MovOpc, Mips::V0, Mips::V1, Mips::F0, Mips::F1, LE); - break; - case CFRet: - EmitMovFPIntPair(STI, MovOpc, Mips::V0, Mips::V1, Mips::F0, Mips::F1, LE); - break; - case CDRet: - EmitMovFPIntPair(STI, MovOpc, Mips::V0, Mips::V1, Mips::F0, Mips::F1, LE); - EmitMovFPIntPair(STI, MovOpc, Mips::A0, Mips::A1, Mips::F2, Mips::F3, LE); - break; - case NoFPRet: - break; - } -} - -void MipsAsmPrinter::EmitFPCallStub( - const char *Symbol, const Mips16HardFloatInfo::FuncSignature *Signature) { - using namespace Mips16HardFloatInfo; - - MCSymbol *MSymbol = OutContext.getOrCreateSymbol(StringRef(Symbol)); - bool LE = getDataLayout().isLittleEndian(); - // Construct a local MCSubtargetInfo here. - // This is because the MachineFunction won't exist (but have not yet been - // freed) and since we're at the global level we can use the default - // constructed subtarget. - std::unique_ptr<MCSubtargetInfo> STI(TM.getTarget().createMCSubtargetInfo( - TM.getTargetTriple().str(), TM.getTargetCPU(), - TM.getTargetFeatureString())); - - // - // .global xxxx - // - OutStreamer->EmitSymbolAttribute(MSymbol, MCSA_Global); - const char *RetType; - // - // make the comment field identifying the return and parameter - // types of the floating point stub - // # Stub function to call rettype xxxx (params) - // - switch (Signature->RetSig) { - case FRet: - RetType = "float"; - break; - case DRet: - RetType = "double"; - break; - case CFRet: - RetType = "complex"; - break; - case CDRet: - RetType = "double complex"; - break; - case NoFPRet: - RetType = ""; - break; - } - const char *Parms; - switch (Signature->ParamSig) { - case FSig: - Parms = "float"; - break; - case FFSig: - Parms = "float, float"; - break; - case FDSig: - Parms = "float, double"; - break; - case DSig: - Parms = "double"; - break; - case DDSig: - Parms = "double, double"; - break; - case DFSig: - Parms = "double, float"; - break; - case NoSig: - Parms = ""; - break; - } - OutStreamer->AddComment("\t# Stub function to call " + Twine(RetType) + " " + - Twine(Symbol) + " (" + Twine(Parms) + ")"); - // - // probably not necessary but we save and restore the current section state - // - OutStreamer->PushSection(); - // - // .section mips16.call.fpxxxx,"ax",@progbits - // - MCSectionELF *M = OutContext.getELFSection( - ".mips16.call.fp." + std::string(Symbol), ELF::SHT_PROGBITS, - ELF::SHF_ALLOC | ELF::SHF_EXECINSTR); - OutStreamer->SwitchSection(M, nullptr); - // - // .align 2 - // - OutStreamer->EmitValueToAlignment(4); - MipsTargetStreamer &TS = getTargetStreamer(); - // - // .set nomips16 - // .set nomicromips - // - TS.emitDirectiveSetNoMips16(); - TS.emitDirectiveSetNoMicroMips(); - // - // .ent __call_stub_fp_xxxx - // .type __call_stub_fp_xxxx,@function - // __call_stub_fp_xxxx: - // - std::string x = "__call_stub_fp_" + std::string(Symbol); - MCSymbolELF *Stub = - cast<MCSymbolELF>(OutContext.getOrCreateSymbol(StringRef(x))); - TS.emitDirectiveEnt(*Stub); - MCSymbol *MType = - OutContext.getOrCreateSymbol("__call_stub_fp_" + Twine(Symbol)); - OutStreamer->EmitSymbolAttribute(MType, MCSA_ELF_TypeFunction); - OutStreamer->EmitLabel(Stub); - - // Only handle non-pic for now. - assert(!isPositionIndependent() && - "should not be here if we are compiling pic"); - TS.emitDirectiveSetReorder(); - // - // We need to add a MipsMCExpr class to MCTargetDesc to fully implement - // stubs without raw text but this current patch is for compiler generated - // functions and they all return some value. - // The calling sequence for non pic is different in that case and we need - // to implement %lo and %hi in order to handle the case of no return value - // See the corresponding method in Mips16HardFloat for details. - // - // mov the return address to S2. - // we have no stack space to store it and we are about to make another call. - // We need to make sure that the enclosing function knows to save S2 - // This should have already been handled. - // - // Mov $18, $31 - - EmitInstrRegRegReg(*STI, Mips::OR, Mips::S2, Mips::RA, Mips::ZERO); - - EmitSwapFPIntParams(*STI, Signature->ParamSig, LE, true); - - // Jal xxxx - // - EmitJal(*STI, MSymbol); - - // fix return values - EmitSwapFPIntRetval(*STI, Signature->RetSig, LE); - // - // do the return - // if (Signature->RetSig == NoFPRet) - // llvm_unreachable("should not be any stubs here with no return value"); - // else - EmitInstrReg(*STI, Mips::JR, Mips::S2); - - MCSymbol *Tmp = OutContext.createTempSymbol(); - OutStreamer->EmitLabel(Tmp); - const MCSymbolRefExpr *E = MCSymbolRefExpr::create(Stub, OutContext); - const MCSymbolRefExpr *T = MCSymbolRefExpr::create(Tmp, OutContext); - const MCExpr *T_min_E = MCBinaryExpr::createSub(T, E, OutContext); - OutStreamer->emitELFSize(Stub, T_min_E); - TS.emitDirectiveEnd(x); - OutStreamer->PopSection(); -} - -void MipsAsmPrinter::EmitEndOfAsmFile(Module &M) { - // Emit needed stubs - // - for (std::map< - const char *, - const Mips16HardFloatInfo::FuncSignature *>::const_iterator - it = StubsNeeded.begin(); - it != StubsNeeded.end(); ++it) { - const char *Symbol = it->first; - const Mips16HardFloatInfo::FuncSignature *Signature = it->second; - EmitFPCallStub(Symbol, Signature); - } - // return to the text section - OutStreamer->SwitchSection(OutContext.getObjectFileInfo()->getTextSection()); -} - -void MipsAsmPrinter::EmitSled(const MachineInstr &MI, SledKind Kind) { - const uint8_t NoopsInSledCount = Subtarget->isGP64bit() ? 15 : 11; - // For mips32 we want to emit the following pattern: - // - // .Lxray_sled_N: - // ALIGN - // B .tmpN - // 11 NOP instructions (44 bytes) - // ADDIU T9, T9, 52 - // .tmpN - // - // We need the 44 bytes (11 instructions) because at runtime, we'd - // be patching over the full 48 bytes (12 instructions) with the following - // pattern: - // - // ADDIU SP, SP, -8 - // NOP - // SW RA, 4(SP) - // SW T9, 0(SP) - // LUI T9, %hi(__xray_FunctionEntry/Exit) - // ORI T9, T9, %lo(__xray_FunctionEntry/Exit) - // LUI T0, %hi(function_id) - // JALR T9 - // ORI T0, T0, %lo(function_id) - // LW T9, 0(SP) - // LW RA, 4(SP) - // ADDIU SP, SP, 8 - // - // We add 52 bytes to t9 because we want to adjust the function pointer to - // the actual start of function i.e. the address just after the noop sled. - // We do this because gp displacement relocation is emitted at the start of - // of the function i.e after the nop sled and to correctly calculate the - // global offset table address, t9 must hold the address of the instruction - // containing the gp displacement relocation. - // FIXME: Is this correct for the static relocation model? - // - // For mips64 we want to emit the following pattern: - // - // .Lxray_sled_N: - // ALIGN - // B .tmpN - // 15 NOP instructions (60 bytes) - // .tmpN - // - // We need the 60 bytes (15 instructions) because at runtime, we'd - // be patching over the full 64 bytes (16 instructions) with the following - // pattern: - // - // DADDIU SP, SP, -16 - // NOP - // SD RA, 8(SP) - // SD T9, 0(SP) - // LUI T9, %highest(__xray_FunctionEntry/Exit) - // ORI T9, T9, %higher(__xray_FunctionEntry/Exit) - // DSLL T9, T9, 16 - // ORI T9, T9, %hi(__xray_FunctionEntry/Exit) - // DSLL T9, T9, 16 - // ORI T9, T9, %lo(__xray_FunctionEntry/Exit) - // LUI T0, %hi(function_id) - // JALR T9 - // ADDIU T0, T0, %lo(function_id) - // LD T9, 0(SP) - // LD RA, 8(SP) - // DADDIU SP, SP, 16 - // - OutStreamer->EmitCodeAlignment(4); - auto CurSled = OutContext.createTempSymbol("xray_sled_", true); - OutStreamer->EmitLabel(CurSled); - auto Target = OutContext.createTempSymbol(); - - // Emit "B .tmpN" instruction, which jumps over the nop sled to the actual - // start of function - const MCExpr *TargetExpr = MCSymbolRefExpr::create( - Target, MCSymbolRefExpr::VariantKind::VK_None, OutContext); - EmitToStreamer(*OutStreamer, MCInstBuilder(Mips::BEQ) - .addReg(Mips::ZERO) - .addReg(Mips::ZERO) - .addExpr(TargetExpr)); - - for (int8_t I = 0; I < NoopsInSledCount; I++) - EmitToStreamer(*OutStreamer, MCInstBuilder(Mips::SLL) - .addReg(Mips::ZERO) - .addReg(Mips::ZERO) - .addImm(0)); - - OutStreamer->EmitLabel(Target); - - if (!Subtarget->isGP64bit()) { - EmitToStreamer(*OutStreamer, - MCInstBuilder(Mips::ADDiu) - .addReg(Mips::T9) - .addReg(Mips::T9) - .addImm(0x34)); - } - - recordSled(CurSled, MI, Kind); -} - -void MipsAsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI) { - EmitSled(MI, SledKind::FUNCTION_ENTER); -} - -void MipsAsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI) { - EmitSled(MI, SledKind::FUNCTION_EXIT); -} - -void MipsAsmPrinter::LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI) { - EmitSled(MI, SledKind::TAIL_CALL); -} - -void MipsAsmPrinter::PrintDebugValueComment(const MachineInstr *MI, - raw_ostream &OS) { - // TODO: implement -} - -// Emit .dtprelword or .dtpreldword directive -// and value for debug thread local expression. -void MipsAsmPrinter::EmitDebugValue(const MCExpr *Value, unsigned Size) const { - if (auto *MipsExpr = dyn_cast<MipsMCExpr>(Value)) { - if (MipsExpr && MipsExpr->getKind() == MipsMCExpr::MEK_DTPREL) { - switch (Size) { - case 4: - OutStreamer->EmitDTPRel32Value(MipsExpr->getSubExpr()); - break; - case 8: - OutStreamer->EmitDTPRel64Value(MipsExpr->getSubExpr()); - break; - default: - llvm_unreachable("Unexpected size of expression value."); - } - return; - } - } - AsmPrinter::EmitDebugValue(Value, Size); -} - -// Align all targets of indirect branches on bundle size. Used only if target -// is NaCl. -void MipsAsmPrinter::NaClAlignIndirectJumpTargets(MachineFunction &MF) { - // Align all blocks that are jumped to through jump table. - if (MachineJumpTableInfo *JtInfo = MF.getJumpTableInfo()) { - const std::vector<MachineJumpTableEntry> &JT = JtInfo->getJumpTables(); - for (unsigned I = 0; I < JT.size(); ++I) { - const std::vector<MachineBasicBlock*> &MBBs = JT[I].MBBs; - - for (unsigned J = 0; J < MBBs.size(); ++J) - MBBs[J]->setAlignment(MIPS_NACL_BUNDLE_ALIGN); - } - } - - // If basic block address is taken, block can be target of indirect branch. - for (auto &MBB : MF) { - if (MBB.hasAddressTaken()) - MBB.setAlignment(MIPS_NACL_BUNDLE_ALIGN); - } -} - -bool MipsAsmPrinter::isLongBranchPseudo(int Opcode) const { - return (Opcode == Mips::LONG_BRANCH_LUi - || Opcode == Mips::LONG_BRANCH_LUi2Op - || Opcode == Mips::LONG_BRANCH_LUi2Op_64 - || Opcode == Mips::LONG_BRANCH_ADDiu - || Opcode == Mips::LONG_BRANCH_ADDiu2Op - || Opcode == Mips::LONG_BRANCH_DADDiu - || Opcode == Mips::LONG_BRANCH_DADDiu2Op); -} - -// Force static initialization. -extern "C" void LLVMInitializeMipsAsmPrinter() { - RegisterAsmPrinter<MipsAsmPrinter> X(getTheMipsTarget()); - RegisterAsmPrinter<MipsAsmPrinter> Y(getTheMipselTarget()); - RegisterAsmPrinter<MipsAsmPrinter> A(getTheMips64Target()); - RegisterAsmPrinter<MipsAsmPrinter> B(getTheMips64elTarget()); -} diff --git a/contrib/llvm/lib/Target/Mips/MipsAsmPrinter.h b/contrib/llvm/lib/Target/Mips/MipsAsmPrinter.h deleted file mode 100644 index 173a1312812e..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsAsmPrinter.h +++ /dev/null @@ -1,165 +0,0 @@ -//===- MipsAsmPrinter.h - Mips LLVM Assembly Printer -----------*- C++ -*--===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Mips Assembly printer class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_MIPS_MIPSASMPRINTER_H -#define LLVM_LIB_TARGET_MIPS_MIPSASMPRINTER_H - -#include "Mips16HardFloatInfo.h" -#include "MipsMCInstLower.h" -#include "MipsSubtarget.h" -#include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/MC/MCStreamer.h" -#include "llvm/Support/Compiler.h" -#include <algorithm> -#include <map> -#include <memory> - -namespace llvm { - -class MCOperand; -class MCSubtargetInfo; -class MCSymbol; -class MachineBasicBlock; -class MachineConstantPool; -class MachineFunction; -class MachineInstr; -class MachineOperand; -class MipsFunctionInfo; -class MipsTargetStreamer; -class Module; -class raw_ostream; -class TargetMachine; - -class LLVM_LIBRARY_VISIBILITY MipsAsmPrinter : public AsmPrinter { - MipsTargetStreamer &getTargetStreamer() const; - - void EmitInstrWithMacroNoAT(const MachineInstr *MI); - - //===------------------------------------------------------------------===// - // XRay implementation - //===------------------------------------------------------------------===// - -public: - // XRay-specific lowering for Mips. - void LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI); - void LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI); - void LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI); - -private: - /// MCP - Keep a pointer to constantpool entries of the current - /// MachineFunction. - const MachineConstantPool *MCP = nullptr; - - /// InConstantPool - Maintain state when emitting a sequence of constant - /// pool entries so we can properly mark them as data regions. - bool InConstantPool = false; - - std::map<const char *, const Mips16HardFloatInfo::FuncSignature *> - StubsNeeded; - - void EmitSled(const MachineInstr &MI, SledKind Kind); - - // tblgen'erated function. - bool emitPseudoExpansionLowering(MCStreamer &OutStreamer, - const MachineInstr *MI); - - // Emit PseudoReturn, PseudoReturn64, PseudoIndirectBranch, - // and PseudoIndirectBranch64 as a JR, JR_MM, JALR, or JALR64 as appropriate - // for the target. - void emitPseudoIndirectBranch(MCStreamer &OutStreamer, - const MachineInstr *MI); - - // lowerOperand - Convert a MachineOperand into the equivalent MCOperand. - bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp); - - void emitInlineAsmStart() const override; - - void emitInlineAsmEnd(const MCSubtargetInfo &StartInfo, - const MCSubtargetInfo *EndInfo) const override; - - void EmitJal(const MCSubtargetInfo &STI, MCSymbol *Symbol); - - void EmitInstrReg(const MCSubtargetInfo &STI, unsigned Opcode, unsigned Reg); - - void EmitInstrRegReg(const MCSubtargetInfo &STI, unsigned Opcode, - unsigned Reg1, unsigned Reg2); - - void EmitInstrRegRegReg(const MCSubtargetInfo &STI, unsigned Opcode, - unsigned Reg1, unsigned Reg2, unsigned Reg3); - - void EmitMovFPIntPair(const MCSubtargetInfo &STI, unsigned MovOpc, - unsigned Reg1, unsigned Reg2, unsigned FPReg1, - unsigned FPReg2, bool LE); - - void EmitSwapFPIntParams(const MCSubtargetInfo &STI, - Mips16HardFloatInfo::FPParamVariant, bool LE, - bool ToFP); - - void EmitSwapFPIntRetval(const MCSubtargetInfo &STI, - Mips16HardFloatInfo::FPReturnVariant, bool LE); - - void EmitFPCallStub(const char *, const Mips16HardFloatInfo::FuncSignature *); - - void NaClAlignIndirectJumpTargets(MachineFunction &MF); - - bool isLongBranchPseudo(int Opcode) const; - -public: - const MipsSubtarget *Subtarget; - const MipsFunctionInfo *MipsFI; - MipsMCInstLower MCInstLowering; - - explicit MipsAsmPrinter(TargetMachine &TM, - std::unique_ptr<MCStreamer> Streamer) - : AsmPrinter(TM, std::move(Streamer)), MCInstLowering(*this) {} - - StringRef getPassName() const override { return "Mips Assembly Printer"; } - - bool runOnMachineFunction(MachineFunction &MF) override; - - void EmitConstantPool() override { - bool UsingConstantPools = - (Subtarget->inMips16Mode() && Subtarget->useConstantIslands()); - if (!UsingConstantPools) - AsmPrinter::EmitConstantPool(); - // we emit constant pools customly! - } - - void EmitInstruction(const MachineInstr *MI) override; - void printSavedRegsBitmask(); - void emitFrameDirective(); - const char *getCurrentABIString() const; - void EmitFunctionEntryLabel() override; - void EmitFunctionBodyStart() override; - void EmitFunctionBodyEnd() override; - void EmitBasicBlockEnd(const MachineBasicBlock &MBB) override; - bool isBlockOnlyReachableByFallthrough( - const MachineBasicBlock* MBB) const override; - bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, - const char *ExtraCode, raw_ostream &O) override; - bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum, - const char *ExtraCode, raw_ostream &O) override; - void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O); - void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O); - void printMemOperandEA(const MachineInstr *MI, int opNum, raw_ostream &O); - void printFCCOperand(const MachineInstr *MI, int opNum, raw_ostream &O, - const char *Modifier = nullptr); - void printRegisterList(const MachineInstr *MI, int opNum, raw_ostream &O); - void EmitStartOfAsmFile(Module &M) override; - void EmitEndOfAsmFile(Module &M) override; - void PrintDebugValueComment(const MachineInstr *MI, raw_ostream &OS); - void EmitDebugValue(const MCExpr *Value, unsigned Size) const override; -}; - -} // end namespace llvm - -#endif // LLVM_LIB_TARGET_MIPS_MIPSASMPRINTER_H diff --git a/contrib/llvm/lib/Target/Mips/MipsBranchExpansion.cpp b/contrib/llvm/lib/Target/Mips/MipsBranchExpansion.cpp deleted file mode 100644 index 1523a6c020aa..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsBranchExpansion.cpp +++ /dev/null @@ -1,863 +0,0 @@ -//===----------------------- MipsBranchExpansion.cpp ----------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// \file -/// -/// This pass do two things: -/// - it expands a branch or jump instruction into a long branch if its offset -/// is too large to fit into its immediate field, -/// - it inserts nops to prevent forbidden slot hazards. -/// -/// The reason why this pass combines these two tasks is that one of these two -/// tasks can break the result of the previous one. -/// -/// Example of that is a situation where at first, no branch should be expanded, -/// but after adding at least one nop somewhere in the code to prevent a -/// forbidden slot hazard, offset of some branches may go out of range. In that -/// case it is necessary to check again if there is some branch that needs -/// expansion. On the other hand, expanding some branch may cause a control -/// transfer instruction to appear in the forbidden slot, which is a hazard that -/// should be fixed. This pass alternates between this two tasks untill no -/// changes are made. Only then we can be sure that all branches are expanded -/// properly, and no hazard situations exist. -/// -/// Regarding branch expanding: -/// -/// When branch instruction like beqzc or bnezc has offset that is too large -/// to fit into its immediate field, it has to be expanded to another -/// instruction or series of instructions. -/// -/// FIXME: Fix pc-region jump instructions which cross 256MB segment boundaries. -/// TODO: Handle out of range bc, b (pseudo) instructions. -/// -/// Regarding compact branch hazard prevention: -/// -/// Hazards handled: forbidden slots for MIPSR6. -/// -/// A forbidden slot hazard occurs when a compact branch instruction is executed -/// and the adjacent instruction in memory is a control transfer instruction -/// such as a branch or jump, ERET, ERETNC, DERET, WAIT and PAUSE. -/// -/// For example: -/// -/// 0x8004 bnec a1,v0,<P+0x18> -/// 0x8008 beqc a1,a2,<P+0x54> -/// -/// In such cases, the processor is required to signal a Reserved Instruction -/// exception. -/// -/// Here, if the instruction at 0x8004 is executed, the processor will raise an -/// exception as there is a control transfer instruction at 0x8008. -/// -/// There are two sources of forbidden slot hazards: -/// -/// A) A previous pass has created a compact branch directly. -/// B) Transforming a delay slot branch into compact branch. This case can be -/// difficult to process as lookahead for hazards is insufficient, as -/// backwards delay slot fillling can also produce hazards in previously -/// processed instuctions. -/// -/// In future this pass can be extended (or new pass can be created) to handle -/// other pipeline hazards, such as various MIPS1 hazards, processor errata that -/// require instruction reorganization, etc. -/// -/// This pass has to run after the delay slot filler as that pass can introduce -/// pipeline hazards such as compact branch hazard, hence the existing hazard -/// recognizer is not suitable. -/// -//===----------------------------------------------------------------------===// - -#include "MCTargetDesc/MipsABIInfo.h" -#include "MCTargetDesc/MipsBaseInfo.h" -#include "MCTargetDesc/MipsMCNaCl.h" -#include "MCTargetDesc/MipsMCTargetDesc.h" -#include "Mips.h" -#include "MipsInstrInfo.h" -#include "MipsMachineFunction.h" -#include "MipsSubtarget.h" -#include "MipsTargetMachine.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/Statistic.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/MachineModuleInfo.h" -#include "llvm/CodeGen/MachineOperand.h" -#include "llvm/CodeGen/TargetSubtargetInfo.h" -#include "llvm/IR/DebugLoc.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Target/TargetMachine.h" -#include <algorithm> -#include <cassert> -#include <cstdint> -#include <iterator> -#include <utility> - -using namespace llvm; - -#define DEBUG_TYPE "mips-branch-expansion" - -STATISTIC(NumInsertedNops, "Number of nops inserted"); -STATISTIC(LongBranches, "Number of long branches."); - -static cl::opt<bool> - SkipLongBranch("skip-mips-long-branch", cl::init(false), - cl::desc("MIPS: Skip branch expansion pass."), cl::Hidden); - -static cl::opt<bool> - ForceLongBranch("force-mips-long-branch", cl::init(false), - cl::desc("MIPS: Expand all branches to long format."), - cl::Hidden); - -namespace { - -using Iter = MachineBasicBlock::iterator; -using ReverseIter = MachineBasicBlock::reverse_iterator; - -struct MBBInfo { - uint64_t Size = 0; - bool HasLongBranch = false; - MachineInstr *Br = nullptr; - uint64_t Offset = 0; - MBBInfo() = default; -}; - -class MipsBranchExpansion : public MachineFunctionPass { -public: - static char ID; - - MipsBranchExpansion() : MachineFunctionPass(ID), ABI(MipsABIInfo::Unknown()) { - initializeMipsBranchExpansionPass(*PassRegistry::getPassRegistry()); - } - - StringRef getPassName() const override { - return "Mips Branch Expansion Pass"; - } - - bool runOnMachineFunction(MachineFunction &F) override; - - MachineFunctionProperties getRequiredProperties() const override { - return MachineFunctionProperties().set( - MachineFunctionProperties::Property::NoVRegs); - } - -private: - void splitMBB(MachineBasicBlock *MBB); - void initMBBInfo(); - int64_t computeOffset(const MachineInstr *Br); - uint64_t computeOffsetFromTheBeginning(int MBB); - void replaceBranch(MachineBasicBlock &MBB, Iter Br, const DebugLoc &DL, - MachineBasicBlock *MBBOpnd); - bool buildProperJumpMI(MachineBasicBlock *MBB, - MachineBasicBlock::iterator Pos, DebugLoc DL); - void expandToLongBranch(MBBInfo &Info); - bool handleForbiddenSlot(); - bool handlePossibleLongBranch(); - - const MipsSubtarget *STI; - const MipsInstrInfo *TII; - - MachineFunction *MFp; - SmallVector<MBBInfo, 16> MBBInfos; - bool IsPIC; - MipsABIInfo ABI; - bool ForceLongBranchFirstPass = false; -}; - -} // end of anonymous namespace - -char MipsBranchExpansion::ID = 0; - -INITIALIZE_PASS(MipsBranchExpansion, DEBUG_TYPE, - "Expand out of range branch instructions and fix forbidden" - " slot hazards", - false, false) - -/// Returns a pass that clears pipeline hazards. -FunctionPass *llvm::createMipsBranchExpansion() { - return new MipsBranchExpansion(); -} - -// Find the next real instruction from the current position in current basic -// block. -static Iter getNextMachineInstrInBB(Iter Position) { - Iter I = Position, E = Position->getParent()->end(); - I = std::find_if_not(I, E, - [](const Iter &Insn) { return Insn->isTransient(); }); - - return I; -} - -// Find the next real instruction from the current position, looking through -// basic block boundaries. -static std::pair<Iter, bool> getNextMachineInstr(Iter Position, - MachineBasicBlock *Parent) { - if (Position == Parent->end()) { - do { - MachineBasicBlock *Succ = Parent->getNextNode(); - if (Succ != nullptr && Parent->isSuccessor(Succ)) { - Position = Succ->begin(); - Parent = Succ; - } else { - return std::make_pair(Position, true); - } - } while (Parent->empty()); - } - - Iter Instr = getNextMachineInstrInBB(Position); - if (Instr == Parent->end()) { - return getNextMachineInstr(Instr, Parent); - } - return std::make_pair(Instr, false); -} - -/// Iterate over list of Br's operands and search for a MachineBasicBlock -/// operand. -static MachineBasicBlock *getTargetMBB(const MachineInstr &Br) { - for (unsigned I = 0, E = Br.getDesc().getNumOperands(); I < E; ++I) { - const MachineOperand &MO = Br.getOperand(I); - - if (MO.isMBB()) - return MO.getMBB(); - } - - llvm_unreachable("This instruction does not have an MBB operand."); -} - -// Traverse the list of instructions backwards until a non-debug instruction is -// found or it reaches E. -static ReverseIter getNonDebugInstr(ReverseIter B, const ReverseIter &E) { - for (; B != E; ++B) - if (!B->isDebugInstr()) - return B; - - return E; -} - -// Split MBB if it has two direct jumps/branches. -void MipsBranchExpansion::splitMBB(MachineBasicBlock *MBB) { - ReverseIter End = MBB->rend(); - ReverseIter LastBr = getNonDebugInstr(MBB->rbegin(), End); - - // Return if MBB has no branch instructions. - if ((LastBr == End) || - (!LastBr->isConditionalBranch() && !LastBr->isUnconditionalBranch())) - return; - - ReverseIter FirstBr = getNonDebugInstr(std::next(LastBr), End); - - // MBB has only one branch instruction if FirstBr is not a branch - // instruction. - if ((FirstBr == End) || - (!FirstBr->isConditionalBranch() && !FirstBr->isUnconditionalBranch())) - return; - - assert(!FirstBr->isIndirectBranch() && "Unexpected indirect branch found."); - - // Create a new MBB. Move instructions in MBB to the newly created MBB. - MachineBasicBlock *NewMBB = - MFp->CreateMachineBasicBlock(MBB->getBasicBlock()); - - // Insert NewMBB and fix control flow. - MachineBasicBlock *Tgt = getTargetMBB(*FirstBr); - NewMBB->transferSuccessors(MBB); - if (Tgt != getTargetMBB(*LastBr)) - NewMBB->removeSuccessor(Tgt, true); - MBB->addSuccessor(NewMBB); - MBB->addSuccessor(Tgt); - MFp->insert(std::next(MachineFunction::iterator(MBB)), NewMBB); - - NewMBB->splice(NewMBB->end(), MBB, LastBr.getReverse(), MBB->end()); -} - -// Fill MBBInfos. -void MipsBranchExpansion::initMBBInfo() { - // Split the MBBs if they have two branches. Each basic block should have at - // most one branch after this loop is executed. - for (auto &MBB : *MFp) - splitMBB(&MBB); - - MFp->RenumberBlocks(); - MBBInfos.clear(); - MBBInfos.resize(MFp->size()); - - for (unsigned I = 0, E = MBBInfos.size(); I < E; ++I) { - MachineBasicBlock *MBB = MFp->getBlockNumbered(I); - - // Compute size of MBB. - for (MachineBasicBlock::instr_iterator MI = MBB->instr_begin(); - MI != MBB->instr_end(); ++MI) - MBBInfos[I].Size += TII->getInstSizeInBytes(*MI); - } -} - -// Compute offset of branch in number of bytes. -int64_t MipsBranchExpansion::computeOffset(const MachineInstr *Br) { - int64_t Offset = 0; - int ThisMBB = Br->getParent()->getNumber(); - int TargetMBB = getTargetMBB(*Br)->getNumber(); - - // Compute offset of a forward branch. - if (ThisMBB < TargetMBB) { - for (int N = ThisMBB + 1; N < TargetMBB; ++N) - Offset += MBBInfos[N].Size; - - return Offset + 4; - } - - // Compute offset of a backward branch. - for (int N = ThisMBB; N >= TargetMBB; --N) - Offset += MBBInfos[N].Size; - - return -Offset + 4; -} - -// Returns the distance in bytes up until MBB -uint64_t MipsBranchExpansion::computeOffsetFromTheBeginning(int MBB) { - uint64_t Offset = 0; - for (int N = 0; N < MBB; ++N) - Offset += MBBInfos[N].Size; - return Offset; -} - -// Replace Br with a branch which has the opposite condition code and a -// MachineBasicBlock operand MBBOpnd. -void MipsBranchExpansion::replaceBranch(MachineBasicBlock &MBB, Iter Br, - const DebugLoc &DL, - MachineBasicBlock *MBBOpnd) { - unsigned NewOpc = TII->getOppositeBranchOpc(Br->getOpcode()); - const MCInstrDesc &NewDesc = TII->get(NewOpc); - - MachineInstrBuilder MIB = BuildMI(MBB, Br, DL, NewDesc); - - for (unsigned I = 0, E = Br->getDesc().getNumOperands(); I < E; ++I) { - MachineOperand &MO = Br->getOperand(I); - - if (!MO.isReg()) { - assert(MO.isMBB() && "MBB operand expected."); - break; - } - - MIB.addReg(MO.getReg()); - } - - MIB.addMBB(MBBOpnd); - - if (Br->hasDelaySlot()) { - // Bundle the instruction in the delay slot to the newly created branch - // and erase the original branch. - assert(Br->isBundledWithSucc()); - MachineBasicBlock::instr_iterator II = Br.getInstrIterator(); - MIBundleBuilder(&*MIB).append((++II)->removeFromBundle()); - } - Br->eraseFromParent(); -} - -bool MipsBranchExpansion::buildProperJumpMI(MachineBasicBlock *MBB, - MachineBasicBlock::iterator Pos, - DebugLoc DL) { - bool HasR6 = ABI.IsN64() ? STI->hasMips64r6() : STI->hasMips32r6(); - bool AddImm = HasR6 && !STI->useIndirectJumpsHazard(); - - unsigned JR = ABI.IsN64() ? Mips::JR64 : Mips::JR; - unsigned JIC = ABI.IsN64() ? Mips::JIC64 : Mips::JIC; - unsigned JR_HB = ABI.IsN64() ? Mips::JR_HB64 : Mips::JR_HB; - unsigned JR_HB_R6 = ABI.IsN64() ? Mips::JR_HB64_R6 : Mips::JR_HB_R6; - - unsigned JumpOp; - if (STI->useIndirectJumpsHazard()) - JumpOp = HasR6 ? JR_HB_R6 : JR_HB; - else - JumpOp = HasR6 ? JIC : JR; - - if (JumpOp == Mips::JIC && STI->inMicroMipsMode()) - JumpOp = Mips::JIC_MMR6; - - unsigned ATReg = ABI.IsN64() ? Mips::AT_64 : Mips::AT; - MachineInstrBuilder Instr = - BuildMI(*MBB, Pos, DL, TII->get(JumpOp)).addReg(ATReg); - if (AddImm) - Instr.addImm(0); - - return !AddImm; -} - -// Expand branch instructions to long branches. -// TODO: This function has to be fixed for beqz16 and bnez16, because it -// currently assumes that all branches have 16-bit offsets, and will produce -// wrong code if branches whose allowed offsets are [-128, -126, ..., 126] -// are present. -void MipsBranchExpansion::expandToLongBranch(MBBInfo &I) { - MachineBasicBlock::iterator Pos; - MachineBasicBlock *MBB = I.Br->getParent(), *TgtMBB = getTargetMBB(*I.Br); - DebugLoc DL = I.Br->getDebugLoc(); - const BasicBlock *BB = MBB->getBasicBlock(); - MachineFunction::iterator FallThroughMBB = ++MachineFunction::iterator(MBB); - MachineBasicBlock *LongBrMBB = MFp->CreateMachineBasicBlock(BB); - - MFp->insert(FallThroughMBB, LongBrMBB); - MBB->replaceSuccessor(TgtMBB, LongBrMBB); - - if (IsPIC) { - MachineBasicBlock *BalTgtMBB = MFp->CreateMachineBasicBlock(BB); - MFp->insert(FallThroughMBB, BalTgtMBB); - LongBrMBB->addSuccessor(BalTgtMBB); - BalTgtMBB->addSuccessor(TgtMBB); - - // We must select between the MIPS32r6/MIPS64r6 BALC (which is a normal - // instruction) and the pre-MIPS32r6/MIPS64r6 definition (which is an - // pseudo-instruction wrapping BGEZAL). - const unsigned BalOp = - STI->hasMips32r6() - ? STI->inMicroMipsMode() ? Mips::BALC_MMR6 : Mips::BALC - : STI->inMicroMipsMode() ? Mips::BAL_BR_MM : Mips::BAL_BR; - - if (!ABI.IsN64()) { - // Pre R6: - // $longbr: - // addiu $sp, $sp, -8 - // sw $ra, 0($sp) - // lui $at, %hi($tgt - $baltgt) - // bal $baltgt - // addiu $at, $at, %lo($tgt - $baltgt) - // $baltgt: - // addu $at, $ra, $at - // lw $ra, 0($sp) - // jr $at - // addiu $sp, $sp, 8 - // $fallthrough: - // - - // R6: - // $longbr: - // addiu $sp, $sp, -8 - // sw $ra, 0($sp) - // lui $at, %hi($tgt - $baltgt) - // addiu $at, $at, %lo($tgt - $baltgt) - // balc $baltgt - // $baltgt: - // addu $at, $ra, $at - // lw $ra, 0($sp) - // addiu $sp, $sp, 8 - // jic $at, 0 - // $fallthrough: - - Pos = LongBrMBB->begin(); - - BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::ADDiu), Mips::SP) - .addReg(Mips::SP) - .addImm(-8); - BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::SW)) - .addReg(Mips::RA) - .addReg(Mips::SP) - .addImm(0); - - // LUi and ADDiu instructions create 32-bit offset of the target basic - // block from the target of BAL(C) instruction. We cannot use immediate - // value for this offset because it cannot be determined accurately when - // the program has inline assembly statements. We therefore use the - // relocation expressions %hi($tgt-$baltgt) and %lo($tgt-$baltgt) which - // are resolved during the fixup, so the values will always be correct. - // - // Since we cannot create %hi($tgt-$baltgt) and %lo($tgt-$baltgt) - // expressions at this point (it is possible only at the MC layer), - // we replace LUi and ADDiu with pseudo instructions - // LONG_BRANCH_LUi and LONG_BRANCH_ADDiu, and add both basic - // blocks as operands to these instructions. When lowering these pseudo - // instructions to LUi and ADDiu in the MC layer, we will create - // %hi($tgt-$baltgt) and %lo($tgt-$baltgt) expressions and add them as - // operands to lowered instructions. - - BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::LONG_BRANCH_LUi), Mips::AT) - .addMBB(TgtMBB, MipsII::MO_ABS_HI) - .addMBB(BalTgtMBB); - - MachineInstrBuilder BalInstr = - BuildMI(*MFp, DL, TII->get(BalOp)).addMBB(BalTgtMBB); - MachineInstrBuilder ADDiuInstr = - BuildMI(*MFp, DL, TII->get(Mips::LONG_BRANCH_ADDiu), Mips::AT) - .addReg(Mips::AT) - .addMBB(TgtMBB, MipsII::MO_ABS_LO) - .addMBB(BalTgtMBB); - if (STI->hasMips32r6()) { - LongBrMBB->insert(Pos, ADDiuInstr); - LongBrMBB->insert(Pos, BalInstr); - } else { - LongBrMBB->insert(Pos, BalInstr); - LongBrMBB->insert(Pos, ADDiuInstr); - LongBrMBB->rbegin()->bundleWithPred(); - } - - Pos = BalTgtMBB->begin(); - - BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::ADDu), Mips::AT) - .addReg(Mips::RA) - .addReg(Mips::AT); - BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::LW), Mips::RA) - .addReg(Mips::SP) - .addImm(0); - if (STI->isTargetNaCl()) - // Bundle-align the target of indirect branch JR. - TgtMBB->setAlignment(MIPS_NACL_BUNDLE_ALIGN); - - // In NaCl, modifying the sp is not allowed in branch delay slot. - // For MIPS32R6, we can skip using a delay slot branch. - bool hasDelaySlot = buildProperJumpMI(BalTgtMBB, Pos, DL); - - if (STI->isTargetNaCl() || !hasDelaySlot) { - BuildMI(*BalTgtMBB, std::prev(Pos), DL, TII->get(Mips::ADDiu), Mips::SP) - .addReg(Mips::SP) - .addImm(8); - } - if (hasDelaySlot) { - if (STI->isTargetNaCl()) { - BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::NOP)); - } else { - BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::ADDiu), Mips::SP) - .addReg(Mips::SP) - .addImm(8); - } - BalTgtMBB->rbegin()->bundleWithPred(); - } - } else { - // Pre R6: - // $longbr: - // daddiu $sp, $sp, -16 - // sd $ra, 0($sp) - // daddiu $at, $zero, %hi($tgt - $baltgt) - // dsll $at, $at, 16 - // bal $baltgt - // daddiu $at, $at, %lo($tgt - $baltgt) - // $baltgt: - // daddu $at, $ra, $at - // ld $ra, 0($sp) - // jr64 $at - // daddiu $sp, $sp, 16 - // $fallthrough: - - // R6: - // $longbr: - // daddiu $sp, $sp, -16 - // sd $ra, 0($sp) - // daddiu $at, $zero, %hi($tgt - $baltgt) - // dsll $at, $at, 16 - // daddiu $at, $at, %lo($tgt - $baltgt) - // balc $baltgt - // $baltgt: - // daddu $at, $ra, $at - // ld $ra, 0($sp) - // daddiu $sp, $sp, 16 - // jic $at, 0 - // $fallthrough: - - // We assume the branch is within-function, and that offset is within - // +/- 2GB. High 32 bits will therefore always be zero. - - // Note that this will work even if the offset is negative, because - // of the +1 modification that's added in that case. For example, if the - // offset is -1MB (0xFFFFFFFFFFF00000), the computation for %higher is - // - // 0xFFFFFFFFFFF00000 + 0x80008000 = 0x000000007FF08000 - // - // and the bits [47:32] are zero. For %highest - // - // 0xFFFFFFFFFFF00000 + 0x800080008000 = 0x000080007FF08000 - // - // and the bits [63:48] are zero. - - Pos = LongBrMBB->begin(); - - BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::DADDiu), Mips::SP_64) - .addReg(Mips::SP_64) - .addImm(-16); - BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::SD)) - .addReg(Mips::RA_64) - .addReg(Mips::SP_64) - .addImm(0); - BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::LONG_BRANCH_DADDiu), - Mips::AT_64) - .addReg(Mips::ZERO_64) - .addMBB(TgtMBB, MipsII::MO_ABS_HI) - .addMBB(BalTgtMBB); - BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::DSLL), Mips::AT_64) - .addReg(Mips::AT_64) - .addImm(16); - - MachineInstrBuilder BalInstr = - BuildMI(*MFp, DL, TII->get(BalOp)).addMBB(BalTgtMBB); - MachineInstrBuilder DADDiuInstr = - BuildMI(*MFp, DL, TII->get(Mips::LONG_BRANCH_DADDiu), Mips::AT_64) - .addReg(Mips::AT_64) - .addMBB(TgtMBB, MipsII::MO_ABS_LO) - .addMBB(BalTgtMBB); - if (STI->hasMips32r6()) { - LongBrMBB->insert(Pos, DADDiuInstr); - LongBrMBB->insert(Pos, BalInstr); - } else { - LongBrMBB->insert(Pos, BalInstr); - LongBrMBB->insert(Pos, DADDiuInstr); - LongBrMBB->rbegin()->bundleWithPred(); - } - - Pos = BalTgtMBB->begin(); - - BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::DADDu), Mips::AT_64) - .addReg(Mips::RA_64) - .addReg(Mips::AT_64); - BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::LD), Mips::RA_64) - .addReg(Mips::SP_64) - .addImm(0); - - bool hasDelaySlot = buildProperJumpMI(BalTgtMBB, Pos, DL); - // If there is no delay slot, Insert stack adjustment before - if (!hasDelaySlot) { - BuildMI(*BalTgtMBB, std::prev(Pos), DL, TII->get(Mips::DADDiu), - Mips::SP_64) - .addReg(Mips::SP_64) - .addImm(16); - } else { - BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::DADDiu), Mips::SP_64) - .addReg(Mips::SP_64) - .addImm(16); - BalTgtMBB->rbegin()->bundleWithPred(); - } - } - } else { // Not PIC - Pos = LongBrMBB->begin(); - LongBrMBB->addSuccessor(TgtMBB); - - // Compute the position of the potentiall jump instruction (basic blocks - // before + 4 for the instruction) - uint64_t JOffset = computeOffsetFromTheBeginning(MBB->getNumber()) + - MBBInfos[MBB->getNumber()].Size + 4; - uint64_t TgtMBBOffset = computeOffsetFromTheBeginning(TgtMBB->getNumber()); - // If it's a forward jump, then TgtMBBOffset will be shifted by two - // instructions - if (JOffset < TgtMBBOffset) - TgtMBBOffset += 2 * 4; - // Compare 4 upper bits to check if it's the same segment - bool SameSegmentJump = JOffset >> 28 == TgtMBBOffset >> 28; - - if (STI->hasMips32r6() && TII->isBranchOffsetInRange(Mips::BC, I.Offset)) { - // R6: - // $longbr: - // bc $tgt - // $fallthrough: - // - BuildMI(*LongBrMBB, Pos, DL, - TII->get(STI->inMicroMipsMode() ? Mips::BC_MMR6 : Mips::BC)) - .addMBB(TgtMBB); - } else if (SameSegmentJump) { - // Pre R6: - // $longbr: - // j $tgt - // nop - // $fallthrough: - // - MIBundleBuilder(*LongBrMBB, Pos) - .append(BuildMI(*MFp, DL, TII->get(Mips::J)).addMBB(TgtMBB)) - .append(BuildMI(*MFp, DL, TII->get(Mips::NOP))); - } else { - // At this point, offset where we need to branch does not fit into - // immediate field of the branch instruction and is not in the same - // segment as jump instruction. Therefore we will break it into couple - // instructions, where we first load the offset into register, and then we - // do branch register. - if (ABI.IsN64()) { - BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::LONG_BRANCH_LUi2Op_64), - Mips::AT_64) - .addMBB(TgtMBB, MipsII::MO_HIGHEST); - BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::LONG_BRANCH_DADDiu2Op), - Mips::AT_64) - .addReg(Mips::AT_64) - .addMBB(TgtMBB, MipsII::MO_HIGHER); - BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::DSLL), Mips::AT_64) - .addReg(Mips::AT_64) - .addImm(16); - BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::LONG_BRANCH_DADDiu2Op), - Mips::AT_64) - .addReg(Mips::AT_64) - .addMBB(TgtMBB, MipsII::MO_ABS_HI); - BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::DSLL), Mips::AT_64) - .addReg(Mips::AT_64) - .addImm(16); - BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::LONG_BRANCH_DADDiu2Op), - Mips::AT_64) - .addReg(Mips::AT_64) - .addMBB(TgtMBB, MipsII::MO_ABS_LO); - } else { - BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::LONG_BRANCH_LUi2Op), - Mips::AT) - .addMBB(TgtMBB, MipsII::MO_ABS_HI); - BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::LONG_BRANCH_ADDiu2Op), - Mips::AT) - .addReg(Mips::AT) - .addMBB(TgtMBB, MipsII::MO_ABS_LO); - } - buildProperJumpMI(LongBrMBB, Pos, DL); - } - } - - if (I.Br->isUnconditionalBranch()) { - // Change branch destination. - assert(I.Br->getDesc().getNumOperands() == 1); - I.Br->RemoveOperand(0); - I.Br->addOperand(MachineOperand::CreateMBB(LongBrMBB)); - } else - // Change branch destination and reverse condition. - replaceBranch(*MBB, I.Br, DL, &*FallThroughMBB); -} - -static void emitGPDisp(MachineFunction &F, const MipsInstrInfo *TII) { - MachineBasicBlock &MBB = F.front(); - MachineBasicBlock::iterator I = MBB.begin(); - DebugLoc DL = MBB.findDebugLoc(MBB.begin()); - BuildMI(MBB, I, DL, TII->get(Mips::LUi), Mips::V0) - .addExternalSymbol("_gp_disp", MipsII::MO_ABS_HI); - BuildMI(MBB, I, DL, TII->get(Mips::ADDiu), Mips::V0) - .addReg(Mips::V0) - .addExternalSymbol("_gp_disp", MipsII::MO_ABS_LO); - MBB.removeLiveIn(Mips::V0); -} - -bool MipsBranchExpansion::handleForbiddenSlot() { - // Forbidden slot hazards are only defined for MIPSR6 but not microMIPSR6. - if (!STI->hasMips32r6() || STI->inMicroMipsMode()) - return false; - - bool Changed = false; - - for (MachineFunction::iterator FI = MFp->begin(); FI != MFp->end(); ++FI) { - for (Iter I = FI->begin(); I != FI->end(); ++I) { - - // Forbidden slot hazard handling. Use lookahead over state. - if (!TII->HasForbiddenSlot(*I)) - continue; - - Iter Inst; - bool LastInstInFunction = - std::next(I) == FI->end() && std::next(FI) == MFp->end(); - if (!LastInstInFunction) { - std::pair<Iter, bool> Res = getNextMachineInstr(std::next(I), &*FI); - LastInstInFunction |= Res.second; - Inst = Res.first; - } - - if (LastInstInFunction || !TII->SafeInForbiddenSlot(*Inst)) { - - MachineBasicBlock::instr_iterator Iit = I->getIterator(); - if (std::next(Iit) == FI->end() || - std::next(Iit)->getOpcode() != Mips::NOP) { - Changed = true; - MIBundleBuilder(&*I).append( - BuildMI(*MFp, I->getDebugLoc(), TII->get(Mips::NOP))); - NumInsertedNops++; - } - } - } - } - - return Changed; -} - -bool MipsBranchExpansion::handlePossibleLongBranch() { - if (STI->inMips16Mode() || !STI->enableLongBranchPass()) - return false; - - if (SkipLongBranch) - return false; - - bool EverMadeChange = false, MadeChange = true; - - while (MadeChange) { - MadeChange = false; - - initMBBInfo(); - - for (unsigned I = 0, E = MBBInfos.size(); I < E; ++I) { - MachineBasicBlock *MBB = MFp->getBlockNumbered(I); - // Search for MBB's branch instruction. - ReverseIter End = MBB->rend(); - ReverseIter Br = getNonDebugInstr(MBB->rbegin(), End); - - if ((Br != End) && Br->isBranch() && !Br->isIndirectBranch() && - (Br->isConditionalBranch() || - (Br->isUnconditionalBranch() && IsPIC))) { - int64_t Offset = computeOffset(&*Br); - - if (STI->isTargetNaCl()) { - // The offset calculation does not include sandboxing instructions - // that will be added later in the MC layer. Since at this point we - // don't know the exact amount of code that "sandboxing" will add, we - // conservatively estimate that code will not grow more than 100%. - Offset *= 2; - } - - if (ForceLongBranchFirstPass || - !TII->isBranchOffsetInRange(Br->getOpcode(), Offset)) { - MBBInfos[I].Offset = Offset; - MBBInfos[I].Br = &*Br; - } - } - } // End for - - ForceLongBranchFirstPass = false; - - SmallVectorImpl<MBBInfo>::iterator I, E = MBBInfos.end(); - - for (I = MBBInfos.begin(); I != E; ++I) { - // Skip if this MBB doesn't have a branch or the branch has already been - // converted to a long branch. - if (!I->Br) - continue; - - expandToLongBranch(*I); - ++LongBranches; - EverMadeChange = MadeChange = true; - } - - MFp->RenumberBlocks(); - } - - return EverMadeChange; -} - -bool MipsBranchExpansion::runOnMachineFunction(MachineFunction &MF) { - const TargetMachine &TM = MF.getTarget(); - IsPIC = TM.isPositionIndependent(); - ABI = static_cast<const MipsTargetMachine &>(TM).getABI(); - STI = &static_cast<const MipsSubtarget &>(MF.getSubtarget()); - TII = static_cast<const MipsInstrInfo *>(STI->getInstrInfo()); - - if (IsPIC && ABI.IsO32() && - MF.getInfo<MipsFunctionInfo>()->globalBaseRegSet()) - emitGPDisp(MF, TII); - - MFp = &MF; - - ForceLongBranchFirstPass = ForceLongBranch; - // Run these two at least once - bool longBranchChanged = handlePossibleLongBranch(); - bool forbiddenSlotChanged = handleForbiddenSlot(); - - bool Changed = longBranchChanged || forbiddenSlotChanged; - - // Then run them alternatively while there are changes - while (forbiddenSlotChanged) { - longBranchChanged = handlePossibleLongBranch(); - if (!longBranchChanged) - break; - forbiddenSlotChanged = handleForbiddenSlot(); - } - - return Changed; -} diff --git a/contrib/llvm/lib/Target/Mips/MipsCCState.cpp b/contrib/llvm/lib/Target/Mips/MipsCCState.cpp deleted file mode 100644 index ef48c850a1b8..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsCCState.cpp +++ /dev/null @@ -1,175 +0,0 @@ -//===---- MipsCCState.cpp - CCState with Mips specific extensions ---------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "MipsCCState.h" -#include "MipsSubtarget.h" -#include "llvm/IR/Module.h" - -using namespace llvm; - -/// This function returns true if CallSym is a long double emulation routine. -static bool isF128SoftLibCall(const char *CallSym) { - const char *const LibCalls[] = { - "__addtf3", "__divtf3", "__eqtf2", "__extenddftf2", - "__extendsftf2", "__fixtfdi", "__fixtfsi", "__fixtfti", - "__fixunstfdi", "__fixunstfsi", "__fixunstfti", "__floatditf", - "__floatsitf", "__floattitf", "__floatunditf", "__floatunsitf", - "__floatuntitf", "__getf2", "__gttf2", "__letf2", - "__lttf2", "__multf3", "__netf2", "__powitf2", - "__subtf3", "__trunctfdf2", "__trunctfsf2", "__unordtf2", - "ceill", "copysignl", "cosl", "exp2l", - "expl", "floorl", "fmal", "fmaxl", - "fmodl", "log10l", "log2l", "logl", - "nearbyintl", "powl", "rintl", "roundl", - "sinl", "sqrtl", "truncl"}; - - // Check that LibCalls is sorted alphabetically. - auto Comp = [](const char *S1, const char *S2) { return strcmp(S1, S2) < 0; }; - assert(std::is_sorted(std::begin(LibCalls), std::end(LibCalls), Comp)); - return std::binary_search(std::begin(LibCalls), std::end(LibCalls), - CallSym, Comp); -} - -/// This function returns true if Ty is fp128, {f128} or i128 which was -/// originally a fp128. -static bool originalTypeIsF128(const Type *Ty, const char *Func) { - if (Ty->isFP128Ty()) - return true; - - if (Ty->isStructTy() && Ty->getStructNumElements() == 1 && - Ty->getStructElementType(0)->isFP128Ty()) - return true; - - // If the Ty is i128 and the function being called is a long double emulation - // routine, then the original type is f128. - return (Func && Ty->isIntegerTy(128) && isF128SoftLibCall(Func)); -} - -/// Return true if the original type was vXfXX. -static bool originalEVTTypeIsVectorFloat(EVT Ty) { - if (Ty.isVector() && Ty.getVectorElementType().isFloatingPoint()) - return true; - - return false; -} - -/// Return true if the original type was vXfXX / vXfXX. -static bool originalTypeIsVectorFloat(const Type * Ty) { - if (Ty->isVectorTy() && Ty->isFPOrFPVectorTy()) - return true; - - return false; -} - -MipsCCState::SpecialCallingConvType -MipsCCState::getSpecialCallingConvForCallee(const SDNode *Callee, - const MipsSubtarget &Subtarget) { - MipsCCState::SpecialCallingConvType SpecialCallingConv = NoSpecialCallingConv; - if (Subtarget.inMips16HardFloat()) { - if (const GlobalAddressSDNode *G = - dyn_cast<const GlobalAddressSDNode>(Callee)) { - llvm::StringRef Sym = G->getGlobal()->getName(); - Function *F = G->getGlobal()->getParent()->getFunction(Sym); - if (F && F->hasFnAttribute("__Mips16RetHelper")) { - SpecialCallingConv = Mips16RetHelperConv; - } - } - } - return SpecialCallingConv; -} - -void MipsCCState::PreAnalyzeCallResultForF128( - const SmallVectorImpl<ISD::InputArg> &Ins, - const Type *RetTy, const char *Call) { - for (unsigned i = 0; i < Ins.size(); ++i) { - OriginalArgWasF128.push_back( - originalTypeIsF128(RetTy, Call)); - OriginalArgWasFloat.push_back(RetTy->isFloatingPointTy()); - } -} - -/// Identify lowered values that originated from f128 or float arguments and -/// record this for use by RetCC_MipsN. -void MipsCCState::PreAnalyzeReturnForF128( - const SmallVectorImpl<ISD::OutputArg> &Outs) { - const MachineFunction &MF = getMachineFunction(); - for (unsigned i = 0; i < Outs.size(); ++i) { - OriginalArgWasF128.push_back( - originalTypeIsF128(MF.getFunction().getReturnType(), nullptr)); - OriginalArgWasFloat.push_back( - MF.getFunction().getReturnType()->isFloatingPointTy()); - } -} - -/// Identify lower values that originated from vXfXX and record -/// this. -void MipsCCState::PreAnalyzeCallResultForVectorFloat( - const SmallVectorImpl<ISD::InputArg> &Ins, const Type *RetTy) { - for (unsigned i = 0; i < Ins.size(); ++i) { - OriginalRetWasFloatVector.push_back(originalTypeIsVectorFloat(RetTy)); - } -} - -/// Identify lowered values that originated from vXfXX arguments and record -/// this. -void MipsCCState::PreAnalyzeReturnForVectorFloat( - const SmallVectorImpl<ISD::OutputArg> &Outs) { - for (unsigned i = 0; i < Outs.size(); ++i) { - ISD::OutputArg Out = Outs[i]; - OriginalRetWasFloatVector.push_back( - originalEVTTypeIsVectorFloat(Out.ArgVT)); - } -} - -/// Identify lowered values that originated from f128, float and sret to vXfXX -/// arguments and record this. -void MipsCCState::PreAnalyzeCallOperands( - const SmallVectorImpl<ISD::OutputArg> &Outs, - std::vector<TargetLowering::ArgListEntry> &FuncArgs, - const char *Func) { - for (unsigned i = 0; i < Outs.size(); ++i) { - TargetLowering::ArgListEntry FuncArg = FuncArgs[Outs[i].OrigArgIndex]; - - OriginalArgWasF128.push_back(originalTypeIsF128(FuncArg.Ty, Func)); - OriginalArgWasFloat.push_back(FuncArg.Ty->isFloatingPointTy()); - OriginalArgWasFloatVector.push_back(FuncArg.Ty->isVectorTy()); - CallOperandIsFixed.push_back(Outs[i].IsFixed); - } -} - -/// Identify lowered values that originated from f128, float and vXfXX arguments -/// and record this. -void MipsCCState::PreAnalyzeFormalArgumentsForF128( - const SmallVectorImpl<ISD::InputArg> &Ins) { - const MachineFunction &MF = getMachineFunction(); - for (unsigned i = 0; i < Ins.size(); ++i) { - Function::const_arg_iterator FuncArg = MF.getFunction().arg_begin(); - - // SRet arguments cannot originate from f128 or {f128} returns so we just - // push false. We have to handle this specially since SRet arguments - // aren't mapped to an original argument. - if (Ins[i].Flags.isSRet()) { - OriginalArgWasF128.push_back(false); - OriginalArgWasFloat.push_back(false); - OriginalArgWasFloatVector.push_back(false); - continue; - } - - assert(Ins[i].getOrigArgIndex() < MF.getFunction().arg_size()); - std::advance(FuncArg, Ins[i].getOrigArgIndex()); - - OriginalArgWasF128.push_back( - originalTypeIsF128(FuncArg->getType(), nullptr)); - OriginalArgWasFloat.push_back(FuncArg->getType()->isFloatingPointTy()); - - // The MIPS vector ABI exhibits a corner case of sorts or quirk; if the - // first argument is actually an SRet pointer to a vector, then the next - // argument slot is $a2. - OriginalArgWasFloatVector.push_back(FuncArg->getType()->isVectorTy()); - } -} diff --git a/contrib/llvm/lib/Target/Mips/MipsCCState.h b/contrib/llvm/lib/Target/Mips/MipsCCState.h deleted file mode 100644 index fd2fd97c8f13..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsCCState.h +++ /dev/null @@ -1,166 +0,0 @@ -//===---- MipsCCState.h - CCState with Mips specific extensions -----------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef MIPSCCSTATE_H -#define MIPSCCSTATE_H - -#include "MipsISelLowering.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/CodeGen/CallingConvLower.h" - -namespace llvm { -class SDNode; -class MipsSubtarget; - -class MipsCCState : public CCState { -public: - enum SpecialCallingConvType { Mips16RetHelperConv, NoSpecialCallingConv }; - - /// Determine the SpecialCallingConvType for the given callee - static SpecialCallingConvType - getSpecialCallingConvForCallee(const SDNode *Callee, - const MipsSubtarget &Subtarget); - -private: - /// Identify lowered values that originated from f128 arguments and record - /// this for use by RetCC_MipsN. - void PreAnalyzeCallResultForF128(const SmallVectorImpl<ISD::InputArg> &Ins, - const Type *RetTy, const char * Func); - - /// Identify lowered values that originated from f128 arguments and record - /// this for use by RetCC_MipsN. - void PreAnalyzeReturnForF128(const SmallVectorImpl<ISD::OutputArg> &Outs); - - /// Identify lowered values that originated from f128 arguments and record - /// this. - void - PreAnalyzeCallOperands(const SmallVectorImpl<ISD::OutputArg> &Outs, - std::vector<TargetLowering::ArgListEntry> &FuncArgs, - const char *Func); - - /// Identify lowered values that originated from f128 arguments and record - /// this for use by RetCC_MipsN. - void - PreAnalyzeFormalArgumentsForF128(const SmallVectorImpl<ISD::InputArg> &Ins); - - void - PreAnalyzeCallResultForVectorFloat(const SmallVectorImpl<ISD::InputArg> &Ins, - const Type *RetTy); - - void PreAnalyzeFormalArgumentsForVectorFloat( - const SmallVectorImpl<ISD::InputArg> &Ins); - - void - PreAnalyzeReturnForVectorFloat(const SmallVectorImpl<ISD::OutputArg> &Outs); - - /// Records whether the value has been lowered from an f128. - SmallVector<bool, 4> OriginalArgWasF128; - - /// Records whether the value has been lowered from float. - SmallVector<bool, 4> OriginalArgWasFloat; - - /// Records whether the value has been lowered from a floating point vector. - SmallVector<bool, 4> OriginalArgWasFloatVector; - - /// Records whether the return value has been lowered from a floating point - /// vector. - SmallVector<bool, 4> OriginalRetWasFloatVector; - - /// Records whether the value was a fixed argument. - /// See ISD::OutputArg::IsFixed, - SmallVector<bool, 4> CallOperandIsFixed; - - // Used to handle MIPS16-specific calling convention tweaks. - // FIXME: This should probably be a fully fledged calling convention. - SpecialCallingConvType SpecialCallingConv; - -public: - MipsCCState(CallingConv::ID CC, bool isVarArg, MachineFunction &MF, - SmallVectorImpl<CCValAssign> &locs, LLVMContext &C, - SpecialCallingConvType SpecialCC = NoSpecialCallingConv) - : CCState(CC, isVarArg, MF, locs, C), SpecialCallingConv(SpecialCC) {} - - void - AnalyzeCallOperands(const SmallVectorImpl<ISD::OutputArg> &Outs, - CCAssignFn Fn, - std::vector<TargetLowering::ArgListEntry> &FuncArgs, - const char *Func) { - PreAnalyzeCallOperands(Outs, FuncArgs, Func); - CCState::AnalyzeCallOperands(Outs, Fn); - OriginalArgWasF128.clear(); - OriginalArgWasFloat.clear(); - OriginalArgWasFloatVector.clear(); - CallOperandIsFixed.clear(); - } - - // The AnalyzeCallOperands in the base class is not usable since we must - // provide a means of accessing ArgListEntry::IsFixed. Delete them from this - // class. This doesn't stop them being used via the base class though. - void AnalyzeCallOperands(const SmallVectorImpl<ISD::OutputArg> &Outs, - CCAssignFn Fn) = delete; - void AnalyzeCallOperands(const SmallVectorImpl<MVT> &Outs, - SmallVectorImpl<ISD::ArgFlagsTy> &Flags, - CCAssignFn Fn) = delete; - - void AnalyzeFormalArguments(const SmallVectorImpl<ISD::InputArg> &Ins, - CCAssignFn Fn) { - PreAnalyzeFormalArgumentsForF128(Ins); - CCState::AnalyzeFormalArguments(Ins, Fn); - OriginalArgWasFloat.clear(); - OriginalArgWasF128.clear(); - OriginalArgWasFloatVector.clear(); - } - - void AnalyzeCallResult(const SmallVectorImpl<ISD::InputArg> &Ins, - CCAssignFn Fn, const Type *RetTy, - const char *Func) { - PreAnalyzeCallResultForF128(Ins, RetTy, Func); - PreAnalyzeCallResultForVectorFloat(Ins, RetTy); - CCState::AnalyzeCallResult(Ins, Fn); - OriginalArgWasFloat.clear(); - OriginalArgWasF128.clear(); - OriginalArgWasFloatVector.clear(); - } - - void AnalyzeReturn(const SmallVectorImpl<ISD::OutputArg> &Outs, - CCAssignFn Fn) { - PreAnalyzeReturnForF128(Outs); - PreAnalyzeReturnForVectorFloat(Outs); - CCState::AnalyzeReturn(Outs, Fn); - OriginalArgWasFloat.clear(); - OriginalArgWasF128.clear(); - OriginalArgWasFloatVector.clear(); - } - - bool CheckReturn(const SmallVectorImpl<ISD::OutputArg> &ArgsFlags, - CCAssignFn Fn) { - PreAnalyzeReturnForF128(ArgsFlags); - PreAnalyzeReturnForVectorFloat(ArgsFlags); - bool Return = CCState::CheckReturn(ArgsFlags, Fn); - OriginalArgWasFloat.clear(); - OriginalArgWasF128.clear(); - OriginalArgWasFloatVector.clear(); - return Return; - } - - bool WasOriginalArgF128(unsigned ValNo) { return OriginalArgWasF128[ValNo]; } - bool WasOriginalArgFloat(unsigned ValNo) { - return OriginalArgWasFloat[ValNo]; - } - bool WasOriginalArgVectorFloat(unsigned ValNo) const { - return OriginalArgWasFloatVector[ValNo]; - } - bool WasOriginalRetVectorFloat(unsigned ValNo) const { - return OriginalRetWasFloatVector[ValNo]; - } - bool IsCallOperandFixed(unsigned ValNo) { return CallOperandIsFixed[ValNo]; } - SpecialCallingConvType getSpecialCallingConv() { return SpecialCallingConv; } -}; -} - -#endif diff --git a/contrib/llvm/lib/Target/Mips/MipsCallLowering.cpp b/contrib/llvm/lib/Target/Mips/MipsCallLowering.cpp deleted file mode 100644 index da65689ecff5..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsCallLowering.cpp +++ /dev/null @@ -1,668 +0,0 @@ -//===- MipsCallLowering.cpp -------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -/// \file -/// This file implements the lowering of LLVM calls to machine code calls for -/// GlobalISel. -// -//===----------------------------------------------------------------------===// - -#include "MipsCallLowering.h" -#include "MipsCCState.h" -#include "MipsMachineFunction.h" -#include "MipsTargetMachine.h" -#include "llvm/CodeGen/Analysis.h" -#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" - -using namespace llvm; - -MipsCallLowering::MipsCallLowering(const MipsTargetLowering &TLI) - : CallLowering(&TLI) {} - -bool MipsCallLowering::MipsHandler::assign(Register VReg, const CCValAssign &VA, - const EVT &VT) { - if (VA.isRegLoc()) { - assignValueToReg(VReg, VA, VT); - } else if (VA.isMemLoc()) { - assignValueToAddress(VReg, VA); - } else { - return false; - } - return true; -} - -bool MipsCallLowering::MipsHandler::assignVRegs(ArrayRef<Register> VRegs, - ArrayRef<CCValAssign> ArgLocs, - unsigned ArgLocsStartIndex, - const EVT &VT) { - for (unsigned i = 0; i < VRegs.size(); ++i) - if (!assign(VRegs[i], ArgLocs[ArgLocsStartIndex + i], VT)) - return false; - return true; -} - -void MipsCallLowering::MipsHandler::setLeastSignificantFirst( - SmallVectorImpl<Register> &VRegs) { - if (!MIRBuilder.getMF().getDataLayout().isLittleEndian()) - std::reverse(VRegs.begin(), VRegs.end()); -} - -bool MipsCallLowering::MipsHandler::handle( - ArrayRef<CCValAssign> ArgLocs, ArrayRef<CallLowering::ArgInfo> Args) { - SmallVector<Register, 4> VRegs; - unsigned SplitLength; - const Function &F = MIRBuilder.getMF().getFunction(); - const DataLayout &DL = F.getParent()->getDataLayout(); - const MipsTargetLowering &TLI = *static_cast<const MipsTargetLowering *>( - MIRBuilder.getMF().getSubtarget().getTargetLowering()); - - for (unsigned ArgsIndex = 0, ArgLocsIndex = 0; ArgsIndex < Args.size(); - ++ArgsIndex, ArgLocsIndex += SplitLength) { - EVT VT = TLI.getValueType(DL, Args[ArgsIndex].Ty); - SplitLength = TLI.getNumRegistersForCallingConv(F.getContext(), - F.getCallingConv(), VT); - assert(Args[ArgsIndex].Regs.size() == 1 && "Can't handle multple regs yet"); - - if (SplitLength > 1) { - VRegs.clear(); - MVT RegisterVT = TLI.getRegisterTypeForCallingConv( - F.getContext(), F.getCallingConv(), VT); - for (unsigned i = 0; i < SplitLength; ++i) - VRegs.push_back(MRI.createGenericVirtualRegister(LLT{RegisterVT})); - - if (!handleSplit(VRegs, ArgLocs, ArgLocsIndex, Args[ArgsIndex].Regs[0], - VT)) - return false; - } else { - if (!assign(Args[ArgsIndex].Regs[0], ArgLocs[ArgLocsIndex], VT)) - return false; - } - } - return true; -} - -namespace { -class IncomingValueHandler : public MipsCallLowering::MipsHandler { -public: - IncomingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI) - : MipsHandler(MIRBuilder, MRI) {} - -private: - void assignValueToReg(Register ValVReg, const CCValAssign &VA, - const EVT &VT) override; - - Register getStackAddress(const CCValAssign &VA, - MachineMemOperand *&MMO) override; - - void assignValueToAddress(Register ValVReg, const CCValAssign &VA) override; - - bool handleSplit(SmallVectorImpl<Register> &VRegs, - ArrayRef<CCValAssign> ArgLocs, unsigned ArgLocsStartIndex, - Register ArgsReg, const EVT &VT) override; - - virtual void markPhysRegUsed(unsigned PhysReg) { - MIRBuilder.getMBB().addLiveIn(PhysReg); - } - - void buildLoad(Register Val, const CCValAssign &VA) { - MachineMemOperand *MMO; - Register Addr = getStackAddress(VA, MMO); - MIRBuilder.buildLoad(Val, Addr, *MMO); - } -}; - -class CallReturnHandler : public IncomingValueHandler { -public: - CallReturnHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, - MachineInstrBuilder &MIB) - : IncomingValueHandler(MIRBuilder, MRI), MIB(MIB) {} - -private: - void markPhysRegUsed(unsigned PhysReg) override { - MIB.addDef(PhysReg, RegState::Implicit); - } - - MachineInstrBuilder &MIB; -}; - -} // end anonymous namespace - -void IncomingValueHandler::assignValueToReg(Register ValVReg, - const CCValAssign &VA, - const EVT &VT) { - const MipsSubtarget &STI = - static_cast<const MipsSubtarget &>(MIRBuilder.getMF().getSubtarget()); - Register PhysReg = VA.getLocReg(); - if (VT == MVT::f64 && PhysReg >= Mips::A0 && PhysReg <= Mips::A3) { - const MipsSubtarget &STI = - static_cast<const MipsSubtarget &>(MIRBuilder.getMF().getSubtarget()); - - MIRBuilder - .buildInstr(STI.isFP64bit() ? Mips::BuildPairF64_64 - : Mips::BuildPairF64) - .addDef(ValVReg) - .addUse(PhysReg + (STI.isLittle() ? 0 : 1)) - .addUse(PhysReg + (STI.isLittle() ? 1 : 0)) - .constrainAllUses(MIRBuilder.getTII(), *STI.getRegisterInfo(), - *STI.getRegBankInfo()); - markPhysRegUsed(PhysReg); - markPhysRegUsed(PhysReg + 1); - } else if (VT == MVT::f32 && PhysReg >= Mips::A0 && PhysReg <= Mips::A3) { - MIRBuilder.buildInstr(Mips::MTC1) - .addDef(ValVReg) - .addUse(PhysReg) - .constrainAllUses(MIRBuilder.getTII(), *STI.getRegisterInfo(), - *STI.getRegBankInfo()); - markPhysRegUsed(PhysReg); - } else { - switch (VA.getLocInfo()) { - case CCValAssign::LocInfo::SExt: - case CCValAssign::LocInfo::ZExt: - case CCValAssign::LocInfo::AExt: { - auto Copy = MIRBuilder.buildCopy(LLT{VA.getLocVT()}, PhysReg); - MIRBuilder.buildTrunc(ValVReg, Copy); - break; - } - default: - MIRBuilder.buildCopy(ValVReg, PhysReg); - break; - } - markPhysRegUsed(PhysReg); - } -} - -Register IncomingValueHandler::getStackAddress(const CCValAssign &VA, - MachineMemOperand *&MMO) { - MachineFunction &MF = MIRBuilder.getMF(); - unsigned Size = alignTo(VA.getValVT().getSizeInBits(), 8) / 8; - unsigned Offset = VA.getLocMemOffset(); - MachineFrameInfo &MFI = MF.getFrameInfo(); - - int FI = MFI.CreateFixedObject(Size, Offset, true); - MachinePointerInfo MPO = - MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI); - - const TargetFrameLowering *TFL = MF.getSubtarget().getFrameLowering(); - unsigned Align = MinAlign(TFL->getStackAlignment(), Offset); - MMO = MF.getMachineMemOperand(MPO, MachineMemOperand::MOLoad, Size, Align); - - Register AddrReg = MRI.createGenericVirtualRegister(LLT::pointer(0, 32)); - MIRBuilder.buildFrameIndex(AddrReg, FI); - - return AddrReg; -} - -void IncomingValueHandler::assignValueToAddress(Register ValVReg, - const CCValAssign &VA) { - if (VA.getLocInfo() == CCValAssign::SExt || - VA.getLocInfo() == CCValAssign::ZExt || - VA.getLocInfo() == CCValAssign::AExt) { - Register LoadReg = MRI.createGenericVirtualRegister(LLT::scalar(32)); - buildLoad(LoadReg, VA); - MIRBuilder.buildTrunc(ValVReg, LoadReg); - } else - buildLoad(ValVReg, VA); -} - -bool IncomingValueHandler::handleSplit(SmallVectorImpl<Register> &VRegs, - ArrayRef<CCValAssign> ArgLocs, - unsigned ArgLocsStartIndex, - Register ArgsReg, const EVT &VT) { - if (!assignVRegs(VRegs, ArgLocs, ArgLocsStartIndex, VT)) - return false; - setLeastSignificantFirst(VRegs); - MIRBuilder.buildMerge(ArgsReg, VRegs); - return true; -} - -namespace { -class OutgoingValueHandler : public MipsCallLowering::MipsHandler { -public: - OutgoingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, - MachineInstrBuilder &MIB) - : MipsHandler(MIRBuilder, MRI), MIB(MIB) {} - -private: - void assignValueToReg(Register ValVReg, const CCValAssign &VA, - const EVT &VT) override; - - Register getStackAddress(const CCValAssign &VA, - MachineMemOperand *&MMO) override; - - void assignValueToAddress(Register ValVReg, const CCValAssign &VA) override; - - bool handleSplit(SmallVectorImpl<Register> &VRegs, - ArrayRef<CCValAssign> ArgLocs, unsigned ArgLocsStartIndex, - Register ArgsReg, const EVT &VT) override; - - Register extendRegister(Register ValReg, const CCValAssign &VA); - - MachineInstrBuilder &MIB; -}; -} // end anonymous namespace - -void OutgoingValueHandler::assignValueToReg(Register ValVReg, - const CCValAssign &VA, - const EVT &VT) { - Register PhysReg = VA.getLocReg(); - const MipsSubtarget &STI = - static_cast<const MipsSubtarget &>(MIRBuilder.getMF().getSubtarget()); - - if (VT == MVT::f64 && PhysReg >= Mips::A0 && PhysReg <= Mips::A3) { - MIRBuilder - .buildInstr(STI.isFP64bit() ? Mips::ExtractElementF64_64 - : Mips::ExtractElementF64) - .addDef(PhysReg + (STI.isLittle() ? 1 : 0)) - .addUse(ValVReg) - .addImm(1) - .constrainAllUses(MIRBuilder.getTII(), *STI.getRegisterInfo(), - *STI.getRegBankInfo()); - MIRBuilder - .buildInstr(STI.isFP64bit() ? Mips::ExtractElementF64_64 - : Mips::ExtractElementF64) - .addDef(PhysReg + (STI.isLittle() ? 0 : 1)) - .addUse(ValVReg) - .addImm(0) - .constrainAllUses(MIRBuilder.getTII(), *STI.getRegisterInfo(), - *STI.getRegBankInfo()); - } else if (VT == MVT::f32 && PhysReg >= Mips::A0 && PhysReg <= Mips::A3) { - MIRBuilder.buildInstr(Mips::MFC1) - .addDef(PhysReg) - .addUse(ValVReg) - .constrainAllUses(MIRBuilder.getTII(), *STI.getRegisterInfo(), - *STI.getRegBankInfo()); - } else { - Register ExtReg = extendRegister(ValVReg, VA); - MIRBuilder.buildCopy(PhysReg, ExtReg); - MIB.addUse(PhysReg, RegState::Implicit); - } -} - -Register OutgoingValueHandler::getStackAddress(const CCValAssign &VA, - MachineMemOperand *&MMO) { - MachineFunction &MF = MIRBuilder.getMF(); - const TargetFrameLowering *TFL = MF.getSubtarget().getFrameLowering(); - - LLT p0 = LLT::pointer(0, 32); - LLT s32 = LLT::scalar(32); - Register SPReg = MRI.createGenericVirtualRegister(p0); - MIRBuilder.buildCopy(SPReg, Register(Mips::SP)); - - Register OffsetReg = MRI.createGenericVirtualRegister(s32); - unsigned Offset = VA.getLocMemOffset(); - MIRBuilder.buildConstant(OffsetReg, Offset); - - Register AddrReg = MRI.createGenericVirtualRegister(p0); - MIRBuilder.buildGEP(AddrReg, SPReg, OffsetReg); - - MachinePointerInfo MPO = - MachinePointerInfo::getStack(MIRBuilder.getMF(), Offset); - unsigned Size = alignTo(VA.getValVT().getSizeInBits(), 8) / 8; - unsigned Align = MinAlign(TFL->getStackAlignment(), Offset); - MMO = MF.getMachineMemOperand(MPO, MachineMemOperand::MOStore, Size, Align); - - return AddrReg; -} - -void OutgoingValueHandler::assignValueToAddress(Register ValVReg, - const CCValAssign &VA) { - MachineMemOperand *MMO; - Register Addr = getStackAddress(VA, MMO); - Register ExtReg = extendRegister(ValVReg, VA); - MIRBuilder.buildStore(ExtReg, Addr, *MMO); -} - -Register OutgoingValueHandler::extendRegister(Register ValReg, - const CCValAssign &VA) { - LLT LocTy{VA.getLocVT()}; - switch (VA.getLocInfo()) { - case CCValAssign::SExt: { - Register ExtReg = MRI.createGenericVirtualRegister(LocTy); - MIRBuilder.buildSExt(ExtReg, ValReg); - return ExtReg; - } - case CCValAssign::ZExt: { - Register ExtReg = MRI.createGenericVirtualRegister(LocTy); - MIRBuilder.buildZExt(ExtReg, ValReg); - return ExtReg; - } - case CCValAssign::AExt: { - Register ExtReg = MRI.createGenericVirtualRegister(LocTy); - MIRBuilder.buildAnyExt(ExtReg, ValReg); - return ExtReg; - } - // TODO : handle upper extends - case CCValAssign::Full: - return ValReg; - default: - break; - } - llvm_unreachable("unable to extend register"); -} - -bool OutgoingValueHandler::handleSplit(SmallVectorImpl<Register> &VRegs, - ArrayRef<CCValAssign> ArgLocs, - unsigned ArgLocsStartIndex, - Register ArgsReg, const EVT &VT) { - MIRBuilder.buildUnmerge(VRegs, ArgsReg); - setLeastSignificantFirst(VRegs); - if (!assignVRegs(VRegs, ArgLocs, ArgLocsStartIndex, VT)) - return false; - - return true; -} - -static bool isSupportedType(Type *T) { - if (T->isIntegerTy()) - return true; - if (T->isPointerTy()) - return true; - if (T->isFloatingPointTy()) - return true; - return false; -} - -static CCValAssign::LocInfo determineLocInfo(const MVT RegisterVT, const EVT VT, - const ISD::ArgFlagsTy &Flags) { - // > does not mean loss of information as type RegisterVT can't hold type VT, - // it means that type VT is split into multiple registers of type RegisterVT - if (VT.getSizeInBits() >= RegisterVT.getSizeInBits()) - return CCValAssign::LocInfo::Full; - if (Flags.isSExt()) - return CCValAssign::LocInfo::SExt; - if (Flags.isZExt()) - return CCValAssign::LocInfo::ZExt; - return CCValAssign::LocInfo::AExt; -} - -template <typename T> -static void setLocInfo(SmallVectorImpl<CCValAssign> &ArgLocs, - const SmallVectorImpl<T> &Arguments) { - for (unsigned i = 0; i < ArgLocs.size(); ++i) { - const CCValAssign &VA = ArgLocs[i]; - CCValAssign::LocInfo LocInfo = determineLocInfo( - Arguments[i].VT, Arguments[i].ArgVT, Arguments[i].Flags); - if (VA.isMemLoc()) - ArgLocs[i] = - CCValAssign::getMem(VA.getValNo(), VA.getValVT(), - VA.getLocMemOffset(), VA.getLocVT(), LocInfo); - else - ArgLocs[i] = CCValAssign::getReg(VA.getValNo(), VA.getValVT(), - VA.getLocReg(), VA.getLocVT(), LocInfo); - } -} - -bool MipsCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, - const Value *Val, - ArrayRef<Register> VRegs) const { - - MachineInstrBuilder Ret = MIRBuilder.buildInstrNoInsert(Mips::RetRA); - - if (Val != nullptr && !isSupportedType(Val->getType())) - return false; - - if (!VRegs.empty()) { - MachineFunction &MF = MIRBuilder.getMF(); - const Function &F = MF.getFunction(); - const DataLayout &DL = MF.getDataLayout(); - const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>(); - LLVMContext &Ctx = Val->getType()->getContext(); - - SmallVector<EVT, 4> SplitEVTs; - ComputeValueVTs(TLI, DL, Val->getType(), SplitEVTs); - assert(VRegs.size() == SplitEVTs.size() && - "For each split Type there should be exactly one VReg."); - - SmallVector<ArgInfo, 8> RetInfos; - SmallVector<unsigned, 8> OrigArgIndices; - - for (unsigned i = 0; i < SplitEVTs.size(); ++i) { - ArgInfo CurArgInfo = ArgInfo{VRegs[i], SplitEVTs[i].getTypeForEVT(Ctx)}; - setArgFlags(CurArgInfo, AttributeList::ReturnIndex, DL, F); - splitToValueTypes(CurArgInfo, 0, RetInfos, OrigArgIndices); - } - - SmallVector<ISD::OutputArg, 8> Outs; - subTargetRegTypeForCallingConv(F, RetInfos, OrigArgIndices, Outs); - - SmallVector<CCValAssign, 16> ArgLocs; - MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, - F.getContext()); - CCInfo.AnalyzeReturn(Outs, TLI.CCAssignFnForReturn()); - setLocInfo(ArgLocs, Outs); - - OutgoingValueHandler RetHandler(MIRBuilder, MF.getRegInfo(), Ret); - if (!RetHandler.handle(ArgLocs, RetInfos)) { - return false; - } - } - MIRBuilder.insertInstr(Ret); - return true; -} - -bool MipsCallLowering::lowerFormalArguments( - MachineIRBuilder &MIRBuilder, const Function &F, - ArrayRef<ArrayRef<Register>> VRegs) const { - - // Quick exit if there aren't any args. - if (F.arg_empty()) - return true; - - if (F.isVarArg()) { - return false; - } - - for (auto &Arg : F.args()) { - if (!isSupportedType(Arg.getType())) - return false; - } - - MachineFunction &MF = MIRBuilder.getMF(); - const DataLayout &DL = MF.getDataLayout(); - const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>(); - - SmallVector<ArgInfo, 8> ArgInfos; - SmallVector<unsigned, 8> OrigArgIndices; - unsigned i = 0; - for (auto &Arg : F.args()) { - ArgInfo AInfo(VRegs[i], Arg.getType()); - setArgFlags(AInfo, i + AttributeList::FirstArgIndex, DL, F); - splitToValueTypes(AInfo, i, ArgInfos, OrigArgIndices); - ++i; - } - - SmallVector<ISD::InputArg, 8> Ins; - subTargetRegTypeForCallingConv(F, ArgInfos, OrigArgIndices, Ins); - - SmallVector<CCValAssign, 16> ArgLocs; - MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, - F.getContext()); - - const MipsTargetMachine &TM = - static_cast<const MipsTargetMachine &>(MF.getTarget()); - const MipsABIInfo &ABI = TM.getABI(); - CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(F.getCallingConv()), - 1); - CCInfo.AnalyzeFormalArguments(Ins, TLI.CCAssignFnForCall()); - setLocInfo(ArgLocs, Ins); - - IncomingValueHandler Handler(MIRBuilder, MF.getRegInfo()); - if (!Handler.handle(ArgLocs, ArgInfos)) - return false; - - return true; -} - -bool MipsCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, - CallingConv::ID CallConv, - const MachineOperand &Callee, - const ArgInfo &OrigRet, - ArrayRef<ArgInfo> OrigArgs) const { - - if (CallConv != CallingConv::C) - return false; - - for (auto &Arg : OrigArgs) { - if (!isSupportedType(Arg.Ty)) - return false; - if (Arg.Flags.isByVal() || Arg.Flags.isSRet()) - return false; - } - - if (OrigRet.Regs[0] && !isSupportedType(OrigRet.Ty)) - return false; - - MachineFunction &MF = MIRBuilder.getMF(); - const Function &F = MF.getFunction(); - const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>(); - const MipsTargetMachine &TM = - static_cast<const MipsTargetMachine &>(MF.getTarget()); - const MipsABIInfo &ABI = TM.getABI(); - - MachineInstrBuilder CallSeqStart = - MIRBuilder.buildInstr(Mips::ADJCALLSTACKDOWN); - - const bool IsCalleeGlobalPIC = - Callee.isGlobal() && TM.isPositionIndependent(); - - MachineInstrBuilder MIB = MIRBuilder.buildInstrNoInsert( - Callee.isReg() || IsCalleeGlobalPIC ? Mips::JALRPseudo : Mips::JAL); - MIB.addDef(Mips::SP, RegState::Implicit); - if (IsCalleeGlobalPIC) { - Register CalleeReg = - MF.getRegInfo().createGenericVirtualRegister(LLT::pointer(0, 32)); - MachineInstr *CalleeGlobalValue = - MIRBuilder.buildGlobalValue(CalleeReg, Callee.getGlobal()); - if (!Callee.getGlobal()->hasLocalLinkage()) - CalleeGlobalValue->getOperand(1).setTargetFlags(MipsII::MO_GOT_CALL); - MIB.addUse(CalleeReg); - } else - MIB.add(Callee); - const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); - MIB.addRegMask(TRI->getCallPreservedMask(MF, F.getCallingConv())); - - TargetLowering::ArgListTy FuncOrigArgs; - FuncOrigArgs.reserve(OrigArgs.size()); - - SmallVector<ArgInfo, 8> ArgInfos; - SmallVector<unsigned, 8> OrigArgIndices; - unsigned i = 0; - for (auto &Arg : OrigArgs) { - - TargetLowering::ArgListEntry Entry; - Entry.Ty = Arg.Ty; - FuncOrigArgs.push_back(Entry); - - splitToValueTypes(Arg, i, ArgInfos, OrigArgIndices); - ++i; - } - - SmallVector<ISD::OutputArg, 8> Outs; - subTargetRegTypeForCallingConv(F, ArgInfos, OrigArgIndices, Outs); - - SmallVector<CCValAssign, 8> ArgLocs; - MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, - F.getContext()); - - CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(CallConv), 1); - const char *Call = Callee.isSymbol() ? Callee.getSymbolName() : nullptr; - CCInfo.AnalyzeCallOperands(Outs, TLI.CCAssignFnForCall(), FuncOrigArgs, Call); - setLocInfo(ArgLocs, Outs); - - OutgoingValueHandler RetHandler(MIRBuilder, MF.getRegInfo(), MIB); - if (!RetHandler.handle(ArgLocs, ArgInfos)) { - return false; - } - - unsigned NextStackOffset = CCInfo.getNextStackOffset(); - const TargetFrameLowering *TFL = MF.getSubtarget().getFrameLowering(); - unsigned StackAlignment = TFL->getStackAlignment(); - NextStackOffset = alignTo(NextStackOffset, StackAlignment); - CallSeqStart.addImm(NextStackOffset).addImm(0); - - if (IsCalleeGlobalPIC) { - MIRBuilder.buildCopy( - Register(Mips::GP), - MF.getInfo<MipsFunctionInfo>()->getGlobalBaseRegForGlobalISel()); - MIB.addDef(Mips::GP, RegState::Implicit); - } - MIRBuilder.insertInstr(MIB); - if (MIB->getOpcode() == Mips::JALRPseudo) { - const MipsSubtarget &STI = - static_cast<const MipsSubtarget &>(MIRBuilder.getMF().getSubtarget()); - MIB.constrainAllUses(MIRBuilder.getTII(), *STI.getRegisterInfo(), - *STI.getRegBankInfo()); - } - - if (OrigRet.Regs[0]) { - ArgInfos.clear(); - SmallVector<unsigned, 8> OrigRetIndices; - - splitToValueTypes(OrigRet, 0, ArgInfos, OrigRetIndices); - - SmallVector<ISD::InputArg, 8> Ins; - subTargetRegTypeForCallingConv(F, ArgInfos, OrigRetIndices, Ins); - - SmallVector<CCValAssign, 8> ArgLocs; - MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, - F.getContext()); - - CCInfo.AnalyzeCallResult(Ins, TLI.CCAssignFnForReturn(), OrigRet.Ty, Call); - setLocInfo(ArgLocs, Ins); - - CallReturnHandler Handler(MIRBuilder, MF.getRegInfo(), MIB); - if (!Handler.handle(ArgLocs, ArgInfos)) - return false; - } - - MIRBuilder.buildInstr(Mips::ADJCALLSTACKUP).addImm(NextStackOffset).addImm(0); - - return true; -} - -template <typename T> -void MipsCallLowering::subTargetRegTypeForCallingConv( - const Function &F, ArrayRef<ArgInfo> Args, - ArrayRef<unsigned> OrigArgIndices, SmallVectorImpl<T> &ISDArgs) const { - const DataLayout &DL = F.getParent()->getDataLayout(); - const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>(); - - unsigned ArgNo = 0; - for (auto &Arg : Args) { - - EVT VT = TLI.getValueType(DL, Arg.Ty); - MVT RegisterVT = TLI.getRegisterTypeForCallingConv(F.getContext(), - F.getCallingConv(), VT); - unsigned NumRegs = TLI.getNumRegistersForCallingConv( - F.getContext(), F.getCallingConv(), VT); - - for (unsigned i = 0; i < NumRegs; ++i) { - ISD::ArgFlagsTy Flags = Arg.Flags; - - if (i == 0) - Flags.setOrigAlign(TLI.getABIAlignmentForCallingConv(Arg.Ty, DL)); - else - Flags.setOrigAlign(1); - - ISDArgs.emplace_back(Flags, RegisterVT, VT, true, OrigArgIndices[ArgNo], - 0); - } - ++ArgNo; - } -} - -void MipsCallLowering::splitToValueTypes( - const ArgInfo &OrigArg, unsigned OriginalIndex, - SmallVectorImpl<ArgInfo> &SplitArgs, - SmallVectorImpl<unsigned> &SplitArgsOrigIndices) const { - - // TODO : perform structure and array split. For now we only deal with - // types that pass isSupportedType check. - SplitArgs.push_back(OrigArg); - SplitArgsOrigIndices.push_back(OriginalIndex); -} diff --git a/contrib/llvm/lib/Target/Mips/MipsCallLowering.h b/contrib/llvm/lib/Target/Mips/MipsCallLowering.h deleted file mode 100644 index 11c2d53ad35d..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsCallLowering.h +++ /dev/null @@ -1,93 +0,0 @@ -//===- MipsCallLowering.h ---------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -/// \file -/// This file describes how to lower LLVM calls to machine code calls. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_MIPS_MIPSCALLLOWERING_H -#define LLVM_LIB_TARGET_MIPS_MIPSCALLLOWERING_H - -#include "llvm/CodeGen/GlobalISel/CallLowering.h" - -namespace llvm { - -class MipsTargetLowering; - -class MipsCallLowering : public CallLowering { - -public: - class MipsHandler { - public: - MipsHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI) - : MIRBuilder(MIRBuilder), MRI(MRI) {} - - virtual ~MipsHandler() = default; - - bool handle(ArrayRef<CCValAssign> ArgLocs, - ArrayRef<CallLowering::ArgInfo> Args); - - protected: - bool assignVRegs(ArrayRef<Register> VRegs, ArrayRef<CCValAssign> ArgLocs, - unsigned ArgLocsStartIndex, const EVT &VT); - - void setLeastSignificantFirst(SmallVectorImpl<Register> &VRegs); - - MachineIRBuilder &MIRBuilder; - MachineRegisterInfo &MRI; - - private: - bool assign(Register VReg, const CCValAssign &VA, const EVT &VT); - - virtual Register getStackAddress(const CCValAssign &VA, - MachineMemOperand *&MMO) = 0; - - virtual void assignValueToReg(Register ValVReg, const CCValAssign &VA, - const EVT &VT) = 0; - - virtual void assignValueToAddress(Register ValVReg, - const CCValAssign &VA) = 0; - - virtual bool handleSplit(SmallVectorImpl<Register> &VRegs, - ArrayRef<CCValAssign> ArgLocs, - unsigned ArgLocsStartIndex, Register ArgsReg, - const EVT &VT) = 0; - }; - - MipsCallLowering(const MipsTargetLowering &TLI); - - bool lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val, - ArrayRef<Register> VRegs) const override; - - bool lowerFormalArguments(MachineIRBuilder &MIRBuilder, const Function &F, - ArrayRef<ArrayRef<Register>> VRegs) const override; - - bool lowerCall(MachineIRBuilder &MIRBuilder, CallingConv::ID CallConv, - const MachineOperand &Callee, const ArgInfo &OrigRet, - ArrayRef<ArgInfo> OrigArgs) const override; - -private: - /// Based on registers available on target machine split or extend - /// type if needed, also change pointer type to appropriate integer - /// type. - template <typename T> - void subTargetRegTypeForCallingConv(const Function &F, ArrayRef<ArgInfo> Args, - ArrayRef<unsigned> OrigArgIndices, - SmallVectorImpl<T> &ISDArgs) const; - - /// Split structures and arrays, save original argument indices since - /// Mips calling convention needs info about original argument type. - void splitToValueTypes(const ArgInfo &OrigArg, unsigned OriginalIndex, - SmallVectorImpl<ArgInfo> &SplitArgs, - SmallVectorImpl<unsigned> &SplitArgsOrigIndices) const; -}; - -} // end namespace llvm - -#endif // LLVM_LIB_TARGET_MIPS_MIPSCALLLOWERING_H diff --git a/contrib/llvm/lib/Target/Mips/MipsCallingConv.td b/contrib/llvm/lib/Target/Mips/MipsCallingConv.td deleted file mode 100644 index 88236d8e9abd..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsCallingConv.td +++ /dev/null @@ -1,411 +0,0 @@ -//===-- MipsCallingConv.td - Calling Conventions for Mips --*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// This describes the calling conventions for Mips architecture. -//===----------------------------------------------------------------------===// - -/// CCIfSubtarget - Match if the current subtarget has a feature F. -class CCIfSubtarget<string F, CCAction A, string Invert = ""> - : CCIf<!strconcat(Invert, - "static_cast<const MipsSubtarget&>" - "(State.getMachineFunction().getSubtarget()).", - F), - A>; - -// The inverse of CCIfSubtarget -class CCIfSubtargetNot<string F, CCAction A> : CCIfSubtarget<F, A, "!">; - -/// Match if the original argument (before lowering) was a float. -/// For example, this is true for i32's that were lowered from soft-float. -class CCIfOrigArgWasNotFloat<CCAction A> - : CCIf<"!static_cast<MipsCCState *>(&State)->WasOriginalArgFloat(ValNo)", - A>; - -/// Match if the original argument (before lowering) was a 128-bit float (i.e. -/// long double). -class CCIfOrigArgWasF128<CCAction A> - : CCIf<"static_cast<MipsCCState *>(&State)->WasOriginalArgF128(ValNo)", A>; - -/// Match if this specific argument is a vararg. -/// This is slightly different fro CCIfIsVarArg which matches if any argument is -/// a vararg. -class CCIfArgIsVarArg<CCAction A> - : CCIf<"!static_cast<MipsCCState *>(&State)->IsCallOperandFixed(ValNo)", A>; - -/// Match if the return was a floating point vector. -class CCIfOrigArgWasNotVectorFloat<CCAction A> - : CCIf<"!static_cast<MipsCCState *>(&State)" - "->WasOriginalRetVectorFloat(ValNo)", A>; - -/// Match if the special calling conv is the specified value. -class CCIfSpecialCallingConv<string CC, CCAction A> - : CCIf<"static_cast<MipsCCState *>(&State)->getSpecialCallingConv() == " - "MipsCCState::" # CC, A>; - -// For soft-float, f128 values are returned in A0_64 rather than V1_64. -def RetCC_F128SoftFloat : CallingConv<[ - CCAssignToReg<[V0_64, A0_64]> -]>; - -// For hard-float, f128 values are returned as a pair of f64's rather than a -// pair of i64's. -def RetCC_F128HardFloat : CallingConv<[ - CCBitConvertToType<f64>, - - // Contrary to the ABI documentation, a struct containing a long double is - // returned in $f0, and $f1 instead of the usual $f0, and $f2. This is to - // match the de facto ABI as implemented by GCC. - CCIfInReg<CCAssignToReg<[D0_64, D1_64]>>, - - CCAssignToReg<[D0_64, D2_64]> -]>; - -// Handle F128 specially since we can't identify the original type during the -// tablegen-erated code. -def RetCC_F128 : CallingConv<[ - CCIfSubtarget<"useSoftFloat()", - CCIfType<[i64], CCDelegateTo<RetCC_F128SoftFloat>>>, - CCIfSubtargetNot<"useSoftFloat()", - CCIfType<[i64], CCDelegateTo<RetCC_F128HardFloat>>> -]>; - -//===----------------------------------------------------------------------===// -// Mips O32 Calling Convention -//===----------------------------------------------------------------------===// - -def CC_MipsO32 : CallingConv<[ - // Promote i8/i16 arguments to i32. - CCIfType<[i1, i8, i16], CCPromoteToType<i32>>, - - // Integer values get stored in stack slots that are 4 bytes in - // size and 4-byte aligned. - CCIfType<[i32, f32], CCAssignToStack<4, 4>>, - - // Integer values get stored in stack slots that are 8 bytes in - // size and 8-byte aligned. - CCIfType<[f64], CCAssignToStack<8, 8>> -]>; - -// Only the return rules are defined here for O32. The rules for argument -// passing are defined in MipsISelLowering.cpp. -def RetCC_MipsO32 : CallingConv<[ - // Promote i1/i8/i16 return values to i32. - CCIfType<[i1, i8, i16], CCPromoteToType<i32>>, - - // i32 are returned in registers V0, V1, A0, A1, unless the original return - // type was a vector of floats. - CCIfOrigArgWasNotVectorFloat<CCIfType<[i32], - CCAssignToReg<[V0, V1, A0, A1]>>>, - - // f32 are returned in registers F0, F2 - CCIfType<[f32], CCAssignToReg<[F0, F2]>>, - - // f64 arguments are returned in D0_64 and D2_64 in FP64bit mode or - // in D0 and D1 in FP32bit mode. - CCIfType<[f64], CCIfSubtarget<"isFP64bit()", CCAssignToReg<[D0_64, D2_64]>>>, - CCIfType<[f64], CCIfSubtargetNot<"isFP64bit()", CCAssignToReg<[D0, D1]>>> -]>; - -def CC_MipsO32_FP32 : CustomCallingConv; -def CC_MipsO32_FP64 : CustomCallingConv; - -def CC_MipsO32_FP : CallingConv<[ - CCIfSubtargetNot<"isFP64bit()", CCDelegateTo<CC_MipsO32_FP32>>, - CCIfSubtarget<"isFP64bit()", CCDelegateTo<CC_MipsO32_FP64>> -]>; - -//===----------------------------------------------------------------------===// -// Mips N32/64 Calling Convention -//===----------------------------------------------------------------------===// - -def CC_MipsN_SoftFloat : CallingConv<[ - CCAssignToRegWithShadow<[A0, A1, A2, A3, - T0, T1, T2, T3], - [D12_64, D13_64, D14_64, D15_64, - D16_64, D17_64, D18_64, D19_64]>, - CCAssignToStack<4, 8> -]>; - -def CC_MipsN : CallingConv<[ - CCIfType<[i8, i16, i32, i64], - CCIfSubtargetNot<"isLittle()", - CCIfInReg<CCPromoteToUpperBitsInType<i64>>>>, - - // All integers (except soft-float integers) are promoted to 64-bit. - CCIfType<[i8, i16, i32], CCIfOrigArgWasNotFloat<CCPromoteToType<i64>>>, - - // The only i32's we have left are soft-float arguments. - CCIfSubtarget<"useSoftFloat()", CCIfType<[i32], CCDelegateTo<CC_MipsN_SoftFloat>>>, - - // Integer arguments are passed in integer registers. - CCIfType<[i64], CCAssignToRegWithShadow<[A0_64, A1_64, A2_64, A3_64, - T0_64, T1_64, T2_64, T3_64], - [D12_64, D13_64, D14_64, D15_64, - D16_64, D17_64, D18_64, D19_64]>>, - - // f32 arguments are passed in single precision FP registers. - CCIfType<[f32], CCAssignToRegWithShadow<[F12, F13, F14, F15, - F16, F17, F18, F19], - [A0_64, A1_64, A2_64, A3_64, - T0_64, T1_64, T2_64, T3_64]>>, - - // f64 arguments are passed in double precision FP registers. - CCIfType<[f64], CCAssignToRegWithShadow<[D12_64, D13_64, D14_64, D15_64, - D16_64, D17_64, D18_64, D19_64], - [A0_64, A1_64, A2_64, A3_64, - T0_64, T1_64, T2_64, T3_64]>>, - - // All stack parameter slots become 64-bit doublewords and are 8-byte aligned. - CCIfType<[f32], CCAssignToStack<4, 8>>, - CCIfType<[i64, f64], CCAssignToStack<8, 8>> -]>; - -// N32/64 variable arguments. -// All arguments are passed in integer registers. -def CC_MipsN_VarArg : CallingConv<[ - CCIfType<[i8, i16, i32, i64], - CCIfSubtargetNot<"isLittle()", - CCIfInReg<CCPromoteToUpperBitsInType<i64>>>>, - - // All integers are promoted to 64-bit. - CCIfType<[i8, i16, i32], CCPromoteToType<i64>>, - - CCIfType<[f32], CCAssignToReg<[A0, A1, A2, A3, T0, T1, T2, T3]>>, - - CCIfType<[i64, f64], CCAssignToReg<[A0_64, A1_64, A2_64, A3_64, - T0_64, T1_64, T2_64, T3_64]>>, - - // All stack parameter slots become 64-bit doublewords and are 8-byte aligned. - CCIfType<[f32], CCAssignToStack<4, 8>>, - CCIfType<[i64, f64], CCAssignToStack<8, 8>> -]>; - -def RetCC_MipsN : CallingConv<[ - // f128 needs to be handled similarly to f32 and f64. However, f128 is not - // legal and is lowered to i128 which is further lowered to a pair of i64's. - // This presents us with a problem for the calling convention since hard-float - // still needs to pass them in FPU registers, and soft-float needs to use $v0, - // and $a0 instead of the usual $v0, and $v1. We therefore resort to a - // pre-analyze (see PreAnalyzeReturnForF128()) step to pass information on - // whether the result was originally an f128 into the tablegen-erated code. - // - // f128 should only occur for the N64 ABI where long double is 128-bit. On - // N32, long double is equivalent to double. - CCIfType<[i64], CCIfOrigArgWasF128<CCDelegateTo<RetCC_F128>>>, - - // Aggregate returns are positioned at the lowest address in the slot for - // both little and big-endian targets. When passing in registers, this - // requires that big-endian targets shift the value into the upper bits. - CCIfSubtarget<"isLittle()", - CCIfType<[i8, i16, i32, i64], CCIfInReg<CCPromoteToType<i64>>>>, - CCIfSubtargetNot<"isLittle()", - CCIfType<[i8, i16, i32, i64], - CCIfInReg<CCPromoteToUpperBitsInType<i64>>>>, - - // i64 are returned in registers V0_64, V1_64 - CCIfType<[i64], CCAssignToReg<[V0_64, V1_64]>>, - - // f32 are returned in registers F0, F2 - CCIfType<[f32], CCAssignToReg<[F0, F2]>>, - - // f64 are returned in registers D0, D2 - CCIfType<[f64], CCAssignToReg<[D0_64, D2_64]>> -]>; - -//===----------------------------------------------------------------------===// -// Mips FastCC Calling Convention -//===----------------------------------------------------------------------===// -def CC_MipsO32_FastCC : CallingConv<[ - // f64 arguments are passed in double-precision floating pointer registers. - CCIfType<[f64], CCIfSubtargetNot<"isFP64bit()", - CCAssignToReg<[D0, D1, D2, D3, D4, D5, D6, - D7, D8, D9]>>>, - CCIfType<[f64], CCIfSubtarget<"isFP64bit()", CCIfSubtarget<"useOddSPReg()", - CCAssignToReg<[D0_64, D1_64, D2_64, D3_64, - D4_64, D5_64, D6_64, D7_64, - D8_64, D9_64, D10_64, D11_64, - D12_64, D13_64, D14_64, D15_64, - D16_64, D17_64, D18_64, - D19_64]>>>>, - CCIfType<[f64], CCIfSubtarget<"isFP64bit()", CCIfSubtarget<"noOddSPReg()", - CCAssignToReg<[D0_64, D2_64, D4_64, D6_64, - D8_64, D10_64, D12_64, D14_64, - D16_64, D18_64]>>>>, - - // Stack parameter slots for f64 are 64-bit doublewords and 8-byte aligned. - CCIfType<[f64], CCAssignToStack<8, 8>> -]>; - -def CC_MipsN_FastCC : CallingConv<[ - // Integer arguments are passed in integer registers. - CCIfType<[i64], CCAssignToReg<[A0_64, A1_64, A2_64, A3_64, T0_64, T1_64, - T2_64, T3_64, T4_64, T5_64, T6_64, T7_64, - T8_64, V1_64]>>, - - // f64 arguments are passed in double-precision floating pointer registers. - CCIfType<[f64], CCAssignToReg<[D0_64, D1_64, D2_64, D3_64, D4_64, D5_64, - D6_64, D7_64, D8_64, D9_64, D10_64, D11_64, - D12_64, D13_64, D14_64, D15_64, D16_64, D17_64, - D18_64, D19_64]>>, - - // Stack parameter slots for i64 and f64 are 64-bit doublewords and - // 8-byte aligned. - CCIfType<[i64, f64], CCAssignToStack<8, 8>> -]>; - -def CC_Mips_FastCC : CallingConv<[ - // Handles byval parameters. - CCIfByVal<CCPassByVal<4, 4>>, - - // Promote i8/i16 arguments to i32. - CCIfType<[i8, i16], CCPromoteToType<i32>>, - - // Integer arguments are passed in integer registers. All scratch registers, - // except for AT, V0 and T9, are available to be used as argument registers. - CCIfType<[i32], CCIfSubtargetNot<"isTargetNaCl()", - CCAssignToReg<[A0, A1, A2, A3, T0, T1, T2, T3, T4, T5, T6, T7, T8, V1]>>>, - - // In NaCl, T6, T7 and T8 are reserved and not available as argument - // registers for fastcc. T6 contains the mask for sandboxing control flow - // (indirect jumps and calls). T7 contains the mask for sandboxing memory - // accesses (loads and stores). T8 contains the thread pointer. - CCIfType<[i32], CCIfSubtarget<"isTargetNaCl()", - CCAssignToReg<[A0, A1, A2, A3, T0, T1, T2, T3, T4, T5, V1]>>>, - - // f32 arguments are passed in single-precision floating pointer registers. - CCIfType<[f32], CCIfSubtarget<"useOddSPReg()", - CCAssignToReg<[F0, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, - F14, F15, F16, F17, F18, F19]>>>, - - // Don't use odd numbered single-precision registers for -mno-odd-spreg. - CCIfType<[f32], CCIfSubtarget<"noOddSPReg()", - CCAssignToReg<[F0, F2, F4, F6, F8, F10, F12, F14, F16, F18]>>>, - - // Stack parameter slots for i32 and f32 are 32-bit words and 4-byte aligned. - CCIfType<[i32, f32], CCAssignToStack<4, 4>>, - - CCIfSubtarget<"isABI_O32()", CCDelegateTo<CC_MipsO32_FastCC>>, - CCDelegateTo<CC_MipsN_FastCC> -]>; - -//===----------------------------------------------------------------------===// -// Mips Calling Convention Dispatch -//===----------------------------------------------------------------------===// - -def RetCC_Mips : CallingConv<[ - CCIfSubtarget<"isABI_N32()", CCDelegateTo<RetCC_MipsN>>, - CCIfSubtarget<"isABI_N64()", CCDelegateTo<RetCC_MipsN>>, - CCDelegateTo<RetCC_MipsO32> -]>; - -def CC_Mips_ByVal : CallingConv<[ - CCIfSubtarget<"isABI_O32()", CCIfByVal<CCPassByVal<4, 4>>>, - CCIfByVal<CCPassByVal<8, 8>> -]>; - -def CC_Mips16RetHelper : CallingConv<[ - CCIfByVal<CCDelegateTo<CC_Mips_ByVal>>, - - // Integer arguments are passed in integer registers. - CCIfType<[i32], CCAssignToReg<[V0, V1, A0, A1]>> -]>; - -def CC_Mips_FixedArg : CallingConv<[ - // Mips16 needs special handling on some functions. - CCIf<"State.getCallingConv() != CallingConv::Fast", - CCIfSpecialCallingConv<"Mips16RetHelperConv", - CCDelegateTo<CC_Mips16RetHelper>>>, - - CCIfByVal<CCDelegateTo<CC_Mips_ByVal>>, - - // f128 needs to be handled similarly to f32 and f64 on hard-float. However, - // f128 is not legal and is lowered to i128 which is further lowered to a pair - // of i64's. - // This presents us with a problem for the calling convention since hard-float - // still needs to pass them in FPU registers. We therefore resort to a - // pre-analyze (see PreAnalyzeFormalArgsForF128()) step to pass information on - // whether the argument was originally an f128 into the tablegen-erated code. - // - // f128 should only occur for the N64 ABI where long double is 128-bit. On - // N32, long double is equivalent to double. - CCIfType<[i64], - CCIfSubtargetNot<"useSoftFloat()", - CCIfOrigArgWasF128<CCBitConvertToType<f64>>>>, - - CCIfCC<"CallingConv::Fast", CCDelegateTo<CC_Mips_FastCC>>, - - CCIfSubtarget<"isABI_O32()", CCDelegateTo<CC_MipsO32_FP>>, - CCDelegateTo<CC_MipsN> -]>; - -def CC_Mips_VarArg : CallingConv<[ - CCIfByVal<CCDelegateTo<CC_Mips_ByVal>>, - - CCIfSubtarget<"isABI_O32()", CCDelegateTo<CC_MipsO32_FP>>, - CCDelegateTo<CC_MipsN_VarArg> -]>; - -def CC_Mips : CallingConv<[ - CCIfVarArg<CCIfArgIsVarArg<CCDelegateTo<CC_Mips_VarArg>>>, - CCDelegateTo<CC_Mips_FixedArg> -]>; - -//===----------------------------------------------------------------------===// -// Callee-saved register lists. -//===----------------------------------------------------------------------===// - -def CSR_SingleFloatOnly : CalleeSavedRegs<(add (sequence "F%u", 31, 20), RA, FP, - (sequence "S%u", 7, 0))>; - -def CSR_O32_FPXX : CalleeSavedRegs<(add (sequence "D%u", 15, 10), RA, FP, - (sequence "S%u", 7, 0))> { - let OtherPreserved = (add (decimate (sequence "F%u", 30, 20), 2)); -} - -def CSR_O32 : CalleeSavedRegs<(add (sequence "D%u", 15, 10), RA, FP, - (sequence "S%u", 7, 0))>; - -def CSR_O32_FP64 : - CalleeSavedRegs<(add (decimate (sequence "D%u_64", 30, 20), 2), RA, FP, - (sequence "S%u", 7, 0))>; - -def CSR_N32 : CalleeSavedRegs<(add D20_64, D22_64, D24_64, D26_64, D28_64, - D30_64, RA_64, FP_64, GP_64, - (sequence "S%u_64", 7, 0))>; - -def CSR_N64 : CalleeSavedRegs<(add (sequence "D%u_64", 31, 24), RA_64, FP_64, - GP_64, (sequence "S%u_64", 7, 0))>; - -def CSR_Mips16RetHelper : - CalleeSavedRegs<(add V0, V1, FP, - (sequence "A%u", 3, 0), (sequence "S%u", 7, 0), - (sequence "D%u", 15, 10))>; - -def CSR_Interrupt_32R6 : CalleeSavedRegs<(add (sequence "A%u", 3, 0), - (sequence "S%u", 7, 0), - (sequence "V%u", 1, 0), - (sequence "T%u", 9, 0), - RA, FP, GP, AT)>; - -def CSR_Interrupt_32 : CalleeSavedRegs<(add (sequence "A%u", 3, 0), - (sequence "S%u", 7, 0), - (sequence "V%u", 1, 0), - (sequence "T%u", 9, 0), - RA, FP, GP, AT, LO0, HI0)>; - -def CSR_Interrupt_64R6 : CalleeSavedRegs<(add (sequence "A%u_64", 3, 0), - (sequence "V%u_64", 1, 0), - (sequence "S%u_64", 7, 0), - (sequence "T%u_64", 9, 0), - RA_64, FP_64, GP_64, AT_64)>; - -def CSR_Interrupt_64 : CalleeSavedRegs<(add (sequence "A%u_64", 3, 0), - (sequence "S%u_64", 7, 0), - (sequence "T%u_64", 9, 0), - (sequence "V%u_64", 1, 0), - RA_64, FP_64, GP_64, AT_64, - LO0_64, HI0_64)>; diff --git a/contrib/llvm/lib/Target/Mips/MipsCondMov.td b/contrib/llvm/lib/Target/Mips/MipsCondMov.td deleted file mode 100644 index 5affbcbc2101..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsCondMov.td +++ /dev/null @@ -1,309 +0,0 @@ -//===-- MipsCondMov.td - Describe Mips Conditional Moves --*- tablegen -*--===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This is the Conditional Moves implementation. -// -//===----------------------------------------------------------------------===// - -// Conditional moves: -// These instructions are expanded in -// MipsISelLowering::EmitInstrWithCustomInserter if target does not have -// conditional move instructions. -// cond:int, data:int -class CMov_I_I_FT<string opstr, RegisterOperand CRC, RegisterOperand DRC, - InstrItinClass Itin> : - InstSE<(outs DRC:$rd), (ins DRC:$rs, CRC:$rt, DRC:$F), - !strconcat(opstr, "\t$rd, $rs, $rt"), [], Itin, FrmFR, opstr> { - let Constraints = "$F = $rd"; -} - -// cond:int, data:float -class CMov_I_F_FT<string opstr, RegisterOperand CRC, RegisterOperand DRC, - InstrItinClass Itin> : - InstSE<(outs DRC:$fd), (ins DRC:$fs, CRC:$rt, DRC:$F), - !strconcat(opstr, "\t$fd, $fs, $rt"), [], Itin, FrmFR, opstr>, - HARDFLOAT { - let Constraints = "$F = $fd"; -} - -// cond:float, data:int -class CMov_F_I_FT<string opstr, RegisterOperand RC, InstrItinClass Itin, - SDPatternOperator OpNode = null_frag> : - InstSE<(outs RC:$rd), (ins RC:$rs, FCCRegsOpnd:$fcc, RC:$F), - !strconcat(opstr, "\t$rd, $rs, $fcc"), - [(set RC:$rd, (OpNode RC:$rs, FCCRegsOpnd:$fcc, RC:$F))], - Itin, FrmFR, opstr>, HARDFLOAT { - let Constraints = "$F = $rd"; -} - -// cond:float, data:float -class CMov_F_F_FT<string opstr, RegisterOperand RC, InstrItinClass Itin, - SDPatternOperator OpNode = null_frag> : - InstSE<(outs RC:$fd), (ins RC:$fs, FCCRegsOpnd:$fcc, RC:$F), - !strconcat(opstr, "\t$fd, $fs, $fcc"), - [(set RC:$fd, (OpNode RC:$fs, FCCRegsOpnd:$fcc, RC:$F))], - Itin, FrmFR, opstr>, HARDFLOAT { - let Constraints = "$F = $fd"; -} - -// select patterns -multiclass MovzPats0<RegisterClass CRC, RegisterClass DRC, - Instruction MOVZInst, Instruction SLTOp, - Instruction SLTuOp, Instruction SLTiOp, - Instruction SLTiuOp> { - def : MipsPat<(select (i32 (setge CRC:$lhs, CRC:$rhs)), DRC:$T, DRC:$F), - (MOVZInst DRC:$T, (SLTOp CRC:$lhs, CRC:$rhs), DRC:$F)>; - def : MipsPat<(select (i32 (setuge CRC:$lhs, CRC:$rhs)), DRC:$T, DRC:$F), - (MOVZInst DRC:$T, (SLTuOp CRC:$lhs, CRC:$rhs), DRC:$F)>; - def : MipsPat<(select (i32 (setge CRC:$lhs, immSExt16:$rhs)), DRC:$T, DRC:$F), - (MOVZInst DRC:$T, (SLTiOp CRC:$lhs, immSExt16:$rhs), DRC:$F)>; - def : MipsPat<(select (i32 (setuge CRC:$lh, immSExt16:$rh)), DRC:$T, DRC:$F), - (MOVZInst DRC:$T, (SLTiuOp CRC:$lh, immSExt16:$rh), DRC:$F)>; - def : MipsPat<(select (i32 (setle CRC:$lhs, CRC:$rhs)), DRC:$T, DRC:$F), - (MOVZInst DRC:$T, (SLTOp CRC:$rhs, CRC:$lhs), DRC:$F)>; - def : MipsPat<(select (i32 (setule CRC:$lhs, CRC:$rhs)), DRC:$T, DRC:$F), - (MOVZInst DRC:$T, (SLTuOp CRC:$rhs, CRC:$lhs), DRC:$F)>; - def : MipsPat<(select (i32 (setgt CRC:$lhs, immSExt16Plus1:$rhs)), - DRC:$T, DRC:$F), - (MOVZInst DRC:$T, (SLTiOp CRC:$lhs, (Plus1 imm:$rhs)), DRC:$F)>; - def : MipsPat<(select (i32 (setugt CRC:$lhs, immSExt16Plus1:$rhs)), - DRC:$T, DRC:$F), - (MOVZInst DRC:$T, (SLTiuOp CRC:$lhs, (Plus1 imm:$rhs)), - DRC:$F)>; -} - -multiclass MovzPats1<RegisterClass CRC, RegisterClass DRC, - Instruction MOVZInst, Instruction XOROp> { - def : MipsPat<(select (i32 (seteq CRC:$lhs, CRC:$rhs)), DRC:$T, DRC:$F), - (MOVZInst DRC:$T, (XOROp CRC:$lhs, CRC:$rhs), DRC:$F)>; - def : MipsPat<(select (i32 (seteq CRC:$lhs, 0)), DRC:$T, DRC:$F), - (MOVZInst DRC:$T, CRC:$lhs, DRC:$F)>; -} - -multiclass MovzPats2<RegisterClass CRC, RegisterClass DRC, - Instruction MOVZInst, Instruction XORiOp> { - def : MipsPat< - (select (i32 (seteq CRC:$lhs, immZExt16:$uimm16)), DRC:$T, DRC:$F), - (MOVZInst DRC:$T, (XORiOp CRC:$lhs, immZExt16:$uimm16), DRC:$F)>; -} - -multiclass MovnPats<RegisterClass CRC, RegisterClass DRC, Instruction MOVNInst, - Instruction XOROp> { - def : MipsPat<(select (i32 (setne CRC:$lhs, CRC:$rhs)), DRC:$T, DRC:$F), - (MOVNInst DRC:$T, (XOROp CRC:$lhs, CRC:$rhs), DRC:$F)>; - def : MipsPat<(select CRC:$cond, DRC:$T, DRC:$F), - (MOVNInst DRC:$T, CRC:$cond, DRC:$F)>; - def : MipsPat<(select (i32 (setne CRC:$lhs, 0)),DRC:$T, DRC:$F), - (MOVNInst DRC:$T, CRC:$lhs, DRC:$F)>; -} - -// Instantiation of instructions. -let AdditionalPredicates = [NotInMicroMips] in { - def MOVZ_I_I : MMRel, CMov_I_I_FT<"movz", GPR32Opnd, GPR32Opnd, II_MOVZ>, - ADD_FM<0, 0xa>, INSN_MIPS4_32_NOT_32R6_64R6; - - let isCodeGenOnly = 1 in { - def MOVZ_I_I64 : CMov_I_I_FT<"movz", GPR32Opnd, GPR64Opnd, II_MOVZ>, - ADD_FM<0, 0xa>, INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; - def MOVZ_I64_I : CMov_I_I_FT<"movz", GPR64Opnd, GPR32Opnd, II_MOVZ>, - ADD_FM<0, 0xa>, INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; - def MOVZ_I64_I64 : CMov_I_I_FT<"movz", GPR64Opnd, GPR64Opnd, II_MOVZ>, - ADD_FM<0, 0xa>, INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; - } - - def MOVN_I_I : MMRel, CMov_I_I_FT<"movn", GPR32Opnd, GPR32Opnd, II_MOVN>, - ADD_FM<0, 0xb>, INSN_MIPS4_32_NOT_32R6_64R6; - - let isCodeGenOnly = 1 in { - def MOVN_I_I64 : CMov_I_I_FT<"movn", GPR32Opnd, GPR64Opnd, II_MOVN>, - ADD_FM<0, 0xb>, INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; - def MOVN_I64_I : CMov_I_I_FT<"movn", GPR64Opnd, GPR32Opnd, II_MOVN>, - ADD_FM<0, 0xb>, INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; - def MOVN_I64_I64 : CMov_I_I_FT<"movn", GPR64Opnd, GPR64Opnd, II_MOVN>, - ADD_FM<0, 0xb>, INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; - } - def MOVZ_I_S : MMRel, CMov_I_F_FT<"movz.s", GPR32Opnd, FGR32Opnd, II_MOVZ_S>, - CMov_I_F_FM<18, 16>, INSN_MIPS4_32_NOT_32R6_64R6; - - let isCodeGenOnly = 1 in - def MOVZ_I64_S : CMov_I_F_FT<"movz.s", GPR64Opnd, FGR32Opnd, II_MOVZ_S>, - CMov_I_F_FM<18, 16>, INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; - - def MOVN_I_S : MMRel, CMov_I_F_FT<"movn.s", GPR32Opnd, FGR32Opnd, II_MOVN_S>, - CMov_I_F_FM<19, 16>, INSN_MIPS4_32_NOT_32R6_64R6; - - let isCodeGenOnly = 1 in - def MOVN_I64_S : CMov_I_F_FT<"movn.s", GPR64Opnd, FGR32Opnd, II_MOVN_S>, - CMov_I_F_FM<19, 16>, INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; - - def MOVZ_I_D32 : MMRel, CMov_I_F_FT<"movz.d", GPR32Opnd, AFGR64Opnd, - II_MOVZ_D>, CMov_I_F_FM<18, 17>, - INSN_MIPS4_32_NOT_32R6_64R6, FGR_32; - def MOVN_I_D32 : MMRel, CMov_I_F_FT<"movn.d", GPR32Opnd, AFGR64Opnd, - II_MOVN_D>, CMov_I_F_FM<19, 17>, - INSN_MIPS4_32_NOT_32R6_64R6, FGR_32; - - let DecoderNamespace = "MipsFP64" in { - def MOVZ_I_D64 : CMov_I_F_FT<"movz.d", GPR32Opnd, FGR64Opnd, II_MOVZ_D>, - CMov_I_F_FM<18, 17>, INSN_MIPS4_32_NOT_32R6_64R6, FGR_64; - def MOVN_I_D64 : CMov_I_F_FT<"movn.d", GPR32Opnd, FGR64Opnd, II_MOVN_D>, - CMov_I_F_FM<19, 17>, INSN_MIPS4_32_NOT_32R6_64R6, FGR_64; - let isCodeGenOnly = 1 in { - def MOVZ_I64_D64 : CMov_I_F_FT<"movz.d", GPR64Opnd, FGR64Opnd, II_MOVZ_D>, - CMov_I_F_FM<18, 17>, - INSN_MIPS4_32_NOT_32R6_64R6, GPR_64, FGR_64; - def MOVN_I64_D64 : CMov_I_F_FT<"movn.d", GPR64Opnd, FGR64Opnd, II_MOVN_D>, - CMov_I_F_FM<19, 17>, - INSN_MIPS4_32_NOT_32R6_64R6, GPR_64, FGR_64; - } - } - - def MOVT_I : MMRel, CMov_F_I_FT<"movt", GPR32Opnd, II_MOVT, MipsCMovFP_T>, - CMov_F_I_FM<1>, INSN_MIPS4_32_NOT_32R6_64R6; - - let isCodeGenOnly = 1 in - def MOVT_I64 : CMov_F_I_FT<"movt", GPR64Opnd, II_MOVT, MipsCMovFP_T>, - CMov_F_I_FM<1>, INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; - - def MOVF_I : MMRel, CMov_F_I_FT<"movf", GPR32Opnd, II_MOVF, MipsCMovFP_F>, - CMov_F_I_FM<0>, INSN_MIPS4_32_NOT_32R6_64R6; - - let isCodeGenOnly = 1 in - def MOVF_I64 : CMov_F_I_FT<"movf", GPR64Opnd, II_MOVF, MipsCMovFP_F>, - CMov_F_I_FM<0>, INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; - def MOVT_S : MMRel, CMov_F_F_FT<"movt.s", FGR32Opnd, II_MOVT_S, MipsCMovFP_T>, - CMov_F_F_FM<16, 1>, INSN_MIPS4_32_NOT_32R6_64R6; - def MOVF_S : MMRel, CMov_F_F_FT<"movf.s", FGR32Opnd, II_MOVF_S, MipsCMovFP_F>, - CMov_F_F_FM<16, 0>, INSN_MIPS4_32_NOT_32R6_64R6; - - def MOVT_D32 : MMRel, CMov_F_F_FT<"movt.d", AFGR64Opnd, II_MOVT_D, - MipsCMovFP_T>, CMov_F_F_FM<17, 1>, - INSN_MIPS4_32_NOT_32R6_64R6, FGR_32; - def MOVF_D32 : MMRel, CMov_F_F_FT<"movf.d", AFGR64Opnd, II_MOVF_D, - MipsCMovFP_F>, CMov_F_F_FM<17, 0>, - INSN_MIPS4_32_NOT_32R6_64R6, FGR_32; - - let DecoderNamespace = "MipsFP64" in { - def MOVT_D64 : CMov_F_F_FT<"movt.d", FGR64Opnd, II_MOVT_D, MipsCMovFP_T>, - CMov_F_F_FM<17, 1>, INSN_MIPS4_32_NOT_32R6_64R6, FGR_64; - def MOVF_D64 : CMov_F_F_FT<"movf.d", FGR64Opnd, II_MOVF_D, MipsCMovFP_F>, - CMov_F_F_FM<17, 0>, INSN_MIPS4_32_NOT_32R6_64R6, FGR_64; - } - - // Instantiation of conditional move patterns. - defm : MovzPats0<GPR32, GPR32, MOVZ_I_I, SLT, SLTu, SLTi, SLTiu>, - INSN_MIPS4_32_NOT_32R6_64R6; - defm : MovzPats1<GPR32, GPR32, MOVZ_I_I, XOR>, INSN_MIPS4_32_NOT_32R6_64R6; - defm : MovzPats2<GPR32, GPR32, MOVZ_I_I, XORi>, INSN_MIPS4_32_NOT_32R6_64R6; - - defm : MovzPats0<GPR32, GPR64, MOVZ_I_I64, SLT, SLTu, SLTi, SLTiu>, - INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; - defm : MovzPats0<GPR64, GPR32, MOVZ_I_I, SLT64, SLTu64, SLTi64, SLTiu64>, - INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; - defm : MovzPats0<GPR64, GPR64, MOVZ_I_I64, SLT64, SLTu64, SLTi64, SLTiu64>, - INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; - defm : MovzPats1<GPR32, GPR64, MOVZ_I_I64, XOR>, - INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; - defm : MovzPats1<GPR64, GPR32, MOVZ_I64_I, XOR64>, - INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; - defm : MovzPats1<GPR64, GPR64, MOVZ_I64_I64, XOR64>, - INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; - defm : MovzPats2<GPR32, GPR64, MOVZ_I_I64, XORi>, - INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; - defm : MovzPats2<GPR64, GPR32, MOVZ_I64_I, XORi64>, - INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; - defm : MovzPats2<GPR64, GPR64, MOVZ_I64_I64, XORi64>, - INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; - - defm : MovnPats<GPR32, GPR32, MOVN_I_I, XOR>, INSN_MIPS4_32_NOT_32R6_64R6; - - defm : MovnPats<GPR32, GPR64, MOVN_I_I64, XOR>, INSN_MIPS4_32_NOT_32R6_64R6, - GPR_64; - defm : MovnPats<GPR64, GPR32, MOVN_I64_I, XOR64>, INSN_MIPS4_32_NOT_32R6_64R6, - GPR_64; - defm : MovnPats<GPR64, GPR64, MOVN_I64_I64, XOR64>, INSN_MIPS4_32_NOT_32R6_64R6, - GPR_64; - - defm : MovzPats0<GPR32, FGR32, MOVZ_I_S, SLT, SLTu, SLTi, SLTiu>, - INSN_MIPS4_32_NOT_32R6_64R6; - defm : MovzPats1<GPR32, FGR32, MOVZ_I_S, XOR>, INSN_MIPS4_32_NOT_32R6_64R6; - defm : MovnPats<GPR32, FGR32, MOVN_I_S, XOR>, INSN_MIPS4_32_NOT_32R6_64R6; - - defm : MovzPats0<GPR64, FGR32, MOVZ_I_S, SLT64, SLTu64, SLTi64, SLTiu64>, - INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; - defm : MovzPats1<GPR64, FGR32, MOVZ_I64_S, XOR64>, INSN_MIPS4_32_NOT_32R6_64R6, - GPR_64; - defm : MovnPats<GPR64, FGR32, MOVN_I64_S, XOR64>, INSN_MIPS4_32_NOT_32R6_64R6, - GPR_64; - - defm : MovzPats0<GPR32, AFGR64, MOVZ_I_D32, SLT, SLTu, SLTi, SLTiu>, - INSN_MIPS4_32_NOT_32R6_64R6, FGR_32; - defm : MovzPats1<GPR32, AFGR64, MOVZ_I_D32, XOR>, INSN_MIPS4_32_NOT_32R6_64R6, - FGR_32; - defm : MovnPats<GPR32, AFGR64, MOVN_I_D32, XOR>, INSN_MIPS4_32_NOT_32R6_64R6, - FGR_32; - - defm : MovzPats0<GPR32, FGR64, MOVZ_I_D64, SLT, SLTu, SLTi, SLTiu>, - INSN_MIPS4_32_NOT_32R6_64R6, FGR_64; - defm : MovzPats0<GPR64, FGR64, MOVZ_I_D64, SLT64, SLTu64, SLTi64, SLTiu64>, - INSN_MIPS4_32_NOT_32R6_64R6, FGR_64; - defm : MovzPats1<GPR32, FGR64, MOVZ_I_D64, XOR>, INSN_MIPS4_32_NOT_32R6_64R6, - FGR_64; - defm : MovzPats1<GPR64, FGR64, MOVZ_I64_D64, XOR64>, - INSN_MIPS4_32_NOT_32R6_64R6, FGR_64; - defm : MovnPats<GPR32, FGR64, MOVN_I_D64, XOR>, INSN_MIPS4_32_NOT_32R6_64R6, - FGR_64; - defm : MovnPats<GPR64, FGR64, MOVN_I64_D64, XOR64>, INSN_MIPS4_32_NOT_32R6_64R6, - FGR_64; -} -// For targets that don't have conditional-move instructions -// we have to match SELECT nodes with pseudo instructions. -let usesCustomInserter = 1, hasNoSchedulingInfo = 1 in { - class Select_Pseudo<RegisterOperand RC> : - PseudoSE<(outs RC:$dst), (ins GPR32Opnd:$cond, RC:$T, RC:$F), - [(set RC:$dst, (select GPR32Opnd:$cond, RC:$T, RC:$F))]>, - ISA_MIPS1_NOT_4_32; - - class SelectFP_Pseudo_T<RegisterOperand RC> : - PseudoSE<(outs RC:$dst), (ins FCCRegsOpnd:$cond, RC:$T, RC:$F), - [(set RC:$dst, (MipsCMovFP_T RC:$T, FCCRegsOpnd:$cond, RC:$F))]>, - ISA_MIPS1_NOT_4_32; - - class SelectFP_Pseudo_F<RegisterOperand RC> : - PseudoSE<(outs RC:$dst), (ins FCCRegsOpnd:$cond, RC:$T, RC:$F), - [(set RC:$dst, (MipsCMovFP_F RC:$T, FCCRegsOpnd:$cond, RC:$F))]>, - ISA_MIPS1_NOT_4_32; -} - -def PseudoSELECT_I : Select_Pseudo<GPR32Opnd>; -def PseudoSELECT_I64 : Select_Pseudo<GPR64Opnd>; -def PseudoSELECT_S : Select_Pseudo<FGR32Opnd>; -def PseudoSELECT_D32 : Select_Pseudo<AFGR64Opnd>, FGR_32; -def PseudoSELECT_D64 : Select_Pseudo<FGR64Opnd>, FGR_64; - -def PseudoSELECTFP_T_I : SelectFP_Pseudo_T<GPR32Opnd>; -def PseudoSELECTFP_T_I64 : SelectFP_Pseudo_T<GPR64Opnd>; -def PseudoSELECTFP_T_S : SelectFP_Pseudo_T<FGR32Opnd>; -def PseudoSELECTFP_T_D32 : SelectFP_Pseudo_T<AFGR64Opnd>, FGR_32; -def PseudoSELECTFP_T_D64 : SelectFP_Pseudo_T<FGR64Opnd>, FGR_64; - -def PseudoSELECTFP_F_I : SelectFP_Pseudo_F<GPR32Opnd>; -def PseudoSELECTFP_F_I64 : SelectFP_Pseudo_F<GPR64Opnd>; -def PseudoSELECTFP_F_S : SelectFP_Pseudo_F<FGR32Opnd>; -def PseudoSELECTFP_F_D32 : SelectFP_Pseudo_F<AFGR64Opnd>, FGR_32; -def PseudoSELECTFP_F_D64 : SelectFP_Pseudo_F<FGR64Opnd>, FGR_64; - -let usesCustomInserter = 1, hasNoSchedulingInfo = 1 in { -class D_SELECT_CLASS<RegisterOperand RC> : - PseudoSE<(outs RC:$dst1, RC:$dst2), - (ins GPR32Opnd:$cond, RC:$a1, RC:$a2, RC:$b1, RC:$b2), []>, - ISA_MIPS1_NOT_4_32; -} - -def PseudoD_SELECT_I : D_SELECT_CLASS<GPR32Opnd>; -def PseudoD_SELECT_I64 : D_SELECT_CLASS<GPR64Opnd>; diff --git a/contrib/llvm/lib/Target/Mips/MipsConstantIslandPass.cpp b/contrib/llvm/lib/Target/Mips/MipsConstantIslandPass.cpp deleted file mode 100644 index eea28df7eda1..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsConstantIslandPass.cpp +++ /dev/null @@ -1,1687 +0,0 @@ -//===- MipsConstantIslandPass.cpp - Emit Pc Relative loads ----------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This pass is used to make Pc relative loads of constants. -// For now, only Mips16 will use this. -// -// Loading constants inline is expensive on Mips16 and it's in general better -// to place the constant nearby in code space and then it can be loaded with a -// simple 16 bit load instruction. -// -// The constants can be not just numbers but addresses of functions and labels. -// This can be particularly helpful in static relocation mode for embedded -// non-linux targets. -// -//===----------------------------------------------------------------------===// - -#include "Mips.h" -#include "Mips16InstrInfo.h" -#include "MipsMachineFunction.h" -#include "MipsSubtarget.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallSet.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/Statistic.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/MachineConstantPool.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/MachineOperand.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/Config/llvm-config.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/DebugLoc.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/Type.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/Format.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/raw_ostream.h" -#include <algorithm> -#include <cassert> -#include <cstdint> -#include <iterator> -#include <vector> - -using namespace llvm; - -#define DEBUG_TYPE "mips-constant-islands" - -STATISTIC(NumCPEs, "Number of constpool entries"); -STATISTIC(NumSplit, "Number of uncond branches inserted"); -STATISTIC(NumCBrFixed, "Number of cond branches fixed"); -STATISTIC(NumUBrFixed, "Number of uncond branches fixed"); - -// FIXME: This option should be removed once it has received sufficient testing. -static cl::opt<bool> -AlignConstantIslands("mips-align-constant-islands", cl::Hidden, cl::init(true), - cl::desc("Align constant islands in code")); - -// Rather than do make check tests with huge amounts of code, we force -// the test to use this amount. -static cl::opt<int> ConstantIslandsSmallOffset( - "mips-constant-islands-small-offset", - cl::init(0), - cl::desc("Make small offsets be this amount for testing purposes"), - cl::Hidden); - -// For testing purposes we tell it to not use relaxed load forms so that it -// will split blocks. -static cl::opt<bool> NoLoadRelaxation( - "mips-constant-islands-no-load-relaxation", - cl::init(false), - cl::desc("Don't relax loads to long loads - for testing purposes"), - cl::Hidden); - -static unsigned int branchTargetOperand(MachineInstr *MI) { - switch (MI->getOpcode()) { - case Mips::Bimm16: - case Mips::BimmX16: - case Mips::Bteqz16: - case Mips::BteqzX16: - case Mips::Btnez16: - case Mips::BtnezX16: - case Mips::JalB16: - return 0; - case Mips::BeqzRxImm16: - case Mips::BeqzRxImmX16: - case Mips::BnezRxImm16: - case Mips::BnezRxImmX16: - return 1; - } - llvm_unreachable("Unknown branch type"); -} - -static unsigned int longformBranchOpcode(unsigned int Opcode) { - switch (Opcode) { - case Mips::Bimm16: - case Mips::BimmX16: - return Mips::BimmX16; - case Mips::Bteqz16: - case Mips::BteqzX16: - return Mips::BteqzX16; - case Mips::Btnez16: - case Mips::BtnezX16: - return Mips::BtnezX16; - case Mips::JalB16: - return Mips::JalB16; - case Mips::BeqzRxImm16: - case Mips::BeqzRxImmX16: - return Mips::BeqzRxImmX16; - case Mips::BnezRxImm16: - case Mips::BnezRxImmX16: - return Mips::BnezRxImmX16; - } - llvm_unreachable("Unknown branch type"); -} - -// FIXME: need to go through this whole constant islands port and check the math -// for branch ranges and clean this up and make some functions to calculate things -// that are done many times identically. -// Need to refactor some of the code to call this routine. -static unsigned int branchMaxOffsets(unsigned int Opcode) { - unsigned Bits, Scale; - switch (Opcode) { - case Mips::Bimm16: - Bits = 11; - Scale = 2; - break; - case Mips::BimmX16: - Bits = 16; - Scale = 2; - break; - case Mips::BeqzRxImm16: - Bits = 8; - Scale = 2; - break; - case Mips::BeqzRxImmX16: - Bits = 16; - Scale = 2; - break; - case Mips::BnezRxImm16: - Bits = 8; - Scale = 2; - break; - case Mips::BnezRxImmX16: - Bits = 16; - Scale = 2; - break; - case Mips::Bteqz16: - Bits = 8; - Scale = 2; - break; - case Mips::BteqzX16: - Bits = 16; - Scale = 2; - break; - case Mips::Btnez16: - Bits = 8; - Scale = 2; - break; - case Mips::BtnezX16: - Bits = 16; - Scale = 2; - break; - default: - llvm_unreachable("Unknown branch type"); - } - unsigned MaxOffs = ((1 << (Bits-1))-1) * Scale; - return MaxOffs; -} - -namespace { - - using Iter = MachineBasicBlock::iterator; - using ReverseIter = MachineBasicBlock::reverse_iterator; - - /// MipsConstantIslands - Due to limited PC-relative displacements, Mips - /// requires constant pool entries to be scattered among the instructions - /// inside a function. To do this, it completely ignores the normal LLVM - /// constant pool; instead, it places constants wherever it feels like with - /// special instructions. - /// - /// The terminology used in this pass includes: - /// Islands - Clumps of constants placed in the function. - /// Water - Potential places where an island could be formed. - /// CPE - A constant pool entry that has been placed somewhere, which - /// tracks a list of users. - - class MipsConstantIslands : public MachineFunctionPass { - /// BasicBlockInfo - Information about the offset and size of a single - /// basic block. - struct BasicBlockInfo { - /// Offset - Distance from the beginning of the function to the beginning - /// of this basic block. - /// - /// Offsets are computed assuming worst case padding before an aligned - /// block. This means that subtracting basic block offsets always gives a - /// conservative estimate of the real distance which may be smaller. - /// - /// Because worst case padding is used, the computed offset of an aligned - /// block may not actually be aligned. - unsigned Offset = 0; - - /// Size - Size of the basic block in bytes. If the block contains - /// inline assembly, this is a worst case estimate. - /// - /// The size does not include any alignment padding whether from the - /// beginning of the block, or from an aligned jump table at the end. - unsigned Size = 0; - - BasicBlockInfo() = default; - - // FIXME: ignore LogAlign for this patch - // - unsigned postOffset(unsigned LogAlign = 0) const { - unsigned PO = Offset + Size; - return PO; - } - }; - - std::vector<BasicBlockInfo> BBInfo; - - /// WaterList - A sorted list of basic blocks where islands could be placed - /// (i.e. blocks that don't fall through to the following block, due - /// to a return, unreachable, or unconditional branch). - std::vector<MachineBasicBlock*> WaterList; - - /// NewWaterList - The subset of WaterList that was created since the - /// previous iteration by inserting unconditional branches. - SmallSet<MachineBasicBlock*, 4> NewWaterList; - - using water_iterator = std::vector<MachineBasicBlock *>::iterator; - - /// CPUser - One user of a constant pool, keeping the machine instruction - /// pointer, the constant pool being referenced, and the max displacement - /// allowed from the instruction to the CP. The HighWaterMark records the - /// highest basic block where a new CPEntry can be placed. To ensure this - /// pass terminates, the CP entries are initially placed at the end of the - /// function and then move monotonically to lower addresses. The - /// exception to this rule is when the current CP entry for a particular - /// CPUser is out of range, but there is another CP entry for the same - /// constant value in range. We want to use the existing in-range CP - /// entry, but if it later moves out of range, the search for new water - /// should resume where it left off. The HighWaterMark is used to record - /// that point. - struct CPUser { - MachineInstr *MI; - MachineInstr *CPEMI; - MachineBasicBlock *HighWaterMark; - - private: - unsigned MaxDisp; - unsigned LongFormMaxDisp; // mips16 has 16/32 bit instructions - // with different displacements - unsigned LongFormOpcode; - - public: - bool NegOk; - - CPUser(MachineInstr *mi, MachineInstr *cpemi, unsigned maxdisp, - bool neg, - unsigned longformmaxdisp, unsigned longformopcode) - : MI(mi), CPEMI(cpemi), MaxDisp(maxdisp), - LongFormMaxDisp(longformmaxdisp), LongFormOpcode(longformopcode), - NegOk(neg){ - HighWaterMark = CPEMI->getParent(); - } - - /// getMaxDisp - Returns the maximum displacement supported by MI. - unsigned getMaxDisp() const { - unsigned xMaxDisp = ConstantIslandsSmallOffset? - ConstantIslandsSmallOffset: MaxDisp; - return xMaxDisp; - } - - void setMaxDisp(unsigned val) { - MaxDisp = val; - } - - unsigned getLongFormMaxDisp() const { - return LongFormMaxDisp; - } - - unsigned getLongFormOpcode() const { - return LongFormOpcode; - } - }; - - /// CPUsers - Keep track of all of the machine instructions that use various - /// constant pools and their max displacement. - std::vector<CPUser> CPUsers; - - /// CPEntry - One per constant pool entry, keeping the machine instruction - /// pointer, the constpool index, and the number of CPUser's which - /// reference this entry. - struct CPEntry { - MachineInstr *CPEMI; - unsigned CPI; - unsigned RefCount; - - CPEntry(MachineInstr *cpemi, unsigned cpi, unsigned rc = 0) - : CPEMI(cpemi), CPI(cpi), RefCount(rc) {} - }; - - /// CPEntries - Keep track of all of the constant pool entry machine - /// instructions. For each original constpool index (i.e. those that - /// existed upon entry to this pass), it keeps a vector of entries. - /// Original elements are cloned as we go along; the clones are - /// put in the vector of the original element, but have distinct CPIs. - std::vector<std::vector<CPEntry>> CPEntries; - - /// ImmBranch - One per immediate branch, keeping the machine instruction - /// pointer, conditional or unconditional, the max displacement, - /// and (if isCond is true) the corresponding unconditional branch - /// opcode. - struct ImmBranch { - MachineInstr *MI; - unsigned MaxDisp : 31; - bool isCond : 1; - int UncondBr; - - ImmBranch(MachineInstr *mi, unsigned maxdisp, bool cond, int ubr) - : MI(mi), MaxDisp(maxdisp), isCond(cond), UncondBr(ubr) {} - }; - - /// ImmBranches - Keep track of all the immediate branch instructions. - /// - std::vector<ImmBranch> ImmBranches; - - /// HasFarJump - True if any far jump instruction has been emitted during - /// the branch fix up pass. - bool HasFarJump; - - const MipsSubtarget *STI = nullptr; - const Mips16InstrInfo *TII; - MipsFunctionInfo *MFI; - MachineFunction *MF = nullptr; - MachineConstantPool *MCP = nullptr; - - unsigned PICLabelUId; - bool PrescannedForConstants = false; - - void initPICLabelUId(unsigned UId) { - PICLabelUId = UId; - } - - unsigned createPICLabelUId() { - return PICLabelUId++; - } - - public: - static char ID; - - MipsConstantIslands() : MachineFunctionPass(ID) {} - - StringRef getPassName() const override { return "Mips Constant Islands"; } - - bool runOnMachineFunction(MachineFunction &F) override; - - MachineFunctionProperties getRequiredProperties() const override { - return MachineFunctionProperties().set( - MachineFunctionProperties::Property::NoVRegs); - } - - void doInitialPlacement(std::vector<MachineInstr*> &CPEMIs); - CPEntry *findConstPoolEntry(unsigned CPI, const MachineInstr *CPEMI); - unsigned getCPELogAlign(const MachineInstr &CPEMI); - void initializeFunctionInfo(const std::vector<MachineInstr*> &CPEMIs); - unsigned getOffsetOf(MachineInstr *MI) const; - unsigned getUserOffset(CPUser&) const; - void dumpBBs(); - - bool isOffsetInRange(unsigned UserOffset, unsigned TrialOffset, - unsigned Disp, bool NegativeOK); - bool isOffsetInRange(unsigned UserOffset, unsigned TrialOffset, - const CPUser &U); - - void computeBlockSize(MachineBasicBlock *MBB); - MachineBasicBlock *splitBlockBeforeInstr(MachineInstr &MI); - void updateForInsertedWaterBlock(MachineBasicBlock *NewBB); - void adjustBBOffsetsAfter(MachineBasicBlock *BB); - bool decrementCPEReferenceCount(unsigned CPI, MachineInstr* CPEMI); - int findInRangeCPEntry(CPUser& U, unsigned UserOffset); - int findLongFormInRangeCPEntry(CPUser& U, unsigned UserOffset); - bool findAvailableWater(CPUser&U, unsigned UserOffset, - water_iterator &WaterIter); - void createNewWater(unsigned CPUserIndex, unsigned UserOffset, - MachineBasicBlock *&NewMBB); - bool handleConstantPoolUser(unsigned CPUserIndex); - void removeDeadCPEMI(MachineInstr *CPEMI); - bool removeUnusedCPEntries(); - bool isCPEntryInRange(MachineInstr *MI, unsigned UserOffset, - MachineInstr *CPEMI, unsigned Disp, bool NegOk, - bool DoDump = false); - bool isWaterInRange(unsigned UserOffset, MachineBasicBlock *Water, - CPUser &U, unsigned &Growth); - bool isBBInRange(MachineInstr *MI, MachineBasicBlock *BB, unsigned Disp); - bool fixupImmediateBr(ImmBranch &Br); - bool fixupConditionalBr(ImmBranch &Br); - bool fixupUnconditionalBr(ImmBranch &Br); - - void prescanForConstants(); - }; - -} // end anonymous namespace - -char MipsConstantIslands::ID = 0; - -bool MipsConstantIslands::isOffsetInRange - (unsigned UserOffset, unsigned TrialOffset, - const CPUser &U) { - return isOffsetInRange(UserOffset, TrialOffset, - U.getMaxDisp(), U.NegOk); -} - -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) -/// print block size and offset information - debugging -LLVM_DUMP_METHOD void MipsConstantIslands::dumpBBs() { - for (unsigned J = 0, E = BBInfo.size(); J !=E; ++J) { - const BasicBlockInfo &BBI = BBInfo[J]; - dbgs() << format("%08x %bb.%u\t", BBI.Offset, J) - << format(" size=%#x\n", BBInfo[J].Size); - } -} -#endif - -bool MipsConstantIslands::runOnMachineFunction(MachineFunction &mf) { - // The intention is for this to be a mips16 only pass for now - // FIXME: - MF = &mf; - MCP = mf.getConstantPool(); - STI = &static_cast<const MipsSubtarget &>(mf.getSubtarget()); - LLVM_DEBUG(dbgs() << "constant island machine function " - << "\n"); - if (!STI->inMips16Mode() || !MipsSubtarget::useConstantIslands()) { - return false; - } - TII = (const Mips16InstrInfo *)STI->getInstrInfo(); - MFI = MF->getInfo<MipsFunctionInfo>(); - LLVM_DEBUG(dbgs() << "constant island processing " - << "\n"); - // - // will need to make predermination if there is any constants we need to - // put in constant islands. TBD. - // - if (!PrescannedForConstants) prescanForConstants(); - - HasFarJump = false; - // This pass invalidates liveness information when it splits basic blocks. - MF->getRegInfo().invalidateLiveness(); - - // Renumber all of the machine basic blocks in the function, guaranteeing that - // the numbers agree with the position of the block in the function. - MF->RenumberBlocks(); - - bool MadeChange = false; - - // Perform the initial placement of the constant pool entries. To start with, - // we put them all at the end of the function. - std::vector<MachineInstr*> CPEMIs; - if (!MCP->isEmpty()) - doInitialPlacement(CPEMIs); - - /// The next UID to take is the first unused one. - initPICLabelUId(CPEMIs.size()); - - // Do the initial scan of the function, building up information about the - // sizes of each block, the location of all the water, and finding all of the - // constant pool users. - initializeFunctionInfo(CPEMIs); - CPEMIs.clear(); - LLVM_DEBUG(dumpBBs()); - - /// Remove dead constant pool entries. - MadeChange |= removeUnusedCPEntries(); - - // Iteratively place constant pool entries and fix up branches until there - // is no change. - unsigned NoCPIters = 0, NoBRIters = 0; - (void)NoBRIters; - while (true) { - LLVM_DEBUG(dbgs() << "Beginning CP iteration #" << NoCPIters << '\n'); - bool CPChange = false; - for (unsigned i = 0, e = CPUsers.size(); i != e; ++i) - CPChange |= handleConstantPoolUser(i); - if (CPChange && ++NoCPIters > 30) - report_fatal_error("Constant Island pass failed to converge!"); - LLVM_DEBUG(dumpBBs()); - - // Clear NewWaterList now. If we split a block for branches, it should - // appear as "new water" for the next iteration of constant pool placement. - NewWaterList.clear(); - - LLVM_DEBUG(dbgs() << "Beginning BR iteration #" << NoBRIters << '\n'); - bool BRChange = false; - for (unsigned i = 0, e = ImmBranches.size(); i != e; ++i) - BRChange |= fixupImmediateBr(ImmBranches[i]); - if (BRChange && ++NoBRIters > 30) - report_fatal_error("Branch Fix Up pass failed to converge!"); - LLVM_DEBUG(dumpBBs()); - if (!CPChange && !BRChange) - break; - MadeChange = true; - } - - LLVM_DEBUG(dbgs() << '\n'; dumpBBs()); - - BBInfo.clear(); - WaterList.clear(); - CPUsers.clear(); - CPEntries.clear(); - ImmBranches.clear(); - return MadeChange; -} - -/// doInitialPlacement - Perform the initial placement of the constant pool -/// entries. To start with, we put them all at the end of the function. -void -MipsConstantIslands::doInitialPlacement(std::vector<MachineInstr*> &CPEMIs) { - // Create the basic block to hold the CPE's. - MachineBasicBlock *BB = MF->CreateMachineBasicBlock(); - MF->push_back(BB); - - // MachineConstantPool measures alignment in bytes. We measure in log2(bytes). - unsigned MaxAlign = Log2_32(MCP->getConstantPoolAlignment()); - - // Mark the basic block as required by the const-pool. - // If AlignConstantIslands isn't set, use 4-byte alignment for everything. - BB->setAlignment(AlignConstantIslands ? MaxAlign : 2); - - // The function needs to be as aligned as the basic blocks. The linker may - // move functions around based on their alignment. - MF->ensureAlignment(BB->getAlignment()); - - // Order the entries in BB by descending alignment. That ensures correct - // alignment of all entries as long as BB is sufficiently aligned. Keep - // track of the insertion point for each alignment. We are going to bucket - // sort the entries as they are created. - SmallVector<MachineBasicBlock::iterator, 8> InsPoint(MaxAlign + 1, BB->end()); - - // Add all of the constants from the constant pool to the end block, use an - // identity mapping of CPI's to CPE's. - const std::vector<MachineConstantPoolEntry> &CPs = MCP->getConstants(); - - const DataLayout &TD = MF->getDataLayout(); - for (unsigned i = 0, e = CPs.size(); i != e; ++i) { - unsigned Size = TD.getTypeAllocSize(CPs[i].getType()); - assert(Size >= 4 && "Too small constant pool entry"); - unsigned Align = CPs[i].getAlignment(); - assert(isPowerOf2_32(Align) && "Invalid alignment"); - // Verify that all constant pool entries are a multiple of their alignment. - // If not, we would have to pad them out so that instructions stay aligned. - assert((Size % Align) == 0 && "CP Entry not multiple of 4 bytes!"); - - // Insert CONSTPOOL_ENTRY before entries with a smaller alignment. - unsigned LogAlign = Log2_32(Align); - MachineBasicBlock::iterator InsAt = InsPoint[LogAlign]; - - MachineInstr *CPEMI = - BuildMI(*BB, InsAt, DebugLoc(), TII->get(Mips::CONSTPOOL_ENTRY)) - .addImm(i).addConstantPoolIndex(i).addImm(Size); - - CPEMIs.push_back(CPEMI); - - // Ensure that future entries with higher alignment get inserted before - // CPEMI. This is bucket sort with iterators. - for (unsigned a = LogAlign + 1; a <= MaxAlign; ++a) - if (InsPoint[a] == InsAt) - InsPoint[a] = CPEMI; - // Add a new CPEntry, but no corresponding CPUser yet. - CPEntries.emplace_back(1, CPEntry(CPEMI, i)); - ++NumCPEs; - LLVM_DEBUG(dbgs() << "Moved CPI#" << i << " to end of function, size = " - << Size << ", align = " << Align << '\n'); - } - LLVM_DEBUG(BB->dump()); -} - -/// BBHasFallthrough - Return true if the specified basic block can fallthrough -/// into the block immediately after it. -static bool BBHasFallthrough(MachineBasicBlock *MBB) { - // Get the next machine basic block in the function. - MachineFunction::iterator MBBI = MBB->getIterator(); - // Can't fall off end of function. - if (std::next(MBBI) == MBB->getParent()->end()) - return false; - - MachineBasicBlock *NextBB = &*std::next(MBBI); - for (MachineBasicBlock::succ_iterator I = MBB->succ_begin(), - E = MBB->succ_end(); I != E; ++I) - if (*I == NextBB) - return true; - - return false; -} - -/// findConstPoolEntry - Given the constpool index and CONSTPOOL_ENTRY MI, -/// look up the corresponding CPEntry. -MipsConstantIslands::CPEntry -*MipsConstantIslands::findConstPoolEntry(unsigned CPI, - const MachineInstr *CPEMI) { - std::vector<CPEntry> &CPEs = CPEntries[CPI]; - // Number of entries per constpool index should be small, just do a - // linear search. - for (unsigned i = 0, e = CPEs.size(); i != e; ++i) { - if (CPEs[i].CPEMI == CPEMI) - return &CPEs[i]; - } - return nullptr; -} - -/// getCPELogAlign - Returns the required alignment of the constant pool entry -/// represented by CPEMI. Alignment is measured in log2(bytes) units. -unsigned MipsConstantIslands::getCPELogAlign(const MachineInstr &CPEMI) { - assert(CPEMI.getOpcode() == Mips::CONSTPOOL_ENTRY); - - // Everything is 4-byte aligned unless AlignConstantIslands is set. - if (!AlignConstantIslands) - return 2; - - unsigned CPI = CPEMI.getOperand(1).getIndex(); - assert(CPI < MCP->getConstants().size() && "Invalid constant pool index."); - unsigned Align = MCP->getConstants()[CPI].getAlignment(); - assert(isPowerOf2_32(Align) && "Invalid CPE alignment"); - return Log2_32(Align); -} - -/// initializeFunctionInfo - Do the initial scan of the function, building up -/// information about the sizes of each block, the location of all the water, -/// and finding all of the constant pool users. -void MipsConstantIslands:: -initializeFunctionInfo(const std::vector<MachineInstr*> &CPEMIs) { - BBInfo.clear(); - BBInfo.resize(MF->getNumBlockIDs()); - - // First thing, compute the size of all basic blocks, and see if the function - // has any inline assembly in it. If so, we have to be conservative about - // alignment assumptions, as we don't know for sure the size of any - // instructions in the inline assembly. - for (MachineFunction::iterator I = MF->begin(), E = MF->end(); I != E; ++I) - computeBlockSize(&*I); - - // Compute block offsets. - adjustBBOffsetsAfter(&MF->front()); - - // Now go back through the instructions and build up our data structures. - for (MachineBasicBlock &MBB : *MF) { - // If this block doesn't fall through into the next MBB, then this is - // 'water' that a constant pool island could be placed. - if (!BBHasFallthrough(&MBB)) - WaterList.push_back(&MBB); - for (MachineInstr &MI : MBB) { - if (MI.isDebugInstr()) - continue; - - int Opc = MI.getOpcode(); - if (MI.isBranch()) { - bool isCond = false; - unsigned Bits = 0; - unsigned Scale = 1; - int UOpc = Opc; - switch (Opc) { - default: - continue; // Ignore other branches for now - case Mips::Bimm16: - Bits = 11; - Scale = 2; - isCond = false; - break; - case Mips::BimmX16: - Bits = 16; - Scale = 2; - isCond = false; - break; - case Mips::BeqzRxImm16: - UOpc=Mips::Bimm16; - Bits = 8; - Scale = 2; - isCond = true; - break; - case Mips::BeqzRxImmX16: - UOpc=Mips::Bimm16; - Bits = 16; - Scale = 2; - isCond = true; - break; - case Mips::BnezRxImm16: - UOpc=Mips::Bimm16; - Bits = 8; - Scale = 2; - isCond = true; - break; - case Mips::BnezRxImmX16: - UOpc=Mips::Bimm16; - Bits = 16; - Scale = 2; - isCond = true; - break; - case Mips::Bteqz16: - UOpc=Mips::Bimm16; - Bits = 8; - Scale = 2; - isCond = true; - break; - case Mips::BteqzX16: - UOpc=Mips::Bimm16; - Bits = 16; - Scale = 2; - isCond = true; - break; - case Mips::Btnez16: - UOpc=Mips::Bimm16; - Bits = 8; - Scale = 2; - isCond = true; - break; - case Mips::BtnezX16: - UOpc=Mips::Bimm16; - Bits = 16; - Scale = 2; - isCond = true; - break; - } - // Record this immediate branch. - unsigned MaxOffs = ((1 << (Bits-1))-1) * Scale; - ImmBranches.push_back(ImmBranch(&MI, MaxOffs, isCond, UOpc)); - } - - if (Opc == Mips::CONSTPOOL_ENTRY) - continue; - - // Scan the instructions for constant pool operands. - for (unsigned op = 0, e = MI.getNumOperands(); op != e; ++op) - if (MI.getOperand(op).isCPI()) { - // We found one. The addressing mode tells us the max displacement - // from the PC that this instruction permits. - - // Basic size info comes from the TSFlags field. - unsigned Bits = 0; - unsigned Scale = 1; - bool NegOk = false; - unsigned LongFormBits = 0; - unsigned LongFormScale = 0; - unsigned LongFormOpcode = 0; - switch (Opc) { - default: - llvm_unreachable("Unknown addressing mode for CP reference!"); - case Mips::LwRxPcTcp16: - Bits = 8; - Scale = 4; - LongFormOpcode = Mips::LwRxPcTcpX16; - LongFormBits = 14; - LongFormScale = 1; - break; - case Mips::LwRxPcTcpX16: - Bits = 14; - Scale = 1; - NegOk = true; - break; - } - // Remember that this is a user of a CP entry. - unsigned CPI = MI.getOperand(op).getIndex(); - MachineInstr *CPEMI = CPEMIs[CPI]; - unsigned MaxOffs = ((1 << Bits)-1) * Scale; - unsigned LongFormMaxOffs = ((1 << LongFormBits)-1) * LongFormScale; - CPUsers.push_back(CPUser(&MI, CPEMI, MaxOffs, NegOk, LongFormMaxOffs, - LongFormOpcode)); - - // Increment corresponding CPEntry reference count. - CPEntry *CPE = findConstPoolEntry(CPI, CPEMI); - assert(CPE && "Cannot find a corresponding CPEntry!"); - CPE->RefCount++; - - // Instructions can only use one CP entry, don't bother scanning the - // rest of the operands. - break; - } - } - } -} - -/// computeBlockSize - Compute the size and some alignment information for MBB. -/// This function updates BBInfo directly. -void MipsConstantIslands::computeBlockSize(MachineBasicBlock *MBB) { - BasicBlockInfo &BBI = BBInfo[MBB->getNumber()]; - BBI.Size = 0; - - for (const MachineInstr &MI : *MBB) - BBI.Size += TII->getInstSizeInBytes(MI); -} - -/// getOffsetOf - Return the current offset of the specified machine instruction -/// from the start of the function. This offset changes as stuff is moved -/// around inside the function. -unsigned MipsConstantIslands::getOffsetOf(MachineInstr *MI) const { - MachineBasicBlock *MBB = MI->getParent(); - - // The offset is composed of two things: the sum of the sizes of all MBB's - // before this instruction's block, and the offset from the start of the block - // it is in. - unsigned Offset = BBInfo[MBB->getNumber()].Offset; - - // Sum instructions before MI in MBB. - for (MachineBasicBlock::iterator I = MBB->begin(); &*I != MI; ++I) { - assert(I != MBB->end() && "Didn't find MI in its own basic block?"); - Offset += TII->getInstSizeInBytes(*I); - } - return Offset; -} - -/// CompareMBBNumbers - Little predicate function to sort the WaterList by MBB -/// ID. -static bool CompareMBBNumbers(const MachineBasicBlock *LHS, - const MachineBasicBlock *RHS) { - return LHS->getNumber() < RHS->getNumber(); -} - -/// updateForInsertedWaterBlock - When a block is newly inserted into the -/// machine function, it upsets all of the block numbers. Renumber the blocks -/// and update the arrays that parallel this numbering. -void MipsConstantIslands::updateForInsertedWaterBlock - (MachineBasicBlock *NewBB) { - // Renumber the MBB's to keep them consecutive. - NewBB->getParent()->RenumberBlocks(NewBB); - - // Insert an entry into BBInfo to align it properly with the (newly - // renumbered) block numbers. - BBInfo.insert(BBInfo.begin() + NewBB->getNumber(), BasicBlockInfo()); - - // Next, update WaterList. Specifically, we need to add NewMBB as having - // available water after it. - water_iterator IP = llvm::lower_bound(WaterList, NewBB, CompareMBBNumbers); - WaterList.insert(IP, NewBB); -} - -unsigned MipsConstantIslands::getUserOffset(CPUser &U) const { - return getOffsetOf(U.MI); -} - -/// Split the basic block containing MI into two blocks, which are joined by -/// an unconditional branch. Update data structures and renumber blocks to -/// account for this change and returns the newly created block. -MachineBasicBlock * -MipsConstantIslands::splitBlockBeforeInstr(MachineInstr &MI) { - MachineBasicBlock *OrigBB = MI.getParent(); - - // Create a new MBB for the code after the OrigBB. - MachineBasicBlock *NewBB = - MF->CreateMachineBasicBlock(OrigBB->getBasicBlock()); - MachineFunction::iterator MBBI = ++OrigBB->getIterator(); - MF->insert(MBBI, NewBB); - - // Splice the instructions starting with MI over to NewBB. - NewBB->splice(NewBB->end(), OrigBB, MI, OrigBB->end()); - - // Add an unconditional branch from OrigBB to NewBB. - // Note the new unconditional branch is not being recorded. - // There doesn't seem to be meaningful DebugInfo available; this doesn't - // correspond to anything in the source. - BuildMI(OrigBB, DebugLoc(), TII->get(Mips::Bimm16)).addMBB(NewBB); - ++NumSplit; - - // Update the CFG. All succs of OrigBB are now succs of NewBB. - NewBB->transferSuccessors(OrigBB); - - // OrigBB branches to NewBB. - OrigBB->addSuccessor(NewBB); - - // Update internal data structures to account for the newly inserted MBB. - // This is almost the same as updateForInsertedWaterBlock, except that - // the Water goes after OrigBB, not NewBB. - MF->RenumberBlocks(NewBB); - - // Insert an entry into BBInfo to align it properly with the (newly - // renumbered) block numbers. - BBInfo.insert(BBInfo.begin() + NewBB->getNumber(), BasicBlockInfo()); - - // Next, update WaterList. Specifically, we need to add OrigMBB as having - // available water after it (but not if it's already there, which happens - // when splitting before a conditional branch that is followed by an - // unconditional branch - in that case we want to insert NewBB). - water_iterator IP = llvm::lower_bound(WaterList, OrigBB, CompareMBBNumbers); - MachineBasicBlock* WaterBB = *IP; - if (WaterBB == OrigBB) - WaterList.insert(std::next(IP), NewBB); - else - WaterList.insert(IP, OrigBB); - NewWaterList.insert(OrigBB); - - // Figure out how large the OrigBB is. As the first half of the original - // block, it cannot contain a tablejump. The size includes - // the new jump we added. (It should be possible to do this without - // recounting everything, but it's very confusing, and this is rarely - // executed.) - computeBlockSize(OrigBB); - - // Figure out how large the NewMBB is. As the second half of the original - // block, it may contain a tablejump. - computeBlockSize(NewBB); - - // All BBOffsets following these blocks must be modified. - adjustBBOffsetsAfter(OrigBB); - - return NewBB; -} - -/// isOffsetInRange - Checks whether UserOffset (the location of a constant pool -/// reference) is within MaxDisp of TrialOffset (a proposed location of a -/// constant pool entry). -bool MipsConstantIslands::isOffsetInRange(unsigned UserOffset, - unsigned TrialOffset, unsigned MaxDisp, - bool NegativeOK) { - if (UserOffset <= TrialOffset) { - // User before the Trial. - if (TrialOffset - UserOffset <= MaxDisp) - return true; - } else if (NegativeOK) { - if (UserOffset - TrialOffset <= MaxDisp) - return true; - } - return false; -} - -/// isWaterInRange - Returns true if a CPE placed after the specified -/// Water (a basic block) will be in range for the specific MI. -/// -/// Compute how much the function will grow by inserting a CPE after Water. -bool MipsConstantIslands::isWaterInRange(unsigned UserOffset, - MachineBasicBlock* Water, CPUser &U, - unsigned &Growth) { - unsigned CPELogAlign = getCPELogAlign(*U.CPEMI); - unsigned CPEOffset = BBInfo[Water->getNumber()].postOffset(CPELogAlign); - unsigned NextBlockOffset, NextBlockAlignment; - MachineFunction::const_iterator NextBlock = ++Water->getIterator(); - if (NextBlock == MF->end()) { - NextBlockOffset = BBInfo[Water->getNumber()].postOffset(); - NextBlockAlignment = 0; - } else { - NextBlockOffset = BBInfo[NextBlock->getNumber()].Offset; - NextBlockAlignment = NextBlock->getAlignment(); - } - unsigned Size = U.CPEMI->getOperand(2).getImm(); - unsigned CPEEnd = CPEOffset + Size; - - // The CPE may be able to hide in the alignment padding before the next - // block. It may also cause more padding to be required if it is more aligned - // that the next block. - if (CPEEnd > NextBlockOffset) { - Growth = CPEEnd - NextBlockOffset; - // Compute the padding that would go at the end of the CPE to align the next - // block. - Growth += OffsetToAlignment(CPEEnd, 1ULL << NextBlockAlignment); - - // If the CPE is to be inserted before the instruction, that will raise - // the offset of the instruction. Also account for unknown alignment padding - // in blocks between CPE and the user. - if (CPEOffset < UserOffset) - UserOffset += Growth; - } else - // CPE fits in existing padding. - Growth = 0; - - return isOffsetInRange(UserOffset, CPEOffset, U); -} - -/// isCPEntryInRange - Returns true if the distance between specific MI and -/// specific ConstPool entry instruction can fit in MI's displacement field. -bool MipsConstantIslands::isCPEntryInRange - (MachineInstr *MI, unsigned UserOffset, - MachineInstr *CPEMI, unsigned MaxDisp, - bool NegOk, bool DoDump) { - unsigned CPEOffset = getOffsetOf(CPEMI); - - if (DoDump) { - LLVM_DEBUG({ - unsigned Block = MI->getParent()->getNumber(); - const BasicBlockInfo &BBI = BBInfo[Block]; - dbgs() << "User of CPE#" << CPEMI->getOperand(0).getImm() - << " max delta=" << MaxDisp - << format(" insn address=%#x", UserOffset) << " in " - << printMBBReference(*MI->getParent()) << ": " - << format("%#x-%x\t", BBI.Offset, BBI.postOffset()) << *MI - << format("CPE address=%#x offset=%+d: ", CPEOffset, - int(CPEOffset - UserOffset)); - }); - } - - return isOffsetInRange(UserOffset, CPEOffset, MaxDisp, NegOk); -} - -#ifndef NDEBUG -/// BBIsJumpedOver - Return true of the specified basic block's only predecessor -/// unconditionally branches to its only successor. -static bool BBIsJumpedOver(MachineBasicBlock *MBB) { - if (MBB->pred_size() != 1 || MBB->succ_size() != 1) - return false; - MachineBasicBlock *Succ = *MBB->succ_begin(); - MachineBasicBlock *Pred = *MBB->pred_begin(); - MachineInstr *PredMI = &Pred->back(); - if (PredMI->getOpcode() == Mips::Bimm16) - return PredMI->getOperand(0).getMBB() == Succ; - return false; -} -#endif - -void MipsConstantIslands::adjustBBOffsetsAfter(MachineBasicBlock *BB) { - unsigned BBNum = BB->getNumber(); - for(unsigned i = BBNum + 1, e = MF->getNumBlockIDs(); i < e; ++i) { - // Get the offset and known bits at the end of the layout predecessor. - // Include the alignment of the current block. - unsigned Offset = BBInfo[i - 1].Offset + BBInfo[i - 1].Size; - BBInfo[i].Offset = Offset; - } -} - -/// decrementCPEReferenceCount - find the constant pool entry with index CPI -/// and instruction CPEMI, and decrement its refcount. If the refcount -/// becomes 0 remove the entry and instruction. Returns true if we removed -/// the entry, false if we didn't. -bool MipsConstantIslands::decrementCPEReferenceCount(unsigned CPI, - MachineInstr *CPEMI) { - // Find the old entry. Eliminate it if it is no longer used. - CPEntry *CPE = findConstPoolEntry(CPI, CPEMI); - assert(CPE && "Unexpected!"); - if (--CPE->RefCount == 0) { - removeDeadCPEMI(CPEMI); - CPE->CPEMI = nullptr; - --NumCPEs; - return true; - } - return false; -} - -/// LookForCPEntryInRange - see if the currently referenced CPE is in range; -/// if not, see if an in-range clone of the CPE is in range, and if so, -/// change the data structures so the user references the clone. Returns: -/// 0 = no existing entry found -/// 1 = entry found, and there were no code insertions or deletions -/// 2 = entry found, and there were code insertions or deletions -int MipsConstantIslands::findInRangeCPEntry(CPUser& U, unsigned UserOffset) -{ - MachineInstr *UserMI = U.MI; - MachineInstr *CPEMI = U.CPEMI; - - // Check to see if the CPE is already in-range. - if (isCPEntryInRange(UserMI, UserOffset, CPEMI, U.getMaxDisp(), U.NegOk, - true)) { - LLVM_DEBUG(dbgs() << "In range\n"); - return 1; - } - - // No. Look for previously created clones of the CPE that are in range. - unsigned CPI = CPEMI->getOperand(1).getIndex(); - std::vector<CPEntry> &CPEs = CPEntries[CPI]; - for (unsigned i = 0, e = CPEs.size(); i != e; ++i) { - // We already tried this one - if (CPEs[i].CPEMI == CPEMI) - continue; - // Removing CPEs can leave empty entries, skip - if (CPEs[i].CPEMI == nullptr) - continue; - if (isCPEntryInRange(UserMI, UserOffset, CPEs[i].CPEMI, U.getMaxDisp(), - U.NegOk)) { - LLVM_DEBUG(dbgs() << "Replacing CPE#" << CPI << " with CPE#" - << CPEs[i].CPI << "\n"); - // Point the CPUser node to the replacement - U.CPEMI = CPEs[i].CPEMI; - // Change the CPI in the instruction operand to refer to the clone. - for (unsigned j = 0, e = UserMI->getNumOperands(); j != e; ++j) - if (UserMI->getOperand(j).isCPI()) { - UserMI->getOperand(j).setIndex(CPEs[i].CPI); - break; - } - // Adjust the refcount of the clone... - CPEs[i].RefCount++; - // ...and the original. If we didn't remove the old entry, none of the - // addresses changed, so we don't need another pass. - return decrementCPEReferenceCount(CPI, CPEMI) ? 2 : 1; - } - } - return 0; -} - -/// LookForCPEntryInRange - see if the currently referenced CPE is in range; -/// This version checks if the longer form of the instruction can be used to -/// to satisfy things. -/// if not, see if an in-range clone of the CPE is in range, and if so, -/// change the data structures so the user references the clone. Returns: -/// 0 = no existing entry found -/// 1 = entry found, and there were no code insertions or deletions -/// 2 = entry found, and there were code insertions or deletions -int MipsConstantIslands::findLongFormInRangeCPEntry - (CPUser& U, unsigned UserOffset) -{ - MachineInstr *UserMI = U.MI; - MachineInstr *CPEMI = U.CPEMI; - - // Check to see if the CPE is already in-range. - if (isCPEntryInRange(UserMI, UserOffset, CPEMI, - U.getLongFormMaxDisp(), U.NegOk, - true)) { - LLVM_DEBUG(dbgs() << "In range\n"); - UserMI->setDesc(TII->get(U.getLongFormOpcode())); - U.setMaxDisp(U.getLongFormMaxDisp()); - return 2; // instruction is longer length now - } - - // No. Look for previously created clones of the CPE that are in range. - unsigned CPI = CPEMI->getOperand(1).getIndex(); - std::vector<CPEntry> &CPEs = CPEntries[CPI]; - for (unsigned i = 0, e = CPEs.size(); i != e; ++i) { - // We already tried this one - if (CPEs[i].CPEMI == CPEMI) - continue; - // Removing CPEs can leave empty entries, skip - if (CPEs[i].CPEMI == nullptr) - continue; - if (isCPEntryInRange(UserMI, UserOffset, CPEs[i].CPEMI, - U.getLongFormMaxDisp(), U.NegOk)) { - LLVM_DEBUG(dbgs() << "Replacing CPE#" << CPI << " with CPE#" - << CPEs[i].CPI << "\n"); - // Point the CPUser node to the replacement - U.CPEMI = CPEs[i].CPEMI; - // Change the CPI in the instruction operand to refer to the clone. - for (unsigned j = 0, e = UserMI->getNumOperands(); j != e; ++j) - if (UserMI->getOperand(j).isCPI()) { - UserMI->getOperand(j).setIndex(CPEs[i].CPI); - break; - } - // Adjust the refcount of the clone... - CPEs[i].RefCount++; - // ...and the original. If we didn't remove the old entry, none of the - // addresses changed, so we don't need another pass. - return decrementCPEReferenceCount(CPI, CPEMI) ? 2 : 1; - } - } - return 0; -} - -/// getUnconditionalBrDisp - Returns the maximum displacement that can fit in -/// the specific unconditional branch instruction. -static inline unsigned getUnconditionalBrDisp(int Opc) { - switch (Opc) { - case Mips::Bimm16: - return ((1<<10)-1)*2; - case Mips::BimmX16: - return ((1<<16)-1)*2; - default: - break; - } - return ((1<<16)-1)*2; -} - -/// findAvailableWater - Look for an existing entry in the WaterList in which -/// we can place the CPE referenced from U so it's within range of U's MI. -/// Returns true if found, false if not. If it returns true, WaterIter -/// is set to the WaterList entry. -/// To ensure that this pass -/// terminates, the CPE location for a particular CPUser is only allowed to -/// move to a lower address, so search backward from the end of the list and -/// prefer the first water that is in range. -bool MipsConstantIslands::findAvailableWater(CPUser &U, unsigned UserOffset, - water_iterator &WaterIter) { - if (WaterList.empty()) - return false; - - unsigned BestGrowth = ~0u; - for (water_iterator IP = std::prev(WaterList.end()), B = WaterList.begin();; - --IP) { - MachineBasicBlock* WaterBB = *IP; - // Check if water is in range and is either at a lower address than the - // current "high water mark" or a new water block that was created since - // the previous iteration by inserting an unconditional branch. In the - // latter case, we want to allow resetting the high water mark back to - // this new water since we haven't seen it before. Inserting branches - // should be relatively uncommon and when it does happen, we want to be - // sure to take advantage of it for all the CPEs near that block, so that - // we don't insert more branches than necessary. - unsigned Growth; - if (isWaterInRange(UserOffset, WaterBB, U, Growth) && - (WaterBB->getNumber() < U.HighWaterMark->getNumber() || - NewWaterList.count(WaterBB)) && Growth < BestGrowth) { - // This is the least amount of required padding seen so far. - BestGrowth = Growth; - WaterIter = IP; - LLVM_DEBUG(dbgs() << "Found water after " << printMBBReference(*WaterBB) - << " Growth=" << Growth << '\n'); - - // Keep looking unless it is perfect. - if (BestGrowth == 0) - return true; - } - if (IP == B) - break; - } - return BestGrowth != ~0u; -} - -/// createNewWater - No existing WaterList entry will work for -/// CPUsers[CPUserIndex], so create a place to put the CPE. The end of the -/// block is used if in range, and the conditional branch munged so control -/// flow is correct. Otherwise the block is split to create a hole with an -/// unconditional branch around it. In either case NewMBB is set to a -/// block following which the new island can be inserted (the WaterList -/// is not adjusted). -void MipsConstantIslands::createNewWater(unsigned CPUserIndex, - unsigned UserOffset, - MachineBasicBlock *&NewMBB) { - CPUser &U = CPUsers[CPUserIndex]; - MachineInstr *UserMI = U.MI; - MachineInstr *CPEMI = U.CPEMI; - unsigned CPELogAlign = getCPELogAlign(*CPEMI); - MachineBasicBlock *UserMBB = UserMI->getParent(); - const BasicBlockInfo &UserBBI = BBInfo[UserMBB->getNumber()]; - - // If the block does not end in an unconditional branch already, and if the - // end of the block is within range, make new water there. - if (BBHasFallthrough(UserMBB)) { - // Size of branch to insert. - unsigned Delta = 2; - // Compute the offset where the CPE will begin. - unsigned CPEOffset = UserBBI.postOffset(CPELogAlign) + Delta; - - if (isOffsetInRange(UserOffset, CPEOffset, U)) { - LLVM_DEBUG(dbgs() << "Split at end of " << printMBBReference(*UserMBB) - << format(", expected CPE offset %#x\n", CPEOffset)); - NewMBB = &*++UserMBB->getIterator(); - // Add an unconditional branch from UserMBB to fallthrough block. Record - // it for branch lengthening; this new branch will not get out of range, - // but if the preceding conditional branch is out of range, the targets - // will be exchanged, and the altered branch may be out of range, so the - // machinery has to know about it. - int UncondBr = Mips::Bimm16; - BuildMI(UserMBB, DebugLoc(), TII->get(UncondBr)).addMBB(NewMBB); - unsigned MaxDisp = getUnconditionalBrDisp(UncondBr); - ImmBranches.push_back(ImmBranch(&UserMBB->back(), - MaxDisp, false, UncondBr)); - BBInfo[UserMBB->getNumber()].Size += Delta; - adjustBBOffsetsAfter(UserMBB); - return; - } - } - - // What a big block. Find a place within the block to split it. - - // Try to split the block so it's fully aligned. Compute the latest split - // point where we can add a 4-byte branch instruction, and then align to - // LogAlign which is the largest possible alignment in the function. - unsigned LogAlign = MF->getAlignment(); - assert(LogAlign >= CPELogAlign && "Over-aligned constant pool entry"); - unsigned BaseInsertOffset = UserOffset + U.getMaxDisp(); - LLVM_DEBUG(dbgs() << format("Split in middle of big block before %#x", - BaseInsertOffset)); - - // The 4 in the following is for the unconditional branch we'll be inserting - // Alignment of the island is handled - // inside isOffsetInRange. - BaseInsertOffset -= 4; - - LLVM_DEBUG(dbgs() << format(", adjusted to %#x", BaseInsertOffset) - << " la=" << LogAlign << '\n'); - - // This could point off the end of the block if we've already got constant - // pool entries following this block; only the last one is in the water list. - // Back past any possible branches (allow for a conditional and a maximally - // long unconditional). - if (BaseInsertOffset + 8 >= UserBBI.postOffset()) { - BaseInsertOffset = UserBBI.postOffset() - 8; - LLVM_DEBUG(dbgs() << format("Move inside block: %#x\n", BaseInsertOffset)); - } - unsigned EndInsertOffset = BaseInsertOffset + 4 + - CPEMI->getOperand(2).getImm(); - MachineBasicBlock::iterator MI = UserMI; - ++MI; - unsigned CPUIndex = CPUserIndex+1; - unsigned NumCPUsers = CPUsers.size(); - //MachineInstr *LastIT = 0; - for (unsigned Offset = UserOffset + TII->getInstSizeInBytes(*UserMI); - Offset < BaseInsertOffset; - Offset += TII->getInstSizeInBytes(*MI), MI = std::next(MI)) { - assert(MI != UserMBB->end() && "Fell off end of block"); - if (CPUIndex < NumCPUsers && CPUsers[CPUIndex].MI == MI) { - CPUser &U = CPUsers[CPUIndex]; - if (!isOffsetInRange(Offset, EndInsertOffset, U)) { - // Shift intertion point by one unit of alignment so it is within reach. - BaseInsertOffset -= 1u << LogAlign; - EndInsertOffset -= 1u << LogAlign; - } - // This is overly conservative, as we don't account for CPEMIs being - // reused within the block, but it doesn't matter much. Also assume CPEs - // are added in order with alignment padding. We may eventually be able - // to pack the aligned CPEs better. - EndInsertOffset += U.CPEMI->getOperand(2).getImm(); - CPUIndex++; - } - } - - NewMBB = splitBlockBeforeInstr(*--MI); -} - -/// handleConstantPoolUser - Analyze the specified user, checking to see if it -/// is out-of-range. If so, pick up the constant pool value and move it some -/// place in-range. Return true if we changed any addresses (thus must run -/// another pass of branch lengthening), false otherwise. -bool MipsConstantIslands::handleConstantPoolUser(unsigned CPUserIndex) { - CPUser &U = CPUsers[CPUserIndex]; - MachineInstr *UserMI = U.MI; - MachineInstr *CPEMI = U.CPEMI; - unsigned CPI = CPEMI->getOperand(1).getIndex(); - unsigned Size = CPEMI->getOperand(2).getImm(); - // Compute this only once, it's expensive. - unsigned UserOffset = getUserOffset(U); - - // See if the current entry is within range, or there is a clone of it - // in range. - int result = findInRangeCPEntry(U, UserOffset); - if (result==1) return false; - else if (result==2) return true; - - // Look for water where we can place this CPE. - MachineBasicBlock *NewIsland = MF->CreateMachineBasicBlock(); - MachineBasicBlock *NewMBB; - water_iterator IP; - if (findAvailableWater(U, UserOffset, IP)) { - LLVM_DEBUG(dbgs() << "Found water in range\n"); - MachineBasicBlock *WaterBB = *IP; - - // If the original WaterList entry was "new water" on this iteration, - // propagate that to the new island. This is just keeping NewWaterList - // updated to match the WaterList, which will be updated below. - if (NewWaterList.erase(WaterBB)) - NewWaterList.insert(NewIsland); - - // The new CPE goes before the following block (NewMBB). - NewMBB = &*++WaterBB->getIterator(); - } else { - // No water found. - // we first see if a longer form of the instrucion could have reached - // the constant. in that case we won't bother to split - if (!NoLoadRelaxation) { - result = findLongFormInRangeCPEntry(U, UserOffset); - if (result != 0) return true; - } - LLVM_DEBUG(dbgs() << "No water found\n"); - createNewWater(CPUserIndex, UserOffset, NewMBB); - - // splitBlockBeforeInstr adds to WaterList, which is important when it is - // called while handling branches so that the water will be seen on the - // next iteration for constant pools, but in this context, we don't want - // it. Check for this so it will be removed from the WaterList. - // Also remove any entry from NewWaterList. - MachineBasicBlock *WaterBB = &*--NewMBB->getIterator(); - IP = llvm::find(WaterList, WaterBB); - if (IP != WaterList.end()) - NewWaterList.erase(WaterBB); - - // We are adding new water. Update NewWaterList. - NewWaterList.insert(NewIsland); - } - - // Remove the original WaterList entry; we want subsequent insertions in - // this vicinity to go after the one we're about to insert. This - // considerably reduces the number of times we have to move the same CPE - // more than once and is also important to ensure the algorithm terminates. - if (IP != WaterList.end()) - WaterList.erase(IP); - - // Okay, we know we can put an island before NewMBB now, do it! - MF->insert(NewMBB->getIterator(), NewIsland); - - // Update internal data structures to account for the newly inserted MBB. - updateForInsertedWaterBlock(NewIsland); - - // Decrement the old entry, and remove it if refcount becomes 0. - decrementCPEReferenceCount(CPI, CPEMI); - - // No existing clone of this CPE is within range. - // We will be generating a new clone. Get a UID for it. - unsigned ID = createPICLabelUId(); - - // Now that we have an island to add the CPE to, clone the original CPE and - // add it to the island. - U.HighWaterMark = NewIsland; - U.CPEMI = BuildMI(NewIsland, DebugLoc(), TII->get(Mips::CONSTPOOL_ENTRY)) - .addImm(ID).addConstantPoolIndex(CPI).addImm(Size); - CPEntries[CPI].push_back(CPEntry(U.CPEMI, ID, 1)); - ++NumCPEs; - - // Mark the basic block as aligned as required by the const-pool entry. - NewIsland->setAlignment(getCPELogAlign(*U.CPEMI)); - - // Increase the size of the island block to account for the new entry. - BBInfo[NewIsland->getNumber()].Size += Size; - adjustBBOffsetsAfter(&*--NewIsland->getIterator()); - - // Finally, change the CPI in the instruction operand to be ID. - for (unsigned i = 0, e = UserMI->getNumOperands(); i != e; ++i) - if (UserMI->getOperand(i).isCPI()) { - UserMI->getOperand(i).setIndex(ID); - break; - } - - LLVM_DEBUG( - dbgs() << " Moved CPE to #" << ID << " CPI=" << CPI - << format(" offset=%#x\n", BBInfo[NewIsland->getNumber()].Offset)); - - return true; -} - -/// removeDeadCPEMI - Remove a dead constant pool entry instruction. Update -/// sizes and offsets of impacted basic blocks. -void MipsConstantIslands::removeDeadCPEMI(MachineInstr *CPEMI) { - MachineBasicBlock *CPEBB = CPEMI->getParent(); - unsigned Size = CPEMI->getOperand(2).getImm(); - CPEMI->eraseFromParent(); - BBInfo[CPEBB->getNumber()].Size -= Size; - // All succeeding offsets have the current size value added in, fix this. - if (CPEBB->empty()) { - BBInfo[CPEBB->getNumber()].Size = 0; - - // This block no longer needs to be aligned. - CPEBB->setAlignment(0); - } else - // Entries are sorted by descending alignment, so realign from the front. - CPEBB->setAlignment(getCPELogAlign(*CPEBB->begin())); - - adjustBBOffsetsAfter(CPEBB); - // An island has only one predecessor BB and one successor BB. Check if - // this BB's predecessor jumps directly to this BB's successor. This - // shouldn't happen currently. - assert(!BBIsJumpedOver(CPEBB) && "How did this happen?"); - // FIXME: remove the empty blocks after all the work is done? -} - -/// removeUnusedCPEntries - Remove constant pool entries whose refcounts -/// are zero. -bool MipsConstantIslands::removeUnusedCPEntries() { - unsigned MadeChange = false; - for (unsigned i = 0, e = CPEntries.size(); i != e; ++i) { - std::vector<CPEntry> &CPEs = CPEntries[i]; - for (unsigned j = 0, ee = CPEs.size(); j != ee; ++j) { - if (CPEs[j].RefCount == 0 && CPEs[j].CPEMI) { - removeDeadCPEMI(CPEs[j].CPEMI); - CPEs[j].CPEMI = nullptr; - MadeChange = true; - } - } - } - return MadeChange; -} - -/// isBBInRange - Returns true if the distance between specific MI and -/// specific BB can fit in MI's displacement field. -bool MipsConstantIslands::isBBInRange - (MachineInstr *MI,MachineBasicBlock *DestBB, unsigned MaxDisp) { - unsigned PCAdj = 4; - unsigned BrOffset = getOffsetOf(MI) + PCAdj; - unsigned DestOffset = BBInfo[DestBB->getNumber()].Offset; - - LLVM_DEBUG(dbgs() << "Branch of destination " << printMBBReference(*DestBB) - << " from " << printMBBReference(*MI->getParent()) - << " max delta=" << MaxDisp << " from " << getOffsetOf(MI) - << " to " << DestOffset << " offset " - << int(DestOffset - BrOffset) << "\t" << *MI); - - if (BrOffset <= DestOffset) { - // Branch before the Dest. - if (DestOffset-BrOffset <= MaxDisp) - return true; - } else { - if (BrOffset-DestOffset <= MaxDisp) - return true; - } - return false; -} - -/// fixupImmediateBr - Fix up an immediate branch whose destination is too far -/// away to fit in its displacement field. -bool MipsConstantIslands::fixupImmediateBr(ImmBranch &Br) { - MachineInstr *MI = Br.MI; - unsigned TargetOperand = branchTargetOperand(MI); - MachineBasicBlock *DestBB = MI->getOperand(TargetOperand).getMBB(); - - // Check to see if the DestBB is already in-range. - if (isBBInRange(MI, DestBB, Br.MaxDisp)) - return false; - - if (!Br.isCond) - return fixupUnconditionalBr(Br); - return fixupConditionalBr(Br); -} - -/// fixupUnconditionalBr - Fix up an unconditional branch whose destination is -/// too far away to fit in its displacement field. If the LR register has been -/// spilled in the epilogue, then we can use BL to implement a far jump. -/// Otherwise, add an intermediate branch instruction to a branch. -bool -MipsConstantIslands::fixupUnconditionalBr(ImmBranch &Br) { - MachineInstr *MI = Br.MI; - MachineBasicBlock *MBB = MI->getParent(); - MachineBasicBlock *DestBB = MI->getOperand(0).getMBB(); - // Use BL to implement far jump. - unsigned BimmX16MaxDisp = ((1 << 16)-1) * 2; - if (isBBInRange(MI, DestBB, BimmX16MaxDisp)) { - Br.MaxDisp = BimmX16MaxDisp; - MI->setDesc(TII->get(Mips::BimmX16)); - } - else { - // need to give the math a more careful look here - // this is really a segment address and not - // a PC relative address. FIXME. But I think that - // just reducing the bits by 1 as I've done is correct. - // The basic block we are branching too much be longword aligned. - // we know that RA is saved because we always save it right now. - // this requirement will be relaxed later but we also have an alternate - // way to implement this that I will implement that does not need jal. - // We should have a way to back out this alignment restriction if we "can" later. - // but it is not harmful. - // - DestBB->setAlignment(2); - Br.MaxDisp = ((1<<24)-1) * 2; - MI->setDesc(TII->get(Mips::JalB16)); - } - BBInfo[MBB->getNumber()].Size += 2; - adjustBBOffsetsAfter(MBB); - HasFarJump = true; - ++NumUBrFixed; - - LLVM_DEBUG(dbgs() << " Changed B to long jump " << *MI); - - return true; -} - -/// fixupConditionalBr - Fix up a conditional branch whose destination is too -/// far away to fit in its displacement field. It is converted to an inverse -/// conditional branch + an unconditional branch to the destination. -bool -MipsConstantIslands::fixupConditionalBr(ImmBranch &Br) { - MachineInstr *MI = Br.MI; - unsigned TargetOperand = branchTargetOperand(MI); - MachineBasicBlock *DestBB = MI->getOperand(TargetOperand).getMBB(); - unsigned Opcode = MI->getOpcode(); - unsigned LongFormOpcode = longformBranchOpcode(Opcode); - unsigned LongFormMaxOff = branchMaxOffsets(LongFormOpcode); - - // Check to see if the DestBB is already in-range. - if (isBBInRange(MI, DestBB, LongFormMaxOff)) { - Br.MaxDisp = LongFormMaxOff; - MI->setDesc(TII->get(LongFormOpcode)); - return true; - } - - // Add an unconditional branch to the destination and invert the branch - // condition to jump over it: - // bteqz L1 - // => - // bnez L2 - // b L1 - // L2: - - // If the branch is at the end of its MBB and that has a fall-through block, - // direct the updated conditional branch to the fall-through block. Otherwise, - // split the MBB before the next instruction. - MachineBasicBlock *MBB = MI->getParent(); - MachineInstr *BMI = &MBB->back(); - bool NeedSplit = (BMI != MI) || !BBHasFallthrough(MBB); - unsigned OppositeBranchOpcode = TII->getOppositeBranchOpc(Opcode); - - ++NumCBrFixed; - if (BMI != MI) { - if (std::next(MachineBasicBlock::iterator(MI)) == std::prev(MBB->end()) && - BMI->isUnconditionalBranch()) { - // Last MI in the BB is an unconditional branch. Can we simply invert the - // condition and swap destinations: - // beqz L1 - // b L2 - // => - // bnez L2 - // b L1 - unsigned BMITargetOperand = branchTargetOperand(BMI); - MachineBasicBlock *NewDest = - BMI->getOperand(BMITargetOperand).getMBB(); - if (isBBInRange(MI, NewDest, Br.MaxDisp)) { - LLVM_DEBUG( - dbgs() << " Invert Bcc condition and swap its destination with " - << *BMI); - MI->setDesc(TII->get(OppositeBranchOpcode)); - BMI->getOperand(BMITargetOperand).setMBB(DestBB); - MI->getOperand(TargetOperand).setMBB(NewDest); - return true; - } - } - } - - if (NeedSplit) { - splitBlockBeforeInstr(*MI); - // No need for the branch to the next block. We're adding an unconditional - // branch to the destination. - int delta = TII->getInstSizeInBytes(MBB->back()); - BBInfo[MBB->getNumber()].Size -= delta; - MBB->back().eraseFromParent(); - // BBInfo[SplitBB].Offset is wrong temporarily, fixed below - } - MachineBasicBlock *NextBB = &*++MBB->getIterator(); - - LLVM_DEBUG(dbgs() << " Insert B to " << printMBBReference(*DestBB) - << " also invert condition and change dest. to " - << printMBBReference(*NextBB) << "\n"); - - // Insert a new conditional branch and a new unconditional branch. - // Also update the ImmBranch as well as adding a new entry for the new branch. - if (MI->getNumExplicitOperands() == 2) { - BuildMI(MBB, DebugLoc(), TII->get(OppositeBranchOpcode)) - .addReg(MI->getOperand(0).getReg()) - .addMBB(NextBB); - } else { - BuildMI(MBB, DebugLoc(), TII->get(OppositeBranchOpcode)) - .addMBB(NextBB); - } - Br.MI = &MBB->back(); - BBInfo[MBB->getNumber()].Size += TII->getInstSizeInBytes(MBB->back()); - BuildMI(MBB, DebugLoc(), TII->get(Br.UncondBr)).addMBB(DestBB); - BBInfo[MBB->getNumber()].Size += TII->getInstSizeInBytes(MBB->back()); - unsigned MaxDisp = getUnconditionalBrDisp(Br.UncondBr); - ImmBranches.push_back(ImmBranch(&MBB->back(), MaxDisp, false, Br.UncondBr)); - - // Remove the old conditional branch. It may or may not still be in MBB. - BBInfo[MI->getParent()->getNumber()].Size -= TII->getInstSizeInBytes(*MI); - MI->eraseFromParent(); - adjustBBOffsetsAfter(MBB); - return true; -} - -void MipsConstantIslands::prescanForConstants() { - unsigned J = 0; - (void)J; - for (MachineFunction::iterator B = - MF->begin(), E = MF->end(); B != E; ++B) { - for (MachineBasicBlock::instr_iterator I = - B->instr_begin(), EB = B->instr_end(); I != EB; ++I) { - switch(I->getDesc().getOpcode()) { - case Mips::LwConstant32: { - PrescannedForConstants = true; - LLVM_DEBUG(dbgs() << "constant island constant " << *I << "\n"); - J = I->getNumOperands(); - LLVM_DEBUG(dbgs() << "num operands " << J << "\n"); - MachineOperand& Literal = I->getOperand(1); - if (Literal.isImm()) { - int64_t V = Literal.getImm(); - LLVM_DEBUG(dbgs() << "literal " << V << "\n"); - Type *Int32Ty = - Type::getInt32Ty(MF->getFunction().getContext()); - const Constant *C = ConstantInt::get(Int32Ty, V); - unsigned index = MCP->getConstantPoolIndex(C, 4); - I->getOperand(2).ChangeToImmediate(index); - LLVM_DEBUG(dbgs() << "constant island constant " << *I << "\n"); - I->setDesc(TII->get(Mips::LwRxPcTcp16)); - I->RemoveOperand(1); - I->RemoveOperand(1); - I->addOperand(MachineOperand::CreateCPI(index, 0)); - I->addOperand(MachineOperand::CreateImm(4)); - } - break; - } - default: - break; - } - } - } -} - -/// Returns a pass that converts branches to long branches. -FunctionPass *llvm::createMipsConstantIslandPass() { - return new MipsConstantIslands(); -} diff --git a/contrib/llvm/lib/Target/Mips/MipsDSPInstrFormats.td b/contrib/llvm/lib/Target/Mips/MipsDSPInstrFormats.td deleted file mode 100644 index 6f062d0f3c25..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsDSPInstrFormats.td +++ /dev/null @@ -1,368 +0,0 @@ -//===- MipsDSPInstrFormats.td - Mips Instruction Formats ---*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -class DspMMRel; - -def Dsp2MicroMips : InstrMapping { - let FilterClass = "DspMMRel"; - // Instructions with the same BaseOpcode and isNVStore values form a row. - let RowFields = ["BaseOpcode"]; - // Instructions with the same predicate sense form a column. - let ColFields = ["Arch"]; - // The key column is the unpredicated instructions. - let KeyCol = ["dsp"]; - // Value columns are PredSense=true and PredSense=false - let ValueCols = [["dsp"], ["mmdsp"]]; -} - -def HasDSP : Predicate<"Subtarget->hasDSP()">, - AssemblerPredicate<"FeatureDSP">; -def HasDSPR2 : Predicate<"Subtarget->hasDSPR2()">, - AssemblerPredicate<"FeatureDSPR2">; -def HasDSPR3 : Predicate<"Subtarget->hasDSPR3()">, - AssemblerPredicate<"FeatureDSPR3">; - -class ISA_DSPR2 { - list<Predicate> ASEPredicate = [HasDSPR2]; -} - -class ISA_DSPR3 { - list<Predicate> ASEPredicate = [HasDSPR3]; -} - -// Fields. -class Field6<bits<6> val> { - bits<6> V = val; -} - -def SPECIAL3_OPCODE : Field6<0b011111>; -def REGIMM_OPCODE : Field6<0b000001>; - -class DSPInst<string opstr = ""> - : MipsInst<(outs), (ins), "", [], NoItinerary, FrmOther> { - let ASEPredicate = [HasDSP]; - string BaseOpcode = opstr; - string Arch = "dsp"; -} - -class PseudoDSP<dag outs, dag ins, list<dag> pattern, - InstrItinClass itin = IIPseudo> - : MipsPseudo<outs, ins, pattern, itin> { - let ASEPredicate = [HasDSP]; -} - -class DSPInstAlias<string Asm, dag Result, bit Emit = 0b1> - : InstAlias<Asm, Result, Emit>, PredicateControl { - let ASEPredicate = [HasDSP]; -} - -// ADDU.QB sub-class format. -class ADDU_QB_FMT<bits<5> op> : DSPInst { - bits<5> rd; - bits<5> rs; - bits<5> rt; - - let Opcode = SPECIAL3_OPCODE.V; - - let Inst{25-21} = rs; - let Inst{20-16} = rt; - let Inst{15-11} = rd; - let Inst{10-6} = op; - let Inst{5-0} = 0b010000; -} - -class RADDU_W_QB_FMT<bits<5> op> : DSPInst { - bits<5> rd; - bits<5> rs; - - let Opcode = SPECIAL3_OPCODE.V; - - let Inst{25-21} = rs; - let Inst{20-16} = 0; - let Inst{15-11} = rd; - let Inst{10-6} = op; - let Inst{5-0} = 0b010000; -} - -// CMPU.EQ.QB sub-class format. -class CMP_EQ_QB_R2_FMT<bits<5> op> : DSPInst { - bits<5> rs; - bits<5> rt; - - let Opcode = SPECIAL3_OPCODE.V; - - let Inst{25-21} = rs; - let Inst{20-16} = rt; - let Inst{15-11} = 0; - let Inst{10-6} = op; - let Inst{5-0} = 0b010001; -} - -class CMP_EQ_QB_R3_FMT<bits<5> op> : DSPInst { - bits<5> rs; - bits<5> rt; - bits<5> rd; - - let Opcode = SPECIAL3_OPCODE.V; - - let Inst{25-21} = rs; - let Inst{20-16} = rt; - let Inst{15-11} = rd; - let Inst{10-6} = op; - let Inst{5-0} = 0b010001; -} - -class PRECR_SRA_PH_W_FMT<bits<5> op> : DSPInst { - bits<5> rs; - bits<5> rt; - bits<5> sa; - - let Opcode = SPECIAL3_OPCODE.V; - - let Inst{25-21} = rs; - let Inst{20-16} = rt; - let Inst{15-11} = sa; - let Inst{10-6} = op; - let Inst{5-0} = 0b010001; -} - -// ABSQ_S.PH sub-class format. -class ABSQ_S_PH_R2_FMT<bits<5> op> : DSPInst { - bits<5> rd; - bits<5> rt; - - let Opcode = SPECIAL3_OPCODE.V; - - let Inst{25-21} = 0; - let Inst{20-16} = rt; - let Inst{15-11} = rd; - let Inst{10-6} = op; - let Inst{5-0} = 0b010010; -} - - -class REPL_FMT<bits<5> op> : DSPInst { - bits<5> rd; - bits<10> imm; - - let Opcode = SPECIAL3_OPCODE.V; - - let Inst{25-16} = imm; - let Inst{15-11} = rd; - let Inst{10-6} = op; - let Inst{5-0} = 0b010010; -} - -// SHLL.QB sub-class format. -class SHLL_QB_FMT<bits<5> op> : DSPInst { - bits<5> rd; - bits<5> rt; - bits<5> rs_sa; - - let Opcode = SPECIAL3_OPCODE.V; - - let Inst{25-21} = rs_sa; - let Inst{20-16} = rt; - let Inst{15-11} = rd; - let Inst{10-6} = op; - let Inst{5-0} = 0b010011; -} - -// LX sub-class format. -class LX_FMT<bits<5> op> : DSPInst { - bits<5> rd; - bits<5> base; - bits<5> index; - - let Opcode = SPECIAL3_OPCODE.V; - - let Inst{25-21} = base; - let Inst{20-16} = index; - let Inst{15-11} = rd; - let Inst{10-6} = op; - let Inst{5-0} = 0b001010; -} - -// ADDUH.QB sub-class format. -class ADDUH_QB_FMT<bits<5> op> : DSPInst { - bits<5> rd; - bits<5> rs; - bits<5> rt; - - let Opcode = SPECIAL3_OPCODE.V; - - let Inst{25-21} = rs; - let Inst{20-16} = rt; - let Inst{15-11} = rd; - let Inst{10-6} = op; - let Inst{5-0} = 0b011000; -} - -// APPEND sub-class format. -class APPEND_FMT<bits<5> op> : DSPInst { - bits<5> rt; - bits<5> rs; - bits<5> sa; - - let Opcode = SPECIAL3_OPCODE.V; - - let Inst{25-21} = rs; - let Inst{20-16} = rt; - let Inst{15-11} = sa; - let Inst{10-6} = op; - let Inst{5-0} = 0b110001; -} - -// DPA.W.PH sub-class format. -class DPA_W_PH_FMT<bits<5> op> : DSPInst { - bits<2> ac; - bits<5> rs; - bits<5> rt; - - let Opcode = SPECIAL3_OPCODE.V; - - let Inst{25-21} = rs; - let Inst{20-16} = rt; - let Inst{15-13} = 0; - let Inst{12-11} = ac; - let Inst{10-6} = op; - let Inst{5-0} = 0b110000; -} - -// MULT sub-class format. -class MULT_FMT<bits<6> opcode, bits<6> funct> : DSPInst { - bits<2> ac; - bits<5> rs; - bits<5> rt; - - let Opcode = opcode; - - let Inst{25-21} = rs; - let Inst{20-16} = rt; - let Inst{15-13} = 0; - let Inst{12-11} = ac; - let Inst{10-6} = 0; - let Inst{5-0} = funct; -} - -// MFHI sub-class format. -class MFHI_FMT<bits<6> funct> : DSPInst { - bits<5> rd; - bits<2> ac; - - let Inst{31-26} = 0; - let Inst{25-23} = 0; - let Inst{22-21} = ac; - let Inst{20-16} = 0; - let Inst{15-11} = rd; - let Inst{10-6} = 0; - let Inst{5-0} = funct; -} - -// MTHI sub-class format. -class MTHI_FMT<bits<6> funct> : DSPInst { - bits<5> rs; - bits<2> ac; - - let Inst{31-26} = 0; - let Inst{25-21} = rs; - let Inst{20-13} = 0; - let Inst{12-11} = ac; - let Inst{10-6} = 0; - let Inst{5-0} = funct; -} - -// EXTR.W sub-class format (type 1). -class EXTR_W_TY1_FMT<bits<5> op> : DSPInst { - bits<5> rt; - bits<2> ac; - bits<5> shift_rs; - - let Opcode = SPECIAL3_OPCODE.V; - - let Inst{25-21} = shift_rs; - let Inst{20-16} = rt; - let Inst{15-13} = 0; - let Inst{12-11} = ac; - let Inst{10-6} = op; - let Inst{5-0} = 0b111000; -} - -// SHILO sub-class format. -class SHILO_R1_FMT<bits<5> op> : DSPInst { - bits<2> ac; - bits<6> shift; - - let Opcode = SPECIAL3_OPCODE.V; - - let Inst{25-20} = shift; - let Inst{19-13} = 0; - let Inst{12-11} = ac; - let Inst{10-6} = op; - let Inst{5-0} = 0b111000; -} - -class SHILO_R2_FMT<bits<5> op> : DSPInst { - bits<2> ac; - bits<5> rs; - - let Opcode = SPECIAL3_OPCODE.V; - - let Inst{25-21} = rs; - let Inst{20-13} = 0; - let Inst{12-11} = ac; - let Inst{10-6} = op; - let Inst{5-0} = 0b111000; -} - -class RDDSP_FMT<bits<5> op> : DSPInst { - bits<5> rd; - bits<10> mask; - - let Opcode = SPECIAL3_OPCODE.V; - - let Inst{25-16} = mask; - let Inst{15-11} = rd; - let Inst{10-6} = op; - let Inst{5-0} = 0b111000; -} - -class WRDSP_FMT<bits<5> op> : DSPInst { - bits<5> rs; - bits<10> mask; - - let Opcode = SPECIAL3_OPCODE.V; - - let Inst{25-21} = rs; - let Inst{20-11} = mask; - let Inst{10-6} = op; - let Inst{5-0} = 0b111000; -} - -class BPOSGE32_FMT<bits<5> op> : DSPInst { - bits<16> offset; - - let Opcode = REGIMM_OPCODE.V; - - let Inst{25-21} = 0; - let Inst{20-16} = op; - let Inst{15-0} = offset; -} - -// INSV sub-class format. -class INSV_FMT<bits<6> op> : DSPInst { - bits<5> rt; - bits<5> rs; - - let Opcode = SPECIAL3_OPCODE.V; - - let Inst{25-21} = rs; - let Inst{20-16} = rt; - let Inst{15-6} = 0; - let Inst{5-0} = op; -} diff --git a/contrib/llvm/lib/Target/Mips/MipsDSPInstrInfo.td b/contrib/llvm/lib/Target/Mips/MipsDSPInstrInfo.td deleted file mode 100644 index daca8b907081..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsDSPInstrInfo.td +++ /dev/null @@ -1,1473 +0,0 @@ -//===- MipsDSPInstrInfo.td - DSP ASE instructions -*- tablegen ------------*-=// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file describes Mips DSP ASE instructions. -// -//===----------------------------------------------------------------------===// - -// ImmLeaf -def immZExt1 : ImmLeaf<i32, [{return isUInt<1>(Imm);}]>; -def immZExt2 : ImmLeaf<i32, [{return isUInt<2>(Imm);}]>; -def immZExt3 : ImmLeaf<i32, [{return isUInt<3>(Imm);}]>; -def immZExt4 : ImmLeaf<i32, [{return isUInt<4>(Imm);}]>; -def immZExt8 : ImmLeaf<i32, [{return isUInt<8>(Imm);}]>; -def immZExt10 : ImmLeaf<i32, [{return isUInt<10>(Imm);}]>; -def immSExt6 : ImmLeaf<i32, [{return isInt<6>(Imm);}]>; -def immSExt10 : ImmLeaf<i32, [{return isInt<10>(Imm);}]>; - -// Mips-specific dsp nodes -def SDT_MipsExtr : SDTypeProfile<1, 2, [SDTCisVT<0, i32>, SDTCisSameAs<0, 1>, - SDTCisVT<2, untyped>]>; -def SDT_MipsShilo : SDTypeProfile<1, 2, [SDTCisVT<0, untyped>, - SDTCisSameAs<0, 2>, SDTCisVT<1, i32>]>; -def SDT_MipsDPA : SDTypeProfile<1, 3, [SDTCisVT<0, untyped>, SDTCisSameAs<0, 3>, - SDTCisVT<1, i32>, SDTCisSameAs<1, 2>]>; -def SDT_MipsSHIFT_DSP : SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisSameAs<0, 1>, - SDTCisVT<2, i32>]>; - -class MipsDSPBase<string Opc, SDTypeProfile Prof> : - SDNode<!strconcat("MipsISD::", Opc), Prof>; - -class MipsDSPSideEffectBase<string Opc, SDTypeProfile Prof> : - SDNode<!strconcat("MipsISD::", Opc), Prof, [SDNPHasChain, SDNPSideEffect]>; - -def MipsEXTP : MipsDSPSideEffectBase<"EXTP", SDT_MipsExtr>; -def MipsEXTPDP : MipsDSPSideEffectBase<"EXTPDP", SDT_MipsExtr>; -def MipsEXTR_S_H : MipsDSPSideEffectBase<"EXTR_S_H", SDT_MipsExtr>; -def MipsEXTR_W : MipsDSPSideEffectBase<"EXTR_W", SDT_MipsExtr>; -def MipsEXTR_R_W : MipsDSPSideEffectBase<"EXTR_R_W", SDT_MipsExtr>; -def MipsEXTR_RS_W : MipsDSPSideEffectBase<"EXTR_RS_W", SDT_MipsExtr>; - -def MipsSHILO : MipsDSPBase<"SHILO", SDT_MipsShilo>; -def MipsMTHLIP : MipsDSPSideEffectBase<"MTHLIP", SDT_MipsShilo>; - -def MipsMULSAQ_S_W_PH : MipsDSPSideEffectBase<"MULSAQ_S_W_PH", SDT_MipsDPA>; -def MipsMAQ_S_W_PHL : MipsDSPSideEffectBase<"MAQ_S_W_PHL", SDT_MipsDPA>; -def MipsMAQ_S_W_PHR : MipsDSPSideEffectBase<"MAQ_S_W_PHR", SDT_MipsDPA>; -def MipsMAQ_SA_W_PHL : MipsDSPSideEffectBase<"MAQ_SA_W_PHL", SDT_MipsDPA>; -def MipsMAQ_SA_W_PHR : MipsDSPSideEffectBase<"MAQ_SA_W_PHR", SDT_MipsDPA>; - -def MipsDPAU_H_QBL : MipsDSPBase<"DPAU_H_QBL", SDT_MipsDPA>; -def MipsDPAU_H_QBR : MipsDSPBase<"DPAU_H_QBR", SDT_MipsDPA>; -def MipsDPSU_H_QBL : MipsDSPBase<"DPSU_H_QBL", SDT_MipsDPA>; -def MipsDPSU_H_QBR : MipsDSPBase<"DPSU_H_QBR", SDT_MipsDPA>; -def MipsDPAQ_S_W_PH : MipsDSPSideEffectBase<"DPAQ_S_W_PH", SDT_MipsDPA>; -def MipsDPSQ_S_W_PH : MipsDSPSideEffectBase<"DPSQ_S_W_PH", SDT_MipsDPA>; -def MipsDPAQ_SA_L_W : MipsDSPSideEffectBase<"DPAQ_SA_L_W", SDT_MipsDPA>; -def MipsDPSQ_SA_L_W : MipsDSPSideEffectBase<"DPSQ_SA_L_W", SDT_MipsDPA>; - -def MipsDPA_W_PH : MipsDSPBase<"DPA_W_PH", SDT_MipsDPA>; -def MipsDPS_W_PH : MipsDSPBase<"DPS_W_PH", SDT_MipsDPA>; -def MipsDPAQX_S_W_PH : MipsDSPSideEffectBase<"DPAQX_S_W_PH", SDT_MipsDPA>; -def MipsDPAQX_SA_W_PH : MipsDSPSideEffectBase<"DPAQX_SA_W_PH", SDT_MipsDPA>; -def MipsDPAX_W_PH : MipsDSPBase<"DPAX_W_PH", SDT_MipsDPA>; -def MipsDPSX_W_PH : MipsDSPBase<"DPSX_W_PH", SDT_MipsDPA>; -def MipsDPSQX_S_W_PH : MipsDSPSideEffectBase<"DPSQX_S_W_PH", SDT_MipsDPA>; -def MipsDPSQX_SA_W_PH : MipsDSPSideEffectBase<"DPSQX_SA_W_PH", SDT_MipsDPA>; -def MipsMULSA_W_PH : MipsDSPBase<"MULSA_W_PH", SDT_MipsDPA>; - -def MipsMULT : MipsDSPBase<"MULT", SDT_MipsDPA>; -def MipsMULTU : MipsDSPBase<"MULTU", SDT_MipsDPA>; -def MipsMADD_DSP : MipsDSPBase<"MADD_DSP", SDT_MipsDPA>; -def MipsMADDU_DSP : MipsDSPBase<"MADDU_DSP", SDT_MipsDPA>; -def MipsMSUB_DSP : MipsDSPBase<"MSUB_DSP", SDT_MipsDPA>; -def MipsMSUBU_DSP : MipsDSPBase<"MSUBU_DSP", SDT_MipsDPA>; -def MipsSHLL_DSP : MipsDSPBase<"SHLL_DSP", SDT_MipsSHIFT_DSP>; -def MipsSHRA_DSP : MipsDSPBase<"SHRA_DSP", SDT_MipsSHIFT_DSP>; -def MipsSHRL_DSP : MipsDSPBase<"SHRL_DSP", SDT_MipsSHIFT_DSP>; -def MipsSETCC_DSP : MipsDSPBase<"SETCC_DSP", SDTSetCC>; -def MipsSELECT_CC_DSP : MipsDSPBase<"SELECT_CC_DSP", SDTSelectCC>; - -// Flags. -class Uses<list<Register> Regs> { - list<Register> Uses = Regs; -} - -class Defs<list<Register> Regs> { - list<Register> Defs = Regs; -} - -// Instruction encoding. -class ADDU_QB_ENC : ADDU_QB_FMT<0b00000>; -class ADDU_S_QB_ENC : ADDU_QB_FMT<0b00100>; -class SUBU_QB_ENC : ADDU_QB_FMT<0b00001>; -class SUBU_S_QB_ENC : ADDU_QB_FMT<0b00101>; -class ADDQ_PH_ENC : ADDU_QB_FMT<0b01010>; -class ADDQ_S_PH_ENC : ADDU_QB_FMT<0b01110>; -class SUBQ_PH_ENC : ADDU_QB_FMT<0b01011>; -class SUBQ_S_PH_ENC : ADDU_QB_FMT<0b01111>; -class ADDQ_S_W_ENC : ADDU_QB_FMT<0b10110>; -class SUBQ_S_W_ENC : ADDU_QB_FMT<0b10111>; -class ADDSC_ENC : ADDU_QB_FMT<0b10000>; -class ADDWC_ENC : ADDU_QB_FMT<0b10001>; -class MODSUB_ENC : ADDU_QB_FMT<0b10010>; -class RADDU_W_QB_ENC : RADDU_W_QB_FMT<0b10100>; -class ABSQ_S_PH_ENC : ABSQ_S_PH_R2_FMT<0b01001>; -class ABSQ_S_W_ENC : ABSQ_S_PH_R2_FMT<0b10001>; -class PRECRQ_QB_PH_ENC : CMP_EQ_QB_R3_FMT<0b01100>; -class PRECRQ_PH_W_ENC : CMP_EQ_QB_R3_FMT<0b10100>; -class PRECRQ_RS_PH_W_ENC : CMP_EQ_QB_R3_FMT<0b10101>; -class PRECRQU_S_QB_PH_ENC : CMP_EQ_QB_R3_FMT<0b01111>; -class PRECEQ_W_PHL_ENC : ABSQ_S_PH_R2_FMT<0b01100>; -class PRECEQ_W_PHR_ENC : ABSQ_S_PH_R2_FMT<0b01101>; -class PRECEQU_PH_QBL_ENC : ABSQ_S_PH_R2_FMT<0b00100>; -class PRECEQU_PH_QBR_ENC : ABSQ_S_PH_R2_FMT<0b00101>; -class PRECEQU_PH_QBLA_ENC : ABSQ_S_PH_R2_FMT<0b00110>; -class PRECEQU_PH_QBRA_ENC : ABSQ_S_PH_R2_FMT<0b00111>; -class PRECEU_PH_QBL_ENC : ABSQ_S_PH_R2_FMT<0b11100>; -class PRECEU_PH_QBR_ENC : ABSQ_S_PH_R2_FMT<0b11101>; -class PRECEU_PH_QBLA_ENC : ABSQ_S_PH_R2_FMT<0b11110>; -class PRECEU_PH_QBRA_ENC : ABSQ_S_PH_R2_FMT<0b11111>; -class SHLL_QB_ENC : SHLL_QB_FMT<0b00000>; -class SHLLV_QB_ENC : SHLL_QB_FMT<0b00010>; -class SHRL_QB_ENC : SHLL_QB_FMT<0b00001>; -class SHRLV_QB_ENC : SHLL_QB_FMT<0b00011>; -class SHLL_PH_ENC : SHLL_QB_FMT<0b01000>; -class SHLLV_PH_ENC : SHLL_QB_FMT<0b01010>; -class SHLL_S_PH_ENC : SHLL_QB_FMT<0b01100>; -class SHLLV_S_PH_ENC : SHLL_QB_FMT<0b01110>; -class SHRA_PH_ENC : SHLL_QB_FMT<0b01001>; -class SHRAV_PH_ENC : SHLL_QB_FMT<0b01011>; -class SHRA_R_PH_ENC : SHLL_QB_FMT<0b01101>; -class SHRAV_R_PH_ENC : SHLL_QB_FMT<0b01111>; -class SHLL_S_W_ENC : SHLL_QB_FMT<0b10100>; -class SHLLV_S_W_ENC : SHLL_QB_FMT<0b10110>; -class SHRA_R_W_ENC : SHLL_QB_FMT<0b10101>; -class SHRAV_R_W_ENC : SHLL_QB_FMT<0b10111>; -class MULEU_S_PH_QBL_ENC : ADDU_QB_FMT<0b00110>; -class MULEU_S_PH_QBR_ENC : ADDU_QB_FMT<0b00111>; -class MULEQ_S_W_PHL_ENC : ADDU_QB_FMT<0b11100>; -class MULEQ_S_W_PHR_ENC : ADDU_QB_FMT<0b11101>; -class MULQ_RS_PH_ENC : ADDU_QB_FMT<0b11111>; -class MULSAQ_S_W_PH_ENC : DPA_W_PH_FMT<0b00110>; -class MAQ_S_W_PHL_ENC : DPA_W_PH_FMT<0b10100>; -class MAQ_S_W_PHR_ENC : DPA_W_PH_FMT<0b10110>; -class MAQ_SA_W_PHL_ENC : DPA_W_PH_FMT<0b10000>; -class MAQ_SA_W_PHR_ENC : DPA_W_PH_FMT<0b10010>; -class MFHI_ENC : MFHI_FMT<0b010000>; -class MFLO_ENC : MFHI_FMT<0b010010>; -class MTHI_ENC : MTHI_FMT<0b010001>; -class MTLO_ENC : MTHI_FMT<0b010011>; -class DPAU_H_QBL_ENC : DPA_W_PH_FMT<0b00011>; -class DPAU_H_QBR_ENC : DPA_W_PH_FMT<0b00111>; -class DPSU_H_QBL_ENC : DPA_W_PH_FMT<0b01011>; -class DPSU_H_QBR_ENC : DPA_W_PH_FMT<0b01111>; -class DPAQ_S_W_PH_ENC : DPA_W_PH_FMT<0b00100>; -class DPSQ_S_W_PH_ENC : DPA_W_PH_FMT<0b00101>; -class DPAQ_SA_L_W_ENC : DPA_W_PH_FMT<0b01100>; -class DPSQ_SA_L_W_ENC : DPA_W_PH_FMT<0b01101>; -class MULT_DSP_ENC : MULT_FMT<0b000000, 0b011000>; -class MULTU_DSP_ENC : MULT_FMT<0b000000, 0b011001>; -class MADD_DSP_ENC : MULT_FMT<0b011100, 0b000000>; -class MADDU_DSP_ENC : MULT_FMT<0b011100, 0b000001>; -class MSUB_DSP_ENC : MULT_FMT<0b011100, 0b000100>; -class MSUBU_DSP_ENC : MULT_FMT<0b011100, 0b000101>; -class CMPU_EQ_QB_ENC : CMP_EQ_QB_R2_FMT<0b00000>; -class CMPU_LT_QB_ENC : CMP_EQ_QB_R2_FMT<0b00001>; -class CMPU_LE_QB_ENC : CMP_EQ_QB_R2_FMT<0b00010>; -class CMPGU_EQ_QB_ENC : CMP_EQ_QB_R3_FMT<0b00100>; -class CMPGU_LT_QB_ENC : CMP_EQ_QB_R3_FMT<0b00101>; -class CMPGU_LE_QB_ENC : CMP_EQ_QB_R3_FMT<0b00110>; -class CMP_EQ_PH_ENC : CMP_EQ_QB_R2_FMT<0b01000>; -class CMP_LT_PH_ENC : CMP_EQ_QB_R2_FMT<0b01001>; -class CMP_LE_PH_ENC : CMP_EQ_QB_R2_FMT<0b01010>; -class BITREV_ENC : ABSQ_S_PH_R2_FMT<0b11011>; -class PACKRL_PH_ENC : CMP_EQ_QB_R3_FMT<0b01110>; -class REPL_QB_ENC : REPL_FMT<0b00010>; -class REPL_PH_ENC : REPL_FMT<0b01010>; -class REPLV_QB_ENC : ABSQ_S_PH_R2_FMT<0b00011>; -class REPLV_PH_ENC : ABSQ_S_PH_R2_FMT<0b01011>; -class PICK_QB_ENC : CMP_EQ_QB_R3_FMT<0b00011>; -class PICK_PH_ENC : CMP_EQ_QB_R3_FMT<0b01011>; -class LWX_ENC : LX_FMT<0b00000>; -class LHX_ENC : LX_FMT<0b00100>; -class LBUX_ENC : LX_FMT<0b00110>; -class BPOSGE32_ENC : BPOSGE32_FMT<0b11100>; -class INSV_ENC : INSV_FMT<0b001100>; - -class EXTP_ENC : EXTR_W_TY1_FMT<0b00010>; -class EXTPV_ENC : EXTR_W_TY1_FMT<0b00011>; -class EXTPDP_ENC : EXTR_W_TY1_FMT<0b01010>; -class EXTPDPV_ENC : EXTR_W_TY1_FMT<0b01011>; -class EXTR_W_ENC : EXTR_W_TY1_FMT<0b00000>; -class EXTRV_W_ENC : EXTR_W_TY1_FMT<0b00001>; -class EXTR_R_W_ENC : EXTR_W_TY1_FMT<0b00100>; -class EXTRV_R_W_ENC : EXTR_W_TY1_FMT<0b00101>; -class EXTR_RS_W_ENC : EXTR_W_TY1_FMT<0b00110>; -class EXTRV_RS_W_ENC : EXTR_W_TY1_FMT<0b00111>; -class EXTR_S_H_ENC : EXTR_W_TY1_FMT<0b01110>; -class EXTRV_S_H_ENC : EXTR_W_TY1_FMT<0b01111>; -class SHILO_ENC : SHILO_R1_FMT<0b11010>; -class SHILOV_ENC : SHILO_R2_FMT<0b11011>; -class MTHLIP_ENC : SHILO_R2_FMT<0b11111>; - -class RDDSP_ENC : RDDSP_FMT<0b10010>; -class WRDSP_ENC : WRDSP_FMT<0b10011>; -class ADDU_PH_ENC : ADDU_QB_FMT<0b01000>; -class ADDU_S_PH_ENC : ADDU_QB_FMT<0b01100>; -class SUBU_PH_ENC : ADDU_QB_FMT<0b01001>; -class SUBU_S_PH_ENC : ADDU_QB_FMT<0b01101>; -class CMPGDU_EQ_QB_ENC : CMP_EQ_QB_R3_FMT<0b11000>; -class CMPGDU_LT_QB_ENC : CMP_EQ_QB_R3_FMT<0b11001>; -class CMPGDU_LE_QB_ENC : CMP_EQ_QB_R3_FMT<0b11010>; -class ABSQ_S_QB_ENC : ABSQ_S_PH_R2_FMT<0b00001>; -class ADDUH_QB_ENC : ADDUH_QB_FMT<0b00000>; -class ADDUH_R_QB_ENC : ADDUH_QB_FMT<0b00010>; -class SUBUH_QB_ENC : ADDUH_QB_FMT<0b00001>; -class SUBUH_R_QB_ENC : ADDUH_QB_FMT<0b00011>; -class ADDQH_PH_ENC : ADDUH_QB_FMT<0b01000>; -class ADDQH_R_PH_ENC : ADDUH_QB_FMT<0b01010>; -class SUBQH_PH_ENC : ADDUH_QB_FMT<0b01001>; -class SUBQH_R_PH_ENC : ADDUH_QB_FMT<0b01011>; -class ADDQH_W_ENC : ADDUH_QB_FMT<0b10000>; -class ADDQH_R_W_ENC : ADDUH_QB_FMT<0b10010>; -class SUBQH_W_ENC : ADDUH_QB_FMT<0b10001>; -class SUBQH_R_W_ENC : ADDUH_QB_FMT<0b10011>; -class MUL_PH_ENC : ADDUH_QB_FMT<0b01100>; -class MUL_S_PH_ENC : ADDUH_QB_FMT<0b01110>; -class MULQ_S_W_ENC : ADDUH_QB_FMT<0b10110>; -class MULQ_RS_W_ENC : ADDUH_QB_FMT<0b10111>; -class MULQ_S_PH_ENC : ADDU_QB_FMT<0b11110>; -class DPA_W_PH_ENC : DPA_W_PH_FMT<0b00000>; -class DPS_W_PH_ENC : DPA_W_PH_FMT<0b00001>; -class DPAQX_S_W_PH_ENC : DPA_W_PH_FMT<0b11000>; -class DPAQX_SA_W_PH_ENC : DPA_W_PH_FMT<0b11010>; -class DPAX_W_PH_ENC : DPA_W_PH_FMT<0b01000>; -class DPSX_W_PH_ENC : DPA_W_PH_FMT<0b01001>; -class DPSQX_S_W_PH_ENC : DPA_W_PH_FMT<0b11001>; -class DPSQX_SA_W_PH_ENC : DPA_W_PH_FMT<0b11011>; -class MULSA_W_PH_ENC : DPA_W_PH_FMT<0b00010>; -class PRECR_QB_PH_ENC : CMP_EQ_QB_R3_FMT<0b01101>; -class PRECR_SRA_PH_W_ENC : PRECR_SRA_PH_W_FMT<0b11110>; -class PRECR_SRA_R_PH_W_ENC : PRECR_SRA_PH_W_FMT<0b11111>; -class SHRA_QB_ENC : SHLL_QB_FMT<0b00100>; -class SHRAV_QB_ENC : SHLL_QB_FMT<0b00110>; -class SHRA_R_QB_ENC : SHLL_QB_FMT<0b00101>; -class SHRAV_R_QB_ENC : SHLL_QB_FMT<0b00111>; -class SHRL_PH_ENC : SHLL_QB_FMT<0b11001>; -class SHRLV_PH_ENC : SHLL_QB_FMT<0b11011>; -class APPEND_ENC : APPEND_FMT<0b00000>; -class BALIGN_ENC : APPEND_FMT<0b10000>; -class PREPEND_ENC : APPEND_FMT<0b00001>; - -// Instruction desc. -class ADDU_QB_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - InstrItinClass itin, RegisterOperand ROD, - RegisterOperand ROS, RegisterOperand ROT = ROS> { - dag OutOperandList = (outs ROD:$rd); - dag InOperandList = (ins ROS:$rs, ROT:$rt); - string AsmString = !strconcat(instr_asm, "\t$rd, $rs, $rt"); - list<dag> Pattern = [(set ROD:$rd, (OpNode ROS:$rs, ROT:$rt))]; - InstrItinClass Itinerary = itin; - string BaseOpcode = instr_asm; -} - -class RADDU_W_QB_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - InstrItinClass itin, RegisterOperand ROD, - RegisterOperand ROS = ROD> { - dag OutOperandList = (outs ROD:$rd); - dag InOperandList = (ins ROS:$rs); - string AsmString = !strconcat(instr_asm, "\t$rd, $rs"); - list<dag> Pattern = [(set ROD:$rd, (OpNode ROS:$rs))]; - InstrItinClass Itinerary = itin; - string BaseOpcode = instr_asm; -} - -class CMP_EQ_QB_R2_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - InstrItinClass itin, RegisterOperand ROS, - RegisterOperand ROT = ROS> { - dag OutOperandList = (outs); - dag InOperandList = (ins ROS:$rs, ROT:$rt); - string AsmString = !strconcat(instr_asm, "\t$rs, $rt"); - list<dag> Pattern = [(OpNode ROS:$rs, ROT:$rt)]; - InstrItinClass Itinerary = itin; - string BaseOpcode = instr_asm; -} - -class CMP_EQ_QB_R3_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - InstrItinClass itin, RegisterOperand ROD, - RegisterOperand ROS, RegisterOperand ROT = ROS> { - dag OutOperandList = (outs ROD:$rd); - dag InOperandList = (ins ROS:$rs, ROT:$rt); - string AsmString = !strconcat(instr_asm, "\t$rd, $rs, $rt"); - list<dag> Pattern = [(set ROD:$rd, (OpNode ROS:$rs, ROT:$rt))]; - InstrItinClass Itinerary = itin; - string BaseOpcode = instr_asm; -} - -class PRECR_SRA_PH_W_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - InstrItinClass itin, RegisterOperand ROT, - RegisterOperand ROS = ROT> { - dag OutOperandList = (outs ROT:$rt); - dag InOperandList = (ins ROS:$rs, uimm5:$sa, ROS:$src); - string AsmString = !strconcat(instr_asm, "\t$rt, $rs, $sa"); - list<dag> Pattern = [(set ROT:$rt, (OpNode ROS:$src, ROS:$rs, immZExt5:$sa))]; - InstrItinClass Itinerary = itin; - string Constraints = "$src = $rt"; - string BaseOpcode = instr_asm; -} - -class ABSQ_S_PH_R2_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - InstrItinClass itin, RegisterOperand ROD, - RegisterOperand ROT = ROD> { - dag OutOperandList = (outs ROD:$rd); - dag InOperandList = (ins ROT:$rt); - string AsmString = !strconcat(instr_asm, "\t$rd, $rt"); - list<dag> Pattern = [(set ROD:$rd, (OpNode ROT:$rt))]; - InstrItinClass Itinerary = itin; - string BaseOpcode = instr_asm; -} - -class REPL_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - Operand ImmOp, ImmLeaf immPat, InstrItinClass itin, - RegisterOperand RO> { - dag OutOperandList = (outs RO:$rd); - dag InOperandList = (ins ImmOp:$imm); - string AsmString = !strconcat(instr_asm, "\t$rd, $imm"); - list<dag> Pattern = [(set RO:$rd, (OpNode immPat:$imm))]; - InstrItinClass Itinerary = itin; - string BaseOpcode = instr_asm; -} - -class SHLL_QB_R3_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - InstrItinClass itin, RegisterOperand RO> { - dag OutOperandList = (outs RO:$rd); - dag InOperandList = (ins RO:$rt, GPR32Opnd:$rs_sa); - string AsmString = !strconcat(instr_asm, "\t$rd, $rt, $rs_sa"); - list<dag> Pattern = [(set RO:$rd, (OpNode RO:$rt, GPR32Opnd:$rs_sa))]; - InstrItinClass Itinerary = itin; - string BaseOpcode = instr_asm; -} - -class SHLL_QB_R2_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - SDPatternOperator ImmPat, InstrItinClass itin, - RegisterOperand RO, Operand ImmOpnd> { - dag OutOperandList = (outs RO:$rd); - dag InOperandList = (ins RO:$rt, ImmOpnd:$rs_sa); - string AsmString = !strconcat(instr_asm, "\t$rd, $rt, $rs_sa"); - list<dag> Pattern = [(set RO:$rd, (OpNode RO:$rt, ImmPat:$rs_sa))]; - InstrItinClass Itinerary = itin; - bit hasSideEffects = 1; - string BaseOpcode = instr_asm; -} - -class LX_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - InstrItinClass itin> { - dag OutOperandList = (outs GPR32Opnd:$rd); - dag InOperandList = (ins PtrRC:$base, PtrRC:$index); - string AsmString = !strconcat(instr_asm, "\t$rd, ${index}(${base})"); - list<dag> Pattern = [(set GPR32Opnd:$rd, (OpNode iPTR:$base, iPTR:$index))]; - InstrItinClass Itinerary = itin; - bit mayLoad = 1; - string BaseOpcode = instr_asm; -} - -class ADDUH_QB_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - InstrItinClass itin, RegisterOperand ROD, - RegisterOperand ROS = ROD, RegisterOperand ROT = ROD> { - dag OutOperandList = (outs ROD:$rd); - dag InOperandList = (ins ROS:$rs, ROT:$rt); - string AsmString = !strconcat(instr_asm, "\t$rd, $rs, $rt"); - list<dag> Pattern = [(set ROD:$rd, (OpNode ROS:$rs, ROT:$rt))]; - InstrItinClass Itinerary = itin; - string BaseOpcode = instr_asm; -} - -class APPEND_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - Operand ImmOp, SDPatternOperator Imm, InstrItinClass itin> { - dag OutOperandList = (outs GPR32Opnd:$rt); - dag InOperandList = (ins GPR32Opnd:$rs, ImmOp:$sa, GPR32Opnd:$src); - string AsmString = !strconcat(instr_asm, "\t$rt, $rs, $sa"); - list<dag> Pattern = [(set GPR32Opnd:$rt, - (OpNode GPR32Opnd:$src, GPR32Opnd:$rs, Imm:$sa))]; - InstrItinClass Itinerary = itin; - string Constraints = "$src = $rt"; - string BaseOpcode = instr_asm; -} - -class EXTR_W_TY1_R2_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - InstrItinClass itin> { - dag OutOperandList = (outs GPR32Opnd:$rt); - dag InOperandList = (ins ACC64DSPOpnd:$ac, GPR32Opnd:$shift_rs); - string AsmString = !strconcat(instr_asm, "\t$rt, $ac, $shift_rs"); - InstrItinClass Itinerary = itin; - string BaseOpcode = instr_asm; -} - -class EXTR_W_TY1_R1_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - InstrItinClass itin> { - dag OutOperandList = (outs GPR32Opnd:$rt); - dag InOperandList = (ins ACC64DSPOpnd:$ac, uimm5:$shift_rs); - string AsmString = !strconcat(instr_asm, "\t$rt, $ac, $shift_rs"); - InstrItinClass Itinerary = itin; - string BaseOpcode = instr_asm; -} - -class SHILO_R1_DESC_BASE<string instr_asm, SDPatternOperator OpNode> { - dag OutOperandList = (outs ACC64DSPOpnd:$ac); - dag InOperandList = (ins simm6:$shift, ACC64DSPOpnd:$acin); - string AsmString = !strconcat(instr_asm, "\t$ac, $shift"); - list<dag> Pattern = [(set ACC64DSPOpnd:$ac, - (OpNode immSExt6:$shift, ACC64DSPOpnd:$acin))]; - string Constraints = "$acin = $ac"; - string BaseOpcode = instr_asm; -} - -class SHILO_R2_DESC_BASE<string instr_asm, SDPatternOperator OpNode> { - dag OutOperandList = (outs ACC64DSPOpnd:$ac); - dag InOperandList = (ins GPR32Opnd:$rs, ACC64DSPOpnd:$acin); - string AsmString = !strconcat(instr_asm, "\t$ac, $rs"); - list<dag> Pattern = [(set ACC64DSPOpnd:$ac, - (OpNode GPR32Opnd:$rs, ACC64DSPOpnd:$acin))]; - string Constraints = "$acin = $ac"; - string BaseOpcode = instr_asm; -} - -class MTHLIP_DESC_BASE<string instr_asm, SDPatternOperator OpNode> { - dag OutOperandList = (outs ACC64DSPOpnd:$ac); - dag InOperandList = (ins GPR32Opnd:$rs, ACC64DSPOpnd:$acin); - string AsmString = !strconcat(instr_asm, "\t$rs, $ac"); - list<dag> Pattern = [(set ACC64DSPOpnd:$ac, - (OpNode GPR32Opnd:$rs, ACC64DSPOpnd:$acin))]; - string Constraints = "$acin = $ac"; - string BaseOpcode = instr_asm; -} - -class RDDSP_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - InstrItinClass itin> { - dag OutOperandList = (outs GPR32Opnd:$rd); - dag InOperandList = (ins uimm10:$mask); - string AsmString = !strconcat(instr_asm, "\t$rd, $mask"); - list<dag> Pattern = [(set GPR32Opnd:$rd, (OpNode immZExt10:$mask))]; - InstrItinClass Itinerary = itin; - string BaseOpcode = instr_asm; - bit isMoveReg = 1; -} - -class WRDSP_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - InstrItinClass itin> { - dag OutOperandList = (outs); - dag InOperandList = (ins GPR32Opnd:$rs, uimm10:$mask); - string AsmString = !strconcat(instr_asm, "\t$rs, $mask"); - list<dag> Pattern = [(OpNode GPR32Opnd:$rs, immZExt10:$mask)]; - InstrItinClass Itinerary = itin; - string BaseOpcode = instr_asm; - bit isMoveReg = 1; -} - -class DPA_W_PH_DESC_BASE<string instr_asm, SDPatternOperator OpNode> { - dag OutOperandList = (outs ACC64DSPOpnd:$ac); - dag InOperandList = (ins GPR32Opnd:$rs, GPR32Opnd:$rt, ACC64DSPOpnd:$acin); - string AsmString = !strconcat(instr_asm, "\t$ac, $rs, $rt"); - list<dag> Pattern = [(set ACC64DSPOpnd:$ac, - (OpNode GPR32Opnd:$rs, GPR32Opnd:$rt, ACC64DSPOpnd:$acin))]; - string Constraints = "$acin = $ac"; - string BaseOpcode = instr_asm; -} - -class MULT_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - InstrItinClass itin> { - dag OutOperandList = (outs ACC64DSPOpnd:$ac); - dag InOperandList = (ins GPR32Opnd:$rs, GPR32Opnd:$rt); - string AsmString = !strconcat(instr_asm, "\t$ac, $rs, $rt"); - list<dag> Pattern = [(set ACC64DSPOpnd:$ac, (OpNode GPR32Opnd:$rs, GPR32Opnd:$rt))]; - InstrItinClass Itinerary = itin; - bit isCommutable = 1; - string BaseOpcode = instr_asm; -} - -class MADD_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - InstrItinClass itin> { - dag OutOperandList = (outs ACC64DSPOpnd:$ac); - dag InOperandList = (ins GPR32Opnd:$rs, GPR32Opnd:$rt, ACC64DSPOpnd:$acin); - string AsmString = !strconcat(instr_asm, "\t$ac, $rs, $rt"); - list<dag> Pattern = [(set ACC64DSPOpnd:$ac, - (OpNode GPR32Opnd:$rs, GPR32Opnd:$rt, ACC64DSPOpnd:$acin))]; - InstrItinClass Itinerary = itin; - string Constraints = "$acin = $ac"; - string BaseOpcode = instr_asm; -} - -class MFHI_DESC_BASE<string instr_asm, RegisterOperand RO, SDNode OpNode, - InstrItinClass itin> { - dag OutOperandList = (outs GPR32Opnd:$rd); - dag InOperandList = (ins RO:$ac); - string AsmString = !strconcat(instr_asm, "\t$rd, $ac"); - list<dag> Pattern = [(set GPR32Opnd:$rd, (OpNode RO:$ac))]; - InstrItinClass Itinerary = itin; - string BaseOpcode = instr_asm; - bit isMoveReg = 1; -} - -class MTHI_DESC_BASE<string instr_asm, RegisterOperand RO, InstrItinClass itin> { - dag OutOperandList = (outs RO:$ac); - dag InOperandList = (ins GPR32Opnd:$rs); - string AsmString = !strconcat(instr_asm, "\t$rs, $ac"); - InstrItinClass Itinerary = itin; - string BaseOpcode = instr_asm; - bit isMoveReg = 1; -} - -class BPOSGE32_PSEUDO_DESC_BASE<SDPatternOperator OpNode, InstrItinClass itin> : - MipsPseudo<(outs GPR32Opnd:$dst), (ins), [(set GPR32Opnd:$dst, (OpNode))]> { - bit hasNoSchedulingInfo = 1; - bit usesCustomInserter = 1; -} - -class BPOSGE32_DESC_BASE<string instr_asm, DAGOperand opnd, - InstrItinClass itin> { - dag OutOperandList = (outs); - dag InOperandList = (ins opnd:$offset); - string AsmString = !strconcat(instr_asm, "\t$offset"); - InstrItinClass Itinerary = itin; - bit isBranch = 1; - bit isTerminator = 1; - bit hasDelaySlot = 1; - string BaseOpcode = instr_asm; -} - -class INSV_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - InstrItinClass itin> { - dag OutOperandList = (outs GPR32Opnd:$rt); - dag InOperandList = (ins GPR32Opnd:$src, GPR32Opnd:$rs); - string AsmString = !strconcat(instr_asm, "\t$rt, $rs"); - list<dag> Pattern = [(set GPR32Opnd:$rt, (OpNode GPR32Opnd:$src, GPR32Opnd:$rs))]; - InstrItinClass Itinerary = itin; - string Constraints = "$src = $rt"; - string BaseOpcode = instr_asm; -} - -//===----------------------------------------------------------------------===// -// MIPS DSP Rev 1 -//===----------------------------------------------------------------------===// - -// Addition/subtraction -class ADDU_QB_DESC : ADDU_QB_DESC_BASE<"addu.qb", null_frag, NoItinerary, - DSPROpnd, DSPROpnd>, IsCommutable, - Defs<[DSPOutFlag20]>; - -class ADDU_S_QB_DESC : ADDU_QB_DESC_BASE<"addu_s.qb", int_mips_addu_s_qb, - NoItinerary, DSPROpnd, DSPROpnd>, - IsCommutable, Defs<[DSPOutFlag20]>; - -class SUBU_QB_DESC : ADDU_QB_DESC_BASE<"subu.qb", null_frag, NoItinerary, - DSPROpnd, DSPROpnd>, - Defs<[DSPOutFlag20]>; - -class SUBU_S_QB_DESC : ADDU_QB_DESC_BASE<"subu_s.qb", int_mips_subu_s_qb, - NoItinerary, DSPROpnd, DSPROpnd>, - Defs<[DSPOutFlag20]>; - -class ADDQ_PH_DESC : ADDU_QB_DESC_BASE<"addq.ph", null_frag, NoItinerary, - DSPROpnd, DSPROpnd>, IsCommutable, - Defs<[DSPOutFlag20]>; - -class ADDQ_S_PH_DESC : ADDU_QB_DESC_BASE<"addq_s.ph", int_mips_addq_s_ph, - NoItinerary, DSPROpnd, DSPROpnd>, - IsCommutable, Defs<[DSPOutFlag20]>; - -class SUBQ_PH_DESC : ADDU_QB_DESC_BASE<"subq.ph", null_frag, NoItinerary, - DSPROpnd, DSPROpnd>, - Defs<[DSPOutFlag20]>; - -class SUBQ_S_PH_DESC : ADDU_QB_DESC_BASE<"subq_s.ph", int_mips_subq_s_ph, - NoItinerary, DSPROpnd, DSPROpnd>, - Defs<[DSPOutFlag20]>; - -class ADDQ_S_W_DESC : ADDU_QB_DESC_BASE<"addq_s.w", int_mips_addq_s_w, - NoItinerary, GPR32Opnd, GPR32Opnd>, - IsCommutable, Defs<[DSPOutFlag20]>; - -class SUBQ_S_W_DESC : ADDU_QB_DESC_BASE<"subq_s.w", int_mips_subq_s_w, - NoItinerary, GPR32Opnd, GPR32Opnd>, - Defs<[DSPOutFlag20]>; - -class ADDSC_DESC : ADDU_QB_DESC_BASE<"addsc", null_frag, NoItinerary, - GPR32Opnd, GPR32Opnd>, IsCommutable, - Defs<[DSPCarry]>; - -class ADDWC_DESC : ADDU_QB_DESC_BASE<"addwc", null_frag, NoItinerary, - GPR32Opnd, GPR32Opnd>, - IsCommutable, Uses<[DSPCarry]>, Defs<[DSPOutFlag20]>; - -class MODSUB_DESC : ADDU_QB_DESC_BASE<"modsub", int_mips_modsub, NoItinerary, - GPR32Opnd, GPR32Opnd>; - -class RADDU_W_QB_DESC : RADDU_W_QB_DESC_BASE<"raddu.w.qb", int_mips_raddu_w_qb, - NoItinerary, GPR32Opnd, DSPROpnd>; - -// Absolute value -class ABSQ_S_PH_DESC : ABSQ_S_PH_R2_DESC_BASE<"absq_s.ph", int_mips_absq_s_ph, - NoItinerary, DSPROpnd>, - Defs<[DSPOutFlag20]>; - -class ABSQ_S_W_DESC : ABSQ_S_PH_R2_DESC_BASE<"absq_s.w", int_mips_absq_s_w, - NoItinerary, GPR32Opnd>, - Defs<[DSPOutFlag20]>; - -// Precision reduce/expand -class PRECRQ_QB_PH_DESC : CMP_EQ_QB_R3_DESC_BASE<"precrq.qb.ph", - int_mips_precrq_qb_ph, - NoItinerary, DSPROpnd, DSPROpnd>; - -class PRECRQ_PH_W_DESC : CMP_EQ_QB_R3_DESC_BASE<"precrq.ph.w", - int_mips_precrq_ph_w, - NoItinerary, DSPROpnd, GPR32Opnd>; - -class PRECRQ_RS_PH_W_DESC : CMP_EQ_QB_R3_DESC_BASE<"precrq_rs.ph.w", - int_mips_precrq_rs_ph_w, - NoItinerary, DSPROpnd, - GPR32Opnd>, - Defs<[DSPOutFlag22]>; - -class PRECRQU_S_QB_PH_DESC : CMP_EQ_QB_R3_DESC_BASE<"precrqu_s.qb.ph", - int_mips_precrqu_s_qb_ph, - NoItinerary, DSPROpnd, - DSPROpnd>, - Defs<[DSPOutFlag22]>; - -class PRECEQ_W_PHL_DESC : ABSQ_S_PH_R2_DESC_BASE<"preceq.w.phl", - int_mips_preceq_w_phl, - NoItinerary, GPR32Opnd, DSPROpnd>; - -class PRECEQ_W_PHR_DESC : ABSQ_S_PH_R2_DESC_BASE<"preceq.w.phr", - int_mips_preceq_w_phr, - NoItinerary, GPR32Opnd, DSPROpnd>; - -class PRECEQU_PH_QBL_DESC : ABSQ_S_PH_R2_DESC_BASE<"precequ.ph.qbl", - int_mips_precequ_ph_qbl, - NoItinerary, DSPROpnd>; - -class PRECEQU_PH_QBR_DESC : ABSQ_S_PH_R2_DESC_BASE<"precequ.ph.qbr", - int_mips_precequ_ph_qbr, - NoItinerary, DSPROpnd>; - -class PRECEQU_PH_QBLA_DESC : ABSQ_S_PH_R2_DESC_BASE<"precequ.ph.qbla", - int_mips_precequ_ph_qbla, - NoItinerary, DSPROpnd>; - -class PRECEQU_PH_QBRA_DESC : ABSQ_S_PH_R2_DESC_BASE<"precequ.ph.qbra", - int_mips_precequ_ph_qbra, - NoItinerary, DSPROpnd>; - -class PRECEU_PH_QBL_DESC : ABSQ_S_PH_R2_DESC_BASE<"preceu.ph.qbl", - int_mips_preceu_ph_qbl, - NoItinerary, DSPROpnd>; - -class PRECEU_PH_QBR_DESC : ABSQ_S_PH_R2_DESC_BASE<"preceu.ph.qbr", - int_mips_preceu_ph_qbr, - NoItinerary, DSPROpnd>; - -class PRECEU_PH_QBLA_DESC : ABSQ_S_PH_R2_DESC_BASE<"preceu.ph.qbla", - int_mips_preceu_ph_qbla, - NoItinerary, DSPROpnd>; - -class PRECEU_PH_QBRA_DESC : ABSQ_S_PH_R2_DESC_BASE<"preceu.ph.qbra", - int_mips_preceu_ph_qbra, - NoItinerary, DSPROpnd>; - -// Shift -class SHLL_QB_DESC : SHLL_QB_R2_DESC_BASE<"shll.qb", null_frag, immZExt3, - NoItinerary, DSPROpnd, uimm3>, - Defs<[DSPOutFlag22]>; - -class SHLLV_QB_DESC : SHLL_QB_R3_DESC_BASE<"shllv.qb", int_mips_shll_qb, - NoItinerary, DSPROpnd>, - Defs<[DSPOutFlag22]>; - -class SHRL_QB_DESC : SHLL_QB_R2_DESC_BASE<"shrl.qb", null_frag, immZExt3, - NoItinerary, DSPROpnd, uimm3>; - -class SHRLV_QB_DESC : SHLL_QB_R3_DESC_BASE<"shrlv.qb", int_mips_shrl_qb, - NoItinerary, DSPROpnd>; - -class SHLL_PH_DESC : SHLL_QB_R2_DESC_BASE<"shll.ph", null_frag, immZExt4, - NoItinerary, DSPROpnd, uimm4>, - Defs<[DSPOutFlag22]>; - -class SHLLV_PH_DESC : SHLL_QB_R3_DESC_BASE<"shllv.ph", int_mips_shll_ph, - NoItinerary, DSPROpnd>, - Defs<[DSPOutFlag22]>; - -class SHLL_S_PH_DESC : SHLL_QB_R2_DESC_BASE<"shll_s.ph", int_mips_shll_s_ph, - immZExt4, NoItinerary, DSPROpnd, - uimm4>, - Defs<[DSPOutFlag22]>; - -class SHLLV_S_PH_DESC : SHLL_QB_R3_DESC_BASE<"shllv_s.ph", int_mips_shll_s_ph, - NoItinerary, DSPROpnd>, - Defs<[DSPOutFlag22]>; - -class SHRA_PH_DESC : SHLL_QB_R2_DESC_BASE<"shra.ph", null_frag, immZExt4, - NoItinerary, DSPROpnd, uimm4>; - -class SHRAV_PH_DESC : SHLL_QB_R3_DESC_BASE<"shrav.ph", int_mips_shra_ph, - NoItinerary, DSPROpnd>; - -class SHRA_R_PH_DESC : SHLL_QB_R2_DESC_BASE<"shra_r.ph", int_mips_shra_r_ph, - immZExt4, NoItinerary, DSPROpnd, - uimm4>; - -class SHRAV_R_PH_DESC : SHLL_QB_R3_DESC_BASE<"shrav_r.ph", int_mips_shra_r_ph, - NoItinerary, DSPROpnd>; - -class SHLL_S_W_DESC : SHLL_QB_R2_DESC_BASE<"shll_s.w", int_mips_shll_s_w, - immZExt5, NoItinerary, GPR32Opnd, - uimm5>, - Defs<[DSPOutFlag22]>; - -class SHLLV_S_W_DESC : SHLL_QB_R3_DESC_BASE<"shllv_s.w", int_mips_shll_s_w, - NoItinerary, GPR32Opnd>, - Defs<[DSPOutFlag22]>; - -class SHRA_R_W_DESC : SHLL_QB_R2_DESC_BASE<"shra_r.w", int_mips_shra_r_w, - immZExt5, NoItinerary, GPR32Opnd, - uimm5>; - -class SHRAV_R_W_DESC : SHLL_QB_R3_DESC_BASE<"shrav_r.w", int_mips_shra_r_w, - NoItinerary, GPR32Opnd>; - -// Multiplication -class MULEU_S_PH_QBL_DESC : ADDU_QB_DESC_BASE<"muleu_s.ph.qbl", - int_mips_muleu_s_ph_qbl, - NoItinerary, DSPROpnd, DSPROpnd>, - Defs<[DSPOutFlag21]>; - -class MULEU_S_PH_QBR_DESC : ADDU_QB_DESC_BASE<"muleu_s.ph.qbr", - int_mips_muleu_s_ph_qbr, - NoItinerary, DSPROpnd, DSPROpnd>, - Defs<[DSPOutFlag21]>; - -class MULEQ_S_W_PHL_DESC : ADDU_QB_DESC_BASE<"muleq_s.w.phl", - int_mips_muleq_s_w_phl, - NoItinerary, GPR32Opnd, DSPROpnd>, - IsCommutable, Defs<[DSPOutFlag21]>; - -class MULEQ_S_W_PHR_DESC : ADDU_QB_DESC_BASE<"muleq_s.w.phr", - int_mips_muleq_s_w_phr, - NoItinerary, GPR32Opnd, DSPROpnd>, - IsCommutable, Defs<[DSPOutFlag21]>; - -class MULQ_RS_PH_DESC : ADDU_QB_DESC_BASE<"mulq_rs.ph", int_mips_mulq_rs_ph, - NoItinerary, DSPROpnd, DSPROpnd>, - IsCommutable, Defs<[DSPOutFlag21]>; - -class MULSAQ_S_W_PH_DESC : DPA_W_PH_DESC_BASE<"mulsaq_s.w.ph", - MipsMULSAQ_S_W_PH>, - Defs<[DSPOutFlag16_19]>; - -class MAQ_S_W_PHL_DESC : DPA_W_PH_DESC_BASE<"maq_s.w.phl", MipsMAQ_S_W_PHL>, - Defs<[DSPOutFlag16_19]>; - -class MAQ_S_W_PHR_DESC : DPA_W_PH_DESC_BASE<"maq_s.w.phr", MipsMAQ_S_W_PHR>, - Defs<[DSPOutFlag16_19]>; - -class MAQ_SA_W_PHL_DESC : DPA_W_PH_DESC_BASE<"maq_sa.w.phl", MipsMAQ_SA_W_PHL>, - Defs<[DSPOutFlag16_19]>; - -class MAQ_SA_W_PHR_DESC : DPA_W_PH_DESC_BASE<"maq_sa.w.phr", MipsMAQ_SA_W_PHR>, - Defs<[DSPOutFlag16_19]>; - -// Move from/to hi/lo. -class MFHI_DESC : MFHI_DESC_BASE<"mfhi", ACC64DSPOpnd, MipsMFHI, NoItinerary>; -class MFLO_DESC : MFHI_DESC_BASE<"mflo", ACC64DSPOpnd, MipsMFLO, NoItinerary>; -class MTHI_DESC : MTHI_DESC_BASE<"mthi", HI32DSPOpnd, NoItinerary>; -class MTLO_DESC : MTHI_DESC_BASE<"mtlo", LO32DSPOpnd, NoItinerary>; - -// Dot product with accumulate/subtract -class DPAU_H_QBL_DESC : DPA_W_PH_DESC_BASE<"dpau.h.qbl", MipsDPAU_H_QBL>; - -class DPAU_H_QBR_DESC : DPA_W_PH_DESC_BASE<"dpau.h.qbr", MipsDPAU_H_QBR>; - -class DPSU_H_QBL_DESC : DPA_W_PH_DESC_BASE<"dpsu.h.qbl", MipsDPSU_H_QBL>; - -class DPSU_H_QBR_DESC : DPA_W_PH_DESC_BASE<"dpsu.h.qbr", MipsDPSU_H_QBR>; - -class DPAQ_S_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpaq_s.w.ph", MipsDPAQ_S_W_PH>, - Defs<[DSPOutFlag16_19]>; - -class DPSQ_S_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpsq_s.w.ph", MipsDPSQ_S_W_PH>, - Defs<[DSPOutFlag16_19]>; - -class DPAQ_SA_L_W_DESC : DPA_W_PH_DESC_BASE<"dpaq_sa.l.w", MipsDPAQ_SA_L_W>, - Defs<[DSPOutFlag16_19]>; - -class DPSQ_SA_L_W_DESC : DPA_W_PH_DESC_BASE<"dpsq_sa.l.w", MipsDPSQ_SA_L_W>, - Defs<[DSPOutFlag16_19]>; - -class MULT_DSP_DESC : MULT_DESC_BASE<"mult", MipsMult, NoItinerary>; -class MULTU_DSP_DESC : MULT_DESC_BASE<"multu", MipsMultu, NoItinerary>; -class MADD_DSP_DESC : MADD_DESC_BASE<"madd", MipsMAdd, NoItinerary>; -class MADDU_DSP_DESC : MADD_DESC_BASE<"maddu", MipsMAddu, NoItinerary>; -class MSUB_DSP_DESC : MADD_DESC_BASE<"msub", MipsMSub, NoItinerary>; -class MSUBU_DSP_DESC : MADD_DESC_BASE<"msubu", MipsMSubu, NoItinerary>; - -// Comparison -class CMPU_EQ_QB_DESC : CMP_EQ_QB_R2_DESC_BASE<"cmpu.eq.qb", - int_mips_cmpu_eq_qb, NoItinerary, - DSPROpnd>, - IsCommutable, Defs<[DSPCCond]>; - -class CMPU_LT_QB_DESC : CMP_EQ_QB_R2_DESC_BASE<"cmpu.lt.qb", - int_mips_cmpu_lt_qb, NoItinerary, - DSPROpnd>, Defs<[DSPCCond]>; - -class CMPU_LE_QB_DESC : CMP_EQ_QB_R2_DESC_BASE<"cmpu.le.qb", - int_mips_cmpu_le_qb, NoItinerary, - DSPROpnd>, Defs<[DSPCCond]>; - -class CMPGU_EQ_QB_DESC : CMP_EQ_QB_R3_DESC_BASE<"cmpgu.eq.qb", - int_mips_cmpgu_eq_qb, - NoItinerary, GPR32Opnd, DSPROpnd>, - IsCommutable; - -class CMPGU_LT_QB_DESC : CMP_EQ_QB_R3_DESC_BASE<"cmpgu.lt.qb", - int_mips_cmpgu_lt_qb, - NoItinerary, GPR32Opnd, DSPROpnd>; - -class CMPGU_LE_QB_DESC : CMP_EQ_QB_R3_DESC_BASE<"cmpgu.le.qb", - int_mips_cmpgu_le_qb, - NoItinerary, GPR32Opnd, DSPROpnd>; - -class CMP_EQ_PH_DESC : CMP_EQ_QB_R2_DESC_BASE<"cmp.eq.ph", int_mips_cmp_eq_ph, - NoItinerary, DSPROpnd>, - IsCommutable, Defs<[DSPCCond]>; - -class CMP_LT_PH_DESC : CMP_EQ_QB_R2_DESC_BASE<"cmp.lt.ph", int_mips_cmp_lt_ph, - NoItinerary, DSPROpnd>, - Defs<[DSPCCond]>; - -class CMP_LE_PH_DESC : CMP_EQ_QB_R2_DESC_BASE<"cmp.le.ph", int_mips_cmp_le_ph, - NoItinerary, DSPROpnd>, - Defs<[DSPCCond]>; - -// Misc -class BITREV_DESC : ABSQ_S_PH_R2_DESC_BASE<"bitrev", int_mips_bitrev, - NoItinerary, GPR32Opnd>; - -class PACKRL_PH_DESC : CMP_EQ_QB_R3_DESC_BASE<"packrl.ph", int_mips_packrl_ph, - NoItinerary, DSPROpnd, DSPROpnd>; - -class REPL_QB_DESC : REPL_DESC_BASE<"repl.qb", int_mips_repl_qb, uimm8, - immZExt8, NoItinerary, DSPROpnd>; - -class REPL_PH_DESC : REPL_DESC_BASE<"repl.ph", int_mips_repl_ph, simm10, - immSExt10, NoItinerary, DSPROpnd>; - -class REPLV_QB_DESC : ABSQ_S_PH_R2_DESC_BASE<"replv.qb", int_mips_repl_qb, - NoItinerary, DSPROpnd, GPR32Opnd>; - -class REPLV_PH_DESC : ABSQ_S_PH_R2_DESC_BASE<"replv.ph", int_mips_repl_ph, - NoItinerary, DSPROpnd, GPR32Opnd>; - -class PICK_QB_DESC : CMP_EQ_QB_R3_DESC_BASE<"pick.qb", int_mips_pick_qb, - NoItinerary, DSPROpnd, DSPROpnd>, - Uses<[DSPCCond]>; - -class PICK_PH_DESC : CMP_EQ_QB_R3_DESC_BASE<"pick.ph", int_mips_pick_ph, - NoItinerary, DSPROpnd, DSPROpnd>, - Uses<[DSPCCond]>; - -class LWX_DESC : LX_DESC_BASE<"lwx", int_mips_lwx, NoItinerary>; - -class LHX_DESC : LX_DESC_BASE<"lhx", int_mips_lhx, NoItinerary>; - -class LBUX_DESC : LX_DESC_BASE<"lbux", int_mips_lbux, NoItinerary>; - -class BPOSGE32_DESC : BPOSGE32_DESC_BASE<"bposge32", brtarget, NoItinerary>; - -// Extr -class EXTP_DESC : EXTR_W_TY1_R1_DESC_BASE<"extp", MipsEXTP, NoItinerary>, - Uses<[DSPPos]>, Defs<[DSPEFI]>; - -class EXTPV_DESC : EXTR_W_TY1_R2_DESC_BASE<"extpv", MipsEXTP, NoItinerary>, - Uses<[DSPPos]>, Defs<[DSPEFI]>; - -class EXTPDP_DESC : EXTR_W_TY1_R1_DESC_BASE<"extpdp", MipsEXTPDP, NoItinerary>, - Uses<[DSPPos]>, Defs<[DSPPos, DSPEFI]>; - -class EXTPDPV_DESC : EXTR_W_TY1_R2_DESC_BASE<"extpdpv", MipsEXTPDP, - NoItinerary>, - Uses<[DSPPos]>, Defs<[DSPPos, DSPEFI]>; - -class EXTR_W_DESC : EXTR_W_TY1_R1_DESC_BASE<"extr.w", MipsEXTR_W, NoItinerary>, - Defs<[DSPOutFlag23]>; - -class EXTRV_W_DESC : EXTR_W_TY1_R2_DESC_BASE<"extrv.w", MipsEXTR_W, - NoItinerary>, Defs<[DSPOutFlag23]>; - -class EXTR_R_W_DESC : EXTR_W_TY1_R1_DESC_BASE<"extr_r.w", MipsEXTR_R_W, - NoItinerary>, - Defs<[DSPOutFlag23]>; - -class EXTRV_R_W_DESC : EXTR_W_TY1_R2_DESC_BASE<"extrv_r.w", MipsEXTR_R_W, - NoItinerary>, - Defs<[DSPOutFlag23]>; - -class EXTR_RS_W_DESC : EXTR_W_TY1_R1_DESC_BASE<"extr_rs.w", MipsEXTR_RS_W, - NoItinerary>, - Defs<[DSPOutFlag23]>; - -class EXTRV_RS_W_DESC : EXTR_W_TY1_R2_DESC_BASE<"extrv_rs.w", MipsEXTR_RS_W, - NoItinerary>, - Defs<[DSPOutFlag23]>; - -class EXTR_S_H_DESC : EXTR_W_TY1_R1_DESC_BASE<"extr_s.h", MipsEXTR_S_H, - NoItinerary>, - Defs<[DSPOutFlag23]>; - -class EXTRV_S_H_DESC : EXTR_W_TY1_R2_DESC_BASE<"extrv_s.h", MipsEXTR_S_H, - NoItinerary>, - Defs<[DSPOutFlag23]>; - -class SHILO_DESC : SHILO_R1_DESC_BASE<"shilo", MipsSHILO>; - -class SHILOV_DESC : SHILO_R2_DESC_BASE<"shilov", MipsSHILO>; - -class MTHLIP_DESC : MTHLIP_DESC_BASE<"mthlip", MipsMTHLIP>, Defs<[DSPPos]>; - -class RDDSP_DESC : RDDSP_DESC_BASE<"rddsp", int_mips_rddsp, NoItinerary>; - -class WRDSP_DESC : WRDSP_DESC_BASE<"wrdsp", int_mips_wrdsp, NoItinerary>; - -class INSV_DESC : INSV_DESC_BASE<"insv", int_mips_insv, NoItinerary>, - Uses<[DSPPos, DSPSCount]>; - -//===----------------------------------------------------------------------===// -// MIPS DSP Rev 2 -// Addition/subtraction -class ADDU_PH_DESC : ADDU_QB_DESC_BASE<"addu.ph", int_mips_addu_ph, NoItinerary, - DSPROpnd, DSPROpnd>, IsCommutable, - Defs<[DSPOutFlag20]>; - -class ADDU_S_PH_DESC : ADDU_QB_DESC_BASE<"addu_s.ph", int_mips_addu_s_ph, - NoItinerary, DSPROpnd, DSPROpnd>, - IsCommutable, Defs<[DSPOutFlag20]>; - -class SUBU_PH_DESC : ADDU_QB_DESC_BASE<"subu.ph", int_mips_subu_ph, NoItinerary, - DSPROpnd, DSPROpnd>, - Defs<[DSPOutFlag20]>; - -class SUBU_S_PH_DESC : ADDU_QB_DESC_BASE<"subu_s.ph", int_mips_subu_s_ph, - NoItinerary, DSPROpnd, DSPROpnd>, - Defs<[DSPOutFlag20]>; - -class ADDUH_QB_DESC : ADDUH_QB_DESC_BASE<"adduh.qb", int_mips_adduh_qb, - NoItinerary, DSPROpnd>, IsCommutable; - -class ADDUH_R_QB_DESC : ADDUH_QB_DESC_BASE<"adduh_r.qb", int_mips_adduh_r_qb, - NoItinerary, DSPROpnd>, IsCommutable; - -class SUBUH_QB_DESC : ADDUH_QB_DESC_BASE<"subuh.qb", int_mips_subuh_qb, - NoItinerary, DSPROpnd>; - -class SUBUH_R_QB_DESC : ADDUH_QB_DESC_BASE<"subuh_r.qb", int_mips_subuh_r_qb, - NoItinerary, DSPROpnd>; - -class ADDQH_PH_DESC : ADDUH_QB_DESC_BASE<"addqh.ph", int_mips_addqh_ph, - NoItinerary, DSPROpnd>, IsCommutable; - -class ADDQH_R_PH_DESC : ADDUH_QB_DESC_BASE<"addqh_r.ph", int_mips_addqh_r_ph, - NoItinerary, DSPROpnd>, IsCommutable; - -class SUBQH_PH_DESC : ADDUH_QB_DESC_BASE<"subqh.ph", int_mips_subqh_ph, - NoItinerary, DSPROpnd>; - -class SUBQH_R_PH_DESC : ADDUH_QB_DESC_BASE<"subqh_r.ph", int_mips_subqh_r_ph, - NoItinerary, DSPROpnd>; - -class ADDQH_W_DESC : ADDUH_QB_DESC_BASE<"addqh.w", int_mips_addqh_w, - NoItinerary, GPR32Opnd>, IsCommutable; - -class ADDQH_R_W_DESC : ADDUH_QB_DESC_BASE<"addqh_r.w", int_mips_addqh_r_w, - NoItinerary, GPR32Opnd>, IsCommutable; - -class SUBQH_W_DESC : ADDUH_QB_DESC_BASE<"subqh.w", int_mips_subqh_w, - NoItinerary, GPR32Opnd>; - -class SUBQH_R_W_DESC : ADDUH_QB_DESC_BASE<"subqh_r.w", int_mips_subqh_r_w, - NoItinerary, GPR32Opnd>; - -// Comparison -class CMPGDU_EQ_QB_DESC : CMP_EQ_QB_R3_DESC_BASE<"cmpgdu.eq.qb", - int_mips_cmpgdu_eq_qb, - NoItinerary, GPR32Opnd, DSPROpnd>, - IsCommutable, Defs<[DSPCCond]>; - -class CMPGDU_LT_QB_DESC : CMP_EQ_QB_R3_DESC_BASE<"cmpgdu.lt.qb", - int_mips_cmpgdu_lt_qb, - NoItinerary, GPR32Opnd, DSPROpnd>, - Defs<[DSPCCond]>; - -class CMPGDU_LE_QB_DESC : CMP_EQ_QB_R3_DESC_BASE<"cmpgdu.le.qb", - int_mips_cmpgdu_le_qb, - NoItinerary, GPR32Opnd, DSPROpnd>, - Defs<[DSPCCond]>; - -// Absolute -class ABSQ_S_QB_DESC : ABSQ_S_PH_R2_DESC_BASE<"absq_s.qb", int_mips_absq_s_qb, - NoItinerary, DSPROpnd>, - Defs<[DSPOutFlag20]>; - -// Multiplication -class MUL_PH_DESC : ADDUH_QB_DESC_BASE<"mul.ph", null_frag, NoItinerary, - DSPROpnd>, IsCommutable, - Defs<[DSPOutFlag21]>; - -class MUL_S_PH_DESC : ADDUH_QB_DESC_BASE<"mul_s.ph", int_mips_mul_s_ph, - NoItinerary, DSPROpnd>, IsCommutable, - Defs<[DSPOutFlag21]>; - -class MULQ_S_W_DESC : ADDUH_QB_DESC_BASE<"mulq_s.w", int_mips_mulq_s_w, - NoItinerary, GPR32Opnd>, IsCommutable, - Defs<[DSPOutFlag21]>; - -class MULQ_RS_W_DESC : ADDUH_QB_DESC_BASE<"mulq_rs.w", int_mips_mulq_rs_w, - NoItinerary, GPR32Opnd>, IsCommutable, - Defs<[DSPOutFlag21]>; - -class MULQ_S_PH_DESC : ADDU_QB_DESC_BASE<"mulq_s.ph", int_mips_mulq_s_ph, - NoItinerary, DSPROpnd, DSPROpnd>, - IsCommutable, Defs<[DSPOutFlag21]>; - -// Dot product with accumulate/subtract -class DPA_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpa.w.ph", MipsDPA_W_PH>; - -class DPS_W_PH_DESC : DPA_W_PH_DESC_BASE<"dps.w.ph", MipsDPS_W_PH>; - -class DPAQX_S_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpaqx_s.w.ph", MipsDPAQX_S_W_PH>, - Defs<[DSPOutFlag16_19]>; - -class DPAQX_SA_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpaqx_sa.w.ph", - MipsDPAQX_SA_W_PH>, - Defs<[DSPOutFlag16_19]>; - -class DPAX_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpax.w.ph", MipsDPAX_W_PH>; - -class DPSX_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpsx.w.ph", MipsDPSX_W_PH>; - -class DPSQX_S_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpsqx_s.w.ph", MipsDPSQX_S_W_PH>, - Defs<[DSPOutFlag16_19]>; - -class DPSQX_SA_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpsqx_sa.w.ph", - MipsDPSQX_SA_W_PH>, - Defs<[DSPOutFlag16_19]>; - -class MULSA_W_PH_DESC : DPA_W_PH_DESC_BASE<"mulsa.w.ph", MipsMULSA_W_PH>; - -// Precision reduce/expand -class PRECR_QB_PH_DESC : CMP_EQ_QB_R3_DESC_BASE<"precr.qb.ph", - int_mips_precr_qb_ph, - NoItinerary, DSPROpnd, DSPROpnd>; - -class PRECR_SRA_PH_W_DESC : PRECR_SRA_PH_W_DESC_BASE<"precr_sra.ph.w", - int_mips_precr_sra_ph_w, - NoItinerary, DSPROpnd, - GPR32Opnd>; - -class PRECR_SRA_R_PH_W_DESC : PRECR_SRA_PH_W_DESC_BASE<"precr_sra_r.ph.w", - int_mips_precr_sra_r_ph_w, - NoItinerary, DSPROpnd, - GPR32Opnd>; - -// Shift -class SHRA_QB_DESC : SHLL_QB_R2_DESC_BASE<"shra.qb", null_frag, immZExt3, - NoItinerary, DSPROpnd, uimm3>; - -class SHRAV_QB_DESC : SHLL_QB_R3_DESC_BASE<"shrav.qb", int_mips_shra_qb, - NoItinerary, DSPROpnd>; - -class SHRA_R_QB_DESC : SHLL_QB_R2_DESC_BASE<"shra_r.qb", int_mips_shra_r_qb, - immZExt3, NoItinerary, DSPROpnd, - uimm3>; - -class SHRAV_R_QB_DESC : SHLL_QB_R3_DESC_BASE<"shrav_r.qb", int_mips_shra_r_qb, - NoItinerary, DSPROpnd>; - -class SHRL_PH_DESC : SHLL_QB_R2_DESC_BASE<"shrl.ph", null_frag, immZExt4, - NoItinerary, DSPROpnd, uimm4>; - -class SHRLV_PH_DESC : SHLL_QB_R3_DESC_BASE<"shrlv.ph", int_mips_shrl_ph, - NoItinerary, DSPROpnd>; - -// Misc -class APPEND_DESC : APPEND_DESC_BASE<"append", int_mips_append, uimm5, immZExt5, - NoItinerary>; - -class BALIGN_DESC : APPEND_DESC_BASE<"balign", int_mips_balign, uimm2, immZExt2, - NoItinerary>; - -class PREPEND_DESC : APPEND_DESC_BASE<"prepend", int_mips_prepend, uimm5, - immZExt5, NoItinerary>; - -// Pseudos. -def BPOSGE32_PSEUDO : BPOSGE32_PSEUDO_DESC_BASE<int_mips_bposge32, - NoItinerary>, Uses<[DSPPos]>; - -// Instruction defs. -// MIPS DSP Rev 1 -def ADDU_QB : DspMMRel, ADDU_QB_ENC, ADDU_QB_DESC; -def ADDU_S_QB : DspMMRel, ADDU_S_QB_ENC, ADDU_S_QB_DESC; -def SUBU_QB : DspMMRel, SUBU_QB_ENC, SUBU_QB_DESC; -def SUBU_S_QB : DspMMRel, SUBU_S_QB_ENC, SUBU_S_QB_DESC; -def ADDQ_PH : DspMMRel, ADDQ_PH_ENC, ADDQ_PH_DESC; -def ADDQ_S_PH : DspMMRel, ADDQ_S_PH_ENC, ADDQ_S_PH_DESC; -def SUBQ_PH : DspMMRel, SUBQ_PH_ENC, SUBQ_PH_DESC; -def SUBQ_S_PH : DspMMRel, SUBQ_S_PH_ENC, SUBQ_S_PH_DESC; -def ADDQ_S_W : DspMMRel, ADDQ_S_W_ENC, ADDQ_S_W_DESC; -def SUBQ_S_W : DspMMRel, SUBQ_S_W_ENC, SUBQ_S_W_DESC; -def ADDSC : DspMMRel, ADDSC_ENC, ADDSC_DESC; -def ADDWC : DspMMRel, ADDWC_ENC, ADDWC_DESC; -def MODSUB : DspMMRel, MODSUB_ENC, MODSUB_DESC; -def RADDU_W_QB : DspMMRel, RADDU_W_QB_ENC, RADDU_W_QB_DESC; -def ABSQ_S_PH : DspMMRel, ABSQ_S_PH_ENC, ABSQ_S_PH_DESC; -def ABSQ_S_W : DspMMRel, ABSQ_S_W_ENC, ABSQ_S_W_DESC; -def PRECRQ_QB_PH : DspMMRel, PRECRQ_QB_PH_ENC, PRECRQ_QB_PH_DESC; -def PRECRQ_PH_W : DspMMRel, PRECRQ_PH_W_ENC, PRECRQ_PH_W_DESC; -def PRECRQ_RS_PH_W : DspMMRel, PRECRQ_RS_PH_W_ENC, PRECRQ_RS_PH_W_DESC; -def PRECRQU_S_QB_PH : DspMMRel, PRECRQU_S_QB_PH_ENC, PRECRQU_S_QB_PH_DESC; -def PRECEQ_W_PHL : DspMMRel, PRECEQ_W_PHL_ENC, PRECEQ_W_PHL_DESC; -def PRECEQ_W_PHR : DspMMRel, PRECEQ_W_PHR_ENC, PRECEQ_W_PHR_DESC; -def PRECEQU_PH_QBL : DspMMRel, PRECEQU_PH_QBL_ENC, PRECEQU_PH_QBL_DESC; -def PRECEQU_PH_QBR : DspMMRel, PRECEQU_PH_QBR_ENC, PRECEQU_PH_QBR_DESC; -def PRECEQU_PH_QBLA : DspMMRel, PRECEQU_PH_QBLA_ENC, PRECEQU_PH_QBLA_DESC; -def PRECEQU_PH_QBRA : DspMMRel, PRECEQU_PH_QBRA_ENC, PRECEQU_PH_QBRA_DESC; -def PRECEU_PH_QBL : DspMMRel, PRECEU_PH_QBL_ENC, PRECEU_PH_QBL_DESC; -def PRECEU_PH_QBR : DspMMRel, PRECEU_PH_QBR_ENC, PRECEU_PH_QBR_DESC; -def PRECEU_PH_QBLA : DspMMRel, PRECEU_PH_QBLA_ENC, PRECEU_PH_QBLA_DESC; -def PRECEU_PH_QBRA : DspMMRel, PRECEU_PH_QBRA_ENC, PRECEU_PH_QBRA_DESC; -def SHLL_QB : DspMMRel, SHLL_QB_ENC, SHLL_QB_DESC; -def SHLLV_QB : DspMMRel, SHLLV_QB_ENC, SHLLV_QB_DESC; -def SHRL_QB : DspMMRel, SHRL_QB_ENC, SHRL_QB_DESC; -def SHRLV_QB : DspMMRel, SHRLV_QB_ENC, SHRLV_QB_DESC; -def SHLL_PH : DspMMRel, SHLL_PH_ENC, SHLL_PH_DESC; -def SHLLV_PH : DspMMRel, SHLLV_PH_ENC, SHLLV_PH_DESC; -def SHLL_S_PH : DspMMRel, SHLL_S_PH_ENC, SHLL_S_PH_DESC; -def SHLLV_S_PH : DspMMRel, SHLLV_S_PH_ENC, SHLLV_S_PH_DESC; -def SHRA_PH : DspMMRel, SHRA_PH_ENC, SHRA_PH_DESC; -def SHRAV_PH : DspMMRel, SHRAV_PH_ENC, SHRAV_PH_DESC; -def SHRA_R_PH : DspMMRel, SHRA_R_PH_ENC, SHRA_R_PH_DESC; -def SHRAV_R_PH : DspMMRel, SHRAV_R_PH_ENC, SHRAV_R_PH_DESC; -def SHLL_S_W : DspMMRel, SHLL_S_W_ENC, SHLL_S_W_DESC; -def SHLLV_S_W : DspMMRel, SHLLV_S_W_ENC, SHLLV_S_W_DESC; -def SHRA_R_W : DspMMRel, SHRA_R_W_ENC, SHRA_R_W_DESC; -def SHRAV_R_W : DspMMRel, SHRAV_R_W_ENC, SHRAV_R_W_DESC; -def MULEU_S_PH_QBL : DspMMRel, MULEU_S_PH_QBL_ENC, MULEU_S_PH_QBL_DESC; -def MULEU_S_PH_QBR : DspMMRel, MULEU_S_PH_QBR_ENC, MULEU_S_PH_QBR_DESC; -def MULEQ_S_W_PHL : DspMMRel, MULEQ_S_W_PHL_ENC, MULEQ_S_W_PHL_DESC; -def MULEQ_S_W_PHR : DspMMRel, MULEQ_S_W_PHR_ENC, MULEQ_S_W_PHR_DESC; -def MULQ_RS_PH : DspMMRel, MULQ_RS_PH_ENC, MULQ_RS_PH_DESC; -def MULSAQ_S_W_PH : DspMMRel, MULSAQ_S_W_PH_ENC, MULSAQ_S_W_PH_DESC; -def MAQ_S_W_PHL : DspMMRel, MAQ_S_W_PHL_ENC, MAQ_S_W_PHL_DESC; -def MAQ_S_W_PHR : DspMMRel, MAQ_S_W_PHR_ENC, MAQ_S_W_PHR_DESC; -def MAQ_SA_W_PHL : DspMMRel, MAQ_SA_W_PHL_ENC, MAQ_SA_W_PHL_DESC; -def MAQ_SA_W_PHR : DspMMRel, MAQ_SA_W_PHR_ENC, MAQ_SA_W_PHR_DESC; -def MFHI_DSP : DspMMRel, MFHI_ENC, MFHI_DESC; -def MFLO_DSP : DspMMRel, MFLO_ENC, MFLO_DESC; -def MTHI_DSP : DspMMRel, MTHI_ENC, MTHI_DESC; -def MTLO_DSP : DspMMRel, MTLO_ENC, MTLO_DESC; -def DPAU_H_QBL : DspMMRel, DPAU_H_QBL_ENC, DPAU_H_QBL_DESC; -def DPAU_H_QBR : DspMMRel, DPAU_H_QBR_ENC, DPAU_H_QBR_DESC; -def DPSU_H_QBL : DspMMRel, DPSU_H_QBL_ENC, DPSU_H_QBL_DESC; -def DPSU_H_QBR : DspMMRel, DPSU_H_QBR_ENC, DPSU_H_QBR_DESC; -def DPAQ_S_W_PH : DspMMRel, DPAQ_S_W_PH_ENC, DPAQ_S_W_PH_DESC; -def DPSQ_S_W_PH : DspMMRel, DPSQ_S_W_PH_ENC, DPSQ_S_W_PH_DESC; -def DPAQ_SA_L_W : DspMMRel, DPAQ_SA_L_W_ENC, DPAQ_SA_L_W_DESC; -def DPSQ_SA_L_W : DspMMRel, DPSQ_SA_L_W_ENC, DPSQ_SA_L_W_DESC; -def MULT_DSP : DspMMRel, MULT_DSP_ENC, MULT_DSP_DESC; -def MULTU_DSP : DspMMRel, MULTU_DSP_ENC, MULTU_DSP_DESC; -def MADD_DSP : DspMMRel, MADD_DSP_ENC, MADD_DSP_DESC; -def MADDU_DSP : DspMMRel, MADDU_DSP_ENC, MADDU_DSP_DESC; -def MSUB_DSP : DspMMRel, MSUB_DSP_ENC, MSUB_DSP_DESC; -def MSUBU_DSP : DspMMRel, MSUBU_DSP_ENC, MSUBU_DSP_DESC; -def CMPU_EQ_QB : DspMMRel, CMPU_EQ_QB_ENC, CMPU_EQ_QB_DESC; -def CMPU_LT_QB : DspMMRel, CMPU_LT_QB_ENC, CMPU_LT_QB_DESC; -def CMPU_LE_QB : DspMMRel, CMPU_LE_QB_ENC, CMPU_LE_QB_DESC; -def CMPGU_EQ_QB : DspMMRel, CMPGU_EQ_QB_ENC, CMPGU_EQ_QB_DESC; -def CMPGU_LT_QB : DspMMRel, CMPGU_LT_QB_ENC, CMPGU_LT_QB_DESC; -def CMPGU_LE_QB : DspMMRel, CMPGU_LE_QB_ENC, CMPGU_LE_QB_DESC; -def CMP_EQ_PH : DspMMRel, CMP_EQ_PH_ENC, CMP_EQ_PH_DESC; -def CMP_LT_PH : DspMMRel, CMP_LT_PH_ENC, CMP_LT_PH_DESC; -def CMP_LE_PH : DspMMRel, CMP_LE_PH_ENC, CMP_LE_PH_DESC; -def BITREV : DspMMRel, BITREV_ENC, BITREV_DESC; -def PACKRL_PH : DspMMRel, PACKRL_PH_ENC, PACKRL_PH_DESC; -def REPL_QB : DspMMRel, REPL_QB_ENC, REPL_QB_DESC; -def REPL_PH : DspMMRel, REPL_PH_ENC, REPL_PH_DESC; -def REPLV_QB : DspMMRel, REPLV_QB_ENC, REPLV_QB_DESC; -def REPLV_PH : DspMMRel, REPLV_PH_ENC, REPLV_PH_DESC; -def PICK_QB : DspMMRel, PICK_QB_ENC, PICK_QB_DESC; -def PICK_PH : DspMMRel, PICK_PH_ENC, PICK_PH_DESC; -def LWX : DspMMRel, LWX_ENC, LWX_DESC; -def LHX : DspMMRel, LHX_ENC, LHX_DESC; -def LBUX : DspMMRel, LBUX_ENC, LBUX_DESC; -let AdditionalPredicates = [NotInMicroMips] in { - def BPOSGE32 : DspMMRel, BPOSGE32_ENC, BPOSGE32_DESC; -} -def INSV : DspMMRel, INSV_ENC, INSV_DESC; -def EXTP : DspMMRel, EXTP_ENC, EXTP_DESC; -def EXTPV : DspMMRel, EXTPV_ENC, EXTPV_DESC; -def EXTPDP : DspMMRel, EXTPDP_ENC, EXTPDP_DESC; -def EXTPDPV : DspMMRel, EXTPDPV_ENC, EXTPDPV_DESC; -def EXTR_W : DspMMRel, EXTR_W_ENC, EXTR_W_DESC; -def EXTRV_W : DspMMRel, EXTRV_W_ENC, EXTRV_W_DESC; -def EXTR_R_W : DspMMRel, EXTR_R_W_ENC, EXTR_R_W_DESC; -def EXTRV_R_W : DspMMRel, EXTRV_R_W_ENC, EXTRV_R_W_DESC; -def EXTR_RS_W : DspMMRel, EXTR_RS_W_ENC, EXTR_RS_W_DESC; -def EXTRV_RS_W : DspMMRel, EXTRV_RS_W_ENC, EXTRV_RS_W_DESC; -def EXTR_S_H : DspMMRel, EXTR_S_H_ENC, EXTR_S_H_DESC; -def EXTRV_S_H : DspMMRel, EXTRV_S_H_ENC, EXTRV_S_H_DESC; -def SHILO : DspMMRel, SHILO_ENC, SHILO_DESC; -def SHILOV : DspMMRel, SHILOV_ENC, SHILOV_DESC; -def MTHLIP : DspMMRel, MTHLIP_ENC, MTHLIP_DESC; -def RDDSP : DspMMRel, RDDSP_ENC, RDDSP_DESC; -let AdditionalPredicates = [NotInMicroMips] in { - def WRDSP : WRDSP_ENC, WRDSP_DESC; -} - -// MIPS DSP Rev 2 -def ADDU_PH : DspMMRel, ADDU_PH_ENC, ADDU_PH_DESC, ISA_DSPR2; -def ADDU_S_PH : DspMMRel, ADDU_S_PH_ENC, ADDU_S_PH_DESC, ISA_DSPR2; -def SUBU_PH : DspMMRel, SUBU_PH_ENC, SUBU_PH_DESC, ISA_DSPR2; -def SUBU_S_PH : DspMMRel, SUBU_S_PH_ENC, SUBU_S_PH_DESC, ISA_DSPR2; -def CMPGDU_EQ_QB : DspMMRel, CMPGDU_EQ_QB_ENC, CMPGDU_EQ_QB_DESC, ISA_DSPR2; -def CMPGDU_LT_QB : DspMMRel, CMPGDU_LT_QB_ENC, CMPGDU_LT_QB_DESC, ISA_DSPR2; -def CMPGDU_LE_QB : DspMMRel, CMPGDU_LE_QB_ENC, CMPGDU_LE_QB_DESC, ISA_DSPR2; -def ABSQ_S_QB : DspMMRel, ABSQ_S_QB_ENC, ABSQ_S_QB_DESC, ISA_DSPR2; -def ADDUH_QB : DspMMRel, ADDUH_QB_ENC, ADDUH_QB_DESC, ISA_DSPR2; -def ADDUH_R_QB : DspMMRel, ADDUH_R_QB_ENC, ADDUH_R_QB_DESC, ISA_DSPR2; -def SUBUH_QB : DspMMRel, SUBUH_QB_ENC, SUBUH_QB_DESC, ISA_DSPR2; -def SUBUH_R_QB : DspMMRel, SUBUH_R_QB_ENC, SUBUH_R_QB_DESC, ISA_DSPR2; -def ADDQH_PH : DspMMRel, ADDQH_PH_ENC, ADDQH_PH_DESC, ISA_DSPR2; -def ADDQH_R_PH : DspMMRel, ADDQH_R_PH_ENC, ADDQH_R_PH_DESC, ISA_DSPR2; -def SUBQH_PH : DspMMRel, SUBQH_PH_ENC, SUBQH_PH_DESC, ISA_DSPR2; -def SUBQH_R_PH : DspMMRel, SUBQH_R_PH_ENC, SUBQH_R_PH_DESC, ISA_DSPR2; -def ADDQH_W : DspMMRel, ADDQH_W_ENC, ADDQH_W_DESC, ISA_DSPR2; -def ADDQH_R_W : DspMMRel, ADDQH_R_W_ENC, ADDQH_R_W_DESC, ISA_DSPR2; -def SUBQH_W : DspMMRel, SUBQH_W_ENC, SUBQH_W_DESC, ISA_DSPR2; -def SUBQH_R_W : DspMMRel, SUBQH_R_W_ENC, SUBQH_R_W_DESC, ISA_DSPR2; -def MUL_PH : DspMMRel, MUL_PH_ENC, MUL_PH_DESC, ISA_DSPR2; -def MUL_S_PH : DspMMRel, MUL_S_PH_ENC, MUL_S_PH_DESC, ISA_DSPR2; -def MULQ_S_W : DspMMRel, MULQ_S_W_ENC, MULQ_S_W_DESC, ISA_DSPR2; -def MULQ_RS_W : DspMMRel, MULQ_RS_W_ENC, MULQ_RS_W_DESC, ISA_DSPR2; -def MULQ_S_PH : DspMMRel, MULQ_S_PH_ENC, MULQ_S_PH_DESC, ISA_DSPR2; -def DPA_W_PH : DspMMRel, DPA_W_PH_ENC, DPA_W_PH_DESC, ISA_DSPR2; -def DPS_W_PH : DspMMRel, DPS_W_PH_ENC, DPS_W_PH_DESC, ISA_DSPR2; -def DPAQX_S_W_PH : DspMMRel, DPAQX_S_W_PH_ENC, DPAQX_S_W_PH_DESC, ISA_DSPR2; -def DPAQX_SA_W_PH : DspMMRel, DPAQX_SA_W_PH_ENC, DPAQX_SA_W_PH_DESC, ISA_DSPR2; -def DPAX_W_PH : DspMMRel, DPAX_W_PH_ENC, DPAX_W_PH_DESC, ISA_DSPR2; -def DPSX_W_PH : DspMMRel, DPSX_W_PH_ENC, DPSX_W_PH_DESC, ISA_DSPR2; -def DPSQX_S_W_PH : DspMMRel, DPSQX_S_W_PH_ENC, DPSQX_S_W_PH_DESC, ISA_DSPR2; -def DPSQX_SA_W_PH : DspMMRel, DPSQX_SA_W_PH_ENC, DPSQX_SA_W_PH_DESC, ISA_DSPR2; -def MULSA_W_PH : DspMMRel, MULSA_W_PH_ENC, MULSA_W_PH_DESC, ISA_DSPR2; -def PRECR_QB_PH : DspMMRel, PRECR_QB_PH_ENC, PRECR_QB_PH_DESC, ISA_DSPR2; -def PRECR_SRA_PH_W : DspMMRel, PRECR_SRA_PH_W_ENC, PRECR_SRA_PH_W_DESC, ISA_DSPR2; -def PRECR_SRA_R_PH_W : DspMMRel, PRECR_SRA_R_PH_W_ENC, PRECR_SRA_R_PH_W_DESC, ISA_DSPR2; -def SHRA_QB : DspMMRel, SHRA_QB_ENC, SHRA_QB_DESC, ISA_DSPR2; -def SHRAV_QB : DspMMRel, SHRAV_QB_ENC, SHRAV_QB_DESC, ISA_DSPR2; -def SHRA_R_QB : DspMMRel, SHRA_R_QB_ENC, SHRA_R_QB_DESC, ISA_DSPR2; -def SHRAV_R_QB : DspMMRel, SHRAV_R_QB_ENC, SHRAV_R_QB_DESC, ISA_DSPR2; -def SHRL_PH : DspMMRel, SHRL_PH_ENC, SHRL_PH_DESC, ISA_DSPR2; -def SHRLV_PH : DspMMRel, SHRLV_PH_ENC, SHRLV_PH_DESC, ISA_DSPR2; -def APPEND : DspMMRel, APPEND_ENC, APPEND_DESC, ISA_DSPR2; -def BALIGN : DspMMRel, BALIGN_ENC, BALIGN_DESC, ISA_DSPR2; -def PREPEND : DspMMRel, PREPEND_ENC, PREPEND_DESC, ISA_DSPR2; - -// Pseudos. -let isPseudo = 1, isCodeGenOnly = 1, hasNoSchedulingInfo = 1 in { - // Pseudo instructions for loading and storing accumulator registers. - def LOAD_ACC64DSP : Load<"", ACC64DSPOpnd>; - def STORE_ACC64DSP : Store<"", ACC64DSPOpnd>; - - // Pseudos for loading and storing ccond field of DSP control register. - def LOAD_CCOND_DSP : Load<"load_ccond_dsp", DSPCC>; - def STORE_CCOND_DSP : Store<"store_ccond_dsp", DSPCC>; -} - -let DecoderNamespace = "MipsDSP", Arch = "dsp", - ASEPredicate = [HasDSP] in { - def LWDSP : Load<"lw", DSPROpnd, null_frag, II_LW>, DspMMRel, LW_FM<0x23>; - def SWDSP : Store<"sw", DSPROpnd, null_frag, II_SW>, DspMMRel, LW_FM<0x2b>; -} - -// Pseudo CMP and PICK instructions. -class PseudoCMP<Instruction RealInst> : - PseudoDSP<(outs DSPCC:$cmp), (ins DSPROpnd:$rs, DSPROpnd:$rt), []>, - PseudoInstExpansion<(RealInst DSPROpnd:$rs, DSPROpnd:$rt)>, NeverHasSideEffects; - -class PseudoPICK<Instruction RealInst> : - PseudoDSP<(outs DSPROpnd:$rd), (ins DSPCC:$cmp, DSPROpnd:$rs, DSPROpnd:$rt), []>, - PseudoInstExpansion<(RealInst DSPROpnd:$rd, DSPROpnd:$rs, DSPROpnd:$rt)>, - NeverHasSideEffects; - -def PseudoCMP_EQ_PH : PseudoCMP<CMP_EQ_PH>; -def PseudoCMP_LT_PH : PseudoCMP<CMP_LT_PH>; -def PseudoCMP_LE_PH : PseudoCMP<CMP_LE_PH>; -def PseudoCMPU_EQ_QB : PseudoCMP<CMPU_EQ_QB>; -def PseudoCMPU_LT_QB : PseudoCMP<CMPU_LT_QB>; -def PseudoCMPU_LE_QB : PseudoCMP<CMPU_LE_QB>; - -def PseudoPICK_PH : PseudoPICK<PICK_PH>; -def PseudoPICK_QB : PseudoPICK<PICK_QB>; - -let AdditionalPredicates = [HasDSP] in { - def PseudoMTLOHI_DSP : PseudoMTLOHI<ACC64DSP, GPR32>; -} - -// Patterns. -class DSPPat<dag pattern, dag result, Predicate pred = HasDSP> : - Pat<pattern, result>, Requires<[pred]>; - -class BitconvertPat<ValueType DstVT, ValueType SrcVT, RegisterClass DstRC, - RegisterClass SrcRC> : - DSPPat<(DstVT (bitconvert (SrcVT SrcRC:$src))), - (COPY_TO_REGCLASS SrcRC:$src, DstRC)>; - -def : BitconvertPat<i32, v2i16, GPR32, DSPR>; -def : BitconvertPat<i32, v4i8, GPR32, DSPR>; -def : BitconvertPat<v2i16, i32, DSPR, GPR32>; -def : BitconvertPat<v4i8, i32, DSPR, GPR32>; -def : BitconvertPat<f32, v2i16, FGR32, DSPR>; -def : BitconvertPat<f32, v4i8, FGR32, DSPR>; -def : BitconvertPat<v2i16, f32, DSPR, FGR32>; -def : BitconvertPat<v4i8, f32, DSPR, FGR32>; - -def : DSPPat<(v2i16 (load addr:$a)), - (v2i16 (COPY_TO_REGCLASS (LW addr:$a), DSPR))>; -def : DSPPat<(v4i8 (load addr:$a)), - (v4i8 (COPY_TO_REGCLASS (LW addr:$a), DSPR))>; -def : DSPPat<(store (v2i16 DSPR:$val), addr:$a), - (SW (COPY_TO_REGCLASS DSPR:$val, GPR32), addr:$a)>; -def : DSPPat<(store (v4i8 DSPR:$val), addr:$a), - (SW (COPY_TO_REGCLASS DSPR:$val, GPR32), addr:$a)>; - -// Binary operations. -class DSPBinPat<Instruction Inst, ValueType ValTy, SDPatternOperator Node, - Predicate Pred = HasDSP> : - DSPPat<(Node ValTy:$a, ValTy:$b), (Inst ValTy:$a, ValTy:$b), Pred>; - -def : DSPBinPat<ADDQ_PH, v2i16, int_mips_addq_ph>; -def : DSPBinPat<ADDQ_PH, v2i16, add>; -def : DSPBinPat<SUBQ_PH, v2i16, int_mips_subq_ph>; -def : DSPBinPat<SUBQ_PH, v2i16, sub>; -def : DSPBinPat<MUL_PH, v2i16, int_mips_mul_ph, HasDSPR2>; -def : DSPBinPat<MUL_PH, v2i16, mul, HasDSPR2>; -def : DSPBinPat<ADDU_QB, v4i8, int_mips_addu_qb>; -def : DSPBinPat<ADDU_QB, v4i8, add>; -def : DSPBinPat<SUBU_QB, v4i8, int_mips_subu_qb>; -def : DSPBinPat<SUBU_QB, v4i8, sub>; -def : DSPBinPat<ADDSC, i32, int_mips_addsc>; -def : DSPBinPat<ADDSC, i32, addc>; -def : DSPBinPat<ADDWC, i32, int_mips_addwc>; -def : DSPBinPat<ADDWC, i32, adde>; - -// Shift immediate patterns. -class DSPShiftPat<Instruction Inst, ValueType ValTy, SDPatternOperator Node, - SDPatternOperator Imm, Predicate Pred = HasDSP> : - DSPPat<(Node ValTy:$a, Imm:$shamt), (Inst ValTy:$a, Imm:$shamt), Pred>; - -def : DSPShiftPat<SHLL_PH, v2i16, MipsSHLL_DSP, imm>; -def : DSPShiftPat<SHRA_PH, v2i16, MipsSHRA_DSP, imm>; -def : DSPShiftPat<SHRL_PH, v2i16, MipsSHRL_DSP, imm, HasDSPR2>; -def : DSPShiftPat<SHLL_PH, v2i16, int_mips_shll_ph, immZExt4>; -def : DSPShiftPat<SHRA_PH, v2i16, int_mips_shra_ph, immZExt4>; -def : DSPShiftPat<SHRL_PH, v2i16, int_mips_shrl_ph, immZExt4, HasDSPR2>; -def : DSPShiftPat<SHLL_QB, v4i8, MipsSHLL_DSP, imm>; -def : DSPShiftPat<SHRA_QB, v4i8, MipsSHRA_DSP, imm, HasDSPR2>; -def : DSPShiftPat<SHRL_QB, v4i8, MipsSHRL_DSP, imm>; -def : DSPShiftPat<SHLL_QB, v4i8, int_mips_shll_qb, immZExt3>; -def : DSPShiftPat<SHRA_QB, v4i8, int_mips_shra_qb, immZExt3, HasDSPR2>; -def : DSPShiftPat<SHRL_QB, v4i8, int_mips_shrl_qb, immZExt3>; - -// SETCC/SELECT_CC patterns. -class DSPSetCCPat<Instruction Cmp, Instruction Pick, ValueType ValTy, - CondCode CC> : - DSPPat<(ValTy (MipsSETCC_DSP ValTy:$a, ValTy:$b, CC)), - (ValTy (Pick (ValTy (Cmp ValTy:$a, ValTy:$b)), - (ValTy (COPY_TO_REGCLASS (ADDiu ZERO, -1), DSPR)), - (ValTy ZERO)))>; - -class DSPSetCCPatInv<Instruction Cmp, Instruction Pick, ValueType ValTy, - CondCode CC> : - DSPPat<(ValTy (MipsSETCC_DSP ValTy:$a, ValTy:$b, CC)), - (ValTy (Pick (ValTy (Cmp ValTy:$a, ValTy:$b)), - (ValTy ZERO), - (ValTy (COPY_TO_REGCLASS (ADDiu ZERO, -1), DSPR))))>; - -class DSPSelectCCPat<Instruction Cmp, Instruction Pick, ValueType ValTy, - CondCode CC> : - DSPPat<(ValTy (MipsSELECT_CC_DSP ValTy:$a, ValTy:$b, ValTy:$c, ValTy:$d, CC)), - (ValTy (Pick (ValTy (Cmp ValTy:$a, ValTy:$b)), $c, $d))>; - -class DSPSelectCCPatInv<Instruction Cmp, Instruction Pick, ValueType ValTy, - CondCode CC> : - DSPPat<(ValTy (MipsSELECT_CC_DSP ValTy:$a, ValTy:$b, ValTy:$c, ValTy:$d, CC)), - (ValTy (Pick (ValTy (Cmp ValTy:$a, ValTy:$b)), $d, $c))>; - -def : DSPSetCCPat<PseudoCMP_EQ_PH, PseudoPICK_PH, v2i16, SETEQ>; -def : DSPSetCCPat<PseudoCMP_LT_PH, PseudoPICK_PH, v2i16, SETLT>; -def : DSPSetCCPat<PseudoCMP_LE_PH, PseudoPICK_PH, v2i16, SETLE>; -def : DSPSetCCPatInv<PseudoCMP_EQ_PH, PseudoPICK_PH, v2i16, SETNE>; -def : DSPSetCCPatInv<PseudoCMP_LT_PH, PseudoPICK_PH, v2i16, SETGE>; -def : DSPSetCCPatInv<PseudoCMP_LE_PH, PseudoPICK_PH, v2i16, SETGT>; -def : DSPSetCCPat<PseudoCMPU_EQ_QB, PseudoPICK_QB, v4i8, SETEQ>; -def : DSPSetCCPat<PseudoCMPU_LT_QB, PseudoPICK_QB, v4i8, SETULT>; -def : DSPSetCCPat<PseudoCMPU_LE_QB, PseudoPICK_QB, v4i8, SETULE>; -def : DSPSetCCPatInv<PseudoCMPU_EQ_QB, PseudoPICK_QB, v4i8, SETNE>; -def : DSPSetCCPatInv<PseudoCMPU_LT_QB, PseudoPICK_QB, v4i8, SETUGE>; -def : DSPSetCCPatInv<PseudoCMPU_LE_QB, PseudoPICK_QB, v4i8, SETUGT>; - -def : DSPSelectCCPat<PseudoCMP_EQ_PH, PseudoPICK_PH, v2i16, SETEQ>; -def : DSPSelectCCPat<PseudoCMP_LT_PH, PseudoPICK_PH, v2i16, SETLT>; -def : DSPSelectCCPat<PseudoCMP_LE_PH, PseudoPICK_PH, v2i16, SETLE>; -def : DSPSelectCCPatInv<PseudoCMP_EQ_PH, PseudoPICK_PH, v2i16, SETNE>; -def : DSPSelectCCPatInv<PseudoCMP_LT_PH, PseudoPICK_PH, v2i16, SETGE>; -def : DSPSelectCCPatInv<PseudoCMP_LE_PH, PseudoPICK_PH, v2i16, SETGT>; -def : DSPSelectCCPat<PseudoCMPU_EQ_QB, PseudoPICK_QB, v4i8, SETEQ>; -def : DSPSelectCCPat<PseudoCMPU_LT_QB, PseudoPICK_QB, v4i8, SETULT>; -def : DSPSelectCCPat<PseudoCMPU_LE_QB, PseudoPICK_QB, v4i8, SETULE>; -def : DSPSelectCCPatInv<PseudoCMPU_EQ_QB, PseudoPICK_QB, v4i8, SETNE>; -def : DSPSelectCCPatInv<PseudoCMPU_LT_QB, PseudoPICK_QB, v4i8, SETUGE>; -def : DSPSelectCCPatInv<PseudoCMPU_LE_QB, PseudoPICK_QB, v4i8, SETUGT>; - -// Extr patterns. -class EXTR_W_TY1_R2_Pat<SDPatternOperator OpNode, Instruction Instr> : - DSPPat<(i32 (OpNode GPR32:$rs, ACC64DSP:$ac)), - (Instr ACC64DSP:$ac, GPR32:$rs)>; - -class EXTR_W_TY1_R1_Pat<SDPatternOperator OpNode, Instruction Instr> : - DSPPat<(i32 (OpNode immZExt5:$shift, ACC64DSP:$ac)), - (Instr ACC64DSP:$ac, immZExt5:$shift)>; - -def : EXTR_W_TY1_R1_Pat<MipsEXTP, EXTP>; -def : EXTR_W_TY1_R2_Pat<MipsEXTP, EXTPV>; -def : EXTR_W_TY1_R1_Pat<MipsEXTPDP, EXTPDP>; -def : EXTR_W_TY1_R2_Pat<MipsEXTPDP, EXTPDPV>; -def : EXTR_W_TY1_R1_Pat<MipsEXTR_W, EXTR_W>; -def : EXTR_W_TY1_R2_Pat<MipsEXTR_W, EXTRV_W>; -def : EXTR_W_TY1_R1_Pat<MipsEXTR_R_W, EXTR_R_W>; -def : EXTR_W_TY1_R2_Pat<MipsEXTR_R_W, EXTRV_R_W>; -def : EXTR_W_TY1_R1_Pat<MipsEXTR_RS_W, EXTR_RS_W>; -def : EXTR_W_TY1_R2_Pat<MipsEXTR_RS_W, EXTRV_RS_W>; -def : EXTR_W_TY1_R1_Pat<MipsEXTR_S_H, EXTR_S_H>; -def : EXTR_W_TY1_R2_Pat<MipsEXTR_S_H, EXTRV_S_H>; - -// Indexed load patterns. -class IndexedLoadPat<SDPatternOperator LoadNode, Instruction Instr> : - DSPPat<(i32 (LoadNode (add i32:$base, i32:$index))), - (Instr i32:$base, i32:$index)>; - -let AddedComplexity = 20 in { - def : IndexedLoadPat<zextloadi8, LBUX>; - def : IndexedLoadPat<sextloadi16, LHX>; - def : IndexedLoadPat<load, LWX>; -} - -// Instruction alias. -let AdditionalPredicates = [NotInMicroMips] in { - def : DSPInstAlias<"wrdsp $rt", (WRDSP GPR32Opnd:$rt, 0x1F), 1>; -} diff --git a/contrib/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp b/contrib/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp deleted file mode 100644 index aa07dac86828..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp +++ /dev/null @@ -1,930 +0,0 @@ -//===- MipsDelaySlotFiller.cpp - Mips Delay Slot Filler -------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Simple pass to fill delay slots with useful instructions. -// -//===----------------------------------------------------------------------===// - -#include "MCTargetDesc/MipsMCNaCl.h" -#include "Mips.h" -#include "MipsInstrInfo.h" -#include "MipsRegisterInfo.h" -#include "MipsSubtarget.h" -#include "llvm/ADT/BitVector.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/PointerUnion.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/Statistic.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Analysis/AliasAnalysis.h" -#include "llvm/Analysis/ValueTracking.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/MachineBranchProbabilityInfo.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/MachineOperand.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/PseudoSourceValue.h" -#include "llvm/CodeGen/TargetRegisterInfo.h" -#include "llvm/CodeGen/TargetSubtargetInfo.h" -#include "llvm/MC/MCInstrDesc.h" -#include "llvm/MC/MCRegisterInfo.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/CodeGen.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Target/TargetMachine.h" -#include <algorithm> -#include <cassert> -#include <iterator> -#include <memory> -#include <utility> - -using namespace llvm; - -#define DEBUG_TYPE "mips-delay-slot-filler" - -STATISTIC(FilledSlots, "Number of delay slots filled"); -STATISTIC(UsefulSlots, "Number of delay slots filled with instructions that" - " are not NOP."); - -static cl::opt<bool> DisableDelaySlotFiller( - "disable-mips-delay-filler", - cl::init(false), - cl::desc("Fill all delay slots with NOPs."), - cl::Hidden); - -static cl::opt<bool> DisableForwardSearch( - "disable-mips-df-forward-search", - cl::init(true), - cl::desc("Disallow MIPS delay filler to search forward."), - cl::Hidden); - -static cl::opt<bool> DisableSuccBBSearch( - "disable-mips-df-succbb-search", - cl::init(true), - cl::desc("Disallow MIPS delay filler to search successor basic blocks."), - cl::Hidden); - -static cl::opt<bool> DisableBackwardSearch( - "disable-mips-df-backward-search", - cl::init(false), - cl::desc("Disallow MIPS delay filler to search backward."), - cl::Hidden); - -enum CompactBranchPolicy { - CB_Never, ///< The policy 'never' may in some circumstances or for some - ///< ISAs not be absolutely adhered to. - CB_Optimal, ///< Optimal is the default and will produce compact branches - ///< when delay slots cannot be filled. - CB_Always ///< 'always' may in some circumstances may not be - ///< absolutely adhered to there may not be a corresponding - ///< compact form of a branch. -}; - -static cl::opt<CompactBranchPolicy> MipsCompactBranchPolicy( - "mips-compact-branches",cl::Optional, - cl::init(CB_Optimal), - cl::desc("MIPS Specific: Compact branch policy."), - cl::values( - clEnumValN(CB_Never, "never", "Do not use compact branches if possible."), - clEnumValN(CB_Optimal, "optimal", "Use compact branches where appropiate (default)."), - clEnumValN(CB_Always, "always", "Always use compact branches if possible.") - ) -); - -namespace { - - using Iter = MachineBasicBlock::iterator; - using ReverseIter = MachineBasicBlock::reverse_iterator; - using BB2BrMap = SmallDenseMap<MachineBasicBlock *, MachineInstr *, 2>; - - class RegDefsUses { - public: - RegDefsUses(const TargetRegisterInfo &TRI); - - void init(const MachineInstr &MI); - - /// This function sets all caller-saved registers in Defs. - void setCallerSaved(const MachineInstr &MI); - - /// This function sets all unallocatable registers in Defs. - void setUnallocatableRegs(const MachineFunction &MF); - - /// Set bits in Uses corresponding to MBB's live-out registers except for - /// the registers that are live-in to SuccBB. - void addLiveOut(const MachineBasicBlock &MBB, - const MachineBasicBlock &SuccBB); - - bool update(const MachineInstr &MI, unsigned Begin, unsigned End); - - private: - bool checkRegDefsUses(BitVector &NewDefs, BitVector &NewUses, unsigned Reg, - bool IsDef) const; - - /// Returns true if Reg or its alias is in RegSet. - bool isRegInSet(const BitVector &RegSet, unsigned Reg) const; - - const TargetRegisterInfo &TRI; - BitVector Defs, Uses; - }; - - /// Base class for inspecting loads and stores. - class InspectMemInstr { - public: - InspectMemInstr(bool ForbidMemInstr_) : ForbidMemInstr(ForbidMemInstr_) {} - virtual ~InspectMemInstr() = default; - - /// Return true if MI cannot be moved to delay slot. - bool hasHazard(const MachineInstr &MI); - - protected: - /// Flags indicating whether loads or stores have been seen. - bool OrigSeenLoad = false; - bool OrigSeenStore = false; - bool SeenLoad = false; - bool SeenStore = false; - - /// Memory instructions are not allowed to move to delay slot if this flag - /// is true. - bool ForbidMemInstr; - - private: - virtual bool hasHazard_(const MachineInstr &MI) = 0; - }; - - /// This subclass rejects any memory instructions. - class NoMemInstr : public InspectMemInstr { - public: - NoMemInstr() : InspectMemInstr(true) {} - - private: - bool hasHazard_(const MachineInstr &MI) override { return true; } - }; - - /// This subclass accepts loads from stacks and constant loads. - class LoadFromStackOrConst : public InspectMemInstr { - public: - LoadFromStackOrConst() : InspectMemInstr(false) {} - - private: - bool hasHazard_(const MachineInstr &MI) override; - }; - - /// This subclass uses memory dependence information to determine whether a - /// memory instruction can be moved to a delay slot. - class MemDefsUses : public InspectMemInstr { - public: - MemDefsUses(const DataLayout &DL, const MachineFrameInfo *MFI); - - private: - using ValueType = PointerUnion<const Value *, const PseudoSourceValue *>; - - bool hasHazard_(const MachineInstr &MI) override; - - /// Update Defs and Uses. Return true if there exist dependences that - /// disqualify the delay slot candidate between V and values in Uses and - /// Defs. - bool updateDefsUses(ValueType V, bool MayStore); - - /// Get the list of underlying objects of MI's memory operand. - bool getUnderlyingObjects(const MachineInstr &MI, - SmallVectorImpl<ValueType> &Objects) const; - - const MachineFrameInfo *MFI; - SmallPtrSet<ValueType, 4> Uses, Defs; - const DataLayout &DL; - - /// Flags indicating whether loads or stores with no underlying objects have - /// been seen. - bool SeenNoObjLoad = false; - bool SeenNoObjStore = false; - }; - - class MipsDelaySlotFiller : public MachineFunctionPass { - public: - MipsDelaySlotFiller() : MachineFunctionPass(ID) { - initializeMipsDelaySlotFillerPass(*PassRegistry::getPassRegistry()); - } - - StringRef getPassName() const override { return "Mips Delay Slot Filler"; } - - bool runOnMachineFunction(MachineFunction &F) override { - TM = &F.getTarget(); - bool Changed = false; - for (MachineFunction::iterator FI = F.begin(), FE = F.end(); - FI != FE; ++FI) - Changed |= runOnMachineBasicBlock(*FI); - - // This pass invalidates liveness information when it reorders - // instructions to fill delay slot. Without this, -verify-machineinstrs - // will fail. - if (Changed) - F.getRegInfo().invalidateLiveness(); - - return Changed; - } - - MachineFunctionProperties getRequiredProperties() const override { - return MachineFunctionProperties().set( - MachineFunctionProperties::Property::NoVRegs); - } - - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.addRequired<MachineBranchProbabilityInfo>(); - MachineFunctionPass::getAnalysisUsage(AU); - } - - static char ID; - - private: - bool runOnMachineBasicBlock(MachineBasicBlock &MBB); - - Iter replaceWithCompactBranch(MachineBasicBlock &MBB, Iter Branch, - const DebugLoc &DL); - - /// This function checks if it is valid to move Candidate to the delay slot - /// and returns true if it isn't. It also updates memory and register - /// dependence information. - bool delayHasHazard(const MachineInstr &Candidate, RegDefsUses &RegDU, - InspectMemInstr &IM) const; - - /// This function searches range [Begin, End) for an instruction that can be - /// moved to the delay slot. Returns true on success. - template<typename IterTy> - bool searchRange(MachineBasicBlock &MBB, IterTy Begin, IterTy End, - RegDefsUses &RegDU, InspectMemInstr &IM, Iter Slot, - IterTy &Filler) const; - - /// This function searches in the backward direction for an instruction that - /// can be moved to the delay slot. Returns true on success. - bool searchBackward(MachineBasicBlock &MBB, MachineInstr &Slot) const; - - /// This function searches MBB in the forward direction for an instruction - /// that can be moved to the delay slot. Returns true on success. - bool searchForward(MachineBasicBlock &MBB, Iter Slot) const; - - /// This function searches one of MBB's successor blocks for an instruction - /// that can be moved to the delay slot and inserts clones of the - /// instruction into the successor's predecessor blocks. - bool searchSuccBBs(MachineBasicBlock &MBB, Iter Slot) const; - - /// Pick a successor block of MBB. Return NULL if MBB doesn't have a - /// successor block that is not a landing pad. - MachineBasicBlock *selectSuccBB(MachineBasicBlock &B) const; - - /// This function analyzes MBB and returns an instruction with an unoccupied - /// slot that branches to Dst. - std::pair<MipsInstrInfo::BranchType, MachineInstr *> - getBranch(MachineBasicBlock &MBB, const MachineBasicBlock &Dst) const; - - /// Examine Pred and see if it is possible to insert an instruction into - /// one of its branches delay slot or its end. - bool examinePred(MachineBasicBlock &Pred, const MachineBasicBlock &Succ, - RegDefsUses &RegDU, bool &HasMultipleSuccs, - BB2BrMap &BrMap) const; - - bool terminateSearch(const MachineInstr &Candidate) const; - - const TargetMachine *TM = nullptr; - }; - -} // end anonymous namespace - -char MipsDelaySlotFiller::ID = 0; - -static bool hasUnoccupiedSlot(const MachineInstr *MI) { - return MI->hasDelaySlot() && !MI->isBundledWithSucc(); -} - -INITIALIZE_PASS(MipsDelaySlotFiller, DEBUG_TYPE, - "Fill delay slot for MIPS", false, false) - -/// This function inserts clones of Filler into predecessor blocks. -static void insertDelayFiller(Iter Filler, const BB2BrMap &BrMap) { - MachineFunction *MF = Filler->getParent()->getParent(); - - for (BB2BrMap::const_iterator I = BrMap.begin(); I != BrMap.end(); ++I) { - if (I->second) { - MIBundleBuilder(I->second).append(MF->CloneMachineInstr(&*Filler)); - ++UsefulSlots; - } else { - I->first->insert(I->first->end(), MF->CloneMachineInstr(&*Filler)); - } - } -} - -/// This function adds registers Filler defines to MBB's live-in register list. -static void addLiveInRegs(Iter Filler, MachineBasicBlock &MBB) { - for (unsigned I = 0, E = Filler->getNumOperands(); I != E; ++I) { - const MachineOperand &MO = Filler->getOperand(I); - unsigned R; - - if (!MO.isReg() || !MO.isDef() || !(R = MO.getReg())) - continue; - -#ifndef NDEBUG - const MachineFunction &MF = *MBB.getParent(); - assert(MF.getSubtarget().getRegisterInfo()->getAllocatableSet(MF).test(R) && - "Shouldn't move an instruction with unallocatable registers across " - "basic block boundaries."); -#endif - - if (!MBB.isLiveIn(R)) - MBB.addLiveIn(R); - } -} - -RegDefsUses::RegDefsUses(const TargetRegisterInfo &TRI) - : TRI(TRI), Defs(TRI.getNumRegs(), false), Uses(TRI.getNumRegs(), false) {} - -void RegDefsUses::init(const MachineInstr &MI) { - // Add all register operands which are explicit and non-variadic. - update(MI, 0, MI.getDesc().getNumOperands()); - - // If MI is a call, add RA to Defs to prevent users of RA from going into - // delay slot. - if (MI.isCall()) - Defs.set(Mips::RA); - - // Add all implicit register operands of branch instructions except - // register AT. - if (MI.isBranch()) { - update(MI, MI.getDesc().getNumOperands(), MI.getNumOperands()); - Defs.reset(Mips::AT); - } -} - -void RegDefsUses::setCallerSaved(const MachineInstr &MI) { - assert(MI.isCall()); - - // Add RA/RA_64 to Defs to prevent users of RA/RA_64 from going into - // the delay slot. The reason is that RA/RA_64 must not be changed - // in the delay slot so that the callee can return to the caller. - if (MI.definesRegister(Mips::RA) || MI.definesRegister(Mips::RA_64)) { - Defs.set(Mips::RA); - Defs.set(Mips::RA_64); - } - - // If MI is a call, add all caller-saved registers to Defs. - BitVector CallerSavedRegs(TRI.getNumRegs(), true); - - CallerSavedRegs.reset(Mips::ZERO); - CallerSavedRegs.reset(Mips::ZERO_64); - - for (const MCPhysReg *R = TRI.getCalleeSavedRegs(MI.getParent()->getParent()); - *R; ++R) - for (MCRegAliasIterator AI(*R, &TRI, true); AI.isValid(); ++AI) - CallerSavedRegs.reset(*AI); - - Defs |= CallerSavedRegs; -} - -void RegDefsUses::setUnallocatableRegs(const MachineFunction &MF) { - BitVector AllocSet = TRI.getAllocatableSet(MF); - - for (unsigned R : AllocSet.set_bits()) - for (MCRegAliasIterator AI(R, &TRI, false); AI.isValid(); ++AI) - AllocSet.set(*AI); - - AllocSet.set(Mips::ZERO); - AllocSet.set(Mips::ZERO_64); - - Defs |= AllocSet.flip(); -} - -void RegDefsUses::addLiveOut(const MachineBasicBlock &MBB, - const MachineBasicBlock &SuccBB) { - for (MachineBasicBlock::const_succ_iterator SI = MBB.succ_begin(), - SE = MBB.succ_end(); SI != SE; ++SI) - if (*SI != &SuccBB) - for (const auto &LI : (*SI)->liveins()) - Uses.set(LI.PhysReg); -} - -bool RegDefsUses::update(const MachineInstr &MI, unsigned Begin, unsigned End) { - BitVector NewDefs(TRI.getNumRegs()), NewUses(TRI.getNumRegs()); - bool HasHazard = false; - - for (unsigned I = Begin; I != End; ++I) { - const MachineOperand &MO = MI.getOperand(I); - - if (MO.isReg() && MO.getReg()) - HasHazard |= checkRegDefsUses(NewDefs, NewUses, MO.getReg(), MO.isDef()); - } - - Defs |= NewDefs; - Uses |= NewUses; - - return HasHazard; -} - -bool RegDefsUses::checkRegDefsUses(BitVector &NewDefs, BitVector &NewUses, - unsigned Reg, bool IsDef) const { - if (IsDef) { - NewDefs.set(Reg); - // check whether Reg has already been defined or used. - return (isRegInSet(Defs, Reg) || isRegInSet(Uses, Reg)); - } - - NewUses.set(Reg); - // check whether Reg has already been defined. - return isRegInSet(Defs, Reg); -} - -bool RegDefsUses::isRegInSet(const BitVector &RegSet, unsigned Reg) const { - // Check Reg and all aliased Registers. - for (MCRegAliasIterator AI(Reg, &TRI, true); AI.isValid(); ++AI) - if (RegSet.test(*AI)) - return true; - return false; -} - -bool InspectMemInstr::hasHazard(const MachineInstr &MI) { - if (!MI.mayStore() && !MI.mayLoad()) - return false; - - if (ForbidMemInstr) - return true; - - OrigSeenLoad = SeenLoad; - OrigSeenStore = SeenStore; - SeenLoad |= MI.mayLoad(); - SeenStore |= MI.mayStore(); - - // If MI is an ordered or volatile memory reference, disallow moving - // subsequent loads and stores to delay slot. - if (MI.hasOrderedMemoryRef() && (OrigSeenLoad || OrigSeenStore)) { - ForbidMemInstr = true; - return true; - } - - return hasHazard_(MI); -} - -bool LoadFromStackOrConst::hasHazard_(const MachineInstr &MI) { - if (MI.mayStore()) - return true; - - if (!MI.hasOneMemOperand() || !(*MI.memoperands_begin())->getPseudoValue()) - return true; - - if (const PseudoSourceValue *PSV = - (*MI.memoperands_begin())->getPseudoValue()) { - if (isa<FixedStackPseudoSourceValue>(PSV)) - return false; - return !PSV->isConstant(nullptr) && !PSV->isStack(); - } - - return true; -} - -MemDefsUses::MemDefsUses(const DataLayout &DL, const MachineFrameInfo *MFI_) - : InspectMemInstr(false), MFI(MFI_), DL(DL) {} - -bool MemDefsUses::hasHazard_(const MachineInstr &MI) { - bool HasHazard = false; - - // Check underlying object list. - SmallVector<ValueType, 4> Objs; - if (getUnderlyingObjects(MI, Objs)) { - for (ValueType VT : Objs) - HasHazard |= updateDefsUses(VT, MI.mayStore()); - return HasHazard; - } - - // No underlying objects found. - HasHazard = MI.mayStore() && (OrigSeenLoad || OrigSeenStore); - HasHazard |= MI.mayLoad() || OrigSeenStore; - - SeenNoObjLoad |= MI.mayLoad(); - SeenNoObjStore |= MI.mayStore(); - - return HasHazard; -} - -bool MemDefsUses::updateDefsUses(ValueType V, bool MayStore) { - if (MayStore) - return !Defs.insert(V).second || Uses.count(V) || SeenNoObjStore || - SeenNoObjLoad; - - Uses.insert(V); - return Defs.count(V) || SeenNoObjStore; -} - -bool MemDefsUses:: -getUnderlyingObjects(const MachineInstr &MI, - SmallVectorImpl<ValueType> &Objects) const { - if (!MI.hasOneMemOperand()) - return false; - - auto & MMO = **MI.memoperands_begin(); - - if (const PseudoSourceValue *PSV = MMO.getPseudoValue()) { - if (!PSV->isAliased(MFI)) - return false; - Objects.push_back(PSV); - return true; - } - - if (const Value *V = MMO.getValue()) { - SmallVector<const Value *, 4> Objs; - GetUnderlyingObjects(V, Objs, DL); - - for (const Value *UValue : Objs) { - if (!isIdentifiedObject(V)) - return false; - - Objects.push_back(UValue); - } - return true; - } - - return false; -} - -// Replace Branch with the compact branch instruction. -Iter MipsDelaySlotFiller::replaceWithCompactBranch(MachineBasicBlock &MBB, - Iter Branch, - const DebugLoc &DL) { - const MipsSubtarget &STI = MBB.getParent()->getSubtarget<MipsSubtarget>(); - const MipsInstrInfo *TII = STI.getInstrInfo(); - - unsigned NewOpcode = TII->getEquivalentCompactForm(Branch); - Branch = TII->genInstrWithNewOpc(NewOpcode, Branch); - - std::next(Branch)->eraseFromParent(); - return Branch; -} - -// For given opcode returns opcode of corresponding instruction with short -// delay slot. -// For the pseudo TAILCALL*_MM instructions return the short delay slot -// form. Unfortunately, TAILCALL<->b16 is denied as b16 has a limited range -// that is too short to make use of for tail calls. -static int getEquivalentCallShort(int Opcode) { - switch (Opcode) { - case Mips::BGEZAL: - return Mips::BGEZALS_MM; - case Mips::BLTZAL: - return Mips::BLTZALS_MM; - case Mips::JAL: - case Mips::JAL_MM: - return Mips::JALS_MM; - case Mips::JALR: - return Mips::JALRS_MM; - case Mips::JALR16_MM: - return Mips::JALRS16_MM; - case Mips::TAILCALL_MM: - llvm_unreachable("Attempting to shorten the TAILCALL_MM pseudo!"); - case Mips::TAILCALLREG: - return Mips::JR16_MM; - default: - llvm_unreachable("Unexpected call instruction for microMIPS."); - } -} - -/// runOnMachineBasicBlock - Fill in delay slots for the given basic block. -/// We assume there is only one delay slot per delayed instruction. -bool MipsDelaySlotFiller::runOnMachineBasicBlock(MachineBasicBlock &MBB) { - bool Changed = false; - const MipsSubtarget &STI = MBB.getParent()->getSubtarget<MipsSubtarget>(); - bool InMicroMipsMode = STI.inMicroMipsMode(); - const MipsInstrInfo *TII = STI.getInstrInfo(); - - for (Iter I = MBB.begin(); I != MBB.end(); ++I) { - if (!hasUnoccupiedSlot(&*I)) - continue; - - // Delay slot filling is disabled at -O0, or in microMIPS32R6. - if (!DisableDelaySlotFiller && (TM->getOptLevel() != CodeGenOpt::None) && - !(InMicroMipsMode && STI.hasMips32r6())) { - - bool Filled = false; - - if (MipsCompactBranchPolicy.getValue() != CB_Always || - !TII->getEquivalentCompactForm(I)) { - if (searchBackward(MBB, *I)) { - Filled = true; - } else if (I->isTerminator()) { - if (searchSuccBBs(MBB, I)) { - Filled = true; - } - } else if (searchForward(MBB, I)) { - Filled = true; - } - } - - if (Filled) { - // Get instruction with delay slot. - MachineBasicBlock::instr_iterator DSI = I.getInstrIterator(); - - if (InMicroMipsMode && TII->getInstSizeInBytes(*std::next(DSI)) == 2 && - DSI->isCall()) { - // If instruction in delay slot is 16b change opcode to - // corresponding instruction with short delay slot. - - // TODO: Implement an instruction mapping table of 16bit opcodes to - // 32bit opcodes so that an instruction can be expanded. This would - // save 16 bits as a TAILCALL_MM pseudo requires a fullsized nop. - // TODO: Permit b16 when branching backwards to the same function - // if it is in range. - DSI->setDesc(TII->get(getEquivalentCallShort(DSI->getOpcode()))); - } - ++FilledSlots; - Changed = true; - continue; - } - } - - // For microMIPS if instruction is BEQ or BNE with one ZERO register, then - // instead of adding NOP replace this instruction with the corresponding - // compact branch instruction, i.e. BEQZC or BNEZC. Additionally - // PseudoReturn and PseudoIndirectBranch are expanded to JR_MM, so they can - // be replaced with JRC16_MM. - - // For MIPSR6 attempt to produce the corresponding compact (no delay slot) - // form of the CTI. For indirect jumps this will not require inserting a - // NOP and for branches will hopefully avoid requiring a NOP. - if ((InMicroMipsMode || - (STI.hasMips32r6() && MipsCompactBranchPolicy != CB_Never)) && - TII->getEquivalentCompactForm(I)) { - I = replaceWithCompactBranch(MBB, I, I->getDebugLoc()); - Changed = true; - continue; - } - - // Bundle the NOP to the instruction with the delay slot. - BuildMI(MBB, std::next(I), I->getDebugLoc(), TII->get(Mips::NOP)); - MIBundleBuilder(MBB, I, std::next(I, 2)); - ++FilledSlots; - Changed = true; - } - - return Changed; -} - -template <typename IterTy> -bool MipsDelaySlotFiller::searchRange(MachineBasicBlock &MBB, IterTy Begin, - IterTy End, RegDefsUses &RegDU, - InspectMemInstr &IM, Iter Slot, - IterTy &Filler) const { - for (IterTy I = Begin; I != End;) { - IterTy CurrI = I; - ++I; - - // skip debug value - if (CurrI->isDebugInstr()) - continue; - - if (terminateSearch(*CurrI)) - break; - - assert((!CurrI->isCall() && !CurrI->isReturn() && !CurrI->isBranch()) && - "Cannot put calls, returns or branches in delay slot."); - - if (CurrI->isKill()) { - CurrI->eraseFromParent(); - continue; - } - - if (delayHasHazard(*CurrI, RegDU, IM)) - continue; - - const MipsSubtarget &STI = MBB.getParent()->getSubtarget<MipsSubtarget>(); - if (STI.isTargetNaCl()) { - // In NaCl, instructions that must be masked are forbidden in delay slots. - // We only check for loads, stores and SP changes. Calls, returns and - // branches are not checked because non-NaCl targets never put them in - // delay slots. - unsigned AddrIdx; - if ((isBasePlusOffsetMemoryAccess(CurrI->getOpcode(), &AddrIdx) && - baseRegNeedsLoadStoreMask(CurrI->getOperand(AddrIdx).getReg())) || - CurrI->modifiesRegister(Mips::SP, STI.getRegisterInfo())) - continue; - } - - bool InMicroMipsMode = STI.inMicroMipsMode(); - const MipsInstrInfo *TII = STI.getInstrInfo(); - unsigned Opcode = (*Slot).getOpcode(); - // This is complicated by the tail call optimization. For non-PIC code - // there is only a 32bit sized unconditional branch which can be assumed - // to be able to reach the target. b16 only has a range of +/- 1 KB. - // It's entirely possible that the target function is reachable with b16 - // but we don't have enough information to make that decision. - if (InMicroMipsMode && TII->getInstSizeInBytes(*CurrI) == 2 && - (Opcode == Mips::JR || Opcode == Mips::PseudoIndirectBranch || - Opcode == Mips::PseudoIndirectBranch_MM || - Opcode == Mips::PseudoReturn || Opcode == Mips::TAILCALL)) - continue; - // Instructions LWP/SWP and MOVEP should not be in a delay slot as that - // results in unpredictable behaviour - if (InMicroMipsMode && (Opcode == Mips::LWP_MM || Opcode == Mips::SWP_MM || - Opcode == Mips::MOVEP_MM)) - continue; - - Filler = CurrI; - return true; - } - - return false; -} - -bool MipsDelaySlotFiller::searchBackward(MachineBasicBlock &MBB, - MachineInstr &Slot) const { - if (DisableBackwardSearch) - return false; - - auto *Fn = MBB.getParent(); - RegDefsUses RegDU(*Fn->getSubtarget().getRegisterInfo()); - MemDefsUses MemDU(Fn->getDataLayout(), &Fn->getFrameInfo()); - ReverseIter Filler; - - RegDU.init(Slot); - - MachineBasicBlock::iterator SlotI = Slot; - if (!searchRange(MBB, ++SlotI.getReverse(), MBB.rend(), RegDU, MemDU, Slot, - Filler)) - return false; - - MBB.splice(std::next(SlotI), &MBB, Filler.getReverse()); - MIBundleBuilder(MBB, SlotI, std::next(SlotI, 2)); - ++UsefulSlots; - return true; -} - -bool MipsDelaySlotFiller::searchForward(MachineBasicBlock &MBB, - Iter Slot) const { - // Can handle only calls. - if (DisableForwardSearch || !Slot->isCall()) - return false; - - RegDefsUses RegDU(*MBB.getParent()->getSubtarget().getRegisterInfo()); - NoMemInstr NM; - Iter Filler; - - RegDU.setCallerSaved(*Slot); - - if (!searchRange(MBB, std::next(Slot), MBB.end(), RegDU, NM, Slot, Filler)) - return false; - - MBB.splice(std::next(Slot), &MBB, Filler); - MIBundleBuilder(MBB, Slot, std::next(Slot, 2)); - ++UsefulSlots; - return true; -} - -bool MipsDelaySlotFiller::searchSuccBBs(MachineBasicBlock &MBB, - Iter Slot) const { - if (DisableSuccBBSearch) - return false; - - MachineBasicBlock *SuccBB = selectSuccBB(MBB); - - if (!SuccBB) - return false; - - RegDefsUses RegDU(*MBB.getParent()->getSubtarget().getRegisterInfo()); - bool HasMultipleSuccs = false; - BB2BrMap BrMap; - std::unique_ptr<InspectMemInstr> IM; - Iter Filler; - auto *Fn = MBB.getParent(); - - // Iterate over SuccBB's predecessor list. - for (MachineBasicBlock::pred_iterator PI = SuccBB->pred_begin(), - PE = SuccBB->pred_end(); PI != PE; ++PI) - if (!examinePred(**PI, *SuccBB, RegDU, HasMultipleSuccs, BrMap)) - return false; - - // Do not allow moving instructions which have unallocatable register operands - // across basic block boundaries. - RegDU.setUnallocatableRegs(*Fn); - - // Only allow moving loads from stack or constants if any of the SuccBB's - // predecessors have multiple successors. - if (HasMultipleSuccs) { - IM.reset(new LoadFromStackOrConst()); - } else { - const MachineFrameInfo &MFI = Fn->getFrameInfo(); - IM.reset(new MemDefsUses(Fn->getDataLayout(), &MFI)); - } - - if (!searchRange(MBB, SuccBB->begin(), SuccBB->end(), RegDU, *IM, Slot, - Filler)) - return false; - - insertDelayFiller(Filler, BrMap); - addLiveInRegs(Filler, *SuccBB); - Filler->eraseFromParent(); - - return true; -} - -MachineBasicBlock * -MipsDelaySlotFiller::selectSuccBB(MachineBasicBlock &B) const { - if (B.succ_empty()) - return nullptr; - - // Select the successor with the larget edge weight. - auto &Prob = getAnalysis<MachineBranchProbabilityInfo>(); - MachineBasicBlock *S = *std::max_element( - B.succ_begin(), B.succ_end(), - [&](const MachineBasicBlock *Dst0, const MachineBasicBlock *Dst1) { - return Prob.getEdgeProbability(&B, Dst0) < - Prob.getEdgeProbability(&B, Dst1); - }); - return S->isEHPad() ? nullptr : S; -} - -std::pair<MipsInstrInfo::BranchType, MachineInstr *> -MipsDelaySlotFiller::getBranch(MachineBasicBlock &MBB, - const MachineBasicBlock &Dst) const { - const MipsInstrInfo *TII = - MBB.getParent()->getSubtarget<MipsSubtarget>().getInstrInfo(); - MachineBasicBlock *TrueBB = nullptr, *FalseBB = nullptr; - SmallVector<MachineInstr*, 2> BranchInstrs; - SmallVector<MachineOperand, 2> Cond; - - MipsInstrInfo::BranchType R = - TII->analyzeBranch(MBB, TrueBB, FalseBB, Cond, false, BranchInstrs); - - if ((R == MipsInstrInfo::BT_None) || (R == MipsInstrInfo::BT_NoBranch)) - return std::make_pair(R, nullptr); - - if (R != MipsInstrInfo::BT_CondUncond) { - if (!hasUnoccupiedSlot(BranchInstrs[0])) - return std::make_pair(MipsInstrInfo::BT_None, nullptr); - - assert(((R != MipsInstrInfo::BT_Uncond) || (TrueBB == &Dst))); - - return std::make_pair(R, BranchInstrs[0]); - } - - assert((TrueBB == &Dst) || (FalseBB == &Dst)); - - // Examine the conditional branch. See if its slot is occupied. - if (hasUnoccupiedSlot(BranchInstrs[0])) - return std::make_pair(MipsInstrInfo::BT_Cond, BranchInstrs[0]); - - // If that fails, try the unconditional branch. - if (hasUnoccupiedSlot(BranchInstrs[1]) && (FalseBB == &Dst)) - return std::make_pair(MipsInstrInfo::BT_Uncond, BranchInstrs[1]); - - return std::make_pair(MipsInstrInfo::BT_None, nullptr); -} - -bool MipsDelaySlotFiller::examinePred(MachineBasicBlock &Pred, - const MachineBasicBlock &Succ, - RegDefsUses &RegDU, - bool &HasMultipleSuccs, - BB2BrMap &BrMap) const { - std::pair<MipsInstrInfo::BranchType, MachineInstr *> P = - getBranch(Pred, Succ); - - // Return if either getBranch wasn't able to analyze the branches or there - // were no branches with unoccupied slots. - if (P.first == MipsInstrInfo::BT_None) - return false; - - if ((P.first != MipsInstrInfo::BT_Uncond) && - (P.first != MipsInstrInfo::BT_NoBranch)) { - HasMultipleSuccs = true; - RegDU.addLiveOut(Pred, Succ); - } - - BrMap[&Pred] = P.second; - return true; -} - -bool MipsDelaySlotFiller::delayHasHazard(const MachineInstr &Candidate, - RegDefsUses &RegDU, - InspectMemInstr &IM) const { - assert(!Candidate.isKill() && - "KILL instructions should have been eliminated at this point."); - - bool HasHazard = Candidate.isImplicitDef(); - - HasHazard |= IM.hasHazard(Candidate); - HasHazard |= RegDU.update(Candidate, 0, Candidate.getNumOperands()); - - return HasHazard; -} - -bool MipsDelaySlotFiller::terminateSearch(const MachineInstr &Candidate) const { - return (Candidate.isTerminator() || Candidate.isCall() || - Candidate.isPosition() || Candidate.isInlineAsm() || - Candidate.hasUnmodeledSideEffects()); -} - -/// createMipsDelaySlotFillerPass - Returns a pass that fills in delay -/// slots in Mips MachineFunctions -FunctionPass *llvm::createMipsDelaySlotFillerPass() { return new MipsDelaySlotFiller(); } diff --git a/contrib/llvm/lib/Target/Mips/MipsEVAInstrFormats.td b/contrib/llvm/lib/Target/Mips/MipsEVAInstrFormats.td deleted file mode 100644 index 9820e4dcfc88..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsEVAInstrFormats.td +++ /dev/null @@ -1,83 +0,0 @@ -//===- MipsEVAInstrFormats.td - Mips Instruction Formats ---*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file describes Mips32r6 instruction formats. -// -//===----------------------------------------------------------------------===// - -class MipsEVAInst : MipsInst<(outs), (ins), "", [], NoItinerary, FrmOther>, - StdArch { - let DecoderNamespace = "Mips"; - let EncodingPredicates = [HasStdEnc]; -} - -//===----------------------------------------------------------------------===// -// -// Field Values -// -//===----------------------------------------------------------------------===// - -// Memory Load/Store EVA -def OPCODE6_LBE : OPCODE6<0b101100>; -def OPCODE6_LBuE : OPCODE6<0b101000>; -def OPCODE6_LHE : OPCODE6<0b101101>; -def OPCODE6_LHuE : OPCODE6<0b101001>; -def OPCODE6_LWE : OPCODE6<0b101111>; - -def OPCODE6_SBE : OPCODE6<0b011100>; -def OPCODE6_SHE : OPCODE6<0b011101>; -def OPCODE6_SWE : OPCODE6<0b011111>; - -// load/store left/right EVA -def OPCODE6_LWLE : OPCODE6<0b011001>; -def OPCODE6_LWRE : OPCODE6<0b011010>; -def OPCODE6_SWLE : OPCODE6<0b100001>; -def OPCODE6_SWRE : OPCODE6<0b100010>; - -// Load-linked EVA, Store-conditional EVA -def OPCODE6_LLE : OPCODE6<0b101110>; -def OPCODE6_SCE : OPCODE6<0b011110>; - -def OPCODE6_TLBINV : OPCODE6<0b000011>; -def OPCODE6_TLBINVF : OPCODE6<0b000100>; - -def OPCODE6_CACHEE : OPCODE6<0b011011>; -def OPCODE6_PREFE : OPCODE6<0b100011>; - -def OPGROUP_COP0_TLB : OPGROUP<0b010000>; - -//===----------------------------------------------------------------------===// -// -// Encoding Formats -// -//===----------------------------------------------------------------------===// - -class SPECIAL3_EVA_LOAD_STORE_FM<OPCODE6 Operation> : MipsEVAInst { - bits<21> addr; - bits<5> hint; - bits<5> base = addr{20-16}; - bits<9> offset = addr{8-0}; - - bits<32> Inst; - - let Inst{31-26} = OPGROUP_SPECIAL3.Value; - let Inst{25-21} = base; - let Inst{20-16} = hint; - let Inst{15-7} = offset; - let Inst{6} = 0; - let Inst{5-0} = Operation.Value; -} - -class TLB_FM<OPCODE6 Operation> : MipsEVAInst { - bits<32> Inst; - - let Inst{31-26} = OPGROUP_COP0_TLB.Value; - let Inst{25} = 1; // CO - let Inst{24-6} = 0; - let Inst{5-0} = Operation.Value; -} diff --git a/contrib/llvm/lib/Target/Mips/MipsEVAInstrInfo.td b/contrib/llvm/lib/Target/Mips/MipsEVAInstrInfo.td deleted file mode 100644 index 73cca8cfa5d9..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsEVAInstrInfo.td +++ /dev/null @@ -1,213 +0,0 @@ -//===- MipsEVAInstrInfo.td - EVA ASE instructions -*- tablegen ------------*-=// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file describes Mips EVA ASE instructions. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// -// Instruction encodings -// -//===----------------------------------------------------------------------===// - -// Memory Load/Store EVA encodings -class LBE_ENC : SPECIAL3_EVA_LOAD_STORE_FM<OPCODE6_LBE>; -class LBuE_ENC : SPECIAL3_EVA_LOAD_STORE_FM<OPCODE6_LBuE>; -class LHE_ENC : SPECIAL3_EVA_LOAD_STORE_FM<OPCODE6_LHE>; -class LHuE_ENC : SPECIAL3_EVA_LOAD_STORE_FM<OPCODE6_LHuE>; -class LWE_ENC : SPECIAL3_EVA_LOAD_STORE_FM<OPCODE6_LWE>; - -class SBE_ENC : SPECIAL3_EVA_LOAD_STORE_FM<OPCODE6_SBE>; -class SHE_ENC : SPECIAL3_EVA_LOAD_STORE_FM<OPCODE6_SHE>; -class SWE_ENC : SPECIAL3_EVA_LOAD_STORE_FM<OPCODE6_SWE>; - -// load/store left/right EVA encodings -class LWLE_ENC : SPECIAL3_EVA_LOAD_STORE_FM<OPCODE6_LWLE>; -class LWRE_ENC : SPECIAL3_EVA_LOAD_STORE_FM<OPCODE6_LWRE>; -class SWLE_ENC : SPECIAL3_EVA_LOAD_STORE_FM<OPCODE6_SWLE>; -class SWRE_ENC : SPECIAL3_EVA_LOAD_STORE_FM<OPCODE6_SWRE>; - -// Load-linked EVA, Store-conditional EVA encodings -class LLE_ENC : SPECIAL3_EVA_LOAD_STORE_FM<OPCODE6_LLE>; -class SCE_ENC : SPECIAL3_EVA_LOAD_STORE_FM<OPCODE6_SCE>; - -class TLBINV_ENC : TLB_FM<OPCODE6_TLBINV>; -class TLBINVF_ENC : TLB_FM<OPCODE6_TLBINVF>; - -class CACHEE_ENC : SPECIAL3_EVA_LOAD_STORE_FM<OPCODE6_CACHEE>; -class PREFE_ENC : SPECIAL3_EVA_LOAD_STORE_FM<OPCODE6_PREFE>; - -//===----------------------------------------------------------------------===// -// -// Instruction descriptions -// -//===----------------------------------------------------------------------===// - -// Memory Load/Store EVA descriptions -class LOAD_EVA_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, - InstrItinClass itin = NoItinerary> { - dag OutOperandList = (outs GPROpnd:$rt); - dag InOperandList = (ins mem_simm9:$addr); - string AsmString = !strconcat(instr_asm, "\t$rt, $addr"); - list<dag> Pattern = []; - string DecoderMethod = "DecodeMemEVA"; - bit canFoldAsLoad = 1; - string BaseOpcode = instr_asm; - bit mayLoad = 1; - InstrItinClass Itinerary = itin; -} - -class LBE_DESC : LOAD_EVA_DESC_BASE<"lbe", GPR32Opnd, II_LBE>; -class LBuE_DESC : LOAD_EVA_DESC_BASE<"lbue", GPR32Opnd, II_LBUE>; -class LHE_DESC : LOAD_EVA_DESC_BASE<"lhe", GPR32Opnd, II_LHE>; -class LHuE_DESC : LOAD_EVA_DESC_BASE<"lhue", GPR32Opnd, II_LHUE>; -class LWE_DESC : LOAD_EVA_DESC_BASE<"lwe", GPR32Opnd, II_LWE>; - -class STORE_EVA_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, - SDPatternOperator OpNode = null_frag, - InstrItinClass itin = NoItinerary> { - dag OutOperandList = (outs); - dag InOperandList = (ins GPROpnd:$rt, mem_simm9:$addr); - string AsmString = !strconcat(instr_asm, "\t$rt, $addr"); - list<dag> Pattern = []; - string DecoderMethod = "DecodeMemEVA"; - string BaseOpcode = instr_asm; - bit mayStore = 1; - InstrItinClass Itinerary = itin; -} - -class SBE_DESC : STORE_EVA_DESC_BASE<"sbe", GPR32Opnd, null_frag, II_SBE>; -class SHE_DESC : STORE_EVA_DESC_BASE<"she", GPR32Opnd, null_frag, II_SHE>; -class SWE_DESC : STORE_EVA_DESC_BASE<"swe", GPR32Opnd, null_frag, II_SWE>; - -// Load/Store Left/Right EVA descriptions -class LOAD_LEFT_RIGHT_EVA_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, - InstrItinClass itin = NoItinerary> { - dag OutOperandList = (outs GPROpnd:$rt); - dag InOperandList = (ins mem_simm9:$addr, GPROpnd:$src); - string AsmString = !strconcat(instr_asm, "\t$rt, $addr"); - list<dag> Pattern = []; - string DecoderMethod = "DecodeMemEVA"; - string BaseOpcode = instr_asm; - string Constraints = "$src = $rt"; - bit canFoldAsLoad = 1; - InstrItinClass Itinerary = itin; - bit mayLoad = 1; - bit mayStore = 0; -} - -class LWLE_DESC : LOAD_LEFT_RIGHT_EVA_DESC_BASE<"lwle", GPR32Opnd, II_LWLE>; -class LWRE_DESC : LOAD_LEFT_RIGHT_EVA_DESC_BASE<"lwre", GPR32Opnd, II_LWRE>; - -class STORE_LEFT_RIGHT_EVA_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, - InstrItinClass itin = NoItinerary> { - dag OutOperandList = (outs); - dag InOperandList = (ins GPROpnd:$rt, mem_simm9:$addr); - string AsmString = !strconcat(instr_asm, "\t$rt, $addr"); - list<dag> Pattern = []; - string DecoderMethod = "DecodeMemEVA"; - string BaseOpcode = instr_asm; - InstrItinClass Itinerary = itin; - bit mayLoad = 0; - bit mayStore = 1; -} - -class SWLE_DESC : STORE_LEFT_RIGHT_EVA_DESC_BASE<"swle", GPR32Opnd, II_SWLE>; -class SWRE_DESC : STORE_LEFT_RIGHT_EVA_DESC_BASE<"swre", GPR32Opnd, II_SWRE>; - -// Load-linked EVA, Store-conditional EVA descriptions -class LLE_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, - InstrItinClass itin = NoItinerary> { - dag OutOperandList = (outs GPROpnd:$rt); - dag InOperandList = (ins mem_simm9:$addr); - string AsmString = !strconcat(instr_asm, "\t$rt, $addr"); - list<dag> Pattern = []; - string BaseOpcode = instr_asm; - bit mayLoad = 1; - string DecoderMethod = "DecodeMemEVA"; - InstrItinClass Itinerary = itin; -} - -class LLE_DESC : LLE_DESC_BASE<"lle", GPR32Opnd, II_LLE>; - -class SCE_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, - InstrItinClass itin = NoItinerary> { - dag OutOperandList = (outs GPROpnd:$dst); - dag InOperandList = (ins GPROpnd:$rt, mem_simm9:$addr); - string AsmString = !strconcat(instr_asm, "\t$rt, $addr"); - list<dag> Pattern = []; - string BaseOpcode = instr_asm; - bit mayStore = 1; - string Constraints = "$rt = $dst"; - string DecoderMethod = "DecodeMemEVA"; - InstrItinClass Itinerary = itin; -} - -class SCE_DESC : SCE_DESC_BASE<"sce", GPR32Opnd, II_SCE>; - -class TLB_DESC_BASE<string instr_asm, InstrItinClass itin = NoItinerary> { - dag OutOperandList = (outs); - dag InOperandList = (ins); - string AsmString = instr_asm; - list<dag> Pattern = []; - InstrItinClass Itinerary = itin; -} - -class TLBINV_DESC : TLB_DESC_BASE<"tlbinv", II_TLBINV>; -class TLBINVF_DESC : TLB_DESC_BASE<"tlbinvf", II_TLBINVF>; - -class CACHEE_DESC_BASE<string instr_asm, Operand MemOpnd, - InstrItinClass itin = NoItinerary> { - dag OutOperandList = (outs); - dag InOperandList = (ins MemOpnd:$addr, uimm5:$hint); - string AsmString = !strconcat(instr_asm, "\t$hint, $addr"); - list<dag> Pattern = []; - string BaseOpcode = instr_asm; - string DecoderMethod = "DecodeCacheeOp_CacheOpR6"; - InstrItinClass Itinerary = itin; -} - -class CACHEE_DESC : CACHEE_DESC_BASE<"cachee", mem_simm9, II_CACHEE>; -class PREFE_DESC : CACHEE_DESC_BASE<"prefe", mem_simm9, II_PREFE>; - -//===----------------------------------------------------------------------===// -// -// Instruction definitions -// -//===----------------------------------------------------------------------===// - -let AdditionalPredicates = [NotInMicroMips] in { - /// Load and Store EVA Instructions - def LBE : MMRel, LBE_ENC, LBE_DESC, ISA_MIPS32R2, ASE_EVA; - def LBuE : MMRel, LBuE_ENC, LBuE_DESC, ISA_MIPS32R2, ASE_EVA; - def LHE : MMRel, LHE_ENC, LHE_DESC, ISA_MIPS32R2, ASE_EVA; - def LHuE : MMRel, LHuE_ENC, LHuE_DESC, ISA_MIPS32R2, ASE_EVA; - def LWE : MMRel, LWE_ENC, LWE_DESC, ISA_MIPS32R2, ASE_EVA; - def SBE : MMRel, SBE_ENC, SBE_DESC, ISA_MIPS32R2, ASE_EVA; - def SHE : MMRel, SHE_ENC, SHE_DESC, ISA_MIPS32R2, ASE_EVA; - def SWE : MMRel, SWE_ENC, SWE_DESC, ISA_MIPS32R2, ASE_EVA; - - /// load/store left/right EVA - def LWLE : MMRel, LWLE_ENC, LWLE_DESC, ISA_MIPS32R2_NOT_32R6_64R6, ASE_EVA; - def LWRE : MMRel, LWRE_ENC, LWRE_DESC, ISA_MIPS32R2_NOT_32R6_64R6, ASE_EVA; - def SWLE : MMRel, SWLE_ENC, SWLE_DESC, ISA_MIPS32R2_NOT_32R6_64R6, ASE_EVA; - def SWRE : MMRel, SWRE_ENC, SWRE_DESC, ISA_MIPS32R2_NOT_32R6_64R6, ASE_EVA; - - /// Load-linked EVA, Store-conditional EVA - def LLE : MMRel, LLE_ENC, LLE_DESC, ISA_MIPS32R2, ASE_EVA; - def SCE : MMRel, SCE_ENC, SCE_DESC, ISA_MIPS32R2, ASE_EVA; - - /// TLB invalidate instructions - def TLBINV : TLBINV_ENC, TLBINV_DESC, ISA_MIPS32R2, ASE_EVA; - def TLBINVF : TLBINVF_ENC, TLBINVF_DESC, ISA_MIPS32R2, ASE_EVA; - - /// EVA versions of cache and pref - def CACHEE : MMRel, CACHEE_ENC, CACHEE_DESC, ISA_MIPS32R2, ASE_EVA; - def PREFE : MMRel, PREFE_ENC, PREFE_DESC, ISA_MIPS32R2, ASE_EVA; -} diff --git a/contrib/llvm/lib/Target/Mips/MipsExpandPseudo.cpp b/contrib/llvm/lib/Target/Mips/MipsExpandPseudo.cpp deleted file mode 100644 index 65d84a6c44a0..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsExpandPseudo.cpp +++ /dev/null @@ -1,701 +0,0 @@ -//===-- MipsExpandPseudoInsts.cpp - Expand pseudo instructions ------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains a pass that expands pseudo instructions into target -// instructions to allow proper scheduling, if-conversion, and other late -// optimizations. This pass should be run after register allocation but before -// the post-regalloc scheduling pass. -// -// This is currently only used for expanding atomic pseudos after register -// allocation. We do this to avoid the fast register allocator introducing -// spills between ll and sc. These stores cause some MIPS implementations to -// abort the atomic RMW sequence. -// -//===----------------------------------------------------------------------===// - -#include "Mips.h" -#include "MipsInstrInfo.h" -#include "MipsSubtarget.h" -#include "llvm/CodeGen/LivePhysRegs.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" - -using namespace llvm; - -#define DEBUG_TYPE "mips-pseudo" - -namespace { - class MipsExpandPseudo : public MachineFunctionPass { - public: - static char ID; - MipsExpandPseudo() : MachineFunctionPass(ID) {} - - const MipsInstrInfo *TII; - const MipsSubtarget *STI; - - bool runOnMachineFunction(MachineFunction &Fn) override; - - MachineFunctionProperties getRequiredProperties() const override { - return MachineFunctionProperties().set( - MachineFunctionProperties::Property::NoVRegs); - } - - StringRef getPassName() const override { - return "Mips pseudo instruction expansion pass"; - } - - private: - bool expandAtomicCmpSwap(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI, - MachineBasicBlock::iterator &NextMBBI); - bool expandAtomicCmpSwapSubword(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI, - MachineBasicBlock::iterator &NextMBBI); - - bool expandAtomicBinOp(MachineBasicBlock &BB, - MachineBasicBlock::iterator I, - MachineBasicBlock::iterator &NMBBI, unsigned Size); - bool expandAtomicBinOpSubword(MachineBasicBlock &BB, - MachineBasicBlock::iterator I, - MachineBasicBlock::iterator &NMBBI); - - bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, - MachineBasicBlock::iterator &NMBB); - bool expandMBB(MachineBasicBlock &MBB); - }; - char MipsExpandPseudo::ID = 0; -} - -bool MipsExpandPseudo::expandAtomicCmpSwapSubword( - MachineBasicBlock &BB, MachineBasicBlock::iterator I, - MachineBasicBlock::iterator &NMBBI) { - - MachineFunction *MF = BB.getParent(); - - const bool ArePtrs64bit = STI->getABI().ArePtrs64bit(); - DebugLoc DL = I->getDebugLoc(); - unsigned LL, SC; - - unsigned ZERO = Mips::ZERO; - unsigned BNE = Mips::BNE; - unsigned BEQ = Mips::BEQ; - unsigned SEOp = - I->getOpcode() == Mips::ATOMIC_CMP_SWAP_I8_POSTRA ? Mips::SEB : Mips::SEH; - - if (STI->inMicroMipsMode()) { - LL = STI->hasMips32r6() ? Mips::LL_MMR6 : Mips::LL_MM; - SC = STI->hasMips32r6() ? Mips::SC_MMR6 : Mips::SC_MM; - BNE = STI->hasMips32r6() ? Mips::BNEC_MMR6 : Mips::BNE_MM; - BEQ = STI->hasMips32r6() ? Mips::BEQC_MMR6 : Mips::BEQ_MM; - } else { - LL = STI->hasMips32r6() ? (ArePtrs64bit ? Mips::LL64_R6 : Mips::LL_R6) - : (ArePtrs64bit ? Mips::LL64 : Mips::LL); - SC = STI->hasMips32r6() ? (ArePtrs64bit ? Mips::SC64_R6 : Mips::SC_R6) - : (ArePtrs64bit ? Mips::SC64 : Mips::SC); - } - - unsigned Dest = I->getOperand(0).getReg(); - unsigned Ptr = I->getOperand(1).getReg(); - unsigned Mask = I->getOperand(2).getReg(); - unsigned ShiftCmpVal = I->getOperand(3).getReg(); - unsigned Mask2 = I->getOperand(4).getReg(); - unsigned ShiftNewVal = I->getOperand(5).getReg(); - unsigned ShiftAmnt = I->getOperand(6).getReg(); - unsigned Scratch = I->getOperand(7).getReg(); - unsigned Scratch2 = I->getOperand(8).getReg(); - - // insert new blocks after the current block - const BasicBlock *LLVM_BB = BB.getBasicBlock(); - MachineBasicBlock *loop1MBB = MF->CreateMachineBasicBlock(LLVM_BB); - MachineBasicBlock *loop2MBB = MF->CreateMachineBasicBlock(LLVM_BB); - MachineBasicBlock *sinkMBB = MF->CreateMachineBasicBlock(LLVM_BB); - MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB); - MachineFunction::iterator It = ++BB.getIterator(); - MF->insert(It, loop1MBB); - MF->insert(It, loop2MBB); - MF->insert(It, sinkMBB); - MF->insert(It, exitMBB); - - // Transfer the remainder of BB and its successor edges to exitMBB. - exitMBB->splice(exitMBB->begin(), &BB, - std::next(MachineBasicBlock::iterator(I)), BB.end()); - exitMBB->transferSuccessorsAndUpdatePHIs(&BB); - - // thisMBB: - // ... - // fallthrough --> loop1MBB - BB.addSuccessor(loop1MBB, BranchProbability::getOne()); - loop1MBB->addSuccessor(sinkMBB); - loop1MBB->addSuccessor(loop2MBB); - loop1MBB->normalizeSuccProbs(); - loop2MBB->addSuccessor(loop1MBB); - loop2MBB->addSuccessor(sinkMBB); - loop2MBB->normalizeSuccProbs(); - sinkMBB->addSuccessor(exitMBB, BranchProbability::getOne()); - - // loop1MBB: - // ll dest, 0(ptr) - // and Mask', dest, Mask - // bne Mask', ShiftCmpVal, exitMBB - BuildMI(loop1MBB, DL, TII->get(LL), Scratch).addReg(Ptr).addImm(0); - BuildMI(loop1MBB, DL, TII->get(Mips::AND), Scratch2) - .addReg(Scratch) - .addReg(Mask); - BuildMI(loop1MBB, DL, TII->get(BNE)) - .addReg(Scratch2).addReg(ShiftCmpVal).addMBB(sinkMBB); - - // loop2MBB: - // and dest, dest, mask2 - // or dest, dest, ShiftNewVal - // sc dest, dest, 0(ptr) - // beq dest, $0, loop1MBB - BuildMI(loop2MBB, DL, TII->get(Mips::AND), Scratch) - .addReg(Scratch, RegState::Kill) - .addReg(Mask2); - BuildMI(loop2MBB, DL, TII->get(Mips::OR), Scratch) - .addReg(Scratch, RegState::Kill) - .addReg(ShiftNewVal); - BuildMI(loop2MBB, DL, TII->get(SC), Scratch) - .addReg(Scratch, RegState::Kill) - .addReg(Ptr) - .addImm(0); - BuildMI(loop2MBB, DL, TII->get(BEQ)) - .addReg(Scratch, RegState::Kill) - .addReg(ZERO) - .addMBB(loop1MBB); - - // sinkMBB: - // srl srlres, Mask', shiftamt - // sign_extend dest,srlres - BuildMI(sinkMBB, DL, TII->get(Mips::SRLV), Dest) - .addReg(Scratch2) - .addReg(ShiftAmnt); - if (STI->hasMips32r2()) { - BuildMI(sinkMBB, DL, TII->get(SEOp), Dest).addReg(Dest); - } else { - const unsigned ShiftImm = - I->getOpcode() == Mips::ATOMIC_CMP_SWAP_I16_POSTRA ? 16 : 24; - BuildMI(sinkMBB, DL, TII->get(Mips::SLL), Dest) - .addReg(Dest, RegState::Kill) - .addImm(ShiftImm); - BuildMI(sinkMBB, DL, TII->get(Mips::SRA), Dest) - .addReg(Dest, RegState::Kill) - .addImm(ShiftImm); - } - - LivePhysRegs LiveRegs; - computeAndAddLiveIns(LiveRegs, *loop1MBB); - computeAndAddLiveIns(LiveRegs, *loop2MBB); - computeAndAddLiveIns(LiveRegs, *sinkMBB); - computeAndAddLiveIns(LiveRegs, *exitMBB); - - NMBBI = BB.end(); - I->eraseFromParent(); - return true; -} - -bool MipsExpandPseudo::expandAtomicCmpSwap(MachineBasicBlock &BB, - MachineBasicBlock::iterator I, - MachineBasicBlock::iterator &NMBBI) { - - const unsigned Size = - I->getOpcode() == Mips::ATOMIC_CMP_SWAP_I32_POSTRA ? 4 : 8; - MachineFunction *MF = BB.getParent(); - - const bool ArePtrs64bit = STI->getABI().ArePtrs64bit(); - DebugLoc DL = I->getDebugLoc(); - - unsigned LL, SC, ZERO, BNE, BEQ, MOVE; - - if (Size == 4) { - if (STI->inMicroMipsMode()) { - LL = STI->hasMips32r6() ? Mips::LL_MMR6 : Mips::LL_MM; - SC = STI->hasMips32r6() ? Mips::SC_MMR6 : Mips::SC_MM; - BNE = STI->hasMips32r6() ? Mips::BNEC_MMR6 : Mips::BNE_MM; - BEQ = STI->hasMips32r6() ? Mips::BEQC_MMR6 : Mips::BEQ_MM; - } else { - LL = STI->hasMips32r6() - ? (ArePtrs64bit ? Mips::LL64_R6 : Mips::LL_R6) - : (ArePtrs64bit ? Mips::LL64 : Mips::LL); - SC = STI->hasMips32r6() - ? (ArePtrs64bit ? Mips::SC64_R6 : Mips::SC_R6) - : (ArePtrs64bit ? Mips::SC64 : Mips::SC); - BNE = Mips::BNE; - BEQ = Mips::BEQ; - } - - ZERO = Mips::ZERO; - MOVE = Mips::OR; - } else { - LL = STI->hasMips64r6() ? Mips::LLD_R6 : Mips::LLD; - SC = STI->hasMips64r6() ? Mips::SCD_R6 : Mips::SCD; - ZERO = Mips::ZERO_64; - BNE = Mips::BNE64; - BEQ = Mips::BEQ64; - MOVE = Mips::OR64; - } - - unsigned Dest = I->getOperand(0).getReg(); - unsigned Ptr = I->getOperand(1).getReg(); - unsigned OldVal = I->getOperand(2).getReg(); - unsigned NewVal = I->getOperand(3).getReg(); - unsigned Scratch = I->getOperand(4).getReg(); - - // insert new blocks after the current block - const BasicBlock *LLVM_BB = BB.getBasicBlock(); - MachineBasicBlock *loop1MBB = MF->CreateMachineBasicBlock(LLVM_BB); - MachineBasicBlock *loop2MBB = MF->CreateMachineBasicBlock(LLVM_BB); - MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB); - MachineFunction::iterator It = ++BB.getIterator(); - MF->insert(It, loop1MBB); - MF->insert(It, loop2MBB); - MF->insert(It, exitMBB); - - // Transfer the remainder of BB and its successor edges to exitMBB. - exitMBB->splice(exitMBB->begin(), &BB, - std::next(MachineBasicBlock::iterator(I)), BB.end()); - exitMBB->transferSuccessorsAndUpdatePHIs(&BB); - - // thisMBB: - // ... - // fallthrough --> loop1MBB - BB.addSuccessor(loop1MBB, BranchProbability::getOne()); - loop1MBB->addSuccessor(exitMBB); - loop1MBB->addSuccessor(loop2MBB); - loop1MBB->normalizeSuccProbs(); - loop2MBB->addSuccessor(loop1MBB); - loop2MBB->addSuccessor(exitMBB); - loop2MBB->normalizeSuccProbs(); - - // loop1MBB: - // ll dest, 0(ptr) - // bne dest, oldval, exitMBB - BuildMI(loop1MBB, DL, TII->get(LL), Dest).addReg(Ptr).addImm(0); - BuildMI(loop1MBB, DL, TII->get(BNE)) - .addReg(Dest, RegState::Kill).addReg(OldVal).addMBB(exitMBB); - - // loop2MBB: - // move scratch, NewVal - // sc Scratch, Scratch, 0(ptr) - // beq Scratch, $0, loop1MBB - BuildMI(loop2MBB, DL, TII->get(MOVE), Scratch).addReg(NewVal).addReg(ZERO); - BuildMI(loop2MBB, DL, TII->get(SC), Scratch) - .addReg(Scratch).addReg(Ptr).addImm(0); - BuildMI(loop2MBB, DL, TII->get(BEQ)) - .addReg(Scratch, RegState::Kill).addReg(ZERO).addMBB(loop1MBB); - - LivePhysRegs LiveRegs; - computeAndAddLiveIns(LiveRegs, *loop1MBB); - computeAndAddLiveIns(LiveRegs, *loop2MBB); - computeAndAddLiveIns(LiveRegs, *exitMBB); - - NMBBI = BB.end(); - I->eraseFromParent(); - return true; -} - -bool MipsExpandPseudo::expandAtomicBinOpSubword( - MachineBasicBlock &BB, MachineBasicBlock::iterator I, - MachineBasicBlock::iterator &NMBBI) { - - MachineFunction *MF = BB.getParent(); - - const bool ArePtrs64bit = STI->getABI().ArePtrs64bit(); - DebugLoc DL = I->getDebugLoc(); - - unsigned LL, SC; - unsigned BEQ = Mips::BEQ; - unsigned SEOp = Mips::SEH; - - if (STI->inMicroMipsMode()) { - LL = STI->hasMips32r6() ? Mips::LL_MMR6 : Mips::LL_MM; - SC = STI->hasMips32r6() ? Mips::SC_MMR6 : Mips::SC_MM; - BEQ = STI->hasMips32r6() ? Mips::BEQC_MMR6 : Mips::BEQ_MM; - } else { - LL = STI->hasMips32r6() ? (ArePtrs64bit ? Mips::LL64_R6 : Mips::LL_R6) - : (ArePtrs64bit ? Mips::LL64 : Mips::LL); - SC = STI->hasMips32r6() ? (ArePtrs64bit ? Mips::SC64_R6 : Mips::SC_R6) - : (ArePtrs64bit ? Mips::SC64 : Mips::SC); - } - - bool IsSwap = false; - bool IsNand = false; - - unsigned Opcode = 0; - switch (I->getOpcode()) { - case Mips::ATOMIC_LOAD_NAND_I8_POSTRA: - SEOp = Mips::SEB; - LLVM_FALLTHROUGH; - case Mips::ATOMIC_LOAD_NAND_I16_POSTRA: - IsNand = true; - break; - case Mips::ATOMIC_SWAP_I8_POSTRA: - SEOp = Mips::SEB; - LLVM_FALLTHROUGH; - case Mips::ATOMIC_SWAP_I16_POSTRA: - IsSwap = true; - break; - case Mips::ATOMIC_LOAD_ADD_I8_POSTRA: - SEOp = Mips::SEB; - LLVM_FALLTHROUGH; - case Mips::ATOMIC_LOAD_ADD_I16_POSTRA: - Opcode = Mips::ADDu; - break; - case Mips::ATOMIC_LOAD_SUB_I8_POSTRA: - SEOp = Mips::SEB; - LLVM_FALLTHROUGH; - case Mips::ATOMIC_LOAD_SUB_I16_POSTRA: - Opcode = Mips::SUBu; - break; - case Mips::ATOMIC_LOAD_AND_I8_POSTRA: - SEOp = Mips::SEB; - LLVM_FALLTHROUGH; - case Mips::ATOMIC_LOAD_AND_I16_POSTRA: - Opcode = Mips::AND; - break; - case Mips::ATOMIC_LOAD_OR_I8_POSTRA: - SEOp = Mips::SEB; - LLVM_FALLTHROUGH; - case Mips::ATOMIC_LOAD_OR_I16_POSTRA: - Opcode = Mips::OR; - break; - case Mips::ATOMIC_LOAD_XOR_I8_POSTRA: - SEOp = Mips::SEB; - LLVM_FALLTHROUGH; - case Mips::ATOMIC_LOAD_XOR_I16_POSTRA: - Opcode = Mips::XOR; - break; - default: - llvm_unreachable("Unknown subword atomic pseudo for expansion!"); - } - - unsigned Dest = I->getOperand(0).getReg(); - unsigned Ptr = I->getOperand(1).getReg(); - unsigned Incr = I->getOperand(2).getReg(); - unsigned Mask = I->getOperand(3).getReg(); - unsigned Mask2 = I->getOperand(4).getReg(); - unsigned ShiftAmnt = I->getOperand(5).getReg(); - unsigned OldVal = I->getOperand(6).getReg(); - unsigned BinOpRes = I->getOperand(7).getReg(); - unsigned StoreVal = I->getOperand(8).getReg(); - - const BasicBlock *LLVM_BB = BB.getBasicBlock(); - MachineBasicBlock *loopMBB = MF->CreateMachineBasicBlock(LLVM_BB); - MachineBasicBlock *sinkMBB = MF->CreateMachineBasicBlock(LLVM_BB); - MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB); - MachineFunction::iterator It = ++BB.getIterator(); - MF->insert(It, loopMBB); - MF->insert(It, sinkMBB); - MF->insert(It, exitMBB); - - exitMBB->splice(exitMBB->begin(), &BB, std::next(I), BB.end()); - exitMBB->transferSuccessorsAndUpdatePHIs(&BB); - - BB.addSuccessor(loopMBB, BranchProbability::getOne()); - loopMBB->addSuccessor(sinkMBB); - loopMBB->addSuccessor(loopMBB); - loopMBB->normalizeSuccProbs(); - - BuildMI(loopMBB, DL, TII->get(LL), OldVal).addReg(Ptr).addImm(0); - if (IsNand) { - // and andres, oldval, incr2 - // nor binopres, $0, andres - // and newval, binopres, mask - BuildMI(loopMBB, DL, TII->get(Mips::AND), BinOpRes) - .addReg(OldVal) - .addReg(Incr); - BuildMI(loopMBB, DL, TII->get(Mips::NOR), BinOpRes) - .addReg(Mips::ZERO) - .addReg(BinOpRes); - BuildMI(loopMBB, DL, TII->get(Mips::AND), BinOpRes) - .addReg(BinOpRes) - .addReg(Mask); - } else if (!IsSwap) { - // <binop> binopres, oldval, incr2 - // and newval, binopres, mask - BuildMI(loopMBB, DL, TII->get(Opcode), BinOpRes) - .addReg(OldVal) - .addReg(Incr); - BuildMI(loopMBB, DL, TII->get(Mips::AND), BinOpRes) - .addReg(BinOpRes) - .addReg(Mask); - } else { // atomic.swap - // and newval, incr2, mask - BuildMI(loopMBB, DL, TII->get(Mips::AND), BinOpRes) - .addReg(Incr) - .addReg(Mask); - } - - // and StoreVal, OlddVal, Mask2 - // or StoreVal, StoreVal, BinOpRes - // StoreVal<tied1> = sc StoreVal, 0(Ptr) - // beq StoreVal, zero, loopMBB - BuildMI(loopMBB, DL, TII->get(Mips::AND), StoreVal) - .addReg(OldVal).addReg(Mask2); - BuildMI(loopMBB, DL, TII->get(Mips::OR), StoreVal) - .addReg(StoreVal).addReg(BinOpRes); - BuildMI(loopMBB, DL, TII->get(SC), StoreVal) - .addReg(StoreVal).addReg(Ptr).addImm(0); - BuildMI(loopMBB, DL, TII->get(BEQ)) - .addReg(StoreVal).addReg(Mips::ZERO).addMBB(loopMBB); - - // sinkMBB: - // and maskedoldval1,oldval,mask - // srl srlres,maskedoldval1,shiftamt - // sign_extend dest,srlres - - sinkMBB->addSuccessor(exitMBB, BranchProbability::getOne()); - - BuildMI(sinkMBB, DL, TII->get(Mips::AND), Dest) - .addReg(OldVal).addReg(Mask); - BuildMI(sinkMBB, DL, TII->get(Mips::SRLV), Dest) - .addReg(Dest).addReg(ShiftAmnt); - - if (STI->hasMips32r2()) { - BuildMI(sinkMBB, DL, TII->get(SEOp), Dest).addReg(Dest); - } else { - const unsigned ShiftImm = SEOp == Mips::SEH ? 16 : 24; - BuildMI(sinkMBB, DL, TII->get(Mips::SLL), Dest) - .addReg(Dest, RegState::Kill) - .addImm(ShiftImm); - BuildMI(sinkMBB, DL, TII->get(Mips::SRA), Dest) - .addReg(Dest, RegState::Kill) - .addImm(ShiftImm); - } - - LivePhysRegs LiveRegs; - computeAndAddLiveIns(LiveRegs, *loopMBB); - computeAndAddLiveIns(LiveRegs, *sinkMBB); - computeAndAddLiveIns(LiveRegs, *exitMBB); - - NMBBI = BB.end(); - I->eraseFromParent(); - - return true; -} - -bool MipsExpandPseudo::expandAtomicBinOp(MachineBasicBlock &BB, - MachineBasicBlock::iterator I, - MachineBasicBlock::iterator &NMBBI, - unsigned Size) { - MachineFunction *MF = BB.getParent(); - - const bool ArePtrs64bit = STI->getABI().ArePtrs64bit(); - DebugLoc DL = I->getDebugLoc(); - - unsigned LL, SC, ZERO, BEQ; - - if (Size == 4) { - if (STI->inMicroMipsMode()) { - LL = STI->hasMips32r6() ? Mips::LL_MMR6 : Mips::LL_MM; - SC = STI->hasMips32r6() ? Mips::SC_MMR6 : Mips::SC_MM; - BEQ = STI->hasMips32r6() ? Mips::BEQC_MMR6 : Mips::BEQ_MM; - } else { - LL = STI->hasMips32r6() - ? (ArePtrs64bit ? Mips::LL64_R6 : Mips::LL_R6) - : (ArePtrs64bit ? Mips::LL64 : Mips::LL); - SC = STI->hasMips32r6() - ? (ArePtrs64bit ? Mips::SC64_R6 : Mips::SC_R6) - : (ArePtrs64bit ? Mips::SC64 : Mips::SC); - BEQ = Mips::BEQ; - } - - ZERO = Mips::ZERO; - } else { - LL = STI->hasMips64r6() ? Mips::LLD_R6 : Mips::LLD; - SC = STI->hasMips64r6() ? Mips::SCD_R6 : Mips::SCD; - ZERO = Mips::ZERO_64; - BEQ = Mips::BEQ64; - } - - unsigned OldVal = I->getOperand(0).getReg(); - unsigned Ptr = I->getOperand(1).getReg(); - unsigned Incr = I->getOperand(2).getReg(); - unsigned Scratch = I->getOperand(3).getReg(); - - unsigned Opcode = 0; - unsigned OR = 0; - unsigned AND = 0; - unsigned NOR = 0; - bool IsNand = false; - switch (I->getOpcode()) { - case Mips::ATOMIC_LOAD_ADD_I32_POSTRA: - Opcode = Mips::ADDu; - break; - case Mips::ATOMIC_LOAD_SUB_I32_POSTRA: - Opcode = Mips::SUBu; - break; - case Mips::ATOMIC_LOAD_AND_I32_POSTRA: - Opcode = Mips::AND; - break; - case Mips::ATOMIC_LOAD_OR_I32_POSTRA: - Opcode = Mips::OR; - break; - case Mips::ATOMIC_LOAD_XOR_I32_POSTRA: - Opcode = Mips::XOR; - break; - case Mips::ATOMIC_LOAD_NAND_I32_POSTRA: - IsNand = true; - AND = Mips::AND; - NOR = Mips::NOR; - break; - case Mips::ATOMIC_SWAP_I32_POSTRA: - OR = Mips::OR; - break; - case Mips::ATOMIC_LOAD_ADD_I64_POSTRA: - Opcode = Mips::DADDu; - break; - case Mips::ATOMIC_LOAD_SUB_I64_POSTRA: - Opcode = Mips::DSUBu; - break; - case Mips::ATOMIC_LOAD_AND_I64_POSTRA: - Opcode = Mips::AND64; - break; - case Mips::ATOMIC_LOAD_OR_I64_POSTRA: - Opcode = Mips::OR64; - break; - case Mips::ATOMIC_LOAD_XOR_I64_POSTRA: - Opcode = Mips::XOR64; - break; - case Mips::ATOMIC_LOAD_NAND_I64_POSTRA: - IsNand = true; - AND = Mips::AND64; - NOR = Mips::NOR64; - break; - case Mips::ATOMIC_SWAP_I64_POSTRA: - OR = Mips::OR64; - break; - default: - llvm_unreachable("Unknown pseudo atomic!"); - } - - const BasicBlock *LLVM_BB = BB.getBasicBlock(); - MachineBasicBlock *loopMBB = MF->CreateMachineBasicBlock(LLVM_BB); - MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB); - MachineFunction::iterator It = ++BB.getIterator(); - MF->insert(It, loopMBB); - MF->insert(It, exitMBB); - - exitMBB->splice(exitMBB->begin(), &BB, std::next(I), BB.end()); - exitMBB->transferSuccessorsAndUpdatePHIs(&BB); - - BB.addSuccessor(loopMBB, BranchProbability::getOne()); - loopMBB->addSuccessor(exitMBB); - loopMBB->addSuccessor(loopMBB); - loopMBB->normalizeSuccProbs(); - - BuildMI(loopMBB, DL, TII->get(LL), OldVal).addReg(Ptr).addImm(0); - assert((OldVal != Ptr) && "Clobbered the wrong ptr reg!"); - assert((OldVal != Incr) && "Clobbered the wrong reg!"); - if (Opcode) { - BuildMI(loopMBB, DL, TII->get(Opcode), Scratch).addReg(OldVal).addReg(Incr); - } else if (IsNand) { - assert(AND && NOR && - "Unknown nand instruction for atomic pseudo expansion"); - BuildMI(loopMBB, DL, TII->get(AND), Scratch).addReg(OldVal).addReg(Incr); - BuildMI(loopMBB, DL, TII->get(NOR), Scratch).addReg(ZERO).addReg(Scratch); - } else { - assert(OR && "Unknown instruction for atomic pseudo expansion!"); - BuildMI(loopMBB, DL, TII->get(OR), Scratch).addReg(Incr).addReg(ZERO); - } - - BuildMI(loopMBB, DL, TII->get(SC), Scratch).addReg(Scratch).addReg(Ptr).addImm(0); - BuildMI(loopMBB, DL, TII->get(BEQ)).addReg(Scratch).addReg(ZERO).addMBB(loopMBB); - - NMBBI = BB.end(); - I->eraseFromParent(); - - LivePhysRegs LiveRegs; - computeAndAddLiveIns(LiveRegs, *loopMBB); - computeAndAddLiveIns(LiveRegs, *exitMBB); - - return true; -} - -bool MipsExpandPseudo::expandMI(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI, - MachineBasicBlock::iterator &NMBB) { - - bool Modified = false; - - switch (MBBI->getOpcode()) { - case Mips::ATOMIC_CMP_SWAP_I32_POSTRA: - case Mips::ATOMIC_CMP_SWAP_I64_POSTRA: - return expandAtomicCmpSwap(MBB, MBBI, NMBB); - case Mips::ATOMIC_CMP_SWAP_I8_POSTRA: - case Mips::ATOMIC_CMP_SWAP_I16_POSTRA: - return expandAtomicCmpSwapSubword(MBB, MBBI, NMBB); - case Mips::ATOMIC_SWAP_I8_POSTRA: - case Mips::ATOMIC_SWAP_I16_POSTRA: - case Mips::ATOMIC_LOAD_NAND_I8_POSTRA: - case Mips::ATOMIC_LOAD_NAND_I16_POSTRA: - case Mips::ATOMIC_LOAD_ADD_I8_POSTRA: - case Mips::ATOMIC_LOAD_ADD_I16_POSTRA: - case Mips::ATOMIC_LOAD_SUB_I8_POSTRA: - case Mips::ATOMIC_LOAD_SUB_I16_POSTRA: - case Mips::ATOMIC_LOAD_AND_I8_POSTRA: - case Mips::ATOMIC_LOAD_AND_I16_POSTRA: - case Mips::ATOMIC_LOAD_OR_I8_POSTRA: - case Mips::ATOMIC_LOAD_OR_I16_POSTRA: - case Mips::ATOMIC_LOAD_XOR_I8_POSTRA: - case Mips::ATOMIC_LOAD_XOR_I16_POSTRA: - return expandAtomicBinOpSubword(MBB, MBBI, NMBB); - case Mips::ATOMIC_LOAD_ADD_I32_POSTRA: - case Mips::ATOMIC_LOAD_SUB_I32_POSTRA: - case Mips::ATOMIC_LOAD_AND_I32_POSTRA: - case Mips::ATOMIC_LOAD_OR_I32_POSTRA: - case Mips::ATOMIC_LOAD_XOR_I32_POSTRA: - case Mips::ATOMIC_LOAD_NAND_I32_POSTRA: - case Mips::ATOMIC_SWAP_I32_POSTRA: - return expandAtomicBinOp(MBB, MBBI, NMBB, 4); - case Mips::ATOMIC_LOAD_ADD_I64_POSTRA: - case Mips::ATOMIC_LOAD_SUB_I64_POSTRA: - case Mips::ATOMIC_LOAD_AND_I64_POSTRA: - case Mips::ATOMIC_LOAD_OR_I64_POSTRA: - case Mips::ATOMIC_LOAD_XOR_I64_POSTRA: - case Mips::ATOMIC_LOAD_NAND_I64_POSTRA: - case Mips::ATOMIC_SWAP_I64_POSTRA: - return expandAtomicBinOp(MBB, MBBI, NMBB, 8); - default: - return Modified; - } -} - -bool MipsExpandPseudo::expandMBB(MachineBasicBlock &MBB) { - bool Modified = false; - - MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); - while (MBBI != E) { - MachineBasicBlock::iterator NMBBI = std::next(MBBI); - Modified |= expandMI(MBB, MBBI, NMBBI); - MBBI = NMBBI; - } - - return Modified; -} - -bool MipsExpandPseudo::runOnMachineFunction(MachineFunction &MF) { - STI = &static_cast<const MipsSubtarget &>(MF.getSubtarget()); - TII = STI->getInstrInfo(); - - bool Modified = false; - for (MachineFunction::iterator MFI = MF.begin(), E = MF.end(); MFI != E; - ++MFI) - Modified |= expandMBB(*MFI); - - if (Modified) - MF.RenumberBlocks(); - - return Modified; -} - -/// createMipsExpandPseudoPass - returns an instance of the pseudo instruction -/// expansion pass. -FunctionPass *llvm::createMipsExpandPseudoPass() { - return new MipsExpandPseudo(); -} diff --git a/contrib/llvm/lib/Target/Mips/MipsFastISel.cpp b/contrib/llvm/lib/Target/Mips/MipsFastISel.cpp deleted file mode 100644 index 123d3cc242f0..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsFastISel.cpp +++ /dev/null @@ -1,2153 +0,0 @@ -//===- MipsFastISel.cpp - Mips FastISel implementation --------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// This file defines the MIPS-specific support for the FastISel class. -/// Some of the target-specific code is generated by tablegen in the file -/// MipsGenFastISel.inc, which is #included here. -/// -//===----------------------------------------------------------------------===// - -#include "MCTargetDesc/MipsABIInfo.h" -#include "MCTargetDesc/MipsBaseInfo.h" -#include "MipsCCState.h" -#include "MipsISelLowering.h" -#include "MipsInstrInfo.h" -#include "MipsMachineFunction.h" -#include "MipsSubtarget.h" -#include "MipsTargetMachine.h" -#include "llvm/ADT/APInt.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/Analysis/TargetLibraryInfo.h" -#include "llvm/CodeGen/CallingConvLower.h" -#include "llvm/CodeGen/FastISel.h" -#include "llvm/CodeGen/FunctionLoweringInfo.h" -#include "llvm/CodeGen/ISDOpcodes.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/MachineMemOperand.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/TargetInstrInfo.h" -#include "llvm/CodeGen/TargetLowering.h" -#include "llvm/CodeGen/ValueTypes.h" -#include "llvm/IR/Attributes.h" -#include "llvm/IR/CallingConv.h" -#include "llvm/IR/Constant.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/GetElementPtrTypeIterator.h" -#include "llvm/IR/GlobalValue.h" -#include "llvm/IR/GlobalVariable.h" -#include "llvm/IR/InstrTypes.h" -#include "llvm/IR/Instruction.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/IntrinsicInst.h" -#include "llvm/IR/Operator.h" -#include "llvm/IR/Type.h" -#include "llvm/IR/User.h" -#include "llvm/IR/Value.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCInstrDesc.h" -#include "llvm/MC/MCRegisterInfo.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MachineValueType.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/raw_ostream.h" -#include <algorithm> -#include <array> -#include <cassert> -#include <cstdint> - -#define DEBUG_TYPE "mips-fastisel" - -using namespace llvm; - -extern cl::opt<bool> EmitJalrReloc; - -namespace { - -class MipsFastISel final : public FastISel { - - // All possible address modes. - class Address { - public: - using BaseKind = enum { RegBase, FrameIndexBase }; - - private: - BaseKind Kind = RegBase; - union { - unsigned Reg; - int FI; - } Base; - - int64_t Offset = 0; - - const GlobalValue *GV = nullptr; - - public: - // Innocuous defaults for our address. - Address() { Base.Reg = 0; } - - void setKind(BaseKind K) { Kind = K; } - BaseKind getKind() const { return Kind; } - bool isRegBase() const { return Kind == RegBase; } - bool isFIBase() const { return Kind == FrameIndexBase; } - - void setReg(unsigned Reg) { - assert(isRegBase() && "Invalid base register access!"); - Base.Reg = Reg; - } - - unsigned getReg() const { - assert(isRegBase() && "Invalid base register access!"); - return Base.Reg; - } - - void setFI(unsigned FI) { - assert(isFIBase() && "Invalid base frame index access!"); - Base.FI = FI; - } - - unsigned getFI() const { - assert(isFIBase() && "Invalid base frame index access!"); - return Base.FI; - } - - void setOffset(int64_t Offset_) { Offset = Offset_; } - int64_t getOffset() const { return Offset; } - void setGlobalValue(const GlobalValue *G) { GV = G; } - const GlobalValue *getGlobalValue() { return GV; } - }; - - /// Subtarget - Keep a pointer to the MipsSubtarget around so that we can - /// make the right decision when generating code for different targets. - const TargetMachine &TM; - const MipsSubtarget *Subtarget; - const TargetInstrInfo &TII; - const TargetLowering &TLI; - MipsFunctionInfo *MFI; - - // Convenience variables to avoid some queries. - LLVMContext *Context; - - bool fastLowerArguments() override; - bool fastLowerCall(CallLoweringInfo &CLI) override; - bool fastLowerIntrinsicCall(const IntrinsicInst *II) override; - - bool UnsupportedFPMode; // To allow fast-isel to proceed and just not handle - // floating point but not reject doing fast-isel in other - // situations - -private: - // Selection routines. - bool selectLogicalOp(const Instruction *I); - bool selectLoad(const Instruction *I); - bool selectStore(const Instruction *I); - bool selectBranch(const Instruction *I); - bool selectSelect(const Instruction *I); - bool selectCmp(const Instruction *I); - bool selectFPExt(const Instruction *I); - bool selectFPTrunc(const Instruction *I); - bool selectFPToInt(const Instruction *I, bool IsSigned); - bool selectRet(const Instruction *I); - bool selectTrunc(const Instruction *I); - bool selectIntExt(const Instruction *I); - bool selectShift(const Instruction *I); - bool selectDivRem(const Instruction *I, unsigned ISDOpcode); - - // Utility helper routines. - bool isTypeLegal(Type *Ty, MVT &VT); - bool isTypeSupported(Type *Ty, MVT &VT); - bool isLoadTypeLegal(Type *Ty, MVT &VT); - bool computeAddress(const Value *Obj, Address &Addr); - bool computeCallAddress(const Value *V, Address &Addr); - void simplifyAddress(Address &Addr); - - // Emit helper routines. - bool emitCmp(unsigned DestReg, const CmpInst *CI); - bool emitLoad(MVT VT, unsigned &ResultReg, Address &Addr, - unsigned Alignment = 0); - bool emitStore(MVT VT, unsigned SrcReg, Address Addr, - MachineMemOperand *MMO = nullptr); - bool emitStore(MVT VT, unsigned SrcReg, Address &Addr, - unsigned Alignment = 0); - unsigned emitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, bool isZExt); - bool emitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, unsigned DestReg, - - bool IsZExt); - bool emitIntZExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, unsigned DestReg); - - bool emitIntSExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, unsigned DestReg); - bool emitIntSExt32r1(MVT SrcVT, unsigned SrcReg, MVT DestVT, - unsigned DestReg); - bool emitIntSExt32r2(MVT SrcVT, unsigned SrcReg, MVT DestVT, - unsigned DestReg); - - unsigned getRegEnsuringSimpleIntegerWidening(const Value *, bool IsUnsigned); - - unsigned emitLogicalOp(unsigned ISDOpc, MVT RetVT, const Value *LHS, - const Value *RHS); - - unsigned materializeFP(const ConstantFP *CFP, MVT VT); - unsigned materializeGV(const GlobalValue *GV, MVT VT); - unsigned materializeInt(const Constant *C, MVT VT); - unsigned materialize32BitInt(int64_t Imm, const TargetRegisterClass *RC); - unsigned materializeExternalCallSym(MCSymbol *Syn); - - MachineInstrBuilder emitInst(unsigned Opc) { - return BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc)); - } - - MachineInstrBuilder emitInst(unsigned Opc, unsigned DstReg) { - return BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), - DstReg); - } - - MachineInstrBuilder emitInstStore(unsigned Opc, unsigned SrcReg, - unsigned MemReg, int64_t MemOffset) { - return emitInst(Opc).addReg(SrcReg).addReg(MemReg).addImm(MemOffset); - } - - MachineInstrBuilder emitInstLoad(unsigned Opc, unsigned DstReg, - unsigned MemReg, int64_t MemOffset) { - return emitInst(Opc, DstReg).addReg(MemReg).addImm(MemOffset); - } - - unsigned fastEmitInst_rr(unsigned MachineInstOpcode, - const TargetRegisterClass *RC, - unsigned Op0, bool Op0IsKill, - unsigned Op1, bool Op1IsKill); - - // for some reason, this default is not generated by tablegen - // so we explicitly generate it here. - unsigned fastEmitInst_riir(uint64_t inst, const TargetRegisterClass *RC, - unsigned Op0, bool Op0IsKill, uint64_t imm1, - uint64_t imm2, unsigned Op3, bool Op3IsKill) { - return 0; - } - - // Call handling routines. -private: - CCAssignFn *CCAssignFnForCall(CallingConv::ID CC) const; - bool processCallArgs(CallLoweringInfo &CLI, SmallVectorImpl<MVT> &ArgVTs, - unsigned &NumBytes); - bool finishCall(CallLoweringInfo &CLI, MVT RetVT, unsigned NumBytes); - - const MipsABIInfo &getABI() const { - return static_cast<const MipsTargetMachine &>(TM).getABI(); - } - -public: - // Backend specific FastISel code. - explicit MipsFastISel(FunctionLoweringInfo &funcInfo, - const TargetLibraryInfo *libInfo) - : FastISel(funcInfo, libInfo), TM(funcInfo.MF->getTarget()), - Subtarget(&funcInfo.MF->getSubtarget<MipsSubtarget>()), - TII(*Subtarget->getInstrInfo()), TLI(*Subtarget->getTargetLowering()) { - MFI = funcInfo.MF->getInfo<MipsFunctionInfo>(); - Context = &funcInfo.Fn->getContext(); - UnsupportedFPMode = Subtarget->isFP64bit() || Subtarget->useSoftFloat(); - } - - unsigned fastMaterializeAlloca(const AllocaInst *AI) override; - unsigned fastMaterializeConstant(const Constant *C) override; - bool fastSelectInstruction(const Instruction *I) override; - -#include "MipsGenFastISel.inc" -}; - -} // end anonymous namespace - -static bool CC_Mips(unsigned ValNo, MVT ValVT, MVT LocVT, - CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, - CCState &State) LLVM_ATTRIBUTE_UNUSED; - -static bool CC_MipsO32_FP32(unsigned ValNo, MVT ValVT, MVT LocVT, - CCValAssign::LocInfo LocInfo, - ISD::ArgFlagsTy ArgFlags, CCState &State) { - llvm_unreachable("should not be called"); -} - -static bool CC_MipsO32_FP64(unsigned ValNo, MVT ValVT, MVT LocVT, - CCValAssign::LocInfo LocInfo, - ISD::ArgFlagsTy ArgFlags, CCState &State) { - llvm_unreachable("should not be called"); -} - -#include "MipsGenCallingConv.inc" - -CCAssignFn *MipsFastISel::CCAssignFnForCall(CallingConv::ID CC) const { - return CC_MipsO32; -} - -unsigned MipsFastISel::emitLogicalOp(unsigned ISDOpc, MVT RetVT, - const Value *LHS, const Value *RHS) { - // Canonicalize immediates to the RHS first. - if (isa<ConstantInt>(LHS) && !isa<ConstantInt>(RHS)) - std::swap(LHS, RHS); - - unsigned Opc; - switch (ISDOpc) { - case ISD::AND: - Opc = Mips::AND; - break; - case ISD::OR: - Opc = Mips::OR; - break; - case ISD::XOR: - Opc = Mips::XOR; - break; - default: - llvm_unreachable("unexpected opcode"); - } - - unsigned LHSReg = getRegForValue(LHS); - if (!LHSReg) - return 0; - - unsigned RHSReg; - if (const auto *C = dyn_cast<ConstantInt>(RHS)) - RHSReg = materializeInt(C, MVT::i32); - else - RHSReg = getRegForValue(RHS); - if (!RHSReg) - return 0; - - unsigned ResultReg = createResultReg(&Mips::GPR32RegClass); - if (!ResultReg) - return 0; - - emitInst(Opc, ResultReg).addReg(LHSReg).addReg(RHSReg); - return ResultReg; -} - -unsigned MipsFastISel::fastMaterializeAlloca(const AllocaInst *AI) { - assert(TLI.getValueType(DL, AI->getType(), true) == MVT::i32 && - "Alloca should always return a pointer."); - - DenseMap<const AllocaInst *, int>::iterator SI = - FuncInfo.StaticAllocaMap.find(AI); - - if (SI != FuncInfo.StaticAllocaMap.end()) { - unsigned ResultReg = createResultReg(&Mips::GPR32RegClass); - BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Mips::LEA_ADDiu), - ResultReg) - .addFrameIndex(SI->second) - .addImm(0); - return ResultReg; - } - - return 0; -} - -unsigned MipsFastISel::materializeInt(const Constant *C, MVT VT) { - if (VT != MVT::i32 && VT != MVT::i16 && VT != MVT::i8 && VT != MVT::i1) - return 0; - const TargetRegisterClass *RC = &Mips::GPR32RegClass; - const ConstantInt *CI = cast<ConstantInt>(C); - return materialize32BitInt(CI->getZExtValue(), RC); -} - -unsigned MipsFastISel::materialize32BitInt(int64_t Imm, - const TargetRegisterClass *RC) { - unsigned ResultReg = createResultReg(RC); - - if (isInt<16>(Imm)) { - unsigned Opc = Mips::ADDiu; - emitInst(Opc, ResultReg).addReg(Mips::ZERO).addImm(Imm); - return ResultReg; - } else if (isUInt<16>(Imm)) { - emitInst(Mips::ORi, ResultReg).addReg(Mips::ZERO).addImm(Imm); - return ResultReg; - } - unsigned Lo = Imm & 0xFFFF; - unsigned Hi = (Imm >> 16) & 0xFFFF; - if (Lo) { - // Both Lo and Hi have nonzero bits. - unsigned TmpReg = createResultReg(RC); - emitInst(Mips::LUi, TmpReg).addImm(Hi); - emitInst(Mips::ORi, ResultReg).addReg(TmpReg).addImm(Lo); - } else { - emitInst(Mips::LUi, ResultReg).addImm(Hi); - } - return ResultReg; -} - -unsigned MipsFastISel::materializeFP(const ConstantFP *CFP, MVT VT) { - if (UnsupportedFPMode) - return 0; - int64_t Imm = CFP->getValueAPF().bitcastToAPInt().getZExtValue(); - if (VT == MVT::f32) { - const TargetRegisterClass *RC = &Mips::FGR32RegClass; - unsigned DestReg = createResultReg(RC); - unsigned TempReg = materialize32BitInt(Imm, &Mips::GPR32RegClass); - emitInst(Mips::MTC1, DestReg).addReg(TempReg); - return DestReg; - } else if (VT == MVT::f64) { - const TargetRegisterClass *RC = &Mips::AFGR64RegClass; - unsigned DestReg = createResultReg(RC); - unsigned TempReg1 = materialize32BitInt(Imm >> 32, &Mips::GPR32RegClass); - unsigned TempReg2 = - materialize32BitInt(Imm & 0xFFFFFFFF, &Mips::GPR32RegClass); - emitInst(Mips::BuildPairF64, DestReg).addReg(TempReg2).addReg(TempReg1); - return DestReg; - } - return 0; -} - -unsigned MipsFastISel::materializeGV(const GlobalValue *GV, MVT VT) { - // For now 32-bit only. - if (VT != MVT::i32) - return 0; - const TargetRegisterClass *RC = &Mips::GPR32RegClass; - unsigned DestReg = createResultReg(RC); - const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV); - bool IsThreadLocal = GVar && GVar->isThreadLocal(); - // TLS not supported at this time. - if (IsThreadLocal) - return 0; - emitInst(Mips::LW, DestReg) - .addReg(MFI->getGlobalBaseReg()) - .addGlobalAddress(GV, 0, MipsII::MO_GOT); - if ((GV->hasInternalLinkage() || - (GV->hasLocalLinkage() && !isa<Function>(GV)))) { - unsigned TempReg = createResultReg(RC); - emitInst(Mips::ADDiu, TempReg) - .addReg(DestReg) - .addGlobalAddress(GV, 0, MipsII::MO_ABS_LO); - DestReg = TempReg; - } - return DestReg; -} - -unsigned MipsFastISel::materializeExternalCallSym(MCSymbol *Sym) { - const TargetRegisterClass *RC = &Mips::GPR32RegClass; - unsigned DestReg = createResultReg(RC); - emitInst(Mips::LW, DestReg) - .addReg(MFI->getGlobalBaseReg()) - .addSym(Sym, MipsII::MO_GOT); - return DestReg; -} - -// Materialize a constant into a register, and return the register -// number (or zero if we failed to handle it). -unsigned MipsFastISel::fastMaterializeConstant(const Constant *C) { - EVT CEVT = TLI.getValueType(DL, C->getType(), true); - - // Only handle simple types. - if (!CEVT.isSimple()) - return 0; - MVT VT = CEVT.getSimpleVT(); - - if (const ConstantFP *CFP = dyn_cast<ConstantFP>(C)) - return (UnsupportedFPMode) ? 0 : materializeFP(CFP, VT); - else if (const GlobalValue *GV = dyn_cast<GlobalValue>(C)) - return materializeGV(GV, VT); - else if (isa<ConstantInt>(C)) - return materializeInt(C, VT); - - return 0; -} - -bool MipsFastISel::computeAddress(const Value *Obj, Address &Addr) { - const User *U = nullptr; - unsigned Opcode = Instruction::UserOp1; - if (const Instruction *I = dyn_cast<Instruction>(Obj)) { - // Don't walk into other basic blocks unless the object is an alloca from - // another block, otherwise it may not have a virtual register assigned. - if (FuncInfo.StaticAllocaMap.count(static_cast<const AllocaInst *>(Obj)) || - FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB) { - Opcode = I->getOpcode(); - U = I; - } - } else if (const ConstantExpr *C = dyn_cast<ConstantExpr>(Obj)) { - Opcode = C->getOpcode(); - U = C; - } - switch (Opcode) { - default: - break; - case Instruction::BitCast: - // Look through bitcasts. - return computeAddress(U->getOperand(0), Addr); - case Instruction::GetElementPtr: { - Address SavedAddr = Addr; - int64_t TmpOffset = Addr.getOffset(); - // Iterate through the GEP folding the constants into offsets where - // we can. - gep_type_iterator GTI = gep_type_begin(U); - for (User::const_op_iterator i = U->op_begin() + 1, e = U->op_end(); i != e; - ++i, ++GTI) { - const Value *Op = *i; - if (StructType *STy = GTI.getStructTypeOrNull()) { - const StructLayout *SL = DL.getStructLayout(STy); - unsigned Idx = cast<ConstantInt>(Op)->getZExtValue(); - TmpOffset += SL->getElementOffset(Idx); - } else { - uint64_t S = DL.getTypeAllocSize(GTI.getIndexedType()); - while (true) { - if (const ConstantInt *CI = dyn_cast<ConstantInt>(Op)) { - // Constant-offset addressing. - TmpOffset += CI->getSExtValue() * S; - break; - } - if (canFoldAddIntoGEP(U, Op)) { - // A compatible add with a constant operand. Fold the constant. - ConstantInt *CI = - cast<ConstantInt>(cast<AddOperator>(Op)->getOperand(1)); - TmpOffset += CI->getSExtValue() * S; - // Iterate on the other operand. - Op = cast<AddOperator>(Op)->getOperand(0); - continue; - } - // Unsupported - goto unsupported_gep; - } - } - } - // Try to grab the base operand now. - Addr.setOffset(TmpOffset); - if (computeAddress(U->getOperand(0), Addr)) - return true; - // We failed, restore everything and try the other options. - Addr = SavedAddr; - unsupported_gep: - break; - } - case Instruction::Alloca: { - const AllocaInst *AI = cast<AllocaInst>(Obj); - DenseMap<const AllocaInst *, int>::iterator SI = - FuncInfo.StaticAllocaMap.find(AI); - if (SI != FuncInfo.StaticAllocaMap.end()) { - Addr.setKind(Address::FrameIndexBase); - Addr.setFI(SI->second); - return true; - } - break; - } - } - Addr.setReg(getRegForValue(Obj)); - return Addr.getReg() != 0; -} - -bool MipsFastISel::computeCallAddress(const Value *V, Address &Addr) { - const User *U = nullptr; - unsigned Opcode = Instruction::UserOp1; - - if (const auto *I = dyn_cast<Instruction>(V)) { - // Check if the value is defined in the same basic block. This information - // is crucial to know whether or not folding an operand is valid. - if (I->getParent() == FuncInfo.MBB->getBasicBlock()) { - Opcode = I->getOpcode(); - U = I; - } - } else if (const auto *C = dyn_cast<ConstantExpr>(V)) { - Opcode = C->getOpcode(); - U = C; - } - - switch (Opcode) { - default: - break; - case Instruction::BitCast: - // Look past bitcasts if its operand is in the same BB. - return computeCallAddress(U->getOperand(0), Addr); - break; - case Instruction::IntToPtr: - // Look past no-op inttoptrs if its operand is in the same BB. - if (TLI.getValueType(DL, U->getOperand(0)->getType()) == - TLI.getPointerTy(DL)) - return computeCallAddress(U->getOperand(0), Addr); - break; - case Instruction::PtrToInt: - // Look past no-op ptrtoints if its operand is in the same BB. - if (TLI.getValueType(DL, U->getType()) == TLI.getPointerTy(DL)) - return computeCallAddress(U->getOperand(0), Addr); - break; - } - - if (const GlobalValue *GV = dyn_cast<GlobalValue>(V)) { - Addr.setGlobalValue(GV); - return true; - } - - // If all else fails, try to materialize the value in a register. - if (!Addr.getGlobalValue()) { - Addr.setReg(getRegForValue(V)); - return Addr.getReg() != 0; - } - - return false; -} - -bool MipsFastISel::isTypeLegal(Type *Ty, MVT &VT) { - EVT evt = TLI.getValueType(DL, Ty, true); - // Only handle simple types. - if (evt == MVT::Other || !evt.isSimple()) - return false; - VT = evt.getSimpleVT(); - - // Handle all legal types, i.e. a register that will directly hold this - // value. - return TLI.isTypeLegal(VT); -} - -bool MipsFastISel::isTypeSupported(Type *Ty, MVT &VT) { - if (Ty->isVectorTy()) - return false; - - if (isTypeLegal(Ty, VT)) - return true; - - // If this is a type than can be sign or zero-extended to a basic operation - // go ahead and accept it now. - if (VT == MVT::i1 || VT == MVT::i8 || VT == MVT::i16) - return true; - - return false; -} - -bool MipsFastISel::isLoadTypeLegal(Type *Ty, MVT &VT) { - if (isTypeLegal(Ty, VT)) - return true; - // We will extend this in a later patch: - // If this is a type than can be sign or zero-extended to a basic operation - // go ahead and accept it now. - if (VT == MVT::i8 || VT == MVT::i16) - return true; - return false; -} - -// Because of how EmitCmp is called with fast-isel, you can -// end up with redundant "andi" instructions after the sequences emitted below. -// We should try and solve this issue in the future. -// -bool MipsFastISel::emitCmp(unsigned ResultReg, const CmpInst *CI) { - const Value *Left = CI->getOperand(0), *Right = CI->getOperand(1); - bool IsUnsigned = CI->isUnsigned(); - unsigned LeftReg = getRegEnsuringSimpleIntegerWidening(Left, IsUnsigned); - if (LeftReg == 0) - return false; - unsigned RightReg = getRegEnsuringSimpleIntegerWidening(Right, IsUnsigned); - if (RightReg == 0) - return false; - CmpInst::Predicate P = CI->getPredicate(); - - switch (P) { - default: - return false; - case CmpInst::ICMP_EQ: { - unsigned TempReg = createResultReg(&Mips::GPR32RegClass); - emitInst(Mips::XOR, TempReg).addReg(LeftReg).addReg(RightReg); - emitInst(Mips::SLTiu, ResultReg).addReg(TempReg).addImm(1); - break; - } - case CmpInst::ICMP_NE: { - unsigned TempReg = createResultReg(&Mips::GPR32RegClass); - emitInst(Mips::XOR, TempReg).addReg(LeftReg).addReg(RightReg); - emitInst(Mips::SLTu, ResultReg).addReg(Mips::ZERO).addReg(TempReg); - break; - } - case CmpInst::ICMP_UGT: - emitInst(Mips::SLTu, ResultReg).addReg(RightReg).addReg(LeftReg); - break; - case CmpInst::ICMP_ULT: - emitInst(Mips::SLTu, ResultReg).addReg(LeftReg).addReg(RightReg); - break; - case CmpInst::ICMP_UGE: { - unsigned TempReg = createResultReg(&Mips::GPR32RegClass); - emitInst(Mips::SLTu, TempReg).addReg(LeftReg).addReg(RightReg); - emitInst(Mips::XORi, ResultReg).addReg(TempReg).addImm(1); - break; - } - case CmpInst::ICMP_ULE: { - unsigned TempReg = createResultReg(&Mips::GPR32RegClass); - emitInst(Mips::SLTu, TempReg).addReg(RightReg).addReg(LeftReg); - emitInst(Mips::XORi, ResultReg).addReg(TempReg).addImm(1); - break; - } - case CmpInst::ICMP_SGT: - emitInst(Mips::SLT, ResultReg).addReg(RightReg).addReg(LeftReg); - break; - case CmpInst::ICMP_SLT: - emitInst(Mips::SLT, ResultReg).addReg(LeftReg).addReg(RightReg); - break; - case CmpInst::ICMP_SGE: { - unsigned TempReg = createResultReg(&Mips::GPR32RegClass); - emitInst(Mips::SLT, TempReg).addReg(LeftReg).addReg(RightReg); - emitInst(Mips::XORi, ResultReg).addReg(TempReg).addImm(1); - break; - } - case CmpInst::ICMP_SLE: { - unsigned TempReg = createResultReg(&Mips::GPR32RegClass); - emitInst(Mips::SLT, TempReg).addReg(RightReg).addReg(LeftReg); - emitInst(Mips::XORi, ResultReg).addReg(TempReg).addImm(1); - break; - } - case CmpInst::FCMP_OEQ: - case CmpInst::FCMP_UNE: - case CmpInst::FCMP_OLT: - case CmpInst::FCMP_OLE: - case CmpInst::FCMP_OGT: - case CmpInst::FCMP_OGE: { - if (UnsupportedFPMode) - return false; - bool IsFloat = Left->getType()->isFloatTy(); - bool IsDouble = Left->getType()->isDoubleTy(); - if (!IsFloat && !IsDouble) - return false; - unsigned Opc, CondMovOpc; - switch (P) { - case CmpInst::FCMP_OEQ: - Opc = IsFloat ? Mips::C_EQ_S : Mips::C_EQ_D32; - CondMovOpc = Mips::MOVT_I; - break; - case CmpInst::FCMP_UNE: - Opc = IsFloat ? Mips::C_EQ_S : Mips::C_EQ_D32; - CondMovOpc = Mips::MOVF_I; - break; - case CmpInst::FCMP_OLT: - Opc = IsFloat ? Mips::C_OLT_S : Mips::C_OLT_D32; - CondMovOpc = Mips::MOVT_I; - break; - case CmpInst::FCMP_OLE: - Opc = IsFloat ? Mips::C_OLE_S : Mips::C_OLE_D32; - CondMovOpc = Mips::MOVT_I; - break; - case CmpInst::FCMP_OGT: - Opc = IsFloat ? Mips::C_ULE_S : Mips::C_ULE_D32; - CondMovOpc = Mips::MOVF_I; - break; - case CmpInst::FCMP_OGE: - Opc = IsFloat ? Mips::C_ULT_S : Mips::C_ULT_D32; - CondMovOpc = Mips::MOVF_I; - break; - default: - llvm_unreachable("Only switching of a subset of CCs."); - } - unsigned RegWithZero = createResultReg(&Mips::GPR32RegClass); - unsigned RegWithOne = createResultReg(&Mips::GPR32RegClass); - emitInst(Mips::ADDiu, RegWithZero).addReg(Mips::ZERO).addImm(0); - emitInst(Mips::ADDiu, RegWithOne).addReg(Mips::ZERO).addImm(1); - emitInst(Opc).addReg(Mips::FCC0, RegState::Define).addReg(LeftReg) - .addReg(RightReg); - emitInst(CondMovOpc, ResultReg) - .addReg(RegWithOne) - .addReg(Mips::FCC0) - .addReg(RegWithZero); - break; - } - } - return true; -} - -bool MipsFastISel::emitLoad(MVT VT, unsigned &ResultReg, Address &Addr, - unsigned Alignment) { - // - // more cases will be handled here in following patches. - // - unsigned Opc; - switch (VT.SimpleTy) { - case MVT::i32: - ResultReg = createResultReg(&Mips::GPR32RegClass); - Opc = Mips::LW; - break; - case MVT::i16: - ResultReg = createResultReg(&Mips::GPR32RegClass); - Opc = Mips::LHu; - break; - case MVT::i8: - ResultReg = createResultReg(&Mips::GPR32RegClass); - Opc = Mips::LBu; - break; - case MVT::f32: - if (UnsupportedFPMode) - return false; - ResultReg = createResultReg(&Mips::FGR32RegClass); - Opc = Mips::LWC1; - break; - case MVT::f64: - if (UnsupportedFPMode) - return false; - ResultReg = createResultReg(&Mips::AFGR64RegClass); - Opc = Mips::LDC1; - break; - default: - return false; - } - if (Addr.isRegBase()) { - simplifyAddress(Addr); - emitInstLoad(Opc, ResultReg, Addr.getReg(), Addr.getOffset()); - return true; - } - if (Addr.isFIBase()) { - unsigned FI = Addr.getFI(); - unsigned Align = 4; - int64_t Offset = Addr.getOffset(); - MachineFrameInfo &MFI = MF->getFrameInfo(); - MachineMemOperand *MMO = MF->getMachineMemOperand( - MachinePointerInfo::getFixedStack(*MF, FI), MachineMemOperand::MOLoad, - MFI.getObjectSize(FI), Align); - BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg) - .addFrameIndex(FI) - .addImm(Offset) - .addMemOperand(MMO); - return true; - } - return false; -} - -bool MipsFastISel::emitStore(MVT VT, unsigned SrcReg, Address &Addr, - unsigned Alignment) { - // - // more cases will be handled here in following patches. - // - unsigned Opc; - switch (VT.SimpleTy) { - case MVT::i8: - Opc = Mips::SB; - break; - case MVT::i16: - Opc = Mips::SH; - break; - case MVT::i32: - Opc = Mips::SW; - break; - case MVT::f32: - if (UnsupportedFPMode) - return false; - Opc = Mips::SWC1; - break; - case MVT::f64: - if (UnsupportedFPMode) - return false; - Opc = Mips::SDC1; - break; - default: - return false; - } - if (Addr.isRegBase()) { - simplifyAddress(Addr); - emitInstStore(Opc, SrcReg, Addr.getReg(), Addr.getOffset()); - return true; - } - if (Addr.isFIBase()) { - unsigned FI = Addr.getFI(); - unsigned Align = 4; - int64_t Offset = Addr.getOffset(); - MachineFrameInfo &MFI = MF->getFrameInfo(); - MachineMemOperand *MMO = MF->getMachineMemOperand( - MachinePointerInfo::getFixedStack(*MF, FI), MachineMemOperand::MOStore, - MFI.getObjectSize(FI), Align); - BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc)) - .addReg(SrcReg) - .addFrameIndex(FI) - .addImm(Offset) - .addMemOperand(MMO); - return true; - } - return false; -} - -bool MipsFastISel::selectLogicalOp(const Instruction *I) { - MVT VT; - if (!isTypeSupported(I->getType(), VT)) - return false; - - unsigned ResultReg; - switch (I->getOpcode()) { - default: - llvm_unreachable("Unexpected instruction."); - case Instruction::And: - ResultReg = emitLogicalOp(ISD::AND, VT, I->getOperand(0), I->getOperand(1)); - break; - case Instruction::Or: - ResultReg = emitLogicalOp(ISD::OR, VT, I->getOperand(0), I->getOperand(1)); - break; - case Instruction::Xor: - ResultReg = emitLogicalOp(ISD::XOR, VT, I->getOperand(0), I->getOperand(1)); - break; - } - - if (!ResultReg) - return false; - - updateValueMap(I, ResultReg); - return true; -} - -bool MipsFastISel::selectLoad(const Instruction *I) { - // Atomic loads need special handling. - if (cast<LoadInst>(I)->isAtomic()) - return false; - - // Verify we have a legal type before going any further. - MVT VT; - if (!isLoadTypeLegal(I->getType(), VT)) - return false; - - // See if we can handle this address. - Address Addr; - if (!computeAddress(I->getOperand(0), Addr)) - return false; - - unsigned ResultReg; - if (!emitLoad(VT, ResultReg, Addr, cast<LoadInst>(I)->getAlignment())) - return false; - updateValueMap(I, ResultReg); - return true; -} - -bool MipsFastISel::selectStore(const Instruction *I) { - Value *Op0 = I->getOperand(0); - unsigned SrcReg = 0; - - // Atomic stores need special handling. - if (cast<StoreInst>(I)->isAtomic()) - return false; - - // Verify we have a legal type before going any further. - MVT VT; - if (!isLoadTypeLegal(I->getOperand(0)->getType(), VT)) - return false; - - // Get the value to be stored into a register. - SrcReg = getRegForValue(Op0); - if (SrcReg == 0) - return false; - - // See if we can handle this address. - Address Addr; - if (!computeAddress(I->getOperand(1), Addr)) - return false; - - if (!emitStore(VT, SrcReg, Addr, cast<StoreInst>(I)->getAlignment())) - return false; - return true; -} - -// This can cause a redundant sltiu to be generated. -// FIXME: try and eliminate this in a future patch. -bool MipsFastISel::selectBranch(const Instruction *I) { - const BranchInst *BI = cast<BranchInst>(I); - MachineBasicBlock *BrBB = FuncInfo.MBB; - // - // TBB is the basic block for the case where the comparison is true. - // FBB is the basic block for the case where the comparison is false. - // if (cond) goto TBB - // goto FBB - // TBB: - // - MachineBasicBlock *TBB = FuncInfo.MBBMap[BI->getSuccessor(0)]; - MachineBasicBlock *FBB = FuncInfo.MBBMap[BI->getSuccessor(1)]; - - // Fold the common case of a conditional branch with a comparison - // in the same block. - unsigned ZExtCondReg = 0; - if (const CmpInst *CI = dyn_cast<CmpInst>(BI->getCondition())) { - if (CI->hasOneUse() && CI->getParent() == I->getParent()) { - ZExtCondReg = createResultReg(&Mips::GPR32RegClass); - if (!emitCmp(ZExtCondReg, CI)) - return false; - } - } - - // For the general case, we need to mask with 1. - if (ZExtCondReg == 0) { - unsigned CondReg = getRegForValue(BI->getCondition()); - if (CondReg == 0) - return false; - - ZExtCondReg = emitIntExt(MVT::i1, CondReg, MVT::i32, true); - if (ZExtCondReg == 0) - return false; - } - - BuildMI(*BrBB, FuncInfo.InsertPt, DbgLoc, TII.get(Mips::BGTZ)) - .addReg(ZExtCondReg) - .addMBB(TBB); - finishCondBranch(BI->getParent(), TBB, FBB); - return true; -} - -bool MipsFastISel::selectCmp(const Instruction *I) { - const CmpInst *CI = cast<CmpInst>(I); - unsigned ResultReg = createResultReg(&Mips::GPR32RegClass); - if (!emitCmp(ResultReg, CI)) - return false; - updateValueMap(I, ResultReg); - return true; -} - -// Attempt to fast-select a floating-point extend instruction. -bool MipsFastISel::selectFPExt(const Instruction *I) { - if (UnsupportedFPMode) - return false; - Value *Src = I->getOperand(0); - EVT SrcVT = TLI.getValueType(DL, Src->getType(), true); - EVT DestVT = TLI.getValueType(DL, I->getType(), true); - - if (SrcVT != MVT::f32 || DestVT != MVT::f64) - return false; - - unsigned SrcReg = - getRegForValue(Src); // this must be a 32bit floating point register class - // maybe we should handle this differently - if (!SrcReg) - return false; - - unsigned DestReg = createResultReg(&Mips::AFGR64RegClass); - emitInst(Mips::CVT_D32_S, DestReg).addReg(SrcReg); - updateValueMap(I, DestReg); - return true; -} - -bool MipsFastISel::selectSelect(const Instruction *I) { - assert(isa<SelectInst>(I) && "Expected a select instruction."); - - LLVM_DEBUG(dbgs() << "selectSelect\n"); - - MVT VT; - if (!isTypeSupported(I->getType(), VT) || UnsupportedFPMode) { - LLVM_DEBUG( - dbgs() << ".. .. gave up (!isTypeSupported || UnsupportedFPMode)\n"); - return false; - } - - unsigned CondMovOpc; - const TargetRegisterClass *RC; - - if (VT.isInteger() && !VT.isVector() && VT.getSizeInBits() <= 32) { - CondMovOpc = Mips::MOVN_I_I; - RC = &Mips::GPR32RegClass; - } else if (VT == MVT::f32) { - CondMovOpc = Mips::MOVN_I_S; - RC = &Mips::FGR32RegClass; - } else if (VT == MVT::f64) { - CondMovOpc = Mips::MOVN_I_D32; - RC = &Mips::AFGR64RegClass; - } else - return false; - - const SelectInst *SI = cast<SelectInst>(I); - const Value *Cond = SI->getCondition(); - unsigned Src1Reg = getRegForValue(SI->getTrueValue()); - unsigned Src2Reg = getRegForValue(SI->getFalseValue()); - unsigned CondReg = getRegForValue(Cond); - - if (!Src1Reg || !Src2Reg || !CondReg) - return false; - - unsigned ZExtCondReg = createResultReg(&Mips::GPR32RegClass); - if (!ZExtCondReg) - return false; - - if (!emitIntExt(MVT::i1, CondReg, MVT::i32, ZExtCondReg, true)) - return false; - - unsigned ResultReg = createResultReg(RC); - unsigned TempReg = createResultReg(RC); - - if (!ResultReg || !TempReg) - return false; - - emitInst(TargetOpcode::COPY, TempReg).addReg(Src2Reg); - emitInst(CondMovOpc, ResultReg) - .addReg(Src1Reg).addReg(ZExtCondReg).addReg(TempReg); - updateValueMap(I, ResultReg); - return true; -} - -// Attempt to fast-select a floating-point truncate instruction. -bool MipsFastISel::selectFPTrunc(const Instruction *I) { - if (UnsupportedFPMode) - return false; - Value *Src = I->getOperand(0); - EVT SrcVT = TLI.getValueType(DL, Src->getType(), true); - EVT DestVT = TLI.getValueType(DL, I->getType(), true); - - if (SrcVT != MVT::f64 || DestVT != MVT::f32) - return false; - - unsigned SrcReg = getRegForValue(Src); - if (!SrcReg) - return false; - - unsigned DestReg = createResultReg(&Mips::FGR32RegClass); - if (!DestReg) - return false; - - emitInst(Mips::CVT_S_D32, DestReg).addReg(SrcReg); - updateValueMap(I, DestReg); - return true; -} - -// Attempt to fast-select a floating-point-to-integer conversion. -bool MipsFastISel::selectFPToInt(const Instruction *I, bool IsSigned) { - if (UnsupportedFPMode) - return false; - MVT DstVT, SrcVT; - if (!IsSigned) - return false; // We don't handle this case yet. There is no native - // instruction for this but it can be synthesized. - Type *DstTy = I->getType(); - if (!isTypeLegal(DstTy, DstVT)) - return false; - - if (DstVT != MVT::i32) - return false; - - Value *Src = I->getOperand(0); - Type *SrcTy = Src->getType(); - if (!isTypeLegal(SrcTy, SrcVT)) - return false; - - if (SrcVT != MVT::f32 && SrcVT != MVT::f64) - return false; - - unsigned SrcReg = getRegForValue(Src); - if (SrcReg == 0) - return false; - - // Determine the opcode for the conversion, which takes place - // entirely within FPRs. - unsigned DestReg = createResultReg(&Mips::GPR32RegClass); - unsigned TempReg = createResultReg(&Mips::FGR32RegClass); - unsigned Opc = (SrcVT == MVT::f32) ? Mips::TRUNC_W_S : Mips::TRUNC_W_D32; - - // Generate the convert. - emitInst(Opc, TempReg).addReg(SrcReg); - emitInst(Mips::MFC1, DestReg).addReg(TempReg); - - updateValueMap(I, DestReg); - return true; -} - -bool MipsFastISel::processCallArgs(CallLoweringInfo &CLI, - SmallVectorImpl<MVT> &OutVTs, - unsigned &NumBytes) { - CallingConv::ID CC = CLI.CallConv; - SmallVector<CCValAssign, 16> ArgLocs; - CCState CCInfo(CC, false, *FuncInfo.MF, ArgLocs, *Context); - CCInfo.AnalyzeCallOperands(OutVTs, CLI.OutFlags, CCAssignFnForCall(CC)); - // Get a count of how many bytes are to be pushed on the stack. - NumBytes = CCInfo.getNextStackOffset(); - // This is the minimum argument area used for A0-A3. - if (NumBytes < 16) - NumBytes = 16; - - emitInst(Mips::ADJCALLSTACKDOWN).addImm(16).addImm(0); - // Process the args. - MVT firstMVT; - for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { - CCValAssign &VA = ArgLocs[i]; - const Value *ArgVal = CLI.OutVals[VA.getValNo()]; - MVT ArgVT = OutVTs[VA.getValNo()]; - - if (i == 0) { - firstMVT = ArgVT; - if (ArgVT == MVT::f32) { - VA.convertToReg(Mips::F12); - } else if (ArgVT == MVT::f64) { - VA.convertToReg(Mips::D6); - } - } else if (i == 1) { - if ((firstMVT == MVT::f32) || (firstMVT == MVT::f64)) { - if (ArgVT == MVT::f32) { - VA.convertToReg(Mips::F14); - } else if (ArgVT == MVT::f64) { - VA.convertToReg(Mips::D7); - } - } - } - if (((ArgVT == MVT::i32) || (ArgVT == MVT::f32) || (ArgVT == MVT::i16) || - (ArgVT == MVT::i8)) && - VA.isMemLoc()) { - switch (VA.getLocMemOffset()) { - case 0: - VA.convertToReg(Mips::A0); - break; - case 4: - VA.convertToReg(Mips::A1); - break; - case 8: - VA.convertToReg(Mips::A2); - break; - case 12: - VA.convertToReg(Mips::A3); - break; - default: - break; - } - } - unsigned ArgReg = getRegForValue(ArgVal); - if (!ArgReg) - return false; - - // Handle arg promotion: SExt, ZExt, AExt. - switch (VA.getLocInfo()) { - case CCValAssign::Full: - break; - case CCValAssign::AExt: - case CCValAssign::SExt: { - MVT DestVT = VA.getLocVT(); - MVT SrcVT = ArgVT; - ArgReg = emitIntExt(SrcVT, ArgReg, DestVT, /*isZExt=*/false); - if (!ArgReg) - return false; - break; - } - case CCValAssign::ZExt: { - MVT DestVT = VA.getLocVT(); - MVT SrcVT = ArgVT; - ArgReg = emitIntExt(SrcVT, ArgReg, DestVT, /*isZExt=*/true); - if (!ArgReg) - return false; - break; - } - default: - llvm_unreachable("Unknown arg promotion!"); - } - - // Now copy/store arg to correct locations. - if (VA.isRegLoc() && !VA.needsCustom()) { - BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, - TII.get(TargetOpcode::COPY), VA.getLocReg()).addReg(ArgReg); - CLI.OutRegs.push_back(VA.getLocReg()); - } else if (VA.needsCustom()) { - llvm_unreachable("Mips does not use custom args."); - return false; - } else { - // - // FIXME: This path will currently return false. It was copied - // from the AArch64 port and should be essentially fine for Mips too. - // The work to finish up this path will be done in a follow-on patch. - // - assert(VA.isMemLoc() && "Assuming store on stack."); - // Don't emit stores for undef values. - if (isa<UndefValue>(ArgVal)) - continue; - - // Need to store on the stack. - // FIXME: This alignment is incorrect but this path is disabled - // for now (will return false). We need to determine the right alignment - // based on the normal alignment for the underlying machine type. - // - unsigned ArgSize = alignTo(ArgVT.getSizeInBits(), 4); - - unsigned BEAlign = 0; - if (ArgSize < 8 && !Subtarget->isLittle()) - BEAlign = 8 - ArgSize; - - Address Addr; - Addr.setKind(Address::RegBase); - Addr.setReg(Mips::SP); - Addr.setOffset(VA.getLocMemOffset() + BEAlign); - - unsigned Alignment = DL.getABITypeAlignment(ArgVal->getType()); - MachineMemOperand *MMO = FuncInfo.MF->getMachineMemOperand( - MachinePointerInfo::getStack(*FuncInfo.MF, Addr.getOffset()), - MachineMemOperand::MOStore, ArgVT.getStoreSize(), Alignment); - (void)(MMO); - // if (!emitStore(ArgVT, ArgReg, Addr, MMO)) - return false; // can't store on the stack yet. - } - } - - return true; -} - -bool MipsFastISel::finishCall(CallLoweringInfo &CLI, MVT RetVT, - unsigned NumBytes) { - CallingConv::ID CC = CLI.CallConv; - emitInst(Mips::ADJCALLSTACKUP).addImm(16).addImm(0); - if (RetVT != MVT::isVoid) { - SmallVector<CCValAssign, 16> RVLocs; - MipsCCState CCInfo(CC, false, *FuncInfo.MF, RVLocs, *Context); - - CCInfo.AnalyzeCallResult(CLI.Ins, RetCC_Mips, CLI.RetTy, - CLI.Symbol ? CLI.Symbol->getName().data() - : nullptr); - - // Only handle a single return value. - if (RVLocs.size() != 1) - return false; - // Copy all of the result registers out of their specified physreg. - MVT CopyVT = RVLocs[0].getValVT(); - // Special handling for extended integers. - if (RetVT == MVT::i1 || RetVT == MVT::i8 || RetVT == MVT::i16) - CopyVT = MVT::i32; - - unsigned ResultReg = createResultReg(TLI.getRegClassFor(CopyVT)); - if (!ResultReg) - return false; - BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, - TII.get(TargetOpcode::COPY), - ResultReg).addReg(RVLocs[0].getLocReg()); - CLI.InRegs.push_back(RVLocs[0].getLocReg()); - - CLI.ResultReg = ResultReg; - CLI.NumResultRegs = 1; - } - return true; -} - -bool MipsFastISel::fastLowerArguments() { - LLVM_DEBUG(dbgs() << "fastLowerArguments\n"); - - if (!FuncInfo.CanLowerReturn) { - LLVM_DEBUG(dbgs() << ".. gave up (!CanLowerReturn)\n"); - return false; - } - - const Function *F = FuncInfo.Fn; - if (F->isVarArg()) { - LLVM_DEBUG(dbgs() << ".. gave up (varargs)\n"); - return false; - } - - CallingConv::ID CC = F->getCallingConv(); - if (CC != CallingConv::C) { - LLVM_DEBUG(dbgs() << ".. gave up (calling convention is not C)\n"); - return false; - } - - std::array<MCPhysReg, 4> GPR32ArgRegs = {{Mips::A0, Mips::A1, Mips::A2, - Mips::A3}}; - std::array<MCPhysReg, 2> FGR32ArgRegs = {{Mips::F12, Mips::F14}}; - std::array<MCPhysReg, 2> AFGR64ArgRegs = {{Mips::D6, Mips::D7}}; - auto NextGPR32 = GPR32ArgRegs.begin(); - auto NextFGR32 = FGR32ArgRegs.begin(); - auto NextAFGR64 = AFGR64ArgRegs.begin(); - - struct AllocatedReg { - const TargetRegisterClass *RC; - unsigned Reg; - AllocatedReg(const TargetRegisterClass *RC, unsigned Reg) - : RC(RC), Reg(Reg) {} - }; - - // Only handle simple cases. i.e. All arguments are directly mapped to - // registers of the appropriate type. - SmallVector<AllocatedReg, 4> Allocation; - for (const auto &FormalArg : F->args()) { - if (FormalArg.hasAttribute(Attribute::InReg) || - FormalArg.hasAttribute(Attribute::StructRet) || - FormalArg.hasAttribute(Attribute::ByVal)) { - LLVM_DEBUG(dbgs() << ".. gave up (inreg, structret, byval)\n"); - return false; - } - - Type *ArgTy = FormalArg.getType(); - if (ArgTy->isStructTy() || ArgTy->isArrayTy() || ArgTy->isVectorTy()) { - LLVM_DEBUG(dbgs() << ".. gave up (struct, array, or vector)\n"); - return false; - } - - EVT ArgVT = TLI.getValueType(DL, ArgTy); - LLVM_DEBUG(dbgs() << ".. " << FormalArg.getArgNo() << ": " - << ArgVT.getEVTString() << "\n"); - if (!ArgVT.isSimple()) { - LLVM_DEBUG(dbgs() << ".. .. gave up (not a simple type)\n"); - return false; - } - - switch (ArgVT.getSimpleVT().SimpleTy) { - case MVT::i1: - case MVT::i8: - case MVT::i16: - if (!FormalArg.hasAttribute(Attribute::SExt) && - !FormalArg.hasAttribute(Attribute::ZExt)) { - // It must be any extend, this shouldn't happen for clang-generated IR - // so just fall back on SelectionDAG. - LLVM_DEBUG(dbgs() << ".. .. gave up (i8/i16 arg is not extended)\n"); - return false; - } - - if (NextGPR32 == GPR32ArgRegs.end()) { - LLVM_DEBUG(dbgs() << ".. .. gave up (ran out of GPR32 arguments)\n"); - return false; - } - - LLVM_DEBUG(dbgs() << ".. .. GPR32(" << *NextGPR32 << ")\n"); - Allocation.emplace_back(&Mips::GPR32RegClass, *NextGPR32++); - - // Allocating any GPR32 prohibits further use of floating point arguments. - NextFGR32 = FGR32ArgRegs.end(); - NextAFGR64 = AFGR64ArgRegs.end(); - break; - - case MVT::i32: - if (FormalArg.hasAttribute(Attribute::ZExt)) { - // The O32 ABI does not permit a zero-extended i32. - LLVM_DEBUG(dbgs() << ".. .. gave up (i32 arg is zero extended)\n"); - return false; - } - - if (NextGPR32 == GPR32ArgRegs.end()) { - LLVM_DEBUG(dbgs() << ".. .. gave up (ran out of GPR32 arguments)\n"); - return false; - } - - LLVM_DEBUG(dbgs() << ".. .. GPR32(" << *NextGPR32 << ")\n"); - Allocation.emplace_back(&Mips::GPR32RegClass, *NextGPR32++); - - // Allocating any GPR32 prohibits further use of floating point arguments. - NextFGR32 = FGR32ArgRegs.end(); - NextAFGR64 = AFGR64ArgRegs.end(); - break; - - case MVT::f32: - if (UnsupportedFPMode) { - LLVM_DEBUG(dbgs() << ".. .. gave up (UnsupportedFPMode)\n"); - return false; - } - if (NextFGR32 == FGR32ArgRegs.end()) { - LLVM_DEBUG(dbgs() << ".. .. gave up (ran out of FGR32 arguments)\n"); - return false; - } - LLVM_DEBUG(dbgs() << ".. .. FGR32(" << *NextFGR32 << ")\n"); - Allocation.emplace_back(&Mips::FGR32RegClass, *NextFGR32++); - // Allocating an FGR32 also allocates the super-register AFGR64, and - // ABI rules require us to skip the corresponding GPR32. - if (NextGPR32 != GPR32ArgRegs.end()) - NextGPR32++; - if (NextAFGR64 != AFGR64ArgRegs.end()) - NextAFGR64++; - break; - - case MVT::f64: - if (UnsupportedFPMode) { - LLVM_DEBUG(dbgs() << ".. .. gave up (UnsupportedFPMode)\n"); - return false; - } - if (NextAFGR64 == AFGR64ArgRegs.end()) { - LLVM_DEBUG(dbgs() << ".. .. gave up (ran out of AFGR64 arguments)\n"); - return false; - } - LLVM_DEBUG(dbgs() << ".. .. AFGR64(" << *NextAFGR64 << ")\n"); - Allocation.emplace_back(&Mips::AFGR64RegClass, *NextAFGR64++); - // Allocating an FGR32 also allocates the super-register AFGR64, and - // ABI rules require us to skip the corresponding GPR32 pair. - if (NextGPR32 != GPR32ArgRegs.end()) - NextGPR32++; - if (NextGPR32 != GPR32ArgRegs.end()) - NextGPR32++; - if (NextFGR32 != FGR32ArgRegs.end()) - NextFGR32++; - break; - - default: - LLVM_DEBUG(dbgs() << ".. .. gave up (unknown type)\n"); - return false; - } - } - - for (const auto &FormalArg : F->args()) { - unsigned ArgNo = FormalArg.getArgNo(); - unsigned SrcReg = Allocation[ArgNo].Reg; - unsigned DstReg = FuncInfo.MF->addLiveIn(SrcReg, Allocation[ArgNo].RC); - // FIXME: Unfortunately it's necessary to emit a copy from the livein copy. - // Without this, EmitLiveInCopies may eliminate the livein if its only - // use is a bitcast (which isn't turned into an instruction). - unsigned ResultReg = createResultReg(Allocation[ArgNo].RC); - BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, - TII.get(TargetOpcode::COPY), ResultReg) - .addReg(DstReg, getKillRegState(true)); - updateValueMap(&FormalArg, ResultReg); - } - - // Calculate the size of the incoming arguments area. - // We currently reject all the cases where this would be non-zero. - unsigned IncomingArgSizeInBytes = 0; - - // Account for the reserved argument area on ABI's that have one (O32). - // It seems strange to do this on the caller side but it's necessary in - // SelectionDAG's implementation. - IncomingArgSizeInBytes = std::min(getABI().GetCalleeAllocdArgSizeInBytes(CC), - IncomingArgSizeInBytes); - - MF->getInfo<MipsFunctionInfo>()->setFormalArgInfo(IncomingArgSizeInBytes, - false); - - return true; -} - -bool MipsFastISel::fastLowerCall(CallLoweringInfo &CLI) { - CallingConv::ID CC = CLI.CallConv; - bool IsTailCall = CLI.IsTailCall; - bool IsVarArg = CLI.IsVarArg; - const Value *Callee = CLI.Callee; - MCSymbol *Symbol = CLI.Symbol; - - // Do not handle FastCC. - if (CC == CallingConv::Fast) - return false; - - // Allow SelectionDAG isel to handle tail calls. - if (IsTailCall) - return false; - - // Let SDISel handle vararg functions. - if (IsVarArg) - return false; - - // FIXME: Only handle *simple* calls for now. - MVT RetVT; - if (CLI.RetTy->isVoidTy()) - RetVT = MVT::isVoid; - else if (!isTypeSupported(CLI.RetTy, RetVT)) - return false; - - for (auto Flag : CLI.OutFlags) - if (Flag.isInReg() || Flag.isSRet() || Flag.isNest() || Flag.isByVal()) - return false; - - // Set up the argument vectors. - SmallVector<MVT, 16> OutVTs; - OutVTs.reserve(CLI.OutVals.size()); - - for (auto *Val : CLI.OutVals) { - MVT VT; - if (!isTypeLegal(Val->getType(), VT) && - !(VT == MVT::i1 || VT == MVT::i8 || VT == MVT::i16)) - return false; - - // We don't handle vector parameters yet. - if (VT.isVector() || VT.getSizeInBits() > 64) - return false; - - OutVTs.push_back(VT); - } - - Address Addr; - if (!computeCallAddress(Callee, Addr)) - return false; - - // Handle the arguments now that we've gotten them. - unsigned NumBytes; - if (!processCallArgs(CLI, OutVTs, NumBytes)) - return false; - - if (!Addr.getGlobalValue()) - return false; - - // Issue the call. - unsigned DestAddress; - if (Symbol) - DestAddress = materializeExternalCallSym(Symbol); - else - DestAddress = materializeGV(Addr.getGlobalValue(), MVT::i32); - emitInst(TargetOpcode::COPY, Mips::T9).addReg(DestAddress); - MachineInstrBuilder MIB = - BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Mips::JALR), - Mips::RA).addReg(Mips::T9); - - // Add implicit physical register uses to the call. - for (auto Reg : CLI.OutRegs) - MIB.addReg(Reg, RegState::Implicit); - - // Add a register mask with the call-preserved registers. - // Proper defs for return values will be added by setPhysRegsDeadExcept(). - MIB.addRegMask(TRI.getCallPreservedMask(*FuncInfo.MF, CC)); - - CLI.Call = MIB; - - if (EmitJalrReloc && !Subtarget->inMips16Mode()) { - // Attach callee address to the instruction, let asm printer emit - // .reloc R_MIPS_JALR. - if (Symbol) - MIB.addSym(Symbol, MipsII::MO_JALR); - else - MIB.addSym(FuncInfo.MF->getContext().getOrCreateSymbol( - Addr.getGlobalValue()->getName()), MipsII::MO_JALR); - } - - // Finish off the call including any return values. - return finishCall(CLI, RetVT, NumBytes); -} - -bool MipsFastISel::fastLowerIntrinsicCall(const IntrinsicInst *II) { - switch (II->getIntrinsicID()) { - default: - return false; - case Intrinsic::bswap: { - Type *RetTy = II->getCalledFunction()->getReturnType(); - - MVT VT; - if (!isTypeSupported(RetTy, VT)) - return false; - - unsigned SrcReg = getRegForValue(II->getOperand(0)); - if (SrcReg == 0) - return false; - unsigned DestReg = createResultReg(&Mips::GPR32RegClass); - if (DestReg == 0) - return false; - if (VT == MVT::i16) { - if (Subtarget->hasMips32r2()) { - emitInst(Mips::WSBH, DestReg).addReg(SrcReg); - updateValueMap(II, DestReg); - return true; - } else { - unsigned TempReg[3]; - for (int i = 0; i < 3; i++) { - TempReg[i] = createResultReg(&Mips::GPR32RegClass); - if (TempReg[i] == 0) - return false; - } - emitInst(Mips::SLL, TempReg[0]).addReg(SrcReg).addImm(8); - emitInst(Mips::SRL, TempReg[1]).addReg(SrcReg).addImm(8); - emitInst(Mips::OR, TempReg[2]).addReg(TempReg[0]).addReg(TempReg[1]); - emitInst(Mips::ANDi, DestReg).addReg(TempReg[2]).addImm(0xFFFF); - updateValueMap(II, DestReg); - return true; - } - } else if (VT == MVT::i32) { - if (Subtarget->hasMips32r2()) { - unsigned TempReg = createResultReg(&Mips::GPR32RegClass); - emitInst(Mips::WSBH, TempReg).addReg(SrcReg); - emitInst(Mips::ROTR, DestReg).addReg(TempReg).addImm(16); - updateValueMap(II, DestReg); - return true; - } else { - unsigned TempReg[8]; - for (int i = 0; i < 8; i++) { - TempReg[i] = createResultReg(&Mips::GPR32RegClass); - if (TempReg[i] == 0) - return false; - } - - emitInst(Mips::SRL, TempReg[0]).addReg(SrcReg).addImm(8); - emitInst(Mips::SRL, TempReg[1]).addReg(SrcReg).addImm(24); - emitInst(Mips::ANDi, TempReg[2]).addReg(TempReg[0]).addImm(0xFF00); - emitInst(Mips::OR, TempReg[3]).addReg(TempReg[1]).addReg(TempReg[2]); - - emitInst(Mips::ANDi, TempReg[4]).addReg(SrcReg).addImm(0xFF00); - emitInst(Mips::SLL, TempReg[5]).addReg(TempReg[4]).addImm(8); - - emitInst(Mips::SLL, TempReg[6]).addReg(SrcReg).addImm(24); - emitInst(Mips::OR, TempReg[7]).addReg(TempReg[3]).addReg(TempReg[5]); - emitInst(Mips::OR, DestReg).addReg(TempReg[6]).addReg(TempReg[7]); - updateValueMap(II, DestReg); - return true; - } - } - return false; - } - case Intrinsic::memcpy: - case Intrinsic::memmove: { - const auto *MTI = cast<MemTransferInst>(II); - // Don't handle volatile. - if (MTI->isVolatile()) - return false; - if (!MTI->getLength()->getType()->isIntegerTy(32)) - return false; - const char *IntrMemName = isa<MemCpyInst>(II) ? "memcpy" : "memmove"; - return lowerCallTo(II, IntrMemName, II->getNumArgOperands() - 1); - } - case Intrinsic::memset: { - const MemSetInst *MSI = cast<MemSetInst>(II); - // Don't handle volatile. - if (MSI->isVolatile()) - return false; - if (!MSI->getLength()->getType()->isIntegerTy(32)) - return false; - return lowerCallTo(II, "memset", II->getNumArgOperands() - 1); - } - } - return false; -} - -bool MipsFastISel::selectRet(const Instruction *I) { - const Function &F = *I->getParent()->getParent(); - const ReturnInst *Ret = cast<ReturnInst>(I); - - LLVM_DEBUG(dbgs() << "selectRet\n"); - - if (!FuncInfo.CanLowerReturn) - return false; - - // Build a list of return value registers. - SmallVector<unsigned, 4> RetRegs; - - if (Ret->getNumOperands() > 0) { - CallingConv::ID CC = F.getCallingConv(); - - // Do not handle FastCC. - if (CC == CallingConv::Fast) - return false; - - SmallVector<ISD::OutputArg, 4> Outs; - GetReturnInfo(CC, F.getReturnType(), F.getAttributes(), Outs, TLI, DL); - - // Analyze operands of the call, assigning locations to each operand. - SmallVector<CCValAssign, 16> ValLocs; - MipsCCState CCInfo(CC, F.isVarArg(), *FuncInfo.MF, ValLocs, - I->getContext()); - CCAssignFn *RetCC = RetCC_Mips; - CCInfo.AnalyzeReturn(Outs, RetCC); - - // Only handle a single return value for now. - if (ValLocs.size() != 1) - return false; - - CCValAssign &VA = ValLocs[0]; - const Value *RV = Ret->getOperand(0); - - // Don't bother handling odd stuff for now. - if ((VA.getLocInfo() != CCValAssign::Full) && - (VA.getLocInfo() != CCValAssign::BCvt)) - return false; - - // Only handle register returns for now. - if (!VA.isRegLoc()) - return false; - - unsigned Reg = getRegForValue(RV); - if (Reg == 0) - return false; - - unsigned SrcReg = Reg + VA.getValNo(); - unsigned DestReg = VA.getLocReg(); - // Avoid a cross-class copy. This is very unlikely. - if (!MRI.getRegClass(SrcReg)->contains(DestReg)) - return false; - - EVT RVEVT = TLI.getValueType(DL, RV->getType()); - if (!RVEVT.isSimple()) - return false; - - if (RVEVT.isVector()) - return false; - - MVT RVVT = RVEVT.getSimpleVT(); - if (RVVT == MVT::f128) - return false; - - // Do not handle FGR64 returns for now. - if (RVVT == MVT::f64 && UnsupportedFPMode) { - LLVM_DEBUG(dbgs() << ".. .. gave up (UnsupportedFPMode\n"); - return false; - } - - MVT DestVT = VA.getValVT(); - // Special handling for extended integers. - if (RVVT != DestVT) { - if (RVVT != MVT::i1 && RVVT != MVT::i8 && RVVT != MVT::i16) - return false; - - if (Outs[0].Flags.isZExt() || Outs[0].Flags.isSExt()) { - bool IsZExt = Outs[0].Flags.isZExt(); - SrcReg = emitIntExt(RVVT, SrcReg, DestVT, IsZExt); - if (SrcReg == 0) - return false; - } - } - - // Make the copy. - BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, - TII.get(TargetOpcode::COPY), DestReg).addReg(SrcReg); - - // Add register to return instruction. - RetRegs.push_back(VA.getLocReg()); - } - MachineInstrBuilder MIB = emitInst(Mips::RetRA); - for (unsigned i = 0, e = RetRegs.size(); i != e; ++i) - MIB.addReg(RetRegs[i], RegState::Implicit); - return true; -} - -bool MipsFastISel::selectTrunc(const Instruction *I) { - // The high bits for a type smaller than the register size are assumed to be - // undefined. - Value *Op = I->getOperand(0); - - EVT SrcVT, DestVT; - SrcVT = TLI.getValueType(DL, Op->getType(), true); - DestVT = TLI.getValueType(DL, I->getType(), true); - - if (SrcVT != MVT::i32 && SrcVT != MVT::i16 && SrcVT != MVT::i8) - return false; - if (DestVT != MVT::i16 && DestVT != MVT::i8 && DestVT != MVT::i1) - return false; - - unsigned SrcReg = getRegForValue(Op); - if (!SrcReg) - return false; - - // Because the high bits are undefined, a truncate doesn't generate - // any code. - updateValueMap(I, SrcReg); - return true; -} - -bool MipsFastISel::selectIntExt(const Instruction *I) { - Type *DestTy = I->getType(); - Value *Src = I->getOperand(0); - Type *SrcTy = Src->getType(); - - bool isZExt = isa<ZExtInst>(I); - unsigned SrcReg = getRegForValue(Src); - if (!SrcReg) - return false; - - EVT SrcEVT, DestEVT; - SrcEVT = TLI.getValueType(DL, SrcTy, true); - DestEVT = TLI.getValueType(DL, DestTy, true); - if (!SrcEVT.isSimple()) - return false; - if (!DestEVT.isSimple()) - return false; - - MVT SrcVT = SrcEVT.getSimpleVT(); - MVT DestVT = DestEVT.getSimpleVT(); - unsigned ResultReg = createResultReg(&Mips::GPR32RegClass); - - if (!emitIntExt(SrcVT, SrcReg, DestVT, ResultReg, isZExt)) - return false; - updateValueMap(I, ResultReg); - return true; -} - -bool MipsFastISel::emitIntSExt32r1(MVT SrcVT, unsigned SrcReg, MVT DestVT, - unsigned DestReg) { - unsigned ShiftAmt; - switch (SrcVT.SimpleTy) { - default: - return false; - case MVT::i8: - ShiftAmt = 24; - break; - case MVT::i16: - ShiftAmt = 16; - break; - } - unsigned TempReg = createResultReg(&Mips::GPR32RegClass); - emitInst(Mips::SLL, TempReg).addReg(SrcReg).addImm(ShiftAmt); - emitInst(Mips::SRA, DestReg).addReg(TempReg).addImm(ShiftAmt); - return true; -} - -bool MipsFastISel::emitIntSExt32r2(MVT SrcVT, unsigned SrcReg, MVT DestVT, - unsigned DestReg) { - switch (SrcVT.SimpleTy) { - default: - return false; - case MVT::i8: - emitInst(Mips::SEB, DestReg).addReg(SrcReg); - break; - case MVT::i16: - emitInst(Mips::SEH, DestReg).addReg(SrcReg); - break; - } - return true; -} - -bool MipsFastISel::emitIntSExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, - unsigned DestReg) { - if ((DestVT != MVT::i32) && (DestVT != MVT::i16)) - return false; - if (Subtarget->hasMips32r2()) - return emitIntSExt32r2(SrcVT, SrcReg, DestVT, DestReg); - return emitIntSExt32r1(SrcVT, SrcReg, DestVT, DestReg); -} - -bool MipsFastISel::emitIntZExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, - unsigned DestReg) { - int64_t Imm; - - switch (SrcVT.SimpleTy) { - default: - return false; - case MVT::i1: - Imm = 1; - break; - case MVT::i8: - Imm = 0xff; - break; - case MVT::i16: - Imm = 0xffff; - break; - } - - emitInst(Mips::ANDi, DestReg).addReg(SrcReg).addImm(Imm); - return true; -} - -bool MipsFastISel::emitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, - unsigned DestReg, bool IsZExt) { - // FastISel does not have plumbing to deal with extensions where the SrcVT or - // DestVT are odd things, so test to make sure that they are both types we can - // handle (i1/i8/i16/i32 for SrcVT and i8/i16/i32/i64 for DestVT), otherwise - // bail out to SelectionDAG. - if (((DestVT != MVT::i8) && (DestVT != MVT::i16) && (DestVT != MVT::i32)) || - ((SrcVT != MVT::i1) && (SrcVT != MVT::i8) && (SrcVT != MVT::i16))) - return false; - if (IsZExt) - return emitIntZExt(SrcVT, SrcReg, DestVT, DestReg); - return emitIntSExt(SrcVT, SrcReg, DestVT, DestReg); -} - -unsigned MipsFastISel::emitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, - bool isZExt) { - unsigned DestReg = createResultReg(&Mips::GPR32RegClass); - bool Success = emitIntExt(SrcVT, SrcReg, DestVT, DestReg, isZExt); - return Success ? DestReg : 0; -} - -bool MipsFastISel::selectDivRem(const Instruction *I, unsigned ISDOpcode) { - EVT DestEVT = TLI.getValueType(DL, I->getType(), true); - if (!DestEVT.isSimple()) - return false; - - MVT DestVT = DestEVT.getSimpleVT(); - if (DestVT != MVT::i32) - return false; - - unsigned DivOpc; - switch (ISDOpcode) { - default: - return false; - case ISD::SDIV: - case ISD::SREM: - DivOpc = Mips::SDIV; - break; - case ISD::UDIV: - case ISD::UREM: - DivOpc = Mips::UDIV; - break; - } - - unsigned Src0Reg = getRegForValue(I->getOperand(0)); - unsigned Src1Reg = getRegForValue(I->getOperand(1)); - if (!Src0Reg || !Src1Reg) - return false; - - emitInst(DivOpc).addReg(Src0Reg).addReg(Src1Reg); - emitInst(Mips::TEQ).addReg(Src1Reg).addReg(Mips::ZERO).addImm(7); - - unsigned ResultReg = createResultReg(&Mips::GPR32RegClass); - if (!ResultReg) - return false; - - unsigned MFOpc = (ISDOpcode == ISD::SREM || ISDOpcode == ISD::UREM) - ? Mips::MFHI - : Mips::MFLO; - emitInst(MFOpc, ResultReg); - - updateValueMap(I, ResultReg); - return true; -} - -bool MipsFastISel::selectShift(const Instruction *I) { - MVT RetVT; - - if (!isTypeSupported(I->getType(), RetVT)) - return false; - - unsigned ResultReg = createResultReg(&Mips::GPR32RegClass); - if (!ResultReg) - return false; - - unsigned Opcode = I->getOpcode(); - const Value *Op0 = I->getOperand(0); - unsigned Op0Reg = getRegForValue(Op0); - if (!Op0Reg) - return false; - - // If AShr or LShr, then we need to make sure the operand0 is sign extended. - if (Opcode == Instruction::AShr || Opcode == Instruction::LShr) { - unsigned TempReg = createResultReg(&Mips::GPR32RegClass); - if (!TempReg) - return false; - - MVT Op0MVT = TLI.getValueType(DL, Op0->getType(), true).getSimpleVT(); - bool IsZExt = Opcode == Instruction::LShr; - if (!emitIntExt(Op0MVT, Op0Reg, MVT::i32, TempReg, IsZExt)) - return false; - - Op0Reg = TempReg; - } - - if (const auto *C = dyn_cast<ConstantInt>(I->getOperand(1))) { - uint64_t ShiftVal = C->getZExtValue(); - - switch (Opcode) { - default: - llvm_unreachable("Unexpected instruction."); - case Instruction::Shl: - Opcode = Mips::SLL; - break; - case Instruction::AShr: - Opcode = Mips::SRA; - break; - case Instruction::LShr: - Opcode = Mips::SRL; - break; - } - - emitInst(Opcode, ResultReg).addReg(Op0Reg).addImm(ShiftVal); - updateValueMap(I, ResultReg); - return true; - } - - unsigned Op1Reg = getRegForValue(I->getOperand(1)); - if (!Op1Reg) - return false; - - switch (Opcode) { - default: - llvm_unreachable("Unexpected instruction."); - case Instruction::Shl: - Opcode = Mips::SLLV; - break; - case Instruction::AShr: - Opcode = Mips::SRAV; - break; - case Instruction::LShr: - Opcode = Mips::SRLV; - break; - } - - emitInst(Opcode, ResultReg).addReg(Op0Reg).addReg(Op1Reg); - updateValueMap(I, ResultReg); - return true; -} - -bool MipsFastISel::fastSelectInstruction(const Instruction *I) { - switch (I->getOpcode()) { - default: - break; - case Instruction::Load: - return selectLoad(I); - case Instruction::Store: - return selectStore(I); - case Instruction::SDiv: - if (!selectBinaryOp(I, ISD::SDIV)) - return selectDivRem(I, ISD::SDIV); - return true; - case Instruction::UDiv: - if (!selectBinaryOp(I, ISD::UDIV)) - return selectDivRem(I, ISD::UDIV); - return true; - case Instruction::SRem: - if (!selectBinaryOp(I, ISD::SREM)) - return selectDivRem(I, ISD::SREM); - return true; - case Instruction::URem: - if (!selectBinaryOp(I, ISD::UREM)) - return selectDivRem(I, ISD::UREM); - return true; - case Instruction::Shl: - case Instruction::LShr: - case Instruction::AShr: - return selectShift(I); - case Instruction::And: - case Instruction::Or: - case Instruction::Xor: - return selectLogicalOp(I); - case Instruction::Br: - return selectBranch(I); - case Instruction::Ret: - return selectRet(I); - case Instruction::Trunc: - return selectTrunc(I); - case Instruction::ZExt: - case Instruction::SExt: - return selectIntExt(I); - case Instruction::FPTrunc: - return selectFPTrunc(I); - case Instruction::FPExt: - return selectFPExt(I); - case Instruction::FPToSI: - return selectFPToInt(I, /*isSigned*/ true); - case Instruction::FPToUI: - return selectFPToInt(I, /*isSigned*/ false); - case Instruction::ICmp: - case Instruction::FCmp: - return selectCmp(I); - case Instruction::Select: - return selectSelect(I); - } - return false; -} - -unsigned MipsFastISel::getRegEnsuringSimpleIntegerWidening(const Value *V, - bool IsUnsigned) { - unsigned VReg = getRegForValue(V); - if (VReg == 0) - return 0; - MVT VMVT = TLI.getValueType(DL, V->getType(), true).getSimpleVT(); - - if (VMVT == MVT::i1) - return 0; - - if ((VMVT == MVT::i8) || (VMVT == MVT::i16)) { - unsigned TempReg = createResultReg(&Mips::GPR32RegClass); - if (!emitIntExt(VMVT, VReg, MVT::i32, TempReg, IsUnsigned)) - return 0; - VReg = TempReg; - } - return VReg; -} - -void MipsFastISel::simplifyAddress(Address &Addr) { - if (!isInt<16>(Addr.getOffset())) { - unsigned TempReg = - materialize32BitInt(Addr.getOffset(), &Mips::GPR32RegClass); - unsigned DestReg = createResultReg(&Mips::GPR32RegClass); - emitInst(Mips::ADDu, DestReg).addReg(TempReg).addReg(Addr.getReg()); - Addr.setReg(DestReg); - Addr.setOffset(0); - } -} - -unsigned MipsFastISel::fastEmitInst_rr(unsigned MachineInstOpcode, - const TargetRegisterClass *RC, - unsigned Op0, bool Op0IsKill, - unsigned Op1, bool Op1IsKill) { - // We treat the MUL instruction in a special way because it clobbers - // the HI0 & LO0 registers. The TableGen definition of this instruction can - // mark these registers only as implicitly defined. As a result, the - // register allocator runs out of registers when this instruction is - // followed by another instruction that defines the same registers too. - // We can fix this by explicitly marking those registers as dead. - if (MachineInstOpcode == Mips::MUL) { - unsigned ResultReg = createResultReg(RC); - const MCInstrDesc &II = TII.get(MachineInstOpcode); - Op0 = constrainOperandRegClass(II, Op0, II.getNumDefs()); - Op1 = constrainOperandRegClass(II, Op1, II.getNumDefs() + 1); - BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, ResultReg) - .addReg(Op0, getKillRegState(Op0IsKill)) - .addReg(Op1, getKillRegState(Op1IsKill)) - .addReg(Mips::HI0, RegState::ImplicitDefine | RegState::Dead) - .addReg(Mips::LO0, RegState::ImplicitDefine | RegState::Dead); - return ResultReg; - } - - return FastISel::fastEmitInst_rr(MachineInstOpcode, RC, Op0, Op0IsKill, Op1, - Op1IsKill); -} - -namespace llvm { - -FastISel *Mips::createFastISel(FunctionLoweringInfo &funcInfo, - const TargetLibraryInfo *libInfo) { - return new MipsFastISel(funcInfo, libInfo); -} - -} // end namespace llvm diff --git a/contrib/llvm/lib/Target/Mips/MipsFrameLowering.cpp b/contrib/llvm/lib/Target/Mips/MipsFrameLowering.cpp deleted file mode 100644 index 8d5eabf59b71..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsFrameLowering.cpp +++ /dev/null @@ -1,151 +0,0 @@ -//===-- MipsFrameLowering.cpp - Mips Frame Information --------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains the Mips implementation of TargetFrameLowering class. -// -//===----------------------------------------------------------------------===// - -#include "MipsFrameLowering.h" -#include "MCTargetDesc/MipsBaseInfo.h" -#include "MipsInstrInfo.h" -#include "MipsMachineFunction.h" -#include "MipsTargetMachine.h" -#include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/MachineModuleInfo.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/Function.h" -#include "llvm/Target/TargetOptions.h" - -using namespace llvm; - - -//===----------------------------------------------------------------------===// -// -// Stack Frame Processing methods -// +----------------------------+ -// -// The stack is allocated decrementing the stack pointer on -// the first instruction of a function prologue. Once decremented, -// all stack references are done thought a positive offset -// from the stack/frame pointer, so the stack is considering -// to grow up! Otherwise terrible hacks would have to be made -// to get this stack ABI compliant :) -// -// The stack frame required by the ABI (after call): -// Offset -// -// 0 ---------- -// 4 Args to pass -// . saved $GP (used in PIC) -// . Alloca allocations -// . Local Area -// . CPU "Callee Saved" Registers -// . saved FP -// . saved RA -// . FPU "Callee Saved" Registers -// StackSize ----------- -// -// Offset - offset from sp after stack allocation on function prologue -// -// The sp is the stack pointer subtracted/added from the stack size -// at the Prologue/Epilogue -// -// References to the previous stack (to obtain arguments) are done -// with offsets that exceeds the stack size: (stacksize+(4*(num_arg-1)) -// -// Examples: -// - reference to the actual stack frame -// for any local area var there is smt like : FI >= 0, StackOffset: 4 -// sw REGX, 4(SP) -// -// - reference to previous stack frame -// suppose there's a load to the 5th arguments : FI < 0, StackOffset: 16. -// The emitted instruction will be something like: -// lw REGX, 16+StackSize(SP) -// -// Since the total stack size is unknown on LowerFormalArguments, all -// stack references (ObjectOffset) created to reference the function -// arguments, are negative numbers. This way, on eliminateFrameIndex it's -// possible to detect those references and the offsets are adjusted to -// their real location. -// -//===----------------------------------------------------------------------===// - -const MipsFrameLowering *MipsFrameLowering::create(const MipsSubtarget &ST) { - if (ST.inMips16Mode()) - return llvm::createMips16FrameLowering(ST); - - return llvm::createMipsSEFrameLowering(ST); -} - -// hasFP - Return true if the specified function should have a dedicated frame -// pointer register. This is true if the function has variable sized allocas, -// if it needs dynamic stack realignment, if frame pointer elimination is -// disabled, or if the frame address is taken. -bool MipsFrameLowering::hasFP(const MachineFunction &MF) const { - const MachineFrameInfo &MFI = MF.getFrameInfo(); - const TargetRegisterInfo *TRI = STI.getRegisterInfo(); - - return MF.getTarget().Options.DisableFramePointerElim(MF) || - MFI.hasVarSizedObjects() || MFI.isFrameAddressTaken() || - TRI->needsStackRealignment(MF); -} - -bool MipsFrameLowering::hasBP(const MachineFunction &MF) const { - const MachineFrameInfo &MFI = MF.getFrameInfo(); - const TargetRegisterInfo *TRI = STI.getRegisterInfo(); - - return MFI.hasVarSizedObjects() && TRI->needsStackRealignment(MF); -} - -// Estimate the size of the stack, including the incoming arguments. We need to -// account for register spills, local objects, reserved call frame and incoming -// arguments. This is required to determine the largest possible positive offset -// from $sp so that it can be determined if an emergency spill slot for stack -// addresses is required. -uint64_t MipsFrameLowering::estimateStackSize(const MachineFunction &MF) const { - const MachineFrameInfo &MFI = MF.getFrameInfo(); - const TargetRegisterInfo &TRI = *STI.getRegisterInfo(); - - int64_t Size = 0; - - // Iterate over fixed sized objects which are incoming arguments. - for (int I = MFI.getObjectIndexBegin(); I != 0; ++I) - if (MFI.getObjectOffset(I) > 0) - Size += MFI.getObjectSize(I); - - // Conservatively assume all callee-saved registers will be saved. - for (const MCPhysReg *R = TRI.getCalleeSavedRegs(&MF); *R; ++R) { - unsigned RegSize = TRI.getSpillSize(*TRI.getMinimalPhysRegClass(*R)); - Size = alignTo(Size + RegSize, RegSize); - } - - // Get the size of the rest of the frame objects and any possible reserved - // call frame, accounting for alignment. - return Size + MFI.estimateStackSize(MF); -} - -// Eliminate ADJCALLSTACKDOWN, ADJCALLSTACKUP pseudo instructions -MachineBasicBlock::iterator MipsFrameLowering:: -eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, - MachineBasicBlock::iterator I) const { - unsigned SP = STI.getABI().IsN64() ? Mips::SP_64 : Mips::SP; - - if (!hasReservedCallFrame(MF)) { - int64_t Amount = I->getOperand(0).getImm(); - if (I->getOpcode() == Mips::ADJCALLSTACKDOWN) - Amount = -Amount; - - STI.getInstrInfo()->adjustStackPtr(SP, Amount, MBB, I); - } - - return MBB.erase(I); -} diff --git a/contrib/llvm/lib/Target/Mips/MipsFrameLowering.h b/contrib/llvm/lib/Target/Mips/MipsFrameLowering.h deleted file mode 100644 index 0537cfd1cb30..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsFrameLowering.h +++ /dev/null @@ -1,57 +0,0 @@ -//===-- MipsFrameLowering.h - Define frame lowering for Mips ----*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_MIPS_MIPSFRAMELOWERING_H -#define LLVM_LIB_TARGET_MIPS_MIPSFRAMELOWERING_H - -#include "Mips.h" -#include "llvm/CodeGen/TargetFrameLowering.h" - -namespace llvm { - class MipsSubtarget; - -class MipsFrameLowering : public TargetFrameLowering { -protected: - const MipsSubtarget &STI; - -public: - explicit MipsFrameLowering(const MipsSubtarget &sti, unsigned Alignment) - : TargetFrameLowering(StackGrowsDown, Alignment, 0, Alignment), STI(sti) {} - - static const MipsFrameLowering *create(const MipsSubtarget &ST); - - bool hasFP(const MachineFunction &MF) const override; - - bool hasBP(const MachineFunction &MF) const; - - bool isFPCloseToIncomingSP() const override { return false; } - - bool enableShrinkWrapping(const MachineFunction &MF) const override { - return true; - } - - MachineBasicBlock::iterator - eliminateCallFramePseudoInstr(MachineFunction &MF, - MachineBasicBlock &MBB, - MachineBasicBlock::iterator I) const override; - -protected: - uint64_t estimateStackSize(const MachineFunction &MF) const; -}; - -/// Create MipsFrameLowering objects. -const MipsFrameLowering *createMips16FrameLowering(const MipsSubtarget &ST); -const MipsFrameLowering *createMipsSEFrameLowering(const MipsSubtarget &ST); - -} // End llvm namespace - -#endif diff --git a/contrib/llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp b/contrib/llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp deleted file mode 100644 index 9ba54d6bb73c..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp +++ /dev/null @@ -1,274 +0,0 @@ -//===-- MipsISelDAGToDAG.cpp - A Dag to Dag Inst Selector for Mips --------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines an instruction selector for the MIPS target. -// -//===----------------------------------------------------------------------===// - -#include "MipsISelDAGToDAG.h" -#include "MCTargetDesc/MipsBaseInfo.h" -#include "Mips.h" -#include "Mips16ISelDAGToDAG.h" -#include "MipsMachineFunction.h" -#include "MipsRegisterInfo.h" -#include "MipsSEISelDAGToDAG.h" -#include "llvm/CodeGen/MachineConstantPool.h" -#include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/SelectionDAGNodes.h" -#include "llvm/CodeGen/StackProtector.h" -#include "llvm/IR/CFG.h" -#include "llvm/IR/GlobalValue.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/Intrinsics.h" -#include "llvm/IR/Type.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetMachine.h" -using namespace llvm; - -#define DEBUG_TYPE "mips-isel" - -//===----------------------------------------------------------------------===// -// Instruction Selector Implementation -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// MipsDAGToDAGISel - MIPS specific code to select MIPS machine -// instructions for SelectionDAG operations. -//===----------------------------------------------------------------------===// - -void MipsDAGToDAGISel::getAnalysisUsage(AnalysisUsage &AU) const { - // There are multiple MipsDAGToDAGISel instances added to the pass pipeline. - // We need to preserve StackProtector for the next one. - AU.addPreserved<StackProtector>(); - SelectionDAGISel::getAnalysisUsage(AU); -} - -bool MipsDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) { - Subtarget = &static_cast<const MipsSubtarget &>(MF.getSubtarget()); - bool Ret = SelectionDAGISel::runOnMachineFunction(MF); - - processFunctionAfterISel(MF); - - return Ret; -} - -/// getGlobalBaseReg - Output the instructions required to put the -/// GOT address into a register. -SDNode *MipsDAGToDAGISel::getGlobalBaseReg() { - unsigned GlobalBaseReg = MF->getInfo<MipsFunctionInfo>()->getGlobalBaseReg(); - return CurDAG->getRegister(GlobalBaseReg, getTargetLowering()->getPointerTy( - CurDAG->getDataLayout())) - .getNode(); -} - -/// ComplexPattern used on MipsInstrInfo -/// Used on Mips Load/Store instructions -bool MipsDAGToDAGISel::selectAddrRegImm(SDValue Addr, SDValue &Base, - SDValue &Offset) const { - llvm_unreachable("Unimplemented function."); - return false; -} - -bool MipsDAGToDAGISel::selectAddrDefault(SDValue Addr, SDValue &Base, - SDValue &Offset) const { - llvm_unreachable("Unimplemented function."); - return false; -} - -bool MipsDAGToDAGISel::selectIntAddr(SDValue Addr, SDValue &Base, - SDValue &Offset) const { - llvm_unreachable("Unimplemented function."); - return false; -} - -bool MipsDAGToDAGISel::selectIntAddr11MM(SDValue Addr, SDValue &Base, - SDValue &Offset) const { - llvm_unreachable("Unimplemented function."); - return false; -} - -bool MipsDAGToDAGISel::selectIntAddr12MM(SDValue Addr, SDValue &Base, - SDValue &Offset) const { - llvm_unreachable("Unimplemented function."); - return false; -} - -bool MipsDAGToDAGISel::selectIntAddr16MM(SDValue Addr, SDValue &Base, - SDValue &Offset) const { - llvm_unreachable("Unimplemented function."); - return false; -} - -bool MipsDAGToDAGISel::selectIntAddrLSL2MM(SDValue Addr, SDValue &Base, - SDValue &Offset) const { - llvm_unreachable("Unimplemented function."); - return false; -} - -bool MipsDAGToDAGISel::selectIntAddrSImm10(SDValue Addr, SDValue &Base, - SDValue &Offset) const { - llvm_unreachable("Unimplemented function."); - return false; -} - -bool MipsDAGToDAGISel::selectIntAddrSImm10Lsl1(SDValue Addr, SDValue &Base, - SDValue &Offset) const { - llvm_unreachable("Unimplemented function."); - return false; -} - -bool MipsDAGToDAGISel::selectIntAddrSImm10Lsl2(SDValue Addr, SDValue &Base, - SDValue &Offset) const { - llvm_unreachable("Unimplemented function."); - return false; -} - -bool MipsDAGToDAGISel::selectIntAddrSImm10Lsl3(SDValue Addr, SDValue &Base, - SDValue &Offset) const { - llvm_unreachable("Unimplemented function."); - return false; -} - -bool MipsDAGToDAGISel::selectAddr16(SDValue Addr, SDValue &Base, - SDValue &Offset) { - llvm_unreachable("Unimplemented function."); - return false; -} - -bool MipsDAGToDAGISel::selectAddr16SP(SDValue Addr, SDValue &Base, - SDValue &Offset) { - llvm_unreachable("Unimplemented function."); - return false; -} - -bool MipsDAGToDAGISel::selectVSplat(SDNode *N, APInt &Imm, - unsigned MinSizeInBits) const { - llvm_unreachable("Unimplemented function."); - return false; -} - -bool MipsDAGToDAGISel::selectVSplatUimm1(SDValue N, SDValue &Imm) const { - llvm_unreachable("Unimplemented function."); - return false; -} - -bool MipsDAGToDAGISel::selectVSplatUimm2(SDValue N, SDValue &Imm) const { - llvm_unreachable("Unimplemented function."); - return false; -} - -bool MipsDAGToDAGISel::selectVSplatUimm3(SDValue N, SDValue &Imm) const { - llvm_unreachable("Unimplemented function."); - return false; -} - -bool MipsDAGToDAGISel::selectVSplatUimm4(SDValue N, SDValue &Imm) const { - llvm_unreachable("Unimplemented function."); - return false; -} - -bool MipsDAGToDAGISel::selectVSplatUimm5(SDValue N, SDValue &Imm) const { - llvm_unreachable("Unimplemented function."); - return false; -} - -bool MipsDAGToDAGISel::selectVSplatUimm6(SDValue N, SDValue &Imm) const { - llvm_unreachable("Unimplemented function."); - return false; -} - -bool MipsDAGToDAGISel::selectVSplatUimm8(SDValue N, SDValue &Imm) const { - llvm_unreachable("Unimplemented function."); - return false; -} - -bool MipsDAGToDAGISel::selectVSplatSimm5(SDValue N, SDValue &Imm) const { - llvm_unreachable("Unimplemented function."); - return false; -} - -bool MipsDAGToDAGISel::selectVSplatUimmPow2(SDValue N, SDValue &Imm) const { - llvm_unreachable("Unimplemented function."); - return false; -} - -bool MipsDAGToDAGISel::selectVSplatUimmInvPow2(SDValue N, SDValue &Imm) const { - llvm_unreachable("Unimplemented function."); - return false; -} - -bool MipsDAGToDAGISel::selectVSplatMaskL(SDValue N, SDValue &Imm) const { - llvm_unreachable("Unimplemented function."); - return false; -} - -bool MipsDAGToDAGISel::selectVSplatMaskR(SDValue N, SDValue &Imm) const { - llvm_unreachable("Unimplemented function."); - return false; -} - -/// Select instructions not customized! Used for -/// expanded, promoted and normal instructions -void MipsDAGToDAGISel::Select(SDNode *Node) { - unsigned Opcode = Node->getOpcode(); - - // If we have a custom node, we already have selected! - if (Node->isMachineOpcode()) { - LLVM_DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n"); - Node->setNodeId(-1); - return; - } - - // See if subclasses can handle this node. - if (trySelect(Node)) - return; - - switch(Opcode) { - default: break; - - // Get target GOT address. - case ISD::GLOBAL_OFFSET_TABLE: - ReplaceNode(Node, getGlobalBaseReg()); - return; - -#ifndef NDEBUG - case ISD::LOAD: - case ISD::STORE: - assert((Subtarget->systemSupportsUnalignedAccess() || - cast<MemSDNode>(Node)->getMemoryVT().getSizeInBits() / 8 <= - cast<MemSDNode>(Node)->getAlignment()) && - "Unexpected unaligned loads/stores."); - break; -#endif - } - - // Select the default instruction - SelectCode(Node); -} - -bool MipsDAGToDAGISel:: -SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID, - std::vector<SDValue> &OutOps) { - // All memory constraints can at least accept raw pointers. - switch(ConstraintID) { - default: - llvm_unreachable("Unexpected asm memory constraint"); - case InlineAsm::Constraint_i: - case InlineAsm::Constraint_m: - case InlineAsm::Constraint_R: - case InlineAsm::Constraint_ZC: - OutOps.push_back(Op); - return false; - } - return true; -} diff --git a/contrib/llvm/lib/Target/Mips/MipsISelDAGToDAG.h b/contrib/llvm/lib/Target/Mips/MipsISelDAGToDAG.h deleted file mode 100644 index bae3bbf71f3b..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsISelDAGToDAG.h +++ /dev/null @@ -1,145 +0,0 @@ -//===---- MipsISelDAGToDAG.h - A Dag to Dag Inst Selector for Mips --------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines an instruction selector for the MIPS target. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_MIPS_MIPSISELDAGTODAG_H -#define LLVM_LIB_TARGET_MIPS_MIPSISELDAGTODAG_H - -#include "Mips.h" -#include "MipsSubtarget.h" -#include "MipsTargetMachine.h" -#include "llvm/CodeGen/SelectionDAGISel.h" - -//===----------------------------------------------------------------------===// -// Instruction Selector Implementation -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// MipsDAGToDAGISel - MIPS specific code to select MIPS machine -// instructions for SelectionDAG operations. -//===----------------------------------------------------------------------===// -namespace llvm { - -class MipsDAGToDAGISel : public SelectionDAGISel { -public: - explicit MipsDAGToDAGISel(MipsTargetMachine &TM, CodeGenOpt::Level OL) - : SelectionDAGISel(TM, OL), Subtarget(nullptr) {} - - // Pass Name - StringRef getPassName() const override { - return "MIPS DAG->DAG Pattern Instruction Selection"; - } - - bool runOnMachineFunction(MachineFunction &MF) override; - - void getAnalysisUsage(AnalysisUsage &AU) const override; - -protected: - SDNode *getGlobalBaseReg(); - - /// Keep a pointer to the MipsSubtarget around so that we can make the right - /// decision when generating code for different targets. - const MipsSubtarget *Subtarget; - -private: - // Include the pieces autogenerated from the target description. - #include "MipsGenDAGISel.inc" - - // Complex Pattern. - /// (reg + imm). - virtual bool selectAddrRegImm(SDValue Addr, SDValue &Base, - SDValue &Offset) const; - - /// Fall back on this function if all else fails. - virtual bool selectAddrDefault(SDValue Addr, SDValue &Base, - SDValue &Offset) const; - - /// Match integer address pattern. - virtual bool selectIntAddr(SDValue Addr, SDValue &Base, - SDValue &Offset) const; - - virtual bool selectIntAddr11MM(SDValue Addr, SDValue &Base, - SDValue &Offset) const; - - virtual bool selectIntAddr12MM(SDValue Addr, SDValue &Base, - SDValue &Offset) const; - - virtual bool selectIntAddr16MM(SDValue Addr, SDValue &Base, - SDValue &Offset) const; - - virtual bool selectIntAddrLSL2MM(SDValue Addr, SDValue &Base, - SDValue &Offset) const; - - /// Match addr+simm10 and addr - virtual bool selectIntAddrSImm10(SDValue Addr, SDValue &Base, - SDValue &Offset) const; - - virtual bool selectIntAddrSImm10Lsl1(SDValue Addr, SDValue &Base, - SDValue &Offset) const; - - virtual bool selectIntAddrSImm10Lsl2(SDValue Addr, SDValue &Base, - SDValue &Offset) const; - - virtual bool selectIntAddrSImm10Lsl3(SDValue Addr, SDValue &Base, - SDValue &Offset) const; - - virtual bool selectAddr16(SDValue Addr, SDValue &Base, SDValue &Offset); - virtual bool selectAddr16SP(SDValue Addr, SDValue &Base, SDValue &Offset); - - /// Select constant vector splats. - virtual bool selectVSplat(SDNode *N, APInt &Imm, - unsigned MinSizeInBits) const; - /// Select constant vector splats whose value fits in a uimm1. - virtual bool selectVSplatUimm1(SDValue N, SDValue &Imm) const; - /// Select constant vector splats whose value fits in a uimm2. - virtual bool selectVSplatUimm2(SDValue N, SDValue &Imm) const; - /// Select constant vector splats whose value fits in a uimm3. - virtual bool selectVSplatUimm3(SDValue N, SDValue &Imm) const; - /// Select constant vector splats whose value fits in a uimm4. - virtual bool selectVSplatUimm4(SDValue N, SDValue &Imm) const; - /// Select constant vector splats whose value fits in a uimm5. - virtual bool selectVSplatUimm5(SDValue N, SDValue &Imm) const; - /// Select constant vector splats whose value fits in a uimm6. - virtual bool selectVSplatUimm6(SDValue N, SDValue &Imm) const; - /// Select constant vector splats whose value fits in a uimm8. - virtual bool selectVSplatUimm8(SDValue N, SDValue &Imm) const; - /// Select constant vector splats whose value fits in a simm5. - virtual bool selectVSplatSimm5(SDValue N, SDValue &Imm) const; - /// Select constant vector splats whose value is a power of 2. - virtual bool selectVSplatUimmPow2(SDValue N, SDValue &Imm) const; - /// Select constant vector splats whose value is the inverse of a - /// power of 2. - virtual bool selectVSplatUimmInvPow2(SDValue N, SDValue &Imm) const; - /// Select constant vector splats whose value is a run of set bits - /// ending at the most significant bit - virtual bool selectVSplatMaskL(SDValue N, SDValue &Imm) const; - /// Select constant vector splats whose value is a run of set bits - /// starting at bit zero. - virtual bool selectVSplatMaskR(SDValue N, SDValue &Imm) const; - - void Select(SDNode *N) override; - - virtual bool trySelect(SDNode *Node) = 0; - - // getImm - Return a target constant with the specified value. - inline SDValue getImm(const SDNode *Node, uint64_t Imm) { - return CurDAG->getTargetConstant(Imm, SDLoc(Node), Node->getValueType(0)); - } - - virtual void processFunctionAfterISel(MachineFunction &MF) = 0; - - bool SelectInlineAsmMemoryOperand(const SDValue &Op, - unsigned ConstraintID, - std::vector<SDValue> &OutOps) override; -}; -} - -#endif diff --git a/contrib/llvm/lib/Target/Mips/MipsISelLowering.cpp b/contrib/llvm/lib/Target/Mips/MipsISelLowering.cpp deleted file mode 100644 index 0ff09007da4b..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsISelLowering.cpp +++ /dev/null @@ -1,4589 +0,0 @@ -//===- MipsISelLowering.cpp - Mips DAG Lowering Implementation ------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the interfaces that Mips uses to lower LLVM code into a -// selection DAG. -// -//===----------------------------------------------------------------------===// - -#include "MipsISelLowering.h" -#include "MCTargetDesc/MipsBaseInfo.h" -#include "MCTargetDesc/MipsInstPrinter.h" -#include "MCTargetDesc/MipsMCTargetDesc.h" -#include "MipsCCState.h" -#include "MipsInstrInfo.h" -#include "MipsMachineFunction.h" -#include "MipsRegisterInfo.h" -#include "MipsSubtarget.h" -#include "MipsTargetMachine.h" -#include "MipsTargetObjectFile.h" -#include "llvm/ADT/APFloat.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/Statistic.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/StringSwitch.h" -#include "llvm/CodeGen/CallingConvLower.h" -#include "llvm/CodeGen/FunctionLoweringInfo.h" -#include "llvm/CodeGen/ISDOpcodes.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/MachineJumpTableInfo.h" -#include "llvm/CodeGen/MachineMemOperand.h" -#include "llvm/CodeGen/MachineOperand.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/RuntimeLibcalls.h" -#include "llvm/CodeGen/SelectionDAG.h" -#include "llvm/CodeGen/SelectionDAGNodes.h" -#include "llvm/CodeGen/TargetFrameLowering.h" -#include "llvm/CodeGen/TargetInstrInfo.h" -#include "llvm/CodeGen/TargetRegisterInfo.h" -#include "llvm/CodeGen/ValueTypes.h" -#include "llvm/IR/CallingConv.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/DebugLoc.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/GlobalValue.h" -#include "llvm/IR/Type.h" -#include "llvm/IR/Value.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCRegisterInfo.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/CodeGen.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MachineValueType.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetOptions.h" -#include <algorithm> -#include <cassert> -#include <cctype> -#include <cstdint> -#include <deque> -#include <iterator> -#include <utility> -#include <vector> - -using namespace llvm; - -#define DEBUG_TYPE "mips-lower" - -STATISTIC(NumTailCalls, "Number of tail calls"); - -static cl::opt<bool> -LargeGOT("mxgot", cl::Hidden, - cl::desc("MIPS: Enable GOT larger than 64k."), cl::init(false)); - -static cl::opt<bool> -NoZeroDivCheck("mno-check-zero-division", cl::Hidden, - cl::desc("MIPS: Don't trap on integer division by zero."), - cl::init(false)); - -extern cl::opt<bool> EmitJalrReloc; - -static const MCPhysReg Mips64DPRegs[8] = { - Mips::D12_64, Mips::D13_64, Mips::D14_64, Mips::D15_64, - Mips::D16_64, Mips::D17_64, Mips::D18_64, Mips::D19_64 -}; - -// If I is a shifted mask, set the size (Size) and the first bit of the -// mask (Pos), and return true. -// For example, if I is 0x003ff800, (Pos, Size) = (11, 11). -static bool isShiftedMask(uint64_t I, uint64_t &Pos, uint64_t &Size) { - if (!isShiftedMask_64(I)) - return false; - - Size = countPopulation(I); - Pos = countTrailingZeros(I); - return true; -} - -// The MIPS MSA ABI passes vector arguments in the integer register set. -// The number of integer registers used is dependant on the ABI used. -MVT MipsTargetLowering::getRegisterTypeForCallingConv(LLVMContext &Context, - CallingConv::ID CC, - EVT VT) const { - if (VT.isVector()) { - if (Subtarget.isABI_O32()) { - return MVT::i32; - } else { - return (VT.getSizeInBits() == 32) ? MVT::i32 : MVT::i64; - } - } - return MipsTargetLowering::getRegisterType(Context, VT); -} - -unsigned MipsTargetLowering::getNumRegistersForCallingConv(LLVMContext &Context, - CallingConv::ID CC, - EVT VT) const { - if (VT.isVector()) - return std::max((VT.getSizeInBits() / (Subtarget.isABI_O32() ? 32 : 64)), - 1U); - return MipsTargetLowering::getNumRegisters(Context, VT); -} - -unsigned MipsTargetLowering::getVectorTypeBreakdownForCallingConv( - LLVMContext &Context, CallingConv::ID CC, EVT VT, EVT &IntermediateVT, - unsigned &NumIntermediates, MVT &RegisterVT) const { - // Break down vector types to either 2 i64s or 4 i32s. - RegisterVT = getRegisterTypeForCallingConv(Context, CC, VT); - IntermediateVT = RegisterVT; - NumIntermediates = VT.getSizeInBits() < RegisterVT.getSizeInBits() - ? VT.getVectorNumElements() - : VT.getSizeInBits() / RegisterVT.getSizeInBits(); - - return NumIntermediates; -} - -SDValue MipsTargetLowering::getGlobalReg(SelectionDAG &DAG, EVT Ty) const { - MipsFunctionInfo *FI = DAG.getMachineFunction().getInfo<MipsFunctionInfo>(); - return DAG.getRegister(FI->getGlobalBaseReg(), Ty); -} - -SDValue MipsTargetLowering::getTargetNode(GlobalAddressSDNode *N, EVT Ty, - SelectionDAG &DAG, - unsigned Flag) const { - return DAG.getTargetGlobalAddress(N->getGlobal(), SDLoc(N), Ty, 0, Flag); -} - -SDValue MipsTargetLowering::getTargetNode(ExternalSymbolSDNode *N, EVT Ty, - SelectionDAG &DAG, - unsigned Flag) const { - return DAG.getTargetExternalSymbol(N->getSymbol(), Ty, Flag); -} - -SDValue MipsTargetLowering::getTargetNode(BlockAddressSDNode *N, EVT Ty, - SelectionDAG &DAG, - unsigned Flag) const { - return DAG.getTargetBlockAddress(N->getBlockAddress(), Ty, 0, Flag); -} - -SDValue MipsTargetLowering::getTargetNode(JumpTableSDNode *N, EVT Ty, - SelectionDAG &DAG, - unsigned Flag) const { - return DAG.getTargetJumpTable(N->getIndex(), Ty, Flag); -} - -SDValue MipsTargetLowering::getTargetNode(ConstantPoolSDNode *N, EVT Ty, - SelectionDAG &DAG, - unsigned Flag) const { - return DAG.getTargetConstantPool(N->getConstVal(), Ty, N->getAlignment(), - N->getOffset(), Flag); -} - -const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const { - switch ((MipsISD::NodeType)Opcode) { - case MipsISD::FIRST_NUMBER: break; - case MipsISD::JmpLink: return "MipsISD::JmpLink"; - case MipsISD::TailCall: return "MipsISD::TailCall"; - case MipsISD::Highest: return "MipsISD::Highest"; - case MipsISD::Higher: return "MipsISD::Higher"; - case MipsISD::Hi: return "MipsISD::Hi"; - case MipsISD::Lo: return "MipsISD::Lo"; - case MipsISD::GotHi: return "MipsISD::GotHi"; - case MipsISD::TlsHi: return "MipsISD::TlsHi"; - case MipsISD::GPRel: return "MipsISD::GPRel"; - case MipsISD::ThreadPointer: return "MipsISD::ThreadPointer"; - case MipsISD::Ret: return "MipsISD::Ret"; - case MipsISD::ERet: return "MipsISD::ERet"; - case MipsISD::EH_RETURN: return "MipsISD::EH_RETURN"; - case MipsISD::FMS: return "MipsISD::FMS"; - case MipsISD::FPBrcond: return "MipsISD::FPBrcond"; - case MipsISD::FPCmp: return "MipsISD::FPCmp"; - case MipsISD::FSELECT: return "MipsISD::FSELECT"; - case MipsISD::MTC1_D64: return "MipsISD::MTC1_D64"; - case MipsISD::CMovFP_T: return "MipsISD::CMovFP_T"; - case MipsISD::CMovFP_F: return "MipsISD::CMovFP_F"; - case MipsISD::TruncIntFP: return "MipsISD::TruncIntFP"; - case MipsISD::MFHI: return "MipsISD::MFHI"; - case MipsISD::MFLO: return "MipsISD::MFLO"; - case MipsISD::MTLOHI: return "MipsISD::MTLOHI"; - case MipsISD::Mult: return "MipsISD::Mult"; - case MipsISD::Multu: return "MipsISD::Multu"; - case MipsISD::MAdd: return "MipsISD::MAdd"; - case MipsISD::MAddu: return "MipsISD::MAddu"; - case MipsISD::MSub: return "MipsISD::MSub"; - case MipsISD::MSubu: return "MipsISD::MSubu"; - case MipsISD::DivRem: return "MipsISD::DivRem"; - case MipsISD::DivRemU: return "MipsISD::DivRemU"; - case MipsISD::DivRem16: return "MipsISD::DivRem16"; - case MipsISD::DivRemU16: return "MipsISD::DivRemU16"; - case MipsISD::BuildPairF64: return "MipsISD::BuildPairF64"; - case MipsISD::ExtractElementF64: return "MipsISD::ExtractElementF64"; - case MipsISD::Wrapper: return "MipsISD::Wrapper"; - case MipsISD::DynAlloc: return "MipsISD::DynAlloc"; - case MipsISD::Sync: return "MipsISD::Sync"; - case MipsISD::Ext: return "MipsISD::Ext"; - case MipsISD::Ins: return "MipsISD::Ins"; - case MipsISD::CIns: return "MipsISD::CIns"; - case MipsISD::LWL: return "MipsISD::LWL"; - case MipsISD::LWR: return "MipsISD::LWR"; - case MipsISD::SWL: return "MipsISD::SWL"; - case MipsISD::SWR: return "MipsISD::SWR"; - case MipsISD::LDL: return "MipsISD::LDL"; - case MipsISD::LDR: return "MipsISD::LDR"; - case MipsISD::SDL: return "MipsISD::SDL"; - case MipsISD::SDR: return "MipsISD::SDR"; - case MipsISD::EXTP: return "MipsISD::EXTP"; - case MipsISD::EXTPDP: return "MipsISD::EXTPDP"; - case MipsISD::EXTR_S_H: return "MipsISD::EXTR_S_H"; - case MipsISD::EXTR_W: return "MipsISD::EXTR_W"; - case MipsISD::EXTR_R_W: return "MipsISD::EXTR_R_W"; - case MipsISD::EXTR_RS_W: return "MipsISD::EXTR_RS_W"; - case MipsISD::SHILO: return "MipsISD::SHILO"; - case MipsISD::MTHLIP: return "MipsISD::MTHLIP"; - case MipsISD::MULSAQ_S_W_PH: return "MipsISD::MULSAQ_S_W_PH"; - case MipsISD::MAQ_S_W_PHL: return "MipsISD::MAQ_S_W_PHL"; - case MipsISD::MAQ_S_W_PHR: return "MipsISD::MAQ_S_W_PHR"; - case MipsISD::MAQ_SA_W_PHL: return "MipsISD::MAQ_SA_W_PHL"; - case MipsISD::MAQ_SA_W_PHR: return "MipsISD::MAQ_SA_W_PHR"; - case MipsISD::DPAU_H_QBL: return "MipsISD::DPAU_H_QBL"; - case MipsISD::DPAU_H_QBR: return "MipsISD::DPAU_H_QBR"; - case MipsISD::DPSU_H_QBL: return "MipsISD::DPSU_H_QBL"; - case MipsISD::DPSU_H_QBR: return "MipsISD::DPSU_H_QBR"; - case MipsISD::DPAQ_S_W_PH: return "MipsISD::DPAQ_S_W_PH"; - case MipsISD::DPSQ_S_W_PH: return "MipsISD::DPSQ_S_W_PH"; - case MipsISD::DPAQ_SA_L_W: return "MipsISD::DPAQ_SA_L_W"; - case MipsISD::DPSQ_SA_L_W: return "MipsISD::DPSQ_SA_L_W"; - case MipsISD::DPA_W_PH: return "MipsISD::DPA_W_PH"; - case MipsISD::DPS_W_PH: return "MipsISD::DPS_W_PH"; - case MipsISD::DPAQX_S_W_PH: return "MipsISD::DPAQX_S_W_PH"; - case MipsISD::DPAQX_SA_W_PH: return "MipsISD::DPAQX_SA_W_PH"; - case MipsISD::DPAX_W_PH: return "MipsISD::DPAX_W_PH"; - case MipsISD::DPSX_W_PH: return "MipsISD::DPSX_W_PH"; - case MipsISD::DPSQX_S_W_PH: return "MipsISD::DPSQX_S_W_PH"; - case MipsISD::DPSQX_SA_W_PH: return "MipsISD::DPSQX_SA_W_PH"; - case MipsISD::MULSA_W_PH: return "MipsISD::MULSA_W_PH"; - case MipsISD::MULT: return "MipsISD::MULT"; - case MipsISD::MULTU: return "MipsISD::MULTU"; - case MipsISD::MADD_DSP: return "MipsISD::MADD_DSP"; - case MipsISD::MADDU_DSP: return "MipsISD::MADDU_DSP"; - case MipsISD::MSUB_DSP: return "MipsISD::MSUB_DSP"; - case MipsISD::MSUBU_DSP: return "MipsISD::MSUBU_DSP"; - case MipsISD::SHLL_DSP: return "MipsISD::SHLL_DSP"; - case MipsISD::SHRA_DSP: return "MipsISD::SHRA_DSP"; - case MipsISD::SHRL_DSP: return "MipsISD::SHRL_DSP"; - case MipsISD::SETCC_DSP: return "MipsISD::SETCC_DSP"; - case MipsISD::SELECT_CC_DSP: return "MipsISD::SELECT_CC_DSP"; - case MipsISD::VALL_ZERO: return "MipsISD::VALL_ZERO"; - case MipsISD::VANY_ZERO: return "MipsISD::VANY_ZERO"; - case MipsISD::VALL_NONZERO: return "MipsISD::VALL_NONZERO"; - case MipsISD::VANY_NONZERO: return "MipsISD::VANY_NONZERO"; - case MipsISD::VCEQ: return "MipsISD::VCEQ"; - case MipsISD::VCLE_S: return "MipsISD::VCLE_S"; - case MipsISD::VCLE_U: return "MipsISD::VCLE_U"; - case MipsISD::VCLT_S: return "MipsISD::VCLT_S"; - case MipsISD::VCLT_U: return "MipsISD::VCLT_U"; - case MipsISD::VEXTRACT_SEXT_ELT: return "MipsISD::VEXTRACT_SEXT_ELT"; - case MipsISD::VEXTRACT_ZEXT_ELT: return "MipsISD::VEXTRACT_ZEXT_ELT"; - case MipsISD::VNOR: return "MipsISD::VNOR"; - case MipsISD::VSHF: return "MipsISD::VSHF"; - case MipsISD::SHF: return "MipsISD::SHF"; - case MipsISD::ILVEV: return "MipsISD::ILVEV"; - case MipsISD::ILVOD: return "MipsISD::ILVOD"; - case MipsISD::ILVL: return "MipsISD::ILVL"; - case MipsISD::ILVR: return "MipsISD::ILVR"; - case MipsISD::PCKEV: return "MipsISD::PCKEV"; - case MipsISD::PCKOD: return "MipsISD::PCKOD"; - case MipsISD::INSVE: return "MipsISD::INSVE"; - } - return nullptr; -} - -MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM, - const MipsSubtarget &STI) - : TargetLowering(TM), Subtarget(STI), ABI(TM.getABI()) { - // Mips does not have i1 type, so use i32 for - // setcc operations results (slt, sgt, ...). - setBooleanContents(ZeroOrOneBooleanContent); - setBooleanVectorContents(ZeroOrNegativeOneBooleanContent); - // The cmp.cond.fmt instruction in MIPS32r6/MIPS64r6 uses 0 and -1 like MSA - // does. Integer booleans still use 0 and 1. - if (Subtarget.hasMips32r6()) - setBooleanContents(ZeroOrOneBooleanContent, - ZeroOrNegativeOneBooleanContent); - - // Load extented operations for i1 types must be promoted - for (MVT VT : MVT::integer_valuetypes()) { - setLoadExtAction(ISD::EXTLOAD, VT, MVT::i1, Promote); - setLoadExtAction(ISD::ZEXTLOAD, VT, MVT::i1, Promote); - setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i1, Promote); - } - - // MIPS doesn't have extending float->double load/store. Set LoadExtAction - // for f32, f16 - for (MVT VT : MVT::fp_valuetypes()) { - setLoadExtAction(ISD::EXTLOAD, VT, MVT::f32, Expand); - setLoadExtAction(ISD::EXTLOAD, VT, MVT::f16, Expand); - } - - // Set LoadExtAction for f16 vectors to Expand - for (MVT VT : MVT::fp_vector_valuetypes()) { - MVT F16VT = MVT::getVectorVT(MVT::f16, VT.getVectorNumElements()); - if (F16VT.isValid()) - setLoadExtAction(ISD::EXTLOAD, VT, F16VT, Expand); - } - - setTruncStoreAction(MVT::f32, MVT::f16, Expand); - setTruncStoreAction(MVT::f64, MVT::f16, Expand); - - setTruncStoreAction(MVT::f64, MVT::f32, Expand); - - // Used by legalize types to correctly generate the setcc result. - // Without this, every float setcc comes with a AND/OR with the result, - // we don't want this, since the fpcmp result goes to a flag register, - // which is used implicitly by brcond and select operations. - AddPromotedToType(ISD::SETCC, MVT::i1, MVT::i32); - - // Mips Custom Operations - setOperationAction(ISD::BR_JT, MVT::Other, Expand); - setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); - setOperationAction(ISD::BlockAddress, MVT::i32, Custom); - setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom); - setOperationAction(ISD::JumpTable, MVT::i32, Custom); - setOperationAction(ISD::ConstantPool, MVT::i32, Custom); - setOperationAction(ISD::SELECT, MVT::f32, Custom); - setOperationAction(ISD::SELECT, MVT::f64, Custom); - setOperationAction(ISD::SELECT, MVT::i32, Custom); - setOperationAction(ISD::SETCC, MVT::f32, Custom); - setOperationAction(ISD::SETCC, MVT::f64, Custom); - setOperationAction(ISD::BRCOND, MVT::Other, Custom); - setOperationAction(ISD::FCOPYSIGN, MVT::f32, Custom); - setOperationAction(ISD::FCOPYSIGN, MVT::f64, Custom); - setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom); - - if (!(TM.Options.NoNaNsFPMath || Subtarget.inAbs2008Mode())) { - setOperationAction(ISD::FABS, MVT::f32, Custom); - setOperationAction(ISD::FABS, MVT::f64, Custom); - } - - if (Subtarget.isGP64bit()) { - setOperationAction(ISD::GlobalAddress, MVT::i64, Custom); - setOperationAction(ISD::BlockAddress, MVT::i64, Custom); - setOperationAction(ISD::GlobalTLSAddress, MVT::i64, Custom); - setOperationAction(ISD::JumpTable, MVT::i64, Custom); - setOperationAction(ISD::ConstantPool, MVT::i64, Custom); - setOperationAction(ISD::SELECT, MVT::i64, Custom); - setOperationAction(ISD::LOAD, MVT::i64, Custom); - setOperationAction(ISD::STORE, MVT::i64, Custom); - setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom); - setOperationAction(ISD::SHL_PARTS, MVT::i64, Custom); - setOperationAction(ISD::SRA_PARTS, MVT::i64, Custom); - setOperationAction(ISD::SRL_PARTS, MVT::i64, Custom); - } - - if (!Subtarget.isGP64bit()) { - setOperationAction(ISD::SHL_PARTS, MVT::i32, Custom); - setOperationAction(ISD::SRA_PARTS, MVT::i32, Custom); - setOperationAction(ISD::SRL_PARTS, MVT::i32, Custom); - } - - setOperationAction(ISD::EH_DWARF_CFA, MVT::i32, Custom); - if (Subtarget.isGP64bit()) - setOperationAction(ISD::EH_DWARF_CFA, MVT::i64, Custom); - - setOperationAction(ISD::SDIV, MVT::i32, Expand); - setOperationAction(ISD::SREM, MVT::i32, Expand); - setOperationAction(ISD::UDIV, MVT::i32, Expand); - setOperationAction(ISD::UREM, MVT::i32, Expand); - setOperationAction(ISD::SDIV, MVT::i64, Expand); - setOperationAction(ISD::SREM, MVT::i64, Expand); - setOperationAction(ISD::UDIV, MVT::i64, Expand); - setOperationAction(ISD::UREM, MVT::i64, Expand); - - // Operations not directly supported by Mips. - setOperationAction(ISD::BR_CC, MVT::f32, Expand); - setOperationAction(ISD::BR_CC, MVT::f64, Expand); - setOperationAction(ISD::BR_CC, MVT::i32, Expand); - setOperationAction(ISD::BR_CC, MVT::i64, Expand); - setOperationAction(ISD::SELECT_CC, MVT::i32, Expand); - setOperationAction(ISD::SELECT_CC, MVT::i64, Expand); - setOperationAction(ISD::SELECT_CC, MVT::f32, Expand); - setOperationAction(ISD::SELECT_CC, MVT::f64, Expand); - setOperationAction(ISD::UINT_TO_FP, MVT::i32, Expand); - setOperationAction(ISD::UINT_TO_FP, MVT::i64, Expand); - setOperationAction(ISD::FP_TO_UINT, MVT::i32, Expand); - setOperationAction(ISD::FP_TO_UINT, MVT::i64, Expand); - setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); - if (Subtarget.hasCnMips()) { - setOperationAction(ISD::CTPOP, MVT::i32, Legal); - setOperationAction(ISD::CTPOP, MVT::i64, Legal); - } else { - setOperationAction(ISD::CTPOP, MVT::i32, Expand); - setOperationAction(ISD::CTPOP, MVT::i64, Expand); - } - setOperationAction(ISD::CTTZ, MVT::i32, Expand); - setOperationAction(ISD::CTTZ, MVT::i64, Expand); - setOperationAction(ISD::ROTL, MVT::i32, Expand); - setOperationAction(ISD::ROTL, MVT::i64, Expand); - setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand); - setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64, Expand); - - if (!Subtarget.hasMips32r2()) - setOperationAction(ISD::ROTR, MVT::i32, Expand); - - if (!Subtarget.hasMips64r2()) - setOperationAction(ISD::ROTR, MVT::i64, Expand); - - setOperationAction(ISD::FSIN, MVT::f32, Expand); - setOperationAction(ISD::FSIN, MVT::f64, Expand); - setOperationAction(ISD::FCOS, MVT::f32, Expand); - setOperationAction(ISD::FCOS, MVT::f64, Expand); - setOperationAction(ISD::FSINCOS, MVT::f32, Expand); - setOperationAction(ISD::FSINCOS, MVT::f64, Expand); - setOperationAction(ISD::FPOW, MVT::f32, Expand); - setOperationAction(ISD::FPOW, MVT::f64, Expand); - setOperationAction(ISD::FLOG, MVT::f32, Expand); - setOperationAction(ISD::FLOG2, MVT::f32, Expand); - setOperationAction(ISD::FLOG10, MVT::f32, Expand); - setOperationAction(ISD::FEXP, MVT::f32, Expand); - setOperationAction(ISD::FMA, MVT::f32, Expand); - setOperationAction(ISD::FMA, MVT::f64, Expand); - setOperationAction(ISD::FREM, MVT::f32, Expand); - setOperationAction(ISD::FREM, MVT::f64, Expand); - - // Lower f16 conversion operations into library calls - setOperationAction(ISD::FP16_TO_FP, MVT::f32, Expand); - setOperationAction(ISD::FP_TO_FP16, MVT::f32, Expand); - setOperationAction(ISD::FP16_TO_FP, MVT::f64, Expand); - setOperationAction(ISD::FP_TO_FP16, MVT::f64, Expand); - - setOperationAction(ISD::EH_RETURN, MVT::Other, Custom); - - setOperationAction(ISD::VASTART, MVT::Other, Custom); - setOperationAction(ISD::VAARG, MVT::Other, Custom); - setOperationAction(ISD::VACOPY, MVT::Other, Expand); - setOperationAction(ISD::VAEND, MVT::Other, Expand); - - // Use the default for now - setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); - setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand); - - if (!Subtarget.isGP64bit()) { - setOperationAction(ISD::ATOMIC_LOAD, MVT::i64, Expand); - setOperationAction(ISD::ATOMIC_STORE, MVT::i64, Expand); - } - - if (!Subtarget.hasMips32r2()) { - setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8, Expand); - setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16, Expand); - } - - // MIPS16 lacks MIPS32's clz and clo instructions. - if (!Subtarget.hasMips32() || Subtarget.inMips16Mode()) - setOperationAction(ISD::CTLZ, MVT::i32, Expand); - if (!Subtarget.hasMips64()) - setOperationAction(ISD::CTLZ, MVT::i64, Expand); - - if (!Subtarget.hasMips32r2()) - setOperationAction(ISD::BSWAP, MVT::i32, Expand); - if (!Subtarget.hasMips64r2()) - setOperationAction(ISD::BSWAP, MVT::i64, Expand); - - if (Subtarget.isGP64bit()) { - setLoadExtAction(ISD::SEXTLOAD, MVT::i64, MVT::i32, Custom); - setLoadExtAction(ISD::ZEXTLOAD, MVT::i64, MVT::i32, Custom); - setLoadExtAction(ISD::EXTLOAD, MVT::i64, MVT::i32, Custom); - setTruncStoreAction(MVT::i64, MVT::i32, Custom); - } - - setOperationAction(ISD::TRAP, MVT::Other, Legal); - - setTargetDAGCombine(ISD::SDIVREM); - setTargetDAGCombine(ISD::UDIVREM); - setTargetDAGCombine(ISD::SELECT); - setTargetDAGCombine(ISD::AND); - setTargetDAGCombine(ISD::OR); - setTargetDAGCombine(ISD::ADD); - setTargetDAGCombine(ISD::SUB); - setTargetDAGCombine(ISD::AssertZext); - setTargetDAGCombine(ISD::SHL); - - if (ABI.IsO32()) { - // These libcalls are not available in 32-bit. - setLibcallName(RTLIB::SHL_I128, nullptr); - setLibcallName(RTLIB::SRL_I128, nullptr); - setLibcallName(RTLIB::SRA_I128, nullptr); - } - - setMinFunctionAlignment(Subtarget.isGP64bit() ? 3 : 2); - - // The arguments on the stack are defined in terms of 4-byte slots on O32 - // and 8-byte slots on N32/N64. - setMinStackArgumentAlignment((ABI.IsN32() || ABI.IsN64()) ? 8 : 4); - - setStackPointerRegisterToSaveRestore(ABI.IsN64() ? Mips::SP_64 : Mips::SP); - - MaxStoresPerMemcpy = 16; - - isMicroMips = Subtarget.inMicroMipsMode(); -} - -const MipsTargetLowering *MipsTargetLowering::create(const MipsTargetMachine &TM, - const MipsSubtarget &STI) { - if (STI.inMips16Mode()) - return createMips16TargetLowering(TM, STI); - - return createMipsSETargetLowering(TM, STI); -} - -// Create a fast isel object. -FastISel * -MipsTargetLowering::createFastISel(FunctionLoweringInfo &funcInfo, - const TargetLibraryInfo *libInfo) const { - const MipsTargetMachine &TM = - static_cast<const MipsTargetMachine &>(funcInfo.MF->getTarget()); - - // We support only the standard encoding [MIPS32,MIPS32R5] ISAs. - bool UseFastISel = TM.Options.EnableFastISel && Subtarget.hasMips32() && - !Subtarget.hasMips32r6() && !Subtarget.inMips16Mode() && - !Subtarget.inMicroMipsMode(); - - // Disable if either of the following is true: - // We do not generate PIC, the ABI is not O32, LargeGOT is being used. - if (!TM.isPositionIndependent() || !TM.getABI().IsO32() || LargeGOT) - UseFastISel = false; - - return UseFastISel ? Mips::createFastISel(funcInfo, libInfo) : nullptr; -} - -EVT MipsTargetLowering::getSetCCResultType(const DataLayout &, LLVMContext &, - EVT VT) const { - if (!VT.isVector()) - return MVT::i32; - return VT.changeVectorElementTypeToInteger(); -} - -static SDValue performDivRemCombine(SDNode *N, SelectionDAG &DAG, - TargetLowering::DAGCombinerInfo &DCI, - const MipsSubtarget &Subtarget) { - if (DCI.isBeforeLegalizeOps()) - return SDValue(); - - EVT Ty = N->getValueType(0); - unsigned LO = (Ty == MVT::i32) ? Mips::LO0 : Mips::LO0_64; - unsigned HI = (Ty == MVT::i32) ? Mips::HI0 : Mips::HI0_64; - unsigned Opc = N->getOpcode() == ISD::SDIVREM ? MipsISD::DivRem16 : - MipsISD::DivRemU16; - SDLoc DL(N); - - SDValue DivRem = DAG.getNode(Opc, DL, MVT::Glue, - N->getOperand(0), N->getOperand(1)); - SDValue InChain = DAG.getEntryNode(); - SDValue InGlue = DivRem; - - // insert MFLO - if (N->hasAnyUseOfValue(0)) { - SDValue CopyFromLo = DAG.getCopyFromReg(InChain, DL, LO, Ty, - InGlue); - DAG.ReplaceAllUsesOfValueWith(SDValue(N, 0), CopyFromLo); - InChain = CopyFromLo.getValue(1); - InGlue = CopyFromLo.getValue(2); - } - - // insert MFHI - if (N->hasAnyUseOfValue(1)) { - SDValue CopyFromHi = DAG.getCopyFromReg(InChain, DL, - HI, Ty, InGlue); - DAG.ReplaceAllUsesOfValueWith(SDValue(N, 1), CopyFromHi); - } - - return SDValue(); -} - -static Mips::CondCode condCodeToFCC(ISD::CondCode CC) { - switch (CC) { - default: llvm_unreachable("Unknown fp condition code!"); - case ISD::SETEQ: - case ISD::SETOEQ: return Mips::FCOND_OEQ; - case ISD::SETUNE: return Mips::FCOND_UNE; - case ISD::SETLT: - case ISD::SETOLT: return Mips::FCOND_OLT; - case ISD::SETGT: - case ISD::SETOGT: return Mips::FCOND_OGT; - case ISD::SETLE: - case ISD::SETOLE: return Mips::FCOND_OLE; - case ISD::SETGE: - case ISD::SETOGE: return Mips::FCOND_OGE; - case ISD::SETULT: return Mips::FCOND_ULT; - case ISD::SETULE: return Mips::FCOND_ULE; - case ISD::SETUGT: return Mips::FCOND_UGT; - case ISD::SETUGE: return Mips::FCOND_UGE; - case ISD::SETUO: return Mips::FCOND_UN; - case ISD::SETO: return Mips::FCOND_OR; - case ISD::SETNE: - case ISD::SETONE: return Mips::FCOND_ONE; - case ISD::SETUEQ: return Mips::FCOND_UEQ; - } -} - -/// This function returns true if the floating point conditional branches and -/// conditional moves which use condition code CC should be inverted. -static bool invertFPCondCodeUser(Mips::CondCode CC) { - if (CC >= Mips::FCOND_F && CC <= Mips::FCOND_NGT) - return false; - - assert((CC >= Mips::FCOND_T && CC <= Mips::FCOND_GT) && - "Illegal Condition Code"); - - return true; -} - -// Creates and returns an FPCmp node from a setcc node. -// Returns Op if setcc is not a floating point comparison. -static SDValue createFPCmp(SelectionDAG &DAG, const SDValue &Op) { - // must be a SETCC node - if (Op.getOpcode() != ISD::SETCC) - return Op; - - SDValue LHS = Op.getOperand(0); - - if (!LHS.getValueType().isFloatingPoint()) - return Op; - - SDValue RHS = Op.getOperand(1); - SDLoc DL(Op); - - // Assume the 3rd operand is a CondCodeSDNode. Add code to check the type of - // node if necessary. - ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get(); - - return DAG.getNode(MipsISD::FPCmp, DL, MVT::Glue, LHS, RHS, - DAG.getConstant(condCodeToFCC(CC), DL, MVT::i32)); -} - -// Creates and returns a CMovFPT/F node. -static SDValue createCMovFP(SelectionDAG &DAG, SDValue Cond, SDValue True, - SDValue False, const SDLoc &DL) { - ConstantSDNode *CC = cast<ConstantSDNode>(Cond.getOperand(2)); - bool invert = invertFPCondCodeUser((Mips::CondCode)CC->getSExtValue()); - SDValue FCC0 = DAG.getRegister(Mips::FCC0, MVT::i32); - - return DAG.getNode((invert ? MipsISD::CMovFP_F : MipsISD::CMovFP_T), DL, - True.getValueType(), True, FCC0, False, Cond); -} - -static SDValue performSELECTCombine(SDNode *N, SelectionDAG &DAG, - TargetLowering::DAGCombinerInfo &DCI, - const MipsSubtarget &Subtarget) { - if (DCI.isBeforeLegalizeOps()) - return SDValue(); - - SDValue SetCC = N->getOperand(0); - - if ((SetCC.getOpcode() != ISD::SETCC) || - !SetCC.getOperand(0).getValueType().isInteger()) - return SDValue(); - - SDValue False = N->getOperand(2); - EVT FalseTy = False.getValueType(); - - if (!FalseTy.isInteger()) - return SDValue(); - - ConstantSDNode *FalseC = dyn_cast<ConstantSDNode>(False); - - // If the RHS (False) is 0, we swap the order of the operands - // of ISD::SELECT (obviously also inverting the condition) so that we can - // take advantage of conditional moves using the $0 register. - // Example: - // return (a != 0) ? x : 0; - // load $reg, x - // movz $reg, $0, a - if (!FalseC) - return SDValue(); - - const SDLoc DL(N); - - if (!FalseC->getZExtValue()) { - ISD::CondCode CC = cast<CondCodeSDNode>(SetCC.getOperand(2))->get(); - SDValue True = N->getOperand(1); - - SetCC = DAG.getSetCC(DL, SetCC.getValueType(), SetCC.getOperand(0), - SetCC.getOperand(1), ISD::getSetCCInverse(CC, true)); - - return DAG.getNode(ISD::SELECT, DL, FalseTy, SetCC, False, True); - } - - // If both operands are integer constants there's a possibility that we - // can do some interesting optimizations. - SDValue True = N->getOperand(1); - ConstantSDNode *TrueC = dyn_cast<ConstantSDNode>(True); - - if (!TrueC || !True.getValueType().isInteger()) - return SDValue(); - - // We'll also ignore MVT::i64 operands as this optimizations proves - // to be ineffective because of the required sign extensions as the result - // of a SETCC operator is always MVT::i32 for non-vector types. - if (True.getValueType() == MVT::i64) - return SDValue(); - - int64_t Diff = TrueC->getSExtValue() - FalseC->getSExtValue(); - - // 1) (a < x) ? y : y-1 - // slti $reg1, a, x - // addiu $reg2, $reg1, y-1 - if (Diff == 1) - return DAG.getNode(ISD::ADD, DL, SetCC.getValueType(), SetCC, False); - - // 2) (a < x) ? y-1 : y - // slti $reg1, a, x - // xor $reg1, $reg1, 1 - // addiu $reg2, $reg1, y-1 - if (Diff == -1) { - ISD::CondCode CC = cast<CondCodeSDNode>(SetCC.getOperand(2))->get(); - SetCC = DAG.getSetCC(DL, SetCC.getValueType(), SetCC.getOperand(0), - SetCC.getOperand(1), ISD::getSetCCInverse(CC, true)); - return DAG.getNode(ISD::ADD, DL, SetCC.getValueType(), SetCC, True); - } - - // Could not optimize. - return SDValue(); -} - -static SDValue performCMovFPCombine(SDNode *N, SelectionDAG &DAG, - TargetLowering::DAGCombinerInfo &DCI, - const MipsSubtarget &Subtarget) { - if (DCI.isBeforeLegalizeOps()) - return SDValue(); - - SDValue ValueIfTrue = N->getOperand(0), ValueIfFalse = N->getOperand(2); - - ConstantSDNode *FalseC = dyn_cast<ConstantSDNode>(ValueIfFalse); - if (!FalseC || FalseC->getZExtValue()) - return SDValue(); - - // Since RHS (False) is 0, we swap the order of the True/False operands - // (obviously also inverting the condition) so that we can - // take advantage of conditional moves using the $0 register. - // Example: - // return (a != 0) ? x : 0; - // load $reg, x - // movz $reg, $0, a - unsigned Opc = (N->getOpcode() == MipsISD::CMovFP_T) ? MipsISD::CMovFP_F : - MipsISD::CMovFP_T; - - SDValue FCC = N->getOperand(1), Glue = N->getOperand(3); - return DAG.getNode(Opc, SDLoc(N), ValueIfFalse.getValueType(), - ValueIfFalse, FCC, ValueIfTrue, Glue); -} - -static SDValue performANDCombine(SDNode *N, SelectionDAG &DAG, - TargetLowering::DAGCombinerInfo &DCI, - const MipsSubtarget &Subtarget) { - if (DCI.isBeforeLegalizeOps() || !Subtarget.hasExtractInsert()) - return SDValue(); - - SDValue FirstOperand = N->getOperand(0); - unsigned FirstOperandOpc = FirstOperand.getOpcode(); - SDValue Mask = N->getOperand(1); - EVT ValTy = N->getValueType(0); - SDLoc DL(N); - - uint64_t Pos = 0, SMPos, SMSize; - ConstantSDNode *CN; - SDValue NewOperand; - unsigned Opc; - - // Op's second operand must be a shifted mask. - if (!(CN = dyn_cast<ConstantSDNode>(Mask)) || - !isShiftedMask(CN->getZExtValue(), SMPos, SMSize)) - return SDValue(); - - if (FirstOperandOpc == ISD::SRA || FirstOperandOpc == ISD::SRL) { - // Pattern match EXT. - // $dst = and ((sra or srl) $src , pos), (2**size - 1) - // => ext $dst, $src, pos, size - - // The second operand of the shift must be an immediate. - if (!(CN = dyn_cast<ConstantSDNode>(FirstOperand.getOperand(1)))) - return SDValue(); - - Pos = CN->getZExtValue(); - - // Return if the shifted mask does not start at bit 0 or the sum of its size - // and Pos exceeds the word's size. - if (SMPos != 0 || Pos + SMSize > ValTy.getSizeInBits()) - return SDValue(); - - Opc = MipsISD::Ext; - NewOperand = FirstOperand.getOperand(0); - } else if (FirstOperandOpc == ISD::SHL && Subtarget.hasCnMips()) { - // Pattern match CINS. - // $dst = and (shl $src , pos), mask - // => cins $dst, $src, pos, size - // mask is a shifted mask with consecutive 1's, pos = shift amount, - // size = population count. - - // The second operand of the shift must be an immediate. - if (!(CN = dyn_cast<ConstantSDNode>(FirstOperand.getOperand(1)))) - return SDValue(); - - Pos = CN->getZExtValue(); - - if (SMPos != Pos || Pos >= ValTy.getSizeInBits() || SMSize >= 32 || - Pos + SMSize > ValTy.getSizeInBits()) - return SDValue(); - - NewOperand = FirstOperand.getOperand(0); - // SMSize is 'location' (position) in this case, not size. - SMSize--; - Opc = MipsISD::CIns; - } else { - // Pattern match EXT. - // $dst = and $src, (2**size - 1) , if size > 16 - // => ext $dst, $src, pos, size , pos = 0 - - // If the mask is <= 0xffff, andi can be used instead. - if (CN->getZExtValue() <= 0xffff) - return SDValue(); - - // Return if the mask doesn't start at position 0. - if (SMPos) - return SDValue(); - - Opc = MipsISD::Ext; - NewOperand = FirstOperand; - } - return DAG.getNode(Opc, DL, ValTy, NewOperand, - DAG.getConstant(Pos, DL, MVT::i32), - DAG.getConstant(SMSize, DL, MVT::i32)); -} - -static SDValue performORCombine(SDNode *N, SelectionDAG &DAG, - TargetLowering::DAGCombinerInfo &DCI, - const MipsSubtarget &Subtarget) { - // Pattern match INS. - // $dst = or (and $src1 , mask0), (and (shl $src, pos), mask1), - // where mask1 = (2**size - 1) << pos, mask0 = ~mask1 - // => ins $dst, $src, size, pos, $src1 - if (DCI.isBeforeLegalizeOps() || !Subtarget.hasExtractInsert()) - return SDValue(); - - SDValue And0 = N->getOperand(0), And1 = N->getOperand(1); - uint64_t SMPos0, SMSize0, SMPos1, SMSize1; - ConstantSDNode *CN, *CN1; - - // See if Op's first operand matches (and $src1 , mask0). - if (And0.getOpcode() != ISD::AND) - return SDValue(); - - if (!(CN = dyn_cast<ConstantSDNode>(And0.getOperand(1))) || - !isShiftedMask(~CN->getSExtValue(), SMPos0, SMSize0)) - return SDValue(); - - // See if Op's second operand matches (and (shl $src, pos), mask1). - if (And1.getOpcode() == ISD::AND && - And1.getOperand(0).getOpcode() == ISD::SHL) { - - if (!(CN = dyn_cast<ConstantSDNode>(And1.getOperand(1))) || - !isShiftedMask(CN->getZExtValue(), SMPos1, SMSize1)) - return SDValue(); - - // The shift masks must have the same position and size. - if (SMPos0 != SMPos1 || SMSize0 != SMSize1) - return SDValue(); - - SDValue Shl = And1.getOperand(0); - - if (!(CN = dyn_cast<ConstantSDNode>(Shl.getOperand(1)))) - return SDValue(); - - unsigned Shamt = CN->getZExtValue(); - - // Return if the shift amount and the first bit position of mask are not the - // same. - EVT ValTy = N->getValueType(0); - if ((Shamt != SMPos0) || (SMPos0 + SMSize0 > ValTy.getSizeInBits())) - return SDValue(); - - SDLoc DL(N); - return DAG.getNode(MipsISD::Ins, DL, ValTy, Shl.getOperand(0), - DAG.getConstant(SMPos0, DL, MVT::i32), - DAG.getConstant(SMSize0, DL, MVT::i32), - And0.getOperand(0)); - } else { - // Pattern match DINS. - // $dst = or (and $src, mask0), mask1 - // where mask0 = ((1 << SMSize0) -1) << SMPos0 - // => dins $dst, $src, pos, size - if (~CN->getSExtValue() == ((((int64_t)1 << SMSize0) - 1) << SMPos0) && - ((SMSize0 + SMPos0 <= 64 && Subtarget.hasMips64r2()) || - (SMSize0 + SMPos0 <= 32))) { - // Check if AND instruction has constant as argument - bool isConstCase = And1.getOpcode() != ISD::AND; - if (And1.getOpcode() == ISD::AND) { - if (!(CN1 = dyn_cast<ConstantSDNode>(And1->getOperand(1)))) - return SDValue(); - } else { - if (!(CN1 = dyn_cast<ConstantSDNode>(N->getOperand(1)))) - return SDValue(); - } - // Don't generate INS if constant OR operand doesn't fit into bits - // cleared by constant AND operand. - if (CN->getSExtValue() & CN1->getSExtValue()) - return SDValue(); - - SDLoc DL(N); - EVT ValTy = N->getOperand(0)->getValueType(0); - SDValue Const1; - SDValue SrlX; - if (!isConstCase) { - Const1 = DAG.getConstant(SMPos0, DL, MVT::i32); - SrlX = DAG.getNode(ISD::SRL, DL, And1->getValueType(0), And1, Const1); - } - return DAG.getNode( - MipsISD::Ins, DL, N->getValueType(0), - isConstCase - ? DAG.getConstant(CN1->getSExtValue() >> SMPos0, DL, ValTy) - : SrlX, - DAG.getConstant(SMPos0, DL, MVT::i32), - DAG.getConstant(ValTy.getSizeInBits() / 8 < 8 ? SMSize0 & 31 - : SMSize0, - DL, MVT::i32), - And0->getOperand(0)); - - } - return SDValue(); - } -} - -static SDValue performMADD_MSUBCombine(SDNode *ROOTNode, SelectionDAG &CurDAG, - const MipsSubtarget &Subtarget) { - // ROOTNode must have a multiplication as an operand for the match to be - // successful. - if (ROOTNode->getOperand(0).getOpcode() != ISD::MUL && - ROOTNode->getOperand(1).getOpcode() != ISD::MUL) - return SDValue(); - - // We don't handle vector types here. - if (ROOTNode->getValueType(0).isVector()) - return SDValue(); - - // For MIPS64, madd / msub instructions are inefficent to use with 64 bit - // arithmetic. E.g. - // (add (mul a b) c) => - // let res = (madd (mthi (drotr c 32))x(mtlo c) a b) in - // MIPS64: (or (dsll (mfhi res) 32) (dsrl (dsll (mflo res) 32) 32) - // or - // MIPS64R2: (dins (mflo res) (mfhi res) 32 32) - // - // The overhead of setting up the Hi/Lo registers and reassembling the - // result makes this a dubious optimzation for MIPS64. The core of the - // problem is that Hi/Lo contain the upper and lower 32 bits of the - // operand and result. - // - // It requires a chain of 4 add/mul for MIPS64R2 to get better code - // density than doing it naively, 5 for MIPS64. Additionally, using - // madd/msub on MIPS64 requires the operands actually be 32 bit sign - // extended operands, not true 64 bit values. - // - // FIXME: For the moment, disable this completely for MIPS64. - if (Subtarget.hasMips64()) - return SDValue(); - - SDValue Mult = ROOTNode->getOperand(0).getOpcode() == ISD::MUL - ? ROOTNode->getOperand(0) - : ROOTNode->getOperand(1); - - SDValue AddOperand = ROOTNode->getOperand(0).getOpcode() == ISD::MUL - ? ROOTNode->getOperand(1) - : ROOTNode->getOperand(0); - - // Transform this to a MADD only if the user of this node is the add. - // If there are other users of the mul, this function returns here. - if (!Mult.hasOneUse()) - return SDValue(); - - // maddu and madd are unusual instructions in that on MIPS64 bits 63..31 - // must be in canonical form, i.e. sign extended. For MIPS32, the operands - // of the multiply must have 32 or more sign bits, otherwise we cannot - // perform this optimization. We have to check this here as we're performing - // this optimization pre-legalization. - SDValue MultLHS = Mult->getOperand(0); - SDValue MultRHS = Mult->getOperand(1); - - bool IsSigned = MultLHS->getOpcode() == ISD::SIGN_EXTEND && - MultRHS->getOpcode() == ISD::SIGN_EXTEND; - bool IsUnsigned = MultLHS->getOpcode() == ISD::ZERO_EXTEND && - MultRHS->getOpcode() == ISD::ZERO_EXTEND; - - if (!IsSigned && !IsUnsigned) - return SDValue(); - - // Initialize accumulator. - SDLoc DL(ROOTNode); - SDValue TopHalf; - SDValue BottomHalf; - BottomHalf = CurDAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, AddOperand, - CurDAG.getIntPtrConstant(0, DL)); - - TopHalf = CurDAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, AddOperand, - CurDAG.getIntPtrConstant(1, DL)); - SDValue ACCIn = CurDAG.getNode(MipsISD::MTLOHI, DL, MVT::Untyped, - BottomHalf, - TopHalf); - - // Create MipsMAdd(u) / MipsMSub(u) node. - bool IsAdd = ROOTNode->getOpcode() == ISD::ADD; - unsigned Opcode = IsAdd ? (IsUnsigned ? MipsISD::MAddu : MipsISD::MAdd) - : (IsUnsigned ? MipsISD::MSubu : MipsISD::MSub); - SDValue MAddOps[3] = { - CurDAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Mult->getOperand(0)), - CurDAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Mult->getOperand(1)), ACCIn}; - EVT VTs[2] = {MVT::i32, MVT::i32}; - SDValue MAdd = CurDAG.getNode(Opcode, DL, VTs, MAddOps); - - SDValue ResLo = CurDAG.getNode(MipsISD::MFLO, DL, MVT::i32, MAdd); - SDValue ResHi = CurDAG.getNode(MipsISD::MFHI, DL, MVT::i32, MAdd); - SDValue Combined = - CurDAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, ResLo, ResHi); - return Combined; -} - -static SDValue performSUBCombine(SDNode *N, SelectionDAG &DAG, - TargetLowering::DAGCombinerInfo &DCI, - const MipsSubtarget &Subtarget) { - // (sub v0 (mul v1, v2)) => (msub v1, v2, v0) - if (DCI.isBeforeLegalizeOps()) { - if (Subtarget.hasMips32() && !Subtarget.hasMips32r6() && - !Subtarget.inMips16Mode() && N->getValueType(0) == MVT::i64) - return performMADD_MSUBCombine(N, DAG, Subtarget); - - return SDValue(); - } - - return SDValue(); -} - -static SDValue performADDCombine(SDNode *N, SelectionDAG &DAG, - TargetLowering::DAGCombinerInfo &DCI, - const MipsSubtarget &Subtarget) { - // (add v0 (mul v1, v2)) => (madd v1, v2, v0) - if (DCI.isBeforeLegalizeOps()) { - if (Subtarget.hasMips32() && !Subtarget.hasMips32r6() && - !Subtarget.inMips16Mode() && N->getValueType(0) == MVT::i64) - return performMADD_MSUBCombine(N, DAG, Subtarget); - - return SDValue(); - } - - // (add v0, (add v1, abs_lo(tjt))) => (add (add v0, v1), abs_lo(tjt)) - SDValue Add = N->getOperand(1); - - if (Add.getOpcode() != ISD::ADD) - return SDValue(); - - SDValue Lo = Add.getOperand(1); - - if ((Lo.getOpcode() != MipsISD::Lo) || - (Lo.getOperand(0).getOpcode() != ISD::TargetJumpTable)) - return SDValue(); - - EVT ValTy = N->getValueType(0); - SDLoc DL(N); - - SDValue Add1 = DAG.getNode(ISD::ADD, DL, ValTy, N->getOperand(0), - Add.getOperand(0)); - return DAG.getNode(ISD::ADD, DL, ValTy, Add1, Lo); -} - -static SDValue performSHLCombine(SDNode *N, SelectionDAG &DAG, - TargetLowering::DAGCombinerInfo &DCI, - const MipsSubtarget &Subtarget) { - // Pattern match CINS. - // $dst = shl (and $src , imm), pos - // => cins $dst, $src, pos, size - - if (DCI.isBeforeLegalizeOps() || !Subtarget.hasCnMips()) - return SDValue(); - - SDValue FirstOperand = N->getOperand(0); - unsigned FirstOperandOpc = FirstOperand.getOpcode(); - SDValue SecondOperand = N->getOperand(1); - EVT ValTy = N->getValueType(0); - SDLoc DL(N); - - uint64_t Pos = 0, SMPos, SMSize; - ConstantSDNode *CN; - SDValue NewOperand; - - // The second operand of the shift must be an immediate. - if (!(CN = dyn_cast<ConstantSDNode>(SecondOperand))) - return SDValue(); - - Pos = CN->getZExtValue(); - - if (Pos >= ValTy.getSizeInBits()) - return SDValue(); - - if (FirstOperandOpc != ISD::AND) - return SDValue(); - - // AND's second operand must be a shifted mask. - if (!(CN = dyn_cast<ConstantSDNode>(FirstOperand.getOperand(1))) || - !isShiftedMask(CN->getZExtValue(), SMPos, SMSize)) - return SDValue(); - - // Return if the shifted mask does not start at bit 0 or the sum of its size - // and Pos exceeds the word's size. - if (SMPos != 0 || SMSize > 32 || Pos + SMSize > ValTy.getSizeInBits()) - return SDValue(); - - NewOperand = FirstOperand.getOperand(0); - // SMSize is 'location' (position) in this case, not size. - SMSize--; - - return DAG.getNode(MipsISD::CIns, DL, ValTy, NewOperand, - DAG.getConstant(Pos, DL, MVT::i32), - DAG.getConstant(SMSize, DL, MVT::i32)); -} - -SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) - const { - SelectionDAG &DAG = DCI.DAG; - unsigned Opc = N->getOpcode(); - - switch (Opc) { - default: break; - case ISD::SDIVREM: - case ISD::UDIVREM: - return performDivRemCombine(N, DAG, DCI, Subtarget); - case ISD::SELECT: - return performSELECTCombine(N, DAG, DCI, Subtarget); - case MipsISD::CMovFP_F: - case MipsISD::CMovFP_T: - return performCMovFPCombine(N, DAG, DCI, Subtarget); - case ISD::AND: - return performANDCombine(N, DAG, DCI, Subtarget); - case ISD::OR: - return performORCombine(N, DAG, DCI, Subtarget); - case ISD::ADD: - return performADDCombine(N, DAG, DCI, Subtarget); - case ISD::SHL: - return performSHLCombine(N, DAG, DCI, Subtarget); - case ISD::SUB: - return performSUBCombine(N, DAG, DCI, Subtarget); - } - - return SDValue(); -} - -bool MipsTargetLowering::isCheapToSpeculateCttz() const { - return Subtarget.hasMips32(); -} - -bool MipsTargetLowering::isCheapToSpeculateCtlz() const { - return Subtarget.hasMips32(); -} - -bool MipsTargetLowering::shouldFoldConstantShiftPairToMask( - const SDNode *N, CombineLevel Level) const { - if (N->getOperand(0).getValueType().isVector()) - return false; - return true; -} - -void -MipsTargetLowering::LowerOperationWrapper(SDNode *N, - SmallVectorImpl<SDValue> &Results, - SelectionDAG &DAG) const { - SDValue Res = LowerOperation(SDValue(N, 0), DAG); - - if (Res) - for (unsigned I = 0, E = Res->getNumValues(); I != E; ++I) - Results.push_back(Res.getValue(I)); -} - -void -MipsTargetLowering::ReplaceNodeResults(SDNode *N, - SmallVectorImpl<SDValue> &Results, - SelectionDAG &DAG) const { - return LowerOperationWrapper(N, Results, DAG); -} - -SDValue MipsTargetLowering:: -LowerOperation(SDValue Op, SelectionDAG &DAG) const -{ - switch (Op.getOpcode()) - { - case ISD::BRCOND: return lowerBRCOND(Op, DAG); - case ISD::ConstantPool: return lowerConstantPool(Op, DAG); - case ISD::GlobalAddress: return lowerGlobalAddress(Op, DAG); - case ISD::BlockAddress: return lowerBlockAddress(Op, DAG); - case ISD::GlobalTLSAddress: return lowerGlobalTLSAddress(Op, DAG); - case ISD::JumpTable: return lowerJumpTable(Op, DAG); - case ISD::SELECT: return lowerSELECT(Op, DAG); - case ISD::SETCC: return lowerSETCC(Op, DAG); - case ISD::VASTART: return lowerVASTART(Op, DAG); - case ISD::VAARG: return lowerVAARG(Op, DAG); - case ISD::FCOPYSIGN: return lowerFCOPYSIGN(Op, DAG); - case ISD::FABS: return lowerFABS(Op, DAG); - case ISD::FRAMEADDR: return lowerFRAMEADDR(Op, DAG); - case ISD::RETURNADDR: return lowerRETURNADDR(Op, DAG); - case ISD::EH_RETURN: return lowerEH_RETURN(Op, DAG); - case ISD::ATOMIC_FENCE: return lowerATOMIC_FENCE(Op, DAG); - case ISD::SHL_PARTS: return lowerShiftLeftParts(Op, DAG); - case ISD::SRA_PARTS: return lowerShiftRightParts(Op, DAG, true); - case ISD::SRL_PARTS: return lowerShiftRightParts(Op, DAG, false); - case ISD::LOAD: return lowerLOAD(Op, DAG); - case ISD::STORE: return lowerSTORE(Op, DAG); - case ISD::EH_DWARF_CFA: return lowerEH_DWARF_CFA(Op, DAG); - case ISD::FP_TO_SINT: return lowerFP_TO_SINT(Op, DAG); - } - return SDValue(); -} - -//===----------------------------------------------------------------------===// -// Lower helper functions -//===----------------------------------------------------------------------===// - -// addLiveIn - This helper function adds the specified physical register to the -// MachineFunction as a live in value. It also creates a corresponding -// virtual register for it. -static unsigned -addLiveIn(MachineFunction &MF, unsigned PReg, const TargetRegisterClass *RC) -{ - unsigned VReg = MF.getRegInfo().createVirtualRegister(RC); - MF.getRegInfo().addLiveIn(PReg, VReg); - return VReg; -} - -static MachineBasicBlock *insertDivByZeroTrap(MachineInstr &MI, - MachineBasicBlock &MBB, - const TargetInstrInfo &TII, - bool Is64Bit, bool IsMicroMips) { - if (NoZeroDivCheck) - return &MBB; - - // Insert instruction "teq $divisor_reg, $zero, 7". - MachineBasicBlock::iterator I(MI); - MachineInstrBuilder MIB; - MachineOperand &Divisor = MI.getOperand(2); - MIB = BuildMI(MBB, std::next(I), MI.getDebugLoc(), - TII.get(IsMicroMips ? Mips::TEQ_MM : Mips::TEQ)) - .addReg(Divisor.getReg(), getKillRegState(Divisor.isKill())) - .addReg(Mips::ZERO) - .addImm(7); - - // Use the 32-bit sub-register if this is a 64-bit division. - if (Is64Bit) - MIB->getOperand(0).setSubReg(Mips::sub_32); - - // Clear Divisor's kill flag. - Divisor.setIsKill(false); - - // We would normally delete the original instruction here but in this case - // we only needed to inject an additional instruction rather than replace it. - - return &MBB; -} - -MachineBasicBlock * -MipsTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, - MachineBasicBlock *BB) const { - switch (MI.getOpcode()) { - default: - llvm_unreachable("Unexpected instr type to insert"); - case Mips::ATOMIC_LOAD_ADD_I8: - return emitAtomicBinaryPartword(MI, BB, 1); - case Mips::ATOMIC_LOAD_ADD_I16: - return emitAtomicBinaryPartword(MI, BB, 2); - case Mips::ATOMIC_LOAD_ADD_I32: - return emitAtomicBinary(MI, BB); - case Mips::ATOMIC_LOAD_ADD_I64: - return emitAtomicBinary(MI, BB); - - case Mips::ATOMIC_LOAD_AND_I8: - return emitAtomicBinaryPartword(MI, BB, 1); - case Mips::ATOMIC_LOAD_AND_I16: - return emitAtomicBinaryPartword(MI, BB, 2); - case Mips::ATOMIC_LOAD_AND_I32: - return emitAtomicBinary(MI, BB); - case Mips::ATOMIC_LOAD_AND_I64: - return emitAtomicBinary(MI, BB); - - case Mips::ATOMIC_LOAD_OR_I8: - return emitAtomicBinaryPartword(MI, BB, 1); - case Mips::ATOMIC_LOAD_OR_I16: - return emitAtomicBinaryPartword(MI, BB, 2); - case Mips::ATOMIC_LOAD_OR_I32: - return emitAtomicBinary(MI, BB); - case Mips::ATOMIC_LOAD_OR_I64: - return emitAtomicBinary(MI, BB); - - case Mips::ATOMIC_LOAD_XOR_I8: - return emitAtomicBinaryPartword(MI, BB, 1); - case Mips::ATOMIC_LOAD_XOR_I16: - return emitAtomicBinaryPartword(MI, BB, 2); - case Mips::ATOMIC_LOAD_XOR_I32: - return emitAtomicBinary(MI, BB); - case Mips::ATOMIC_LOAD_XOR_I64: - return emitAtomicBinary(MI, BB); - - case Mips::ATOMIC_LOAD_NAND_I8: - return emitAtomicBinaryPartword(MI, BB, 1); - case Mips::ATOMIC_LOAD_NAND_I16: - return emitAtomicBinaryPartword(MI, BB, 2); - case Mips::ATOMIC_LOAD_NAND_I32: - return emitAtomicBinary(MI, BB); - case Mips::ATOMIC_LOAD_NAND_I64: - return emitAtomicBinary(MI, BB); - - case Mips::ATOMIC_LOAD_SUB_I8: - return emitAtomicBinaryPartword(MI, BB, 1); - case Mips::ATOMIC_LOAD_SUB_I16: - return emitAtomicBinaryPartword(MI, BB, 2); - case Mips::ATOMIC_LOAD_SUB_I32: - return emitAtomicBinary(MI, BB); - case Mips::ATOMIC_LOAD_SUB_I64: - return emitAtomicBinary(MI, BB); - - case Mips::ATOMIC_SWAP_I8: - return emitAtomicBinaryPartword(MI, BB, 1); - case Mips::ATOMIC_SWAP_I16: - return emitAtomicBinaryPartword(MI, BB, 2); - case Mips::ATOMIC_SWAP_I32: - return emitAtomicBinary(MI, BB); - case Mips::ATOMIC_SWAP_I64: - return emitAtomicBinary(MI, BB); - - case Mips::ATOMIC_CMP_SWAP_I8: - return emitAtomicCmpSwapPartword(MI, BB, 1); - case Mips::ATOMIC_CMP_SWAP_I16: - return emitAtomicCmpSwapPartword(MI, BB, 2); - case Mips::ATOMIC_CMP_SWAP_I32: - return emitAtomicCmpSwap(MI, BB); - case Mips::ATOMIC_CMP_SWAP_I64: - return emitAtomicCmpSwap(MI, BB); - case Mips::PseudoSDIV: - case Mips::PseudoUDIV: - case Mips::DIV: - case Mips::DIVU: - case Mips::MOD: - case Mips::MODU: - return insertDivByZeroTrap(MI, *BB, *Subtarget.getInstrInfo(), false, - false); - case Mips::SDIV_MM_Pseudo: - case Mips::UDIV_MM_Pseudo: - case Mips::SDIV_MM: - case Mips::UDIV_MM: - case Mips::DIV_MMR6: - case Mips::DIVU_MMR6: - case Mips::MOD_MMR6: - case Mips::MODU_MMR6: - return insertDivByZeroTrap(MI, *BB, *Subtarget.getInstrInfo(), false, true); - case Mips::PseudoDSDIV: - case Mips::PseudoDUDIV: - case Mips::DDIV: - case Mips::DDIVU: - case Mips::DMOD: - case Mips::DMODU: - return insertDivByZeroTrap(MI, *BB, *Subtarget.getInstrInfo(), true, false); - - case Mips::PseudoSELECT_I: - case Mips::PseudoSELECT_I64: - case Mips::PseudoSELECT_S: - case Mips::PseudoSELECT_D32: - case Mips::PseudoSELECT_D64: - return emitPseudoSELECT(MI, BB, false, Mips::BNE); - case Mips::PseudoSELECTFP_F_I: - case Mips::PseudoSELECTFP_F_I64: - case Mips::PseudoSELECTFP_F_S: - case Mips::PseudoSELECTFP_F_D32: - case Mips::PseudoSELECTFP_F_D64: - return emitPseudoSELECT(MI, BB, true, Mips::BC1F); - case Mips::PseudoSELECTFP_T_I: - case Mips::PseudoSELECTFP_T_I64: - case Mips::PseudoSELECTFP_T_S: - case Mips::PseudoSELECTFP_T_D32: - case Mips::PseudoSELECTFP_T_D64: - return emitPseudoSELECT(MI, BB, true, Mips::BC1T); - case Mips::PseudoD_SELECT_I: - case Mips::PseudoD_SELECT_I64: - return emitPseudoD_SELECT(MI, BB); - } -} - -// This function also handles Mips::ATOMIC_SWAP_I32 (when BinOpcode == 0), and -// Mips::ATOMIC_LOAD_NAND_I32 (when Nand == true) -MachineBasicBlock * -MipsTargetLowering::emitAtomicBinary(MachineInstr &MI, - MachineBasicBlock *BB) const { - - MachineFunction *MF = BB->getParent(); - MachineRegisterInfo &RegInfo = MF->getRegInfo(); - const TargetInstrInfo *TII = Subtarget.getInstrInfo(); - DebugLoc DL = MI.getDebugLoc(); - - unsigned AtomicOp; - switch (MI.getOpcode()) { - case Mips::ATOMIC_LOAD_ADD_I32: - AtomicOp = Mips::ATOMIC_LOAD_ADD_I32_POSTRA; - break; - case Mips::ATOMIC_LOAD_SUB_I32: - AtomicOp = Mips::ATOMIC_LOAD_SUB_I32_POSTRA; - break; - case Mips::ATOMIC_LOAD_AND_I32: - AtomicOp = Mips::ATOMIC_LOAD_AND_I32_POSTRA; - break; - case Mips::ATOMIC_LOAD_OR_I32: - AtomicOp = Mips::ATOMIC_LOAD_OR_I32_POSTRA; - break; - case Mips::ATOMIC_LOAD_XOR_I32: - AtomicOp = Mips::ATOMIC_LOAD_XOR_I32_POSTRA; - break; - case Mips::ATOMIC_LOAD_NAND_I32: - AtomicOp = Mips::ATOMIC_LOAD_NAND_I32_POSTRA; - break; - case Mips::ATOMIC_SWAP_I32: - AtomicOp = Mips::ATOMIC_SWAP_I32_POSTRA; - break; - case Mips::ATOMIC_LOAD_ADD_I64: - AtomicOp = Mips::ATOMIC_LOAD_ADD_I64_POSTRA; - break; - case Mips::ATOMIC_LOAD_SUB_I64: - AtomicOp = Mips::ATOMIC_LOAD_SUB_I64_POSTRA; - break; - case Mips::ATOMIC_LOAD_AND_I64: - AtomicOp = Mips::ATOMIC_LOAD_AND_I64_POSTRA; - break; - case Mips::ATOMIC_LOAD_OR_I64: - AtomicOp = Mips::ATOMIC_LOAD_OR_I64_POSTRA; - break; - case Mips::ATOMIC_LOAD_XOR_I64: - AtomicOp = Mips::ATOMIC_LOAD_XOR_I64_POSTRA; - break; - case Mips::ATOMIC_LOAD_NAND_I64: - AtomicOp = Mips::ATOMIC_LOAD_NAND_I64_POSTRA; - break; - case Mips::ATOMIC_SWAP_I64: - AtomicOp = Mips::ATOMIC_SWAP_I64_POSTRA; - break; - default: - llvm_unreachable("Unknown pseudo atomic for replacement!"); - } - - unsigned OldVal = MI.getOperand(0).getReg(); - unsigned Ptr = MI.getOperand(1).getReg(); - unsigned Incr = MI.getOperand(2).getReg(); - unsigned Scratch = RegInfo.createVirtualRegister(RegInfo.getRegClass(OldVal)); - - MachineBasicBlock::iterator II(MI); - - // The scratch registers here with the EarlyClobber | Define | Implicit - // flags is used to persuade the register allocator and the machine - // verifier to accept the usage of this register. This has to be a real - // register which has an UNDEF value but is dead after the instruction which - // is unique among the registers chosen for the instruction. - - // The EarlyClobber flag has the semantic properties that the operand it is - // attached to is clobbered before the rest of the inputs are read. Hence it - // must be unique among the operands to the instruction. - // The Define flag is needed to coerce the machine verifier that an Undef - // value isn't a problem. - // The Dead flag is needed as the value in scratch isn't used by any other - // instruction. Kill isn't used as Dead is more precise. - // The implicit flag is here due to the interaction between the other flags - // and the machine verifier. - - // For correctness purpose, a new pseudo is introduced here. We need this - // new pseudo, so that FastRegisterAllocator does not see an ll/sc sequence - // that is spread over >1 basic blocks. A register allocator which - // introduces (or any codegen infact) a store, can violate the expectations - // of the hardware. - // - // An atomic read-modify-write sequence starts with a linked load - // instruction and ends with a store conditional instruction. The atomic - // read-modify-write sequence fails if any of the following conditions - // occur between the execution of ll and sc: - // * A coherent store is completed by another process or coherent I/O - // module into the block of synchronizable physical memory containing - // the word. The size and alignment of the block is - // implementation-dependent. - // * A coherent store is executed between an LL and SC sequence on the - // same processor to the block of synchornizable physical memory - // containing the word. - // - - unsigned PtrCopy = RegInfo.createVirtualRegister(RegInfo.getRegClass(Ptr)); - unsigned IncrCopy = RegInfo.createVirtualRegister(RegInfo.getRegClass(Incr)); - - BuildMI(*BB, II, DL, TII->get(Mips::COPY), IncrCopy).addReg(Incr); - BuildMI(*BB, II, DL, TII->get(Mips::COPY), PtrCopy).addReg(Ptr); - - BuildMI(*BB, II, DL, TII->get(AtomicOp)) - .addReg(OldVal, RegState::Define | RegState::EarlyClobber) - .addReg(PtrCopy) - .addReg(IncrCopy) - .addReg(Scratch, RegState::Define | RegState::EarlyClobber | - RegState::Implicit | RegState::Dead); - - MI.eraseFromParent(); - - return BB; -} - -MachineBasicBlock *MipsTargetLowering::emitSignExtendToI32InReg( - MachineInstr &MI, MachineBasicBlock *BB, unsigned Size, unsigned DstReg, - unsigned SrcReg) const { - const TargetInstrInfo *TII = Subtarget.getInstrInfo(); - const DebugLoc &DL = MI.getDebugLoc(); - - if (Subtarget.hasMips32r2() && Size == 1) { - BuildMI(BB, DL, TII->get(Mips::SEB), DstReg).addReg(SrcReg); - return BB; - } - - if (Subtarget.hasMips32r2() && Size == 2) { - BuildMI(BB, DL, TII->get(Mips::SEH), DstReg).addReg(SrcReg); - return BB; - } - - MachineFunction *MF = BB->getParent(); - MachineRegisterInfo &RegInfo = MF->getRegInfo(); - const TargetRegisterClass *RC = getRegClassFor(MVT::i32); - unsigned ScrReg = RegInfo.createVirtualRegister(RC); - - assert(Size < 32); - int64_t ShiftImm = 32 - (Size * 8); - - BuildMI(BB, DL, TII->get(Mips::SLL), ScrReg).addReg(SrcReg).addImm(ShiftImm); - BuildMI(BB, DL, TII->get(Mips::SRA), DstReg).addReg(ScrReg).addImm(ShiftImm); - - return BB; -} - -MachineBasicBlock *MipsTargetLowering::emitAtomicBinaryPartword( - MachineInstr &MI, MachineBasicBlock *BB, unsigned Size) const { - assert((Size == 1 || Size == 2) && - "Unsupported size for EmitAtomicBinaryPartial."); - - MachineFunction *MF = BB->getParent(); - MachineRegisterInfo &RegInfo = MF->getRegInfo(); - const TargetRegisterClass *RC = getRegClassFor(MVT::i32); - const bool ArePtrs64bit = ABI.ArePtrs64bit(); - const TargetRegisterClass *RCp = - getRegClassFor(ArePtrs64bit ? MVT::i64 : MVT::i32); - const TargetInstrInfo *TII = Subtarget.getInstrInfo(); - DebugLoc DL = MI.getDebugLoc(); - - unsigned Dest = MI.getOperand(0).getReg(); - unsigned Ptr = MI.getOperand(1).getReg(); - unsigned Incr = MI.getOperand(2).getReg(); - - unsigned AlignedAddr = RegInfo.createVirtualRegister(RCp); - unsigned ShiftAmt = RegInfo.createVirtualRegister(RC); - unsigned Mask = RegInfo.createVirtualRegister(RC); - unsigned Mask2 = RegInfo.createVirtualRegister(RC); - unsigned Incr2 = RegInfo.createVirtualRegister(RC); - unsigned MaskLSB2 = RegInfo.createVirtualRegister(RCp); - unsigned PtrLSB2 = RegInfo.createVirtualRegister(RC); - unsigned MaskUpper = RegInfo.createVirtualRegister(RC); - unsigned Scratch = RegInfo.createVirtualRegister(RC); - unsigned Scratch2 = RegInfo.createVirtualRegister(RC); - unsigned Scratch3 = RegInfo.createVirtualRegister(RC); - - unsigned AtomicOp = 0; - switch (MI.getOpcode()) { - case Mips::ATOMIC_LOAD_NAND_I8: - AtomicOp = Mips::ATOMIC_LOAD_NAND_I8_POSTRA; - break; - case Mips::ATOMIC_LOAD_NAND_I16: - AtomicOp = Mips::ATOMIC_LOAD_NAND_I16_POSTRA; - break; - case Mips::ATOMIC_SWAP_I8: - AtomicOp = Mips::ATOMIC_SWAP_I8_POSTRA; - break; - case Mips::ATOMIC_SWAP_I16: - AtomicOp = Mips::ATOMIC_SWAP_I16_POSTRA; - break; - case Mips::ATOMIC_LOAD_ADD_I8: - AtomicOp = Mips::ATOMIC_LOAD_ADD_I8_POSTRA; - break; - case Mips::ATOMIC_LOAD_ADD_I16: - AtomicOp = Mips::ATOMIC_LOAD_ADD_I16_POSTRA; - break; - case Mips::ATOMIC_LOAD_SUB_I8: - AtomicOp = Mips::ATOMIC_LOAD_SUB_I8_POSTRA; - break; - case Mips::ATOMIC_LOAD_SUB_I16: - AtomicOp = Mips::ATOMIC_LOAD_SUB_I16_POSTRA; - break; - case Mips::ATOMIC_LOAD_AND_I8: - AtomicOp = Mips::ATOMIC_LOAD_AND_I8_POSTRA; - break; - case Mips::ATOMIC_LOAD_AND_I16: - AtomicOp = Mips::ATOMIC_LOAD_AND_I16_POSTRA; - break; - case Mips::ATOMIC_LOAD_OR_I8: - AtomicOp = Mips::ATOMIC_LOAD_OR_I8_POSTRA; - break; - case Mips::ATOMIC_LOAD_OR_I16: - AtomicOp = Mips::ATOMIC_LOAD_OR_I16_POSTRA; - break; - case Mips::ATOMIC_LOAD_XOR_I8: - AtomicOp = Mips::ATOMIC_LOAD_XOR_I8_POSTRA; - break; - case Mips::ATOMIC_LOAD_XOR_I16: - AtomicOp = Mips::ATOMIC_LOAD_XOR_I16_POSTRA; - break; - default: - llvm_unreachable("Unknown subword atomic pseudo for expansion!"); - } - - // insert new blocks after the current block - const BasicBlock *LLVM_BB = BB->getBasicBlock(); - MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB); - MachineFunction::iterator It = ++BB->getIterator(); - MF->insert(It, exitMBB); - - // Transfer the remainder of BB and its successor edges to exitMBB. - exitMBB->splice(exitMBB->begin(), BB, - std::next(MachineBasicBlock::iterator(MI)), BB->end()); - exitMBB->transferSuccessorsAndUpdatePHIs(BB); - - BB->addSuccessor(exitMBB, BranchProbability::getOne()); - - // thisMBB: - // addiu masklsb2,$0,-4 # 0xfffffffc - // and alignedaddr,ptr,masklsb2 - // andi ptrlsb2,ptr,3 - // sll shiftamt,ptrlsb2,3 - // ori maskupper,$0,255 # 0xff - // sll mask,maskupper,shiftamt - // nor mask2,$0,mask - // sll incr2,incr,shiftamt - - int64_t MaskImm = (Size == 1) ? 255 : 65535; - BuildMI(BB, DL, TII->get(ABI.GetPtrAddiuOp()), MaskLSB2) - .addReg(ABI.GetNullPtr()).addImm(-4); - BuildMI(BB, DL, TII->get(ABI.GetPtrAndOp()), AlignedAddr) - .addReg(Ptr).addReg(MaskLSB2); - BuildMI(BB, DL, TII->get(Mips::ANDi), PtrLSB2) - .addReg(Ptr, 0, ArePtrs64bit ? Mips::sub_32 : 0).addImm(3); - if (Subtarget.isLittle()) { - BuildMI(BB, DL, TII->get(Mips::SLL), ShiftAmt).addReg(PtrLSB2).addImm(3); - } else { - unsigned Off = RegInfo.createVirtualRegister(RC); - BuildMI(BB, DL, TII->get(Mips::XORi), Off) - .addReg(PtrLSB2).addImm((Size == 1) ? 3 : 2); - BuildMI(BB, DL, TII->get(Mips::SLL), ShiftAmt).addReg(Off).addImm(3); - } - BuildMI(BB, DL, TII->get(Mips::ORi), MaskUpper) - .addReg(Mips::ZERO).addImm(MaskImm); - BuildMI(BB, DL, TII->get(Mips::SLLV), Mask) - .addReg(MaskUpper).addReg(ShiftAmt); - BuildMI(BB, DL, TII->get(Mips::NOR), Mask2).addReg(Mips::ZERO).addReg(Mask); - BuildMI(BB, DL, TII->get(Mips::SLLV), Incr2).addReg(Incr).addReg(ShiftAmt); - - - // The purposes of the flags on the scratch registers is explained in - // emitAtomicBinary. In summary, we need a scratch register which is going to - // be undef, that is unique among registers chosen for the instruction. - - BuildMI(BB, DL, TII->get(AtomicOp)) - .addReg(Dest, RegState::Define | RegState::EarlyClobber) - .addReg(AlignedAddr) - .addReg(Incr2) - .addReg(Mask) - .addReg(Mask2) - .addReg(ShiftAmt) - .addReg(Scratch, RegState::EarlyClobber | RegState::Define | - RegState::Dead | RegState::Implicit) - .addReg(Scratch2, RegState::EarlyClobber | RegState::Define | - RegState::Dead | RegState::Implicit) - .addReg(Scratch3, RegState::EarlyClobber | RegState::Define | - RegState::Dead | RegState::Implicit); - - MI.eraseFromParent(); // The instruction is gone now. - - return exitMBB; -} - -// Lower atomic compare and swap to a pseudo instruction, taking care to -// define a scratch register for the pseudo instruction's expansion. The -// instruction is expanded after the register allocator as to prevent -// the insertion of stores between the linked load and the store conditional. - -MachineBasicBlock * -MipsTargetLowering::emitAtomicCmpSwap(MachineInstr &MI, - MachineBasicBlock *BB) const { - - assert((MI.getOpcode() == Mips::ATOMIC_CMP_SWAP_I32 || - MI.getOpcode() == Mips::ATOMIC_CMP_SWAP_I64) && - "Unsupported atomic pseudo for EmitAtomicCmpSwap."); - - const unsigned Size = MI.getOpcode() == Mips::ATOMIC_CMP_SWAP_I32 ? 4 : 8; - - MachineFunction *MF = BB->getParent(); - MachineRegisterInfo &MRI = MF->getRegInfo(); - const TargetRegisterClass *RC = getRegClassFor(MVT::getIntegerVT(Size * 8)); - const TargetInstrInfo *TII = Subtarget.getInstrInfo(); - DebugLoc DL = MI.getDebugLoc(); - - unsigned AtomicOp = MI.getOpcode() == Mips::ATOMIC_CMP_SWAP_I32 - ? Mips::ATOMIC_CMP_SWAP_I32_POSTRA - : Mips::ATOMIC_CMP_SWAP_I64_POSTRA; - unsigned Dest = MI.getOperand(0).getReg(); - unsigned Ptr = MI.getOperand(1).getReg(); - unsigned OldVal = MI.getOperand(2).getReg(); - unsigned NewVal = MI.getOperand(3).getReg(); - - unsigned Scratch = MRI.createVirtualRegister(RC); - MachineBasicBlock::iterator II(MI); - - // We need to create copies of the various registers and kill them at the - // atomic pseudo. If the copies are not made, when the atomic is expanded - // after fast register allocation, the spills will end up outside of the - // blocks that their values are defined in, causing livein errors. - - unsigned PtrCopy = MRI.createVirtualRegister(MRI.getRegClass(Ptr)); - unsigned OldValCopy = MRI.createVirtualRegister(MRI.getRegClass(OldVal)); - unsigned NewValCopy = MRI.createVirtualRegister(MRI.getRegClass(NewVal)); - - BuildMI(*BB, II, DL, TII->get(Mips::COPY), PtrCopy).addReg(Ptr); - BuildMI(*BB, II, DL, TII->get(Mips::COPY), OldValCopy).addReg(OldVal); - BuildMI(*BB, II, DL, TII->get(Mips::COPY), NewValCopy).addReg(NewVal); - - // The purposes of the flags on the scratch registers is explained in - // emitAtomicBinary. In summary, we need a scratch register which is going to - // be undef, that is unique among registers chosen for the instruction. - - BuildMI(*BB, II, DL, TII->get(AtomicOp)) - .addReg(Dest, RegState::Define | RegState::EarlyClobber) - .addReg(PtrCopy, RegState::Kill) - .addReg(OldValCopy, RegState::Kill) - .addReg(NewValCopy, RegState::Kill) - .addReg(Scratch, RegState::EarlyClobber | RegState::Define | - RegState::Dead | RegState::Implicit); - - MI.eraseFromParent(); // The instruction is gone now. - - return BB; -} - -MachineBasicBlock *MipsTargetLowering::emitAtomicCmpSwapPartword( - MachineInstr &MI, MachineBasicBlock *BB, unsigned Size) const { - assert((Size == 1 || Size == 2) && - "Unsupported size for EmitAtomicCmpSwapPartial."); - - MachineFunction *MF = BB->getParent(); - MachineRegisterInfo &RegInfo = MF->getRegInfo(); - const TargetRegisterClass *RC = getRegClassFor(MVT::i32); - const bool ArePtrs64bit = ABI.ArePtrs64bit(); - const TargetRegisterClass *RCp = - getRegClassFor(ArePtrs64bit ? MVT::i64 : MVT::i32); - const TargetInstrInfo *TII = Subtarget.getInstrInfo(); - DebugLoc DL = MI.getDebugLoc(); - - unsigned Dest = MI.getOperand(0).getReg(); - unsigned Ptr = MI.getOperand(1).getReg(); - unsigned CmpVal = MI.getOperand(2).getReg(); - unsigned NewVal = MI.getOperand(3).getReg(); - - unsigned AlignedAddr = RegInfo.createVirtualRegister(RCp); - unsigned ShiftAmt = RegInfo.createVirtualRegister(RC); - unsigned Mask = RegInfo.createVirtualRegister(RC); - unsigned Mask2 = RegInfo.createVirtualRegister(RC); - unsigned ShiftedCmpVal = RegInfo.createVirtualRegister(RC); - unsigned ShiftedNewVal = RegInfo.createVirtualRegister(RC); - unsigned MaskLSB2 = RegInfo.createVirtualRegister(RCp); - unsigned PtrLSB2 = RegInfo.createVirtualRegister(RC); - unsigned MaskUpper = RegInfo.createVirtualRegister(RC); - unsigned MaskedCmpVal = RegInfo.createVirtualRegister(RC); - unsigned MaskedNewVal = RegInfo.createVirtualRegister(RC); - unsigned AtomicOp = MI.getOpcode() == Mips::ATOMIC_CMP_SWAP_I8 - ? Mips::ATOMIC_CMP_SWAP_I8_POSTRA - : Mips::ATOMIC_CMP_SWAP_I16_POSTRA; - - // The scratch registers here with the EarlyClobber | Define | Dead | Implicit - // flags are used to coerce the register allocator and the machine verifier to - // accept the usage of these registers. - // The EarlyClobber flag has the semantic properties that the operand it is - // attached to is clobbered before the rest of the inputs are read. Hence it - // must be unique among the operands to the instruction. - // The Define flag is needed to coerce the machine verifier that an Undef - // value isn't a problem. - // The Dead flag is needed as the value in scratch isn't used by any other - // instruction. Kill isn't used as Dead is more precise. - unsigned Scratch = RegInfo.createVirtualRegister(RC); - unsigned Scratch2 = RegInfo.createVirtualRegister(RC); - - // insert new blocks after the current block - const BasicBlock *LLVM_BB = BB->getBasicBlock(); - MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB); - MachineFunction::iterator It = ++BB->getIterator(); - MF->insert(It, exitMBB); - - // Transfer the remainder of BB and its successor edges to exitMBB. - exitMBB->splice(exitMBB->begin(), BB, - std::next(MachineBasicBlock::iterator(MI)), BB->end()); - exitMBB->transferSuccessorsAndUpdatePHIs(BB); - - BB->addSuccessor(exitMBB, BranchProbability::getOne()); - - // thisMBB: - // addiu masklsb2,$0,-4 # 0xfffffffc - // and alignedaddr,ptr,masklsb2 - // andi ptrlsb2,ptr,3 - // xori ptrlsb2,ptrlsb2,3 # Only for BE - // sll shiftamt,ptrlsb2,3 - // ori maskupper,$0,255 # 0xff - // sll mask,maskupper,shiftamt - // nor mask2,$0,mask - // andi maskedcmpval,cmpval,255 - // sll shiftedcmpval,maskedcmpval,shiftamt - // andi maskednewval,newval,255 - // sll shiftednewval,maskednewval,shiftamt - int64_t MaskImm = (Size == 1) ? 255 : 65535; - BuildMI(BB, DL, TII->get(ArePtrs64bit ? Mips::DADDiu : Mips::ADDiu), MaskLSB2) - .addReg(ABI.GetNullPtr()).addImm(-4); - BuildMI(BB, DL, TII->get(ArePtrs64bit ? Mips::AND64 : Mips::AND), AlignedAddr) - .addReg(Ptr).addReg(MaskLSB2); - BuildMI(BB, DL, TII->get(Mips::ANDi), PtrLSB2) - .addReg(Ptr, 0, ArePtrs64bit ? Mips::sub_32 : 0).addImm(3); - if (Subtarget.isLittle()) { - BuildMI(BB, DL, TII->get(Mips::SLL), ShiftAmt).addReg(PtrLSB2).addImm(3); - } else { - unsigned Off = RegInfo.createVirtualRegister(RC); - BuildMI(BB, DL, TII->get(Mips::XORi), Off) - .addReg(PtrLSB2).addImm((Size == 1) ? 3 : 2); - BuildMI(BB, DL, TII->get(Mips::SLL), ShiftAmt).addReg(Off).addImm(3); - } - BuildMI(BB, DL, TII->get(Mips::ORi), MaskUpper) - .addReg(Mips::ZERO).addImm(MaskImm); - BuildMI(BB, DL, TII->get(Mips::SLLV), Mask) - .addReg(MaskUpper).addReg(ShiftAmt); - BuildMI(BB, DL, TII->get(Mips::NOR), Mask2).addReg(Mips::ZERO).addReg(Mask); - BuildMI(BB, DL, TII->get(Mips::ANDi), MaskedCmpVal) - .addReg(CmpVal).addImm(MaskImm); - BuildMI(BB, DL, TII->get(Mips::SLLV), ShiftedCmpVal) - .addReg(MaskedCmpVal).addReg(ShiftAmt); - BuildMI(BB, DL, TII->get(Mips::ANDi), MaskedNewVal) - .addReg(NewVal).addImm(MaskImm); - BuildMI(BB, DL, TII->get(Mips::SLLV), ShiftedNewVal) - .addReg(MaskedNewVal).addReg(ShiftAmt); - - // The purposes of the flags on the scratch registers are explained in - // emitAtomicBinary. In summary, we need a scratch register which is going to - // be undef, that is unique among the register chosen for the instruction. - - BuildMI(BB, DL, TII->get(AtomicOp)) - .addReg(Dest, RegState::Define | RegState::EarlyClobber) - .addReg(AlignedAddr) - .addReg(Mask) - .addReg(ShiftedCmpVal) - .addReg(Mask2) - .addReg(ShiftedNewVal) - .addReg(ShiftAmt) - .addReg(Scratch, RegState::EarlyClobber | RegState::Define | - RegState::Dead | RegState::Implicit) - .addReg(Scratch2, RegState::EarlyClobber | RegState::Define | - RegState::Dead | RegState::Implicit); - - MI.eraseFromParent(); // The instruction is gone now. - - return exitMBB; -} - -SDValue MipsTargetLowering::lowerBRCOND(SDValue Op, SelectionDAG &DAG) const { - // The first operand is the chain, the second is the condition, the third is - // the block to branch to if the condition is true. - SDValue Chain = Op.getOperand(0); - SDValue Dest = Op.getOperand(2); - SDLoc DL(Op); - - assert(!Subtarget.hasMips32r6() && !Subtarget.hasMips64r6()); - SDValue CondRes = createFPCmp(DAG, Op.getOperand(1)); - - // Return if flag is not set by a floating point comparison. - if (CondRes.getOpcode() != MipsISD::FPCmp) - return Op; - - SDValue CCNode = CondRes.getOperand(2); - Mips::CondCode CC = - (Mips::CondCode)cast<ConstantSDNode>(CCNode)->getZExtValue(); - unsigned Opc = invertFPCondCodeUser(CC) ? Mips::BRANCH_F : Mips::BRANCH_T; - SDValue BrCode = DAG.getConstant(Opc, DL, MVT::i32); - SDValue FCC0 = DAG.getRegister(Mips::FCC0, MVT::i32); - return DAG.getNode(MipsISD::FPBrcond, DL, Op.getValueType(), Chain, BrCode, - FCC0, Dest, CondRes); -} - -SDValue MipsTargetLowering:: -lowerSELECT(SDValue Op, SelectionDAG &DAG) const -{ - assert(!Subtarget.hasMips32r6() && !Subtarget.hasMips64r6()); - SDValue Cond = createFPCmp(DAG, Op.getOperand(0)); - - // Return if flag is not set by a floating point comparison. - if (Cond.getOpcode() != MipsISD::FPCmp) - return Op; - - return createCMovFP(DAG, Cond, Op.getOperand(1), Op.getOperand(2), - SDLoc(Op)); -} - -SDValue MipsTargetLowering::lowerSETCC(SDValue Op, SelectionDAG &DAG) const { - assert(!Subtarget.hasMips32r6() && !Subtarget.hasMips64r6()); - SDValue Cond = createFPCmp(DAG, Op); - - assert(Cond.getOpcode() == MipsISD::FPCmp && - "Floating point operand expected."); - - SDLoc DL(Op); - SDValue True = DAG.getConstant(1, DL, MVT::i32); - SDValue False = DAG.getConstant(0, DL, MVT::i32); - - return createCMovFP(DAG, Cond, True, False, DL); -} - -SDValue MipsTargetLowering::lowerGlobalAddress(SDValue Op, - SelectionDAG &DAG) const { - EVT Ty = Op.getValueType(); - GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Op); - const GlobalValue *GV = N->getGlobal(); - - if (!isPositionIndependent()) { - const MipsTargetObjectFile *TLOF = - static_cast<const MipsTargetObjectFile *>( - getTargetMachine().getObjFileLowering()); - const GlobalObject *GO = GV->getBaseObject(); - if (GO && TLOF->IsGlobalInSmallSection(GO, getTargetMachine())) - // %gp_rel relocation - return getAddrGPRel(N, SDLoc(N), Ty, DAG, ABI.IsN64()); - - // %hi/%lo relocation - return Subtarget.hasSym32() ? getAddrNonPIC(N, SDLoc(N), Ty, DAG) - // %highest/%higher/%hi/%lo relocation - : getAddrNonPICSym64(N, SDLoc(N), Ty, DAG); - } - - // Every other architecture would use shouldAssumeDSOLocal in here, but - // mips is special. - // * In PIC code mips requires got loads even for local statics! - // * To save on got entries, for local statics the got entry contains the - // page and an additional add instruction takes care of the low bits. - // * It is legal to access a hidden symbol with a non hidden undefined, - // so one cannot guarantee that all access to a hidden symbol will know - // it is hidden. - // * Mips linkers don't support creating a page and a full got entry for - // the same symbol. - // * Given all that, we have to use a full got entry for hidden symbols :-( - if (GV->hasLocalLinkage()) - return getAddrLocal(N, SDLoc(N), Ty, DAG, ABI.IsN32() || ABI.IsN64()); - - if (LargeGOT) - return getAddrGlobalLargeGOT( - N, SDLoc(N), Ty, DAG, MipsII::MO_GOT_HI16, MipsII::MO_GOT_LO16, - DAG.getEntryNode(), - MachinePointerInfo::getGOT(DAG.getMachineFunction())); - - return getAddrGlobal( - N, SDLoc(N), Ty, DAG, - (ABI.IsN32() || ABI.IsN64()) ? MipsII::MO_GOT_DISP : MipsII::MO_GOT, - DAG.getEntryNode(), MachinePointerInfo::getGOT(DAG.getMachineFunction())); -} - -SDValue MipsTargetLowering::lowerBlockAddress(SDValue Op, - SelectionDAG &DAG) const { - BlockAddressSDNode *N = cast<BlockAddressSDNode>(Op); - EVT Ty = Op.getValueType(); - - if (!isPositionIndependent()) - return Subtarget.hasSym32() ? getAddrNonPIC(N, SDLoc(N), Ty, DAG) - : getAddrNonPICSym64(N, SDLoc(N), Ty, DAG); - - return getAddrLocal(N, SDLoc(N), Ty, DAG, ABI.IsN32() || ABI.IsN64()); -} - -SDValue MipsTargetLowering:: -lowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const -{ - // If the relocation model is PIC, use the General Dynamic TLS Model or - // Local Dynamic TLS model, otherwise use the Initial Exec or - // Local Exec TLS Model. - - GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(Op); - if (DAG.getTarget().useEmulatedTLS()) - return LowerToTLSEmulatedModel(GA, DAG); - - SDLoc DL(GA); - const GlobalValue *GV = GA->getGlobal(); - EVT PtrVT = getPointerTy(DAG.getDataLayout()); - - TLSModel::Model model = getTargetMachine().getTLSModel(GV); - - if (model == TLSModel::GeneralDynamic || model == TLSModel::LocalDynamic) { - // General Dynamic and Local Dynamic TLS Model. - unsigned Flag = (model == TLSModel::LocalDynamic) ? MipsII::MO_TLSLDM - : MipsII::MO_TLSGD; - - SDValue TGA = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, Flag); - SDValue Argument = DAG.getNode(MipsISD::Wrapper, DL, PtrVT, - getGlobalReg(DAG, PtrVT), TGA); - unsigned PtrSize = PtrVT.getSizeInBits(); - IntegerType *PtrTy = Type::getIntNTy(*DAG.getContext(), PtrSize); - - SDValue TlsGetAddr = DAG.getExternalSymbol("__tls_get_addr", PtrVT); - - ArgListTy Args; - ArgListEntry Entry; - Entry.Node = Argument; - Entry.Ty = PtrTy; - Args.push_back(Entry); - - TargetLowering::CallLoweringInfo CLI(DAG); - CLI.setDebugLoc(DL) - .setChain(DAG.getEntryNode()) - .setLibCallee(CallingConv::C, PtrTy, TlsGetAddr, std::move(Args)); - std::pair<SDValue, SDValue> CallResult = LowerCallTo(CLI); - - SDValue Ret = CallResult.first; - - if (model != TLSModel::LocalDynamic) - return Ret; - - SDValue TGAHi = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, - MipsII::MO_DTPREL_HI); - SDValue Hi = DAG.getNode(MipsISD::TlsHi, DL, PtrVT, TGAHi); - SDValue TGALo = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, - MipsII::MO_DTPREL_LO); - SDValue Lo = DAG.getNode(MipsISD::Lo, DL, PtrVT, TGALo); - SDValue Add = DAG.getNode(ISD::ADD, DL, PtrVT, Hi, Ret); - return DAG.getNode(ISD::ADD, DL, PtrVT, Add, Lo); - } - - SDValue Offset; - if (model == TLSModel::InitialExec) { - // Initial Exec TLS Model - SDValue TGA = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, - MipsII::MO_GOTTPREL); - TGA = DAG.getNode(MipsISD::Wrapper, DL, PtrVT, getGlobalReg(DAG, PtrVT), - TGA); - Offset = - DAG.getLoad(PtrVT, DL, DAG.getEntryNode(), TGA, MachinePointerInfo()); - } else { - // Local Exec TLS Model - assert(model == TLSModel::LocalExec); - SDValue TGAHi = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, - MipsII::MO_TPREL_HI); - SDValue TGALo = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, - MipsII::MO_TPREL_LO); - SDValue Hi = DAG.getNode(MipsISD::TlsHi, DL, PtrVT, TGAHi); - SDValue Lo = DAG.getNode(MipsISD::Lo, DL, PtrVT, TGALo); - Offset = DAG.getNode(ISD::ADD, DL, PtrVT, Hi, Lo); - } - - SDValue ThreadPointer = DAG.getNode(MipsISD::ThreadPointer, DL, PtrVT); - return DAG.getNode(ISD::ADD, DL, PtrVT, ThreadPointer, Offset); -} - -SDValue MipsTargetLowering:: -lowerJumpTable(SDValue Op, SelectionDAG &DAG) const -{ - JumpTableSDNode *N = cast<JumpTableSDNode>(Op); - EVT Ty = Op.getValueType(); - - if (!isPositionIndependent()) - return Subtarget.hasSym32() ? getAddrNonPIC(N, SDLoc(N), Ty, DAG) - : getAddrNonPICSym64(N, SDLoc(N), Ty, DAG); - - return getAddrLocal(N, SDLoc(N), Ty, DAG, ABI.IsN32() || ABI.IsN64()); -} - -SDValue MipsTargetLowering:: -lowerConstantPool(SDValue Op, SelectionDAG &DAG) const -{ - ConstantPoolSDNode *N = cast<ConstantPoolSDNode>(Op); - EVT Ty = Op.getValueType(); - - if (!isPositionIndependent()) { - const MipsTargetObjectFile *TLOF = - static_cast<const MipsTargetObjectFile *>( - getTargetMachine().getObjFileLowering()); - - if (TLOF->IsConstantInSmallSection(DAG.getDataLayout(), N->getConstVal(), - getTargetMachine())) - // %gp_rel relocation - return getAddrGPRel(N, SDLoc(N), Ty, DAG, ABI.IsN64()); - - return Subtarget.hasSym32() ? getAddrNonPIC(N, SDLoc(N), Ty, DAG) - : getAddrNonPICSym64(N, SDLoc(N), Ty, DAG); - } - - return getAddrLocal(N, SDLoc(N), Ty, DAG, ABI.IsN32() || ABI.IsN64()); -} - -SDValue MipsTargetLowering::lowerVASTART(SDValue Op, SelectionDAG &DAG) const { - MachineFunction &MF = DAG.getMachineFunction(); - MipsFunctionInfo *FuncInfo = MF.getInfo<MipsFunctionInfo>(); - - SDLoc DL(Op); - SDValue FI = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(), - getPointerTy(MF.getDataLayout())); - - // vastart just stores the address of the VarArgsFrameIndex slot into the - // memory location argument. - const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue(); - return DAG.getStore(Op.getOperand(0), DL, FI, Op.getOperand(1), - MachinePointerInfo(SV)); -} - -SDValue MipsTargetLowering::lowerVAARG(SDValue Op, SelectionDAG &DAG) const { - SDNode *Node = Op.getNode(); - EVT VT = Node->getValueType(0); - SDValue Chain = Node->getOperand(0); - SDValue VAListPtr = Node->getOperand(1); - unsigned Align = Node->getConstantOperandVal(3); - const Value *SV = cast<SrcValueSDNode>(Node->getOperand(2))->getValue(); - SDLoc DL(Node); - unsigned ArgSlotSizeInBytes = (ABI.IsN32() || ABI.IsN64()) ? 8 : 4; - - SDValue VAListLoad = DAG.getLoad(getPointerTy(DAG.getDataLayout()), DL, Chain, - VAListPtr, MachinePointerInfo(SV)); - SDValue VAList = VAListLoad; - - // Re-align the pointer if necessary. - // It should only ever be necessary for 64-bit types on O32 since the minimum - // argument alignment is the same as the maximum type alignment for N32/N64. - // - // FIXME: We currently align too often. The code generator doesn't notice - // when the pointer is still aligned from the last va_arg (or pair of - // va_args for the i64 on O32 case). - if (Align > getMinStackArgumentAlignment()) { - assert(((Align & (Align-1)) == 0) && "Expected Align to be a power of 2"); - - VAList = DAG.getNode(ISD::ADD, DL, VAList.getValueType(), VAList, - DAG.getConstant(Align - 1, DL, VAList.getValueType())); - - VAList = DAG.getNode(ISD::AND, DL, VAList.getValueType(), VAList, - DAG.getConstant(-(int64_t)Align, DL, - VAList.getValueType())); - } - - // Increment the pointer, VAList, to the next vaarg. - auto &TD = DAG.getDataLayout(); - unsigned ArgSizeInBytes = - TD.getTypeAllocSize(VT.getTypeForEVT(*DAG.getContext())); - SDValue Tmp3 = - DAG.getNode(ISD::ADD, DL, VAList.getValueType(), VAList, - DAG.getConstant(alignTo(ArgSizeInBytes, ArgSlotSizeInBytes), - DL, VAList.getValueType())); - // Store the incremented VAList to the legalized pointer - Chain = DAG.getStore(VAListLoad.getValue(1), DL, Tmp3, VAListPtr, - MachinePointerInfo(SV)); - - // In big-endian mode we must adjust the pointer when the load size is smaller - // than the argument slot size. We must also reduce the known alignment to - // match. For example in the N64 ABI, we must add 4 bytes to the offset to get - // the correct half of the slot, and reduce the alignment from 8 (slot - // alignment) down to 4 (type alignment). - if (!Subtarget.isLittle() && ArgSizeInBytes < ArgSlotSizeInBytes) { - unsigned Adjustment = ArgSlotSizeInBytes - ArgSizeInBytes; - VAList = DAG.getNode(ISD::ADD, DL, VAListPtr.getValueType(), VAList, - DAG.getIntPtrConstant(Adjustment, DL)); - } - // Load the actual argument out of the pointer VAList - return DAG.getLoad(VT, DL, Chain, VAList, MachinePointerInfo()); -} - -static SDValue lowerFCOPYSIGN32(SDValue Op, SelectionDAG &DAG, - bool HasExtractInsert) { - EVT TyX = Op.getOperand(0).getValueType(); - EVT TyY = Op.getOperand(1).getValueType(); - SDLoc DL(Op); - SDValue Const1 = DAG.getConstant(1, DL, MVT::i32); - SDValue Const31 = DAG.getConstant(31, DL, MVT::i32); - SDValue Res; - - // If operand is of type f64, extract the upper 32-bit. Otherwise, bitcast it - // to i32. - SDValue X = (TyX == MVT::f32) ? - DAG.getNode(ISD::BITCAST, DL, MVT::i32, Op.getOperand(0)) : - DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32, Op.getOperand(0), - Const1); - SDValue Y = (TyY == MVT::f32) ? - DAG.getNode(ISD::BITCAST, DL, MVT::i32, Op.getOperand(1)) : - DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32, Op.getOperand(1), - Const1); - - if (HasExtractInsert) { - // ext E, Y, 31, 1 ; extract bit31 of Y - // ins X, E, 31, 1 ; insert extracted bit at bit31 of X - SDValue E = DAG.getNode(MipsISD::Ext, DL, MVT::i32, Y, Const31, Const1); - Res = DAG.getNode(MipsISD::Ins, DL, MVT::i32, E, Const31, Const1, X); - } else { - // sll SllX, X, 1 - // srl SrlX, SllX, 1 - // srl SrlY, Y, 31 - // sll SllY, SrlX, 31 - // or Or, SrlX, SllY - SDValue SllX = DAG.getNode(ISD::SHL, DL, MVT::i32, X, Const1); - SDValue SrlX = DAG.getNode(ISD::SRL, DL, MVT::i32, SllX, Const1); - SDValue SrlY = DAG.getNode(ISD::SRL, DL, MVT::i32, Y, Const31); - SDValue SllY = DAG.getNode(ISD::SHL, DL, MVT::i32, SrlY, Const31); - Res = DAG.getNode(ISD::OR, DL, MVT::i32, SrlX, SllY); - } - - if (TyX == MVT::f32) - return DAG.getNode(ISD::BITCAST, DL, Op.getOperand(0).getValueType(), Res); - - SDValue LowX = DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32, - Op.getOperand(0), - DAG.getConstant(0, DL, MVT::i32)); - return DAG.getNode(MipsISD::BuildPairF64, DL, MVT::f64, LowX, Res); -} - -static SDValue lowerFCOPYSIGN64(SDValue Op, SelectionDAG &DAG, - bool HasExtractInsert) { - unsigned WidthX = Op.getOperand(0).getValueSizeInBits(); - unsigned WidthY = Op.getOperand(1).getValueSizeInBits(); - EVT TyX = MVT::getIntegerVT(WidthX), TyY = MVT::getIntegerVT(WidthY); - SDLoc DL(Op); - SDValue Const1 = DAG.getConstant(1, DL, MVT::i32); - - // Bitcast to integer nodes. - SDValue X = DAG.getNode(ISD::BITCAST, DL, TyX, Op.getOperand(0)); - SDValue Y = DAG.getNode(ISD::BITCAST, DL, TyY, Op.getOperand(1)); - - if (HasExtractInsert) { - // ext E, Y, width(Y) - 1, 1 ; extract bit width(Y)-1 of Y - // ins X, E, width(X) - 1, 1 ; insert extracted bit at bit width(X)-1 of X - SDValue E = DAG.getNode(MipsISD::Ext, DL, TyY, Y, - DAG.getConstant(WidthY - 1, DL, MVT::i32), Const1); - - if (WidthX > WidthY) - E = DAG.getNode(ISD::ZERO_EXTEND, DL, TyX, E); - else if (WidthY > WidthX) - E = DAG.getNode(ISD::TRUNCATE, DL, TyX, E); - - SDValue I = DAG.getNode(MipsISD::Ins, DL, TyX, E, - DAG.getConstant(WidthX - 1, DL, MVT::i32), Const1, - X); - return DAG.getNode(ISD::BITCAST, DL, Op.getOperand(0).getValueType(), I); - } - - // (d)sll SllX, X, 1 - // (d)srl SrlX, SllX, 1 - // (d)srl SrlY, Y, width(Y)-1 - // (d)sll SllY, SrlX, width(Y)-1 - // or Or, SrlX, SllY - SDValue SllX = DAG.getNode(ISD::SHL, DL, TyX, X, Const1); - SDValue SrlX = DAG.getNode(ISD::SRL, DL, TyX, SllX, Const1); - SDValue SrlY = DAG.getNode(ISD::SRL, DL, TyY, Y, - DAG.getConstant(WidthY - 1, DL, MVT::i32)); - - if (WidthX > WidthY) - SrlY = DAG.getNode(ISD::ZERO_EXTEND, DL, TyX, SrlY); - else if (WidthY > WidthX) - SrlY = DAG.getNode(ISD::TRUNCATE, DL, TyX, SrlY); - - SDValue SllY = DAG.getNode(ISD::SHL, DL, TyX, SrlY, - DAG.getConstant(WidthX - 1, DL, MVT::i32)); - SDValue Or = DAG.getNode(ISD::OR, DL, TyX, SrlX, SllY); - return DAG.getNode(ISD::BITCAST, DL, Op.getOperand(0).getValueType(), Or); -} - -SDValue -MipsTargetLowering::lowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const { - if (Subtarget.isGP64bit()) - return lowerFCOPYSIGN64(Op, DAG, Subtarget.hasExtractInsert()); - - return lowerFCOPYSIGN32(Op, DAG, Subtarget.hasExtractInsert()); -} - -static SDValue lowerFABS32(SDValue Op, SelectionDAG &DAG, - bool HasExtractInsert) { - SDLoc DL(Op); - SDValue Res, Const1 = DAG.getConstant(1, DL, MVT::i32); - - // If operand is of type f64, extract the upper 32-bit. Otherwise, bitcast it - // to i32. - SDValue X = (Op.getValueType() == MVT::f32) - ? DAG.getNode(ISD::BITCAST, DL, MVT::i32, Op.getOperand(0)) - : DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32, - Op.getOperand(0), Const1); - - // Clear MSB. - if (HasExtractInsert) - Res = DAG.getNode(MipsISD::Ins, DL, MVT::i32, - DAG.getRegister(Mips::ZERO, MVT::i32), - DAG.getConstant(31, DL, MVT::i32), Const1, X); - else { - // TODO: Provide DAG patterns which transform (and x, cst) - // back to a (shl (srl x (clz cst)) (clz cst)) sequence. - SDValue SllX = DAG.getNode(ISD::SHL, DL, MVT::i32, X, Const1); - Res = DAG.getNode(ISD::SRL, DL, MVT::i32, SllX, Const1); - } - - if (Op.getValueType() == MVT::f32) - return DAG.getNode(ISD::BITCAST, DL, MVT::f32, Res); - - // FIXME: For mips32r2, the sequence of (BuildPairF64 (ins (ExtractElementF64 - // Op 1), $zero, 31 1) (ExtractElementF64 Op 0)) and the Op has one use, we - // should be able to drop the usage of mfc1/mtc1 and rewrite the register in - // place. - SDValue LowX = - DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32, Op.getOperand(0), - DAG.getConstant(0, DL, MVT::i32)); - return DAG.getNode(MipsISD::BuildPairF64, DL, MVT::f64, LowX, Res); -} - -static SDValue lowerFABS64(SDValue Op, SelectionDAG &DAG, - bool HasExtractInsert) { - SDLoc DL(Op); - SDValue Res, Const1 = DAG.getConstant(1, DL, MVT::i32); - - // Bitcast to integer node. - SDValue X = DAG.getNode(ISD::BITCAST, DL, MVT::i64, Op.getOperand(0)); - - // Clear MSB. - if (HasExtractInsert) - Res = DAG.getNode(MipsISD::Ins, DL, MVT::i64, - DAG.getRegister(Mips::ZERO_64, MVT::i64), - DAG.getConstant(63, DL, MVT::i32), Const1, X); - else { - SDValue SllX = DAG.getNode(ISD::SHL, DL, MVT::i64, X, Const1); - Res = DAG.getNode(ISD::SRL, DL, MVT::i64, SllX, Const1); - } - - return DAG.getNode(ISD::BITCAST, DL, MVT::f64, Res); -} - -SDValue MipsTargetLowering::lowerFABS(SDValue Op, SelectionDAG &DAG) const { - if ((ABI.IsN32() || ABI.IsN64()) && (Op.getValueType() == MVT::f64)) - return lowerFABS64(Op, DAG, Subtarget.hasExtractInsert()); - - return lowerFABS32(Op, DAG, Subtarget.hasExtractInsert()); -} - -SDValue MipsTargetLowering:: -lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const { - // check the depth - if (cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() != 0) { - DAG.getContext()->emitError( - "return address can be determined only for current frame"); - return SDValue(); - } - - MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo(); - MFI.setFrameAddressIsTaken(true); - EVT VT = Op.getValueType(); - SDLoc DL(Op); - SDValue FrameAddr = DAG.getCopyFromReg( - DAG.getEntryNode(), DL, ABI.IsN64() ? Mips::FP_64 : Mips::FP, VT); - return FrameAddr; -} - -SDValue MipsTargetLowering::lowerRETURNADDR(SDValue Op, - SelectionDAG &DAG) const { - if (verifyReturnAddressArgumentIsConstant(Op, DAG)) - return SDValue(); - - // check the depth - if (cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() != 0) { - DAG.getContext()->emitError( - "return address can be determined only for current frame"); - return SDValue(); - } - - MachineFunction &MF = DAG.getMachineFunction(); - MachineFrameInfo &MFI = MF.getFrameInfo(); - MVT VT = Op.getSimpleValueType(); - unsigned RA = ABI.IsN64() ? Mips::RA_64 : Mips::RA; - MFI.setReturnAddressIsTaken(true); - - // Return RA, which contains the return address. Mark it an implicit live-in. - unsigned Reg = MF.addLiveIn(RA, getRegClassFor(VT)); - return DAG.getCopyFromReg(DAG.getEntryNode(), SDLoc(Op), Reg, VT); -} - -// An EH_RETURN is the result of lowering llvm.eh.return which in turn is -// generated from __builtin_eh_return (offset, handler) -// The effect of this is to adjust the stack pointer by "offset" -// and then branch to "handler". -SDValue MipsTargetLowering::lowerEH_RETURN(SDValue Op, SelectionDAG &DAG) - const { - MachineFunction &MF = DAG.getMachineFunction(); - MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); - - MipsFI->setCallsEhReturn(); - SDValue Chain = Op.getOperand(0); - SDValue Offset = Op.getOperand(1); - SDValue Handler = Op.getOperand(2); - SDLoc DL(Op); - EVT Ty = ABI.IsN64() ? MVT::i64 : MVT::i32; - - // Store stack offset in V1, store jump target in V0. Glue CopyToReg and - // EH_RETURN nodes, so that instructions are emitted back-to-back. - unsigned OffsetReg = ABI.IsN64() ? Mips::V1_64 : Mips::V1; - unsigned AddrReg = ABI.IsN64() ? Mips::V0_64 : Mips::V0; - Chain = DAG.getCopyToReg(Chain, DL, OffsetReg, Offset, SDValue()); - Chain = DAG.getCopyToReg(Chain, DL, AddrReg, Handler, Chain.getValue(1)); - return DAG.getNode(MipsISD::EH_RETURN, DL, MVT::Other, Chain, - DAG.getRegister(OffsetReg, Ty), - DAG.getRegister(AddrReg, getPointerTy(MF.getDataLayout())), - Chain.getValue(1)); -} - -SDValue MipsTargetLowering::lowerATOMIC_FENCE(SDValue Op, - SelectionDAG &DAG) const { - // FIXME: Need pseudo-fence for 'singlethread' fences - // FIXME: Set SType for weaker fences where supported/appropriate. - unsigned SType = 0; - SDLoc DL(Op); - return DAG.getNode(MipsISD::Sync, DL, MVT::Other, Op.getOperand(0), - DAG.getConstant(SType, DL, MVT::i32)); -} - -SDValue MipsTargetLowering::lowerShiftLeftParts(SDValue Op, - SelectionDAG &DAG) const { - SDLoc DL(Op); - MVT VT = Subtarget.isGP64bit() ? MVT::i64 : MVT::i32; - - SDValue Lo = Op.getOperand(0), Hi = Op.getOperand(1); - SDValue Shamt = Op.getOperand(2); - // if shamt < (VT.bits): - // lo = (shl lo, shamt) - // hi = (or (shl hi, shamt) (srl (srl lo, 1), ~shamt)) - // else: - // lo = 0 - // hi = (shl lo, shamt[4:0]) - SDValue Not = DAG.getNode(ISD::XOR, DL, MVT::i32, Shamt, - DAG.getConstant(-1, DL, MVT::i32)); - SDValue ShiftRight1Lo = DAG.getNode(ISD::SRL, DL, VT, Lo, - DAG.getConstant(1, DL, VT)); - SDValue ShiftRightLo = DAG.getNode(ISD::SRL, DL, VT, ShiftRight1Lo, Not); - SDValue ShiftLeftHi = DAG.getNode(ISD::SHL, DL, VT, Hi, Shamt); - SDValue Or = DAG.getNode(ISD::OR, DL, VT, ShiftLeftHi, ShiftRightLo); - SDValue ShiftLeftLo = DAG.getNode(ISD::SHL, DL, VT, Lo, Shamt); - SDValue Cond = DAG.getNode(ISD::AND, DL, MVT::i32, Shamt, - DAG.getConstant(VT.getSizeInBits(), DL, MVT::i32)); - Lo = DAG.getNode(ISD::SELECT, DL, VT, Cond, - DAG.getConstant(0, DL, VT), ShiftLeftLo); - Hi = DAG.getNode(ISD::SELECT, DL, VT, Cond, ShiftLeftLo, Or); - - SDValue Ops[2] = {Lo, Hi}; - return DAG.getMergeValues(Ops, DL); -} - -SDValue MipsTargetLowering::lowerShiftRightParts(SDValue Op, SelectionDAG &DAG, - bool IsSRA) const { - SDLoc DL(Op); - SDValue Lo = Op.getOperand(0), Hi = Op.getOperand(1); - SDValue Shamt = Op.getOperand(2); - MVT VT = Subtarget.isGP64bit() ? MVT::i64 : MVT::i32; - - // if shamt < (VT.bits): - // lo = (or (shl (shl hi, 1), ~shamt) (srl lo, shamt)) - // if isSRA: - // hi = (sra hi, shamt) - // else: - // hi = (srl hi, shamt) - // else: - // if isSRA: - // lo = (sra hi, shamt[4:0]) - // hi = (sra hi, 31) - // else: - // lo = (srl hi, shamt[4:0]) - // hi = 0 - SDValue Not = DAG.getNode(ISD::XOR, DL, MVT::i32, Shamt, - DAG.getConstant(-1, DL, MVT::i32)); - SDValue ShiftLeft1Hi = DAG.getNode(ISD::SHL, DL, VT, Hi, - DAG.getConstant(1, DL, VT)); - SDValue ShiftLeftHi = DAG.getNode(ISD::SHL, DL, VT, ShiftLeft1Hi, Not); - SDValue ShiftRightLo = DAG.getNode(ISD::SRL, DL, VT, Lo, Shamt); - SDValue Or = DAG.getNode(ISD::OR, DL, VT, ShiftLeftHi, ShiftRightLo); - SDValue ShiftRightHi = DAG.getNode(IsSRA ? ISD::SRA : ISD::SRL, - DL, VT, Hi, Shamt); - SDValue Cond = DAG.getNode(ISD::AND, DL, MVT::i32, Shamt, - DAG.getConstant(VT.getSizeInBits(), DL, MVT::i32)); - SDValue Ext = DAG.getNode(ISD::SRA, DL, VT, Hi, - DAG.getConstant(VT.getSizeInBits() - 1, DL, VT)); - - if (!(Subtarget.hasMips4() || Subtarget.hasMips32())) { - SDVTList VTList = DAG.getVTList(VT, VT); - return DAG.getNode(Subtarget.isGP64bit() ? Mips::PseudoD_SELECT_I64 - : Mips::PseudoD_SELECT_I, - DL, VTList, Cond, ShiftRightHi, - IsSRA ? Ext : DAG.getConstant(0, DL, VT), Or, - ShiftRightHi); - } - - Lo = DAG.getNode(ISD::SELECT, DL, VT, Cond, ShiftRightHi, Or); - Hi = DAG.getNode(ISD::SELECT, DL, VT, Cond, - IsSRA ? Ext : DAG.getConstant(0, DL, VT), ShiftRightHi); - - SDValue Ops[2] = {Lo, Hi}; - return DAG.getMergeValues(Ops, DL); -} - -static SDValue createLoadLR(unsigned Opc, SelectionDAG &DAG, LoadSDNode *LD, - SDValue Chain, SDValue Src, unsigned Offset) { - SDValue Ptr = LD->getBasePtr(); - EVT VT = LD->getValueType(0), MemVT = LD->getMemoryVT(); - EVT BasePtrVT = Ptr.getValueType(); - SDLoc DL(LD); - SDVTList VTList = DAG.getVTList(VT, MVT::Other); - - if (Offset) - Ptr = DAG.getNode(ISD::ADD, DL, BasePtrVT, Ptr, - DAG.getConstant(Offset, DL, BasePtrVT)); - - SDValue Ops[] = { Chain, Ptr, Src }; - return DAG.getMemIntrinsicNode(Opc, DL, VTList, Ops, MemVT, - LD->getMemOperand()); -} - -// Expand an unaligned 32 or 64-bit integer load node. -SDValue MipsTargetLowering::lowerLOAD(SDValue Op, SelectionDAG &DAG) const { - LoadSDNode *LD = cast<LoadSDNode>(Op); - EVT MemVT = LD->getMemoryVT(); - - if (Subtarget.systemSupportsUnalignedAccess()) - return Op; - - // Return if load is aligned or if MemVT is neither i32 nor i64. - if ((LD->getAlignment() >= MemVT.getSizeInBits() / 8) || - ((MemVT != MVT::i32) && (MemVT != MVT::i64))) - return SDValue(); - - bool IsLittle = Subtarget.isLittle(); - EVT VT = Op.getValueType(); - ISD::LoadExtType ExtType = LD->getExtensionType(); - SDValue Chain = LD->getChain(), Undef = DAG.getUNDEF(VT); - - assert((VT == MVT::i32) || (VT == MVT::i64)); - - // Expand - // (set dst, (i64 (load baseptr))) - // to - // (set tmp, (ldl (add baseptr, 7), undef)) - // (set dst, (ldr baseptr, tmp)) - if ((VT == MVT::i64) && (ExtType == ISD::NON_EXTLOAD)) { - SDValue LDL = createLoadLR(MipsISD::LDL, DAG, LD, Chain, Undef, - IsLittle ? 7 : 0); - return createLoadLR(MipsISD::LDR, DAG, LD, LDL.getValue(1), LDL, - IsLittle ? 0 : 7); - } - - SDValue LWL = createLoadLR(MipsISD::LWL, DAG, LD, Chain, Undef, - IsLittle ? 3 : 0); - SDValue LWR = createLoadLR(MipsISD::LWR, DAG, LD, LWL.getValue(1), LWL, - IsLittle ? 0 : 3); - - // Expand - // (set dst, (i32 (load baseptr))) or - // (set dst, (i64 (sextload baseptr))) or - // (set dst, (i64 (extload baseptr))) - // to - // (set tmp, (lwl (add baseptr, 3), undef)) - // (set dst, (lwr baseptr, tmp)) - if ((VT == MVT::i32) || (ExtType == ISD::SEXTLOAD) || - (ExtType == ISD::EXTLOAD)) - return LWR; - - assert((VT == MVT::i64) && (ExtType == ISD::ZEXTLOAD)); - - // Expand - // (set dst, (i64 (zextload baseptr))) - // to - // (set tmp0, (lwl (add baseptr, 3), undef)) - // (set tmp1, (lwr baseptr, tmp0)) - // (set tmp2, (shl tmp1, 32)) - // (set dst, (srl tmp2, 32)) - SDLoc DL(LD); - SDValue Const32 = DAG.getConstant(32, DL, MVT::i32); - SDValue SLL = DAG.getNode(ISD::SHL, DL, MVT::i64, LWR, Const32); - SDValue SRL = DAG.getNode(ISD::SRL, DL, MVT::i64, SLL, Const32); - SDValue Ops[] = { SRL, LWR.getValue(1) }; - return DAG.getMergeValues(Ops, DL); -} - -static SDValue createStoreLR(unsigned Opc, SelectionDAG &DAG, StoreSDNode *SD, - SDValue Chain, unsigned Offset) { - SDValue Ptr = SD->getBasePtr(), Value = SD->getValue(); - EVT MemVT = SD->getMemoryVT(), BasePtrVT = Ptr.getValueType(); - SDLoc DL(SD); - SDVTList VTList = DAG.getVTList(MVT::Other); - - if (Offset) - Ptr = DAG.getNode(ISD::ADD, DL, BasePtrVT, Ptr, - DAG.getConstant(Offset, DL, BasePtrVT)); - - SDValue Ops[] = { Chain, Value, Ptr }; - return DAG.getMemIntrinsicNode(Opc, DL, VTList, Ops, MemVT, - SD->getMemOperand()); -} - -// Expand an unaligned 32 or 64-bit integer store node. -static SDValue lowerUnalignedIntStore(StoreSDNode *SD, SelectionDAG &DAG, - bool IsLittle) { - SDValue Value = SD->getValue(), Chain = SD->getChain(); - EVT VT = Value.getValueType(); - - // Expand - // (store val, baseptr) or - // (truncstore val, baseptr) - // to - // (swl val, (add baseptr, 3)) - // (swr val, baseptr) - if ((VT == MVT::i32) || SD->isTruncatingStore()) { - SDValue SWL = createStoreLR(MipsISD::SWL, DAG, SD, Chain, - IsLittle ? 3 : 0); - return createStoreLR(MipsISD::SWR, DAG, SD, SWL, IsLittle ? 0 : 3); - } - - assert(VT == MVT::i64); - - // Expand - // (store val, baseptr) - // to - // (sdl val, (add baseptr, 7)) - // (sdr val, baseptr) - SDValue SDL = createStoreLR(MipsISD::SDL, DAG, SD, Chain, IsLittle ? 7 : 0); - return createStoreLR(MipsISD::SDR, DAG, SD, SDL, IsLittle ? 0 : 7); -} - -// Lower (store (fp_to_sint $fp) $ptr) to (store (TruncIntFP $fp), $ptr). -static SDValue lowerFP_TO_SINT_STORE(StoreSDNode *SD, SelectionDAG &DAG, - bool SingleFloat) { - SDValue Val = SD->getValue(); - - if (Val.getOpcode() != ISD::FP_TO_SINT || - (Val.getValueSizeInBits() > 32 && SingleFloat)) - return SDValue(); - - EVT FPTy = EVT::getFloatingPointVT(Val.getValueSizeInBits()); - SDValue Tr = DAG.getNode(MipsISD::TruncIntFP, SDLoc(Val), FPTy, - Val.getOperand(0)); - return DAG.getStore(SD->getChain(), SDLoc(SD), Tr, SD->getBasePtr(), - SD->getPointerInfo(), SD->getAlignment(), - SD->getMemOperand()->getFlags()); -} - -SDValue MipsTargetLowering::lowerSTORE(SDValue Op, SelectionDAG &DAG) const { - StoreSDNode *SD = cast<StoreSDNode>(Op); - EVT MemVT = SD->getMemoryVT(); - - // Lower unaligned integer stores. - if (!Subtarget.systemSupportsUnalignedAccess() && - (SD->getAlignment() < MemVT.getSizeInBits() / 8) && - ((MemVT == MVT::i32) || (MemVT == MVT::i64))) - return lowerUnalignedIntStore(SD, DAG, Subtarget.isLittle()); - - return lowerFP_TO_SINT_STORE(SD, DAG, Subtarget.isSingleFloat()); -} - -SDValue MipsTargetLowering::lowerEH_DWARF_CFA(SDValue Op, - SelectionDAG &DAG) const { - - // Return a fixed StackObject with offset 0 which points to the old stack - // pointer. - MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo(); - EVT ValTy = Op->getValueType(0); - int FI = MFI.CreateFixedObject(Op.getValueSizeInBits() / 8, 0, false); - return DAG.getFrameIndex(FI, ValTy); -} - -SDValue MipsTargetLowering::lowerFP_TO_SINT(SDValue Op, - SelectionDAG &DAG) const { - if (Op.getValueSizeInBits() > 32 && Subtarget.isSingleFloat()) - return SDValue(); - - EVT FPTy = EVT::getFloatingPointVT(Op.getValueSizeInBits()); - SDValue Trunc = DAG.getNode(MipsISD::TruncIntFP, SDLoc(Op), FPTy, - Op.getOperand(0)); - return DAG.getNode(ISD::BITCAST, SDLoc(Op), Op.getValueType(), Trunc); -} - -//===----------------------------------------------------------------------===// -// Calling Convention Implementation -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// TODO: Implement a generic logic using tblgen that can support this. -// Mips O32 ABI rules: -// --- -// i32 - Passed in A0, A1, A2, A3 and stack -// f32 - Only passed in f32 registers if no int reg has been used yet to hold -// an argument. Otherwise, passed in A1, A2, A3 and stack. -// f64 - Only passed in two aliased f32 registers if no int reg has been used -// yet to hold an argument. Otherwise, use A2, A3 and stack. If A1 is -// not used, it must be shadowed. If only A3 is available, shadow it and -// go to stack. -// vXiX - Received as scalarized i32s, passed in A0 - A3 and the stack. -// vXf32 - Passed in either a pair of registers {A0, A1}, {A2, A3} or {A0 - A3} -// with the remainder spilled to the stack. -// vXf64 - Passed in either {A0, A1, A2, A3} or {A2, A3} and in both cases -// spilling the remainder to the stack. -// -// For vararg functions, all arguments are passed in A0, A1, A2, A3 and stack. -//===----------------------------------------------------------------------===// - -static bool CC_MipsO32(unsigned ValNo, MVT ValVT, MVT LocVT, - CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, - CCState &State, ArrayRef<MCPhysReg> F64Regs) { - const MipsSubtarget &Subtarget = static_cast<const MipsSubtarget &>( - State.getMachineFunction().getSubtarget()); - - static const MCPhysReg IntRegs[] = { Mips::A0, Mips::A1, Mips::A2, Mips::A3 }; - - const MipsCCState * MipsState = static_cast<MipsCCState *>(&State); - - static const MCPhysReg F32Regs[] = { Mips::F12, Mips::F14 }; - - static const MCPhysReg FloatVectorIntRegs[] = { Mips::A0, Mips::A2 }; - - // Do not process byval args here. - if (ArgFlags.isByVal()) - return true; - - // Promote i8 and i16 - if (ArgFlags.isInReg() && !Subtarget.isLittle()) { - if (LocVT == MVT::i8 || LocVT == MVT::i16 || LocVT == MVT::i32) { - LocVT = MVT::i32; - if (ArgFlags.isSExt()) - LocInfo = CCValAssign::SExtUpper; - else if (ArgFlags.isZExt()) - LocInfo = CCValAssign::ZExtUpper; - else - LocInfo = CCValAssign::AExtUpper; - } - } - - // Promote i8 and i16 - if (LocVT == MVT::i8 || LocVT == MVT::i16) { - LocVT = MVT::i32; - if (ArgFlags.isSExt()) - LocInfo = CCValAssign::SExt; - else if (ArgFlags.isZExt()) - LocInfo = CCValAssign::ZExt; - else - LocInfo = CCValAssign::AExt; - } - - unsigned Reg; - - // f32 and f64 are allocated in A0, A1, A2, A3 when either of the following - // is true: function is vararg, argument is 3rd or higher, there is previous - // argument which is not f32 or f64. - bool AllocateFloatsInIntReg = State.isVarArg() || ValNo > 1 || - State.getFirstUnallocated(F32Regs) != ValNo; - unsigned OrigAlign = ArgFlags.getOrigAlign(); - bool isI64 = (ValVT == MVT::i32 && OrigAlign == 8); - bool isVectorFloat = MipsState->WasOriginalArgVectorFloat(ValNo); - - // The MIPS vector ABI for floats passes them in a pair of registers - if (ValVT == MVT::i32 && isVectorFloat) { - // This is the start of an vector that was scalarized into an unknown number - // of components. It doesn't matter how many there are. Allocate one of the - // notional 8 byte aligned registers which map onto the argument stack, and - // shadow the register lost to alignment requirements. - if (ArgFlags.isSplit()) { - Reg = State.AllocateReg(FloatVectorIntRegs); - if (Reg == Mips::A2) - State.AllocateReg(Mips::A1); - else if (Reg == 0) - State.AllocateReg(Mips::A3); - } else { - // If we're an intermediate component of the split, we can just attempt to - // allocate a register directly. - Reg = State.AllocateReg(IntRegs); - } - } else if (ValVT == MVT::i32 || (ValVT == MVT::f32 && AllocateFloatsInIntReg)) { - Reg = State.AllocateReg(IntRegs); - // If this is the first part of an i64 arg, - // the allocated register must be either A0 or A2. - if (isI64 && (Reg == Mips::A1 || Reg == Mips::A3)) - Reg = State.AllocateReg(IntRegs); - LocVT = MVT::i32; - } else if (ValVT == MVT::f64 && AllocateFloatsInIntReg) { - // Allocate int register and shadow next int register. If first - // available register is Mips::A1 or Mips::A3, shadow it too. - Reg = State.AllocateReg(IntRegs); - if (Reg == Mips::A1 || Reg == Mips::A3) - Reg = State.AllocateReg(IntRegs); - State.AllocateReg(IntRegs); - LocVT = MVT::i32; - } else if (ValVT.isFloatingPoint() && !AllocateFloatsInIntReg) { - // we are guaranteed to find an available float register - if (ValVT == MVT::f32) { - Reg = State.AllocateReg(F32Regs); - // Shadow int register - State.AllocateReg(IntRegs); - } else { - Reg = State.AllocateReg(F64Regs); - // Shadow int registers - unsigned Reg2 = State.AllocateReg(IntRegs); - if (Reg2 == Mips::A1 || Reg2 == Mips::A3) - State.AllocateReg(IntRegs); - State.AllocateReg(IntRegs); - } - } else - llvm_unreachable("Cannot handle this ValVT."); - - if (!Reg) { - unsigned Offset = State.AllocateStack(ValVT.getStoreSize(), OrigAlign); - State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo)); - } else - State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); - - return false; -} - -static bool CC_MipsO32_FP32(unsigned ValNo, MVT ValVT, - MVT LocVT, CCValAssign::LocInfo LocInfo, - ISD::ArgFlagsTy ArgFlags, CCState &State) { - static const MCPhysReg F64Regs[] = { Mips::D6, Mips::D7 }; - - return CC_MipsO32(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State, F64Regs); -} - -static bool CC_MipsO32_FP64(unsigned ValNo, MVT ValVT, - MVT LocVT, CCValAssign::LocInfo LocInfo, - ISD::ArgFlagsTy ArgFlags, CCState &State) { - static const MCPhysReg F64Regs[] = { Mips::D12_64, Mips::D14_64 }; - - return CC_MipsO32(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State, F64Regs); -} - -static bool CC_MipsO32(unsigned ValNo, MVT ValVT, MVT LocVT, - CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, - CCState &State) LLVM_ATTRIBUTE_UNUSED; - -#include "MipsGenCallingConv.inc" - - CCAssignFn *MipsTargetLowering::CCAssignFnForCall() const{ - return CC_Mips; - } - - CCAssignFn *MipsTargetLowering::CCAssignFnForReturn() const{ - return RetCC_Mips; - } -//===----------------------------------------------------------------------===// -// Call Calling Convention Implementation -//===----------------------------------------------------------------------===// - -// Return next O32 integer argument register. -static unsigned getNextIntArgReg(unsigned Reg) { - assert((Reg == Mips::A0) || (Reg == Mips::A2)); - return (Reg == Mips::A0) ? Mips::A1 : Mips::A3; -} - -SDValue MipsTargetLowering::passArgOnStack(SDValue StackPtr, unsigned Offset, - SDValue Chain, SDValue Arg, - const SDLoc &DL, bool IsTailCall, - SelectionDAG &DAG) const { - if (!IsTailCall) { - SDValue PtrOff = - DAG.getNode(ISD::ADD, DL, getPointerTy(DAG.getDataLayout()), StackPtr, - DAG.getIntPtrConstant(Offset, DL)); - return DAG.getStore(Chain, DL, Arg, PtrOff, MachinePointerInfo()); - } - - MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo(); - int FI = MFI.CreateFixedObject(Arg.getValueSizeInBits() / 8, Offset, false); - SDValue FIN = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout())); - return DAG.getStore(Chain, DL, Arg, FIN, MachinePointerInfo(), - /* Alignment = */ 0, MachineMemOperand::MOVolatile); -} - -void MipsTargetLowering:: -getOpndList(SmallVectorImpl<SDValue> &Ops, - std::deque<std::pair<unsigned, SDValue>> &RegsToPass, - bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage, - bool IsCallReloc, CallLoweringInfo &CLI, SDValue Callee, - SDValue Chain) const { - // Insert node "GP copy globalreg" before call to function. - // - // R_MIPS_CALL* operators (emitted when non-internal functions are called - // in PIC mode) allow symbols to be resolved via lazy binding. - // The lazy binding stub requires GP to point to the GOT. - // Note that we don't need GP to point to the GOT for indirect calls - // (when R_MIPS_CALL* is not used for the call) because Mips linker generates - // lazy binding stub for a function only when R_MIPS_CALL* are the only relocs - // used for the function (that is, Mips linker doesn't generate lazy binding - // stub for a function whose address is taken in the program). - if (IsPICCall && !InternalLinkage && IsCallReloc) { - unsigned GPReg = ABI.IsN64() ? Mips::GP_64 : Mips::GP; - EVT Ty = ABI.IsN64() ? MVT::i64 : MVT::i32; - RegsToPass.push_back(std::make_pair(GPReg, getGlobalReg(CLI.DAG, Ty))); - } - - // Build a sequence of copy-to-reg nodes chained together with token - // chain and flag operands which copy the outgoing args into registers. - // The InFlag in necessary since all emitted instructions must be - // stuck together. - SDValue InFlag; - - for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { - Chain = CLI.DAG.getCopyToReg(Chain, CLI.DL, RegsToPass[i].first, - RegsToPass[i].second, InFlag); - InFlag = Chain.getValue(1); - } - - // Add argument registers to the end of the list so that they are - // known live into the call. - for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) - Ops.push_back(CLI.DAG.getRegister(RegsToPass[i].first, - RegsToPass[i].second.getValueType())); - - // Add a register mask operand representing the call-preserved registers. - const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo(); - const uint32_t *Mask = - TRI->getCallPreservedMask(CLI.DAG.getMachineFunction(), CLI.CallConv); - assert(Mask && "Missing call preserved mask for calling convention"); - if (Subtarget.inMips16HardFloat()) { - if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(CLI.Callee)) { - StringRef Sym = G->getGlobal()->getName(); - Function *F = G->getGlobal()->getParent()->getFunction(Sym); - if (F && F->hasFnAttribute("__Mips16RetHelper")) { - Mask = MipsRegisterInfo::getMips16RetHelperMask(); - } - } - } - Ops.push_back(CLI.DAG.getRegisterMask(Mask)); - - if (InFlag.getNode()) - Ops.push_back(InFlag); -} - -void MipsTargetLowering::AdjustInstrPostInstrSelection(MachineInstr &MI, - SDNode *Node) const { - switch (MI.getOpcode()) { - default: - return; - case Mips::JALR: - case Mips::JALRPseudo: - case Mips::JALR64: - case Mips::JALR64Pseudo: - case Mips::JALR16_MM: - case Mips::JALRC16_MMR6: - case Mips::TAILCALLREG: - case Mips::TAILCALLREG64: - case Mips::TAILCALLR6REG: - case Mips::TAILCALL64R6REG: - case Mips::TAILCALLREG_MM: - case Mips::TAILCALLREG_MMR6: { - if (!EmitJalrReloc || - Subtarget.inMips16Mode() || - !isPositionIndependent() || - Node->getNumOperands() < 1 || - Node->getOperand(0).getNumOperands() < 2) { - return; - } - // We are after the callee address, set by LowerCall(). - // If added to MI, asm printer will emit .reloc R_MIPS_JALR for the - // symbol. - const SDValue TargetAddr = Node->getOperand(0).getOperand(1); - StringRef Sym; - if (const GlobalAddressSDNode *G = - dyn_cast_or_null<const GlobalAddressSDNode>(TargetAddr)) { - Sym = G->getGlobal()->getName(); - } - else if (const ExternalSymbolSDNode *ES = - dyn_cast_or_null<const ExternalSymbolSDNode>(TargetAddr)) { - Sym = ES->getSymbol(); - } - - if (Sym.empty()) - return; - - MachineFunction *MF = MI.getParent()->getParent(); - MCSymbol *S = MF->getContext().getOrCreateSymbol(Sym); - MI.addOperand(MachineOperand::CreateMCSymbol(S, MipsII::MO_JALR)); - } - } -} - -/// LowerCall - functions arguments are copied from virtual regs to -/// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted. -SDValue -MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, - SmallVectorImpl<SDValue> &InVals) const { - SelectionDAG &DAG = CLI.DAG; - SDLoc DL = CLI.DL; - SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs; - SmallVectorImpl<SDValue> &OutVals = CLI.OutVals; - SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins; - SDValue Chain = CLI.Chain; - SDValue Callee = CLI.Callee; - bool &IsTailCall = CLI.IsTailCall; - CallingConv::ID CallConv = CLI.CallConv; - bool IsVarArg = CLI.IsVarArg; - - MachineFunction &MF = DAG.getMachineFunction(); - MachineFrameInfo &MFI = MF.getFrameInfo(); - const TargetFrameLowering *TFL = Subtarget.getFrameLowering(); - MipsFunctionInfo *FuncInfo = MF.getInfo<MipsFunctionInfo>(); - bool IsPIC = isPositionIndependent(); - - // Analyze operands of the call, assigning locations to each operand. - SmallVector<CCValAssign, 16> ArgLocs; - MipsCCState CCInfo( - CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs, *DAG.getContext(), - MipsCCState::getSpecialCallingConvForCallee(Callee.getNode(), Subtarget)); - - const ExternalSymbolSDNode *ES = - dyn_cast_or_null<const ExternalSymbolSDNode>(Callee.getNode()); - - // There is one case where CALLSEQ_START..CALLSEQ_END can be nested, which - // is during the lowering of a call with a byval argument which produces - // a call to memcpy. For the O32 case, this causes the caller to allocate - // stack space for the reserved argument area for the callee, then recursively - // again for the memcpy call. In the NEWABI case, this doesn't occur as those - // ABIs mandate that the callee allocates the reserved argument area. We do - // still produce nested CALLSEQ_START..CALLSEQ_END with zero space though. - // - // If the callee has a byval argument and memcpy is used, we are mandated - // to already have produced a reserved argument area for the callee for O32. - // Therefore, the reserved argument area can be reused for both calls. - // - // Other cases of calling memcpy cannot have a chain with a CALLSEQ_START - // present, as we have yet to hook that node onto the chain. - // - // Hence, the CALLSEQ_START and CALLSEQ_END nodes can be eliminated in this - // case. GCC does a similar trick, in that wherever possible, it calculates - // the maximum out going argument area (including the reserved area), and - // preallocates the stack space on entrance to the caller. - // - // FIXME: We should do the same for efficiency and space. - - // Note: The check on the calling convention below must match - // MipsABIInfo::GetCalleeAllocdArgSizeInBytes(). - bool MemcpyInByVal = ES && - StringRef(ES->getSymbol()) == StringRef("memcpy") && - CallConv != CallingConv::Fast && - Chain.getOpcode() == ISD::CALLSEQ_START; - - // Allocate the reserved argument area. It seems strange to do this from the - // caller side but removing it breaks the frame size calculation. - unsigned ReservedArgArea = - MemcpyInByVal ? 0 : ABI.GetCalleeAllocdArgSizeInBytes(CallConv); - CCInfo.AllocateStack(ReservedArgArea, 1); - - CCInfo.AnalyzeCallOperands(Outs, CC_Mips, CLI.getArgs(), - ES ? ES->getSymbol() : nullptr); - - // Get a count of how many bytes are to be pushed on the stack. - unsigned NextStackOffset = CCInfo.getNextStackOffset(); - - // Check if it's really possible to do a tail call. Restrict it to functions - // that are part of this compilation unit. - bool InternalLinkage = false; - if (IsTailCall) { - IsTailCall = isEligibleForTailCallOptimization( - CCInfo, NextStackOffset, *MF.getInfo<MipsFunctionInfo>()); - if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) { - InternalLinkage = G->getGlobal()->hasInternalLinkage(); - IsTailCall &= (InternalLinkage || G->getGlobal()->hasLocalLinkage() || - G->getGlobal()->hasPrivateLinkage() || - G->getGlobal()->hasHiddenVisibility() || - G->getGlobal()->hasProtectedVisibility()); - } - } - if (!IsTailCall && CLI.CS && CLI.CS.isMustTailCall()) - report_fatal_error("failed to perform tail call elimination on a call " - "site marked musttail"); - - if (IsTailCall) - ++NumTailCalls; - - // Chain is the output chain of the last Load/Store or CopyToReg node. - // ByValChain is the output chain of the last Memcpy node created for copying - // byval arguments to the stack. - unsigned StackAlignment = TFL->getStackAlignment(); - NextStackOffset = alignTo(NextStackOffset, StackAlignment); - SDValue NextStackOffsetVal = DAG.getIntPtrConstant(NextStackOffset, DL, true); - - if (!(IsTailCall || MemcpyInByVal)) - Chain = DAG.getCALLSEQ_START(Chain, NextStackOffset, 0, DL); - - SDValue StackPtr = - DAG.getCopyFromReg(Chain, DL, ABI.IsN64() ? Mips::SP_64 : Mips::SP, - getPointerTy(DAG.getDataLayout())); - - std::deque<std::pair<unsigned, SDValue>> RegsToPass; - SmallVector<SDValue, 8> MemOpChains; - - CCInfo.rewindByValRegsInfo(); - - // Walk the register/memloc assignments, inserting copies/loads. - for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { - SDValue Arg = OutVals[i]; - CCValAssign &VA = ArgLocs[i]; - MVT ValVT = VA.getValVT(), LocVT = VA.getLocVT(); - ISD::ArgFlagsTy Flags = Outs[i].Flags; - bool UseUpperBits = false; - - // ByVal Arg. - if (Flags.isByVal()) { - unsigned FirstByValReg, LastByValReg; - unsigned ByValIdx = CCInfo.getInRegsParamsProcessed(); - CCInfo.getInRegsParamInfo(ByValIdx, FirstByValReg, LastByValReg); - - assert(Flags.getByValSize() && - "ByVal args of size 0 should have been ignored by front-end."); - assert(ByValIdx < CCInfo.getInRegsParamsCount()); - assert(!IsTailCall && - "Do not tail-call optimize if there is a byval argument."); - passByValArg(Chain, DL, RegsToPass, MemOpChains, StackPtr, MFI, DAG, Arg, - FirstByValReg, LastByValReg, Flags, Subtarget.isLittle(), - VA); - CCInfo.nextInRegsParam(); - continue; - } - - // Promote the value if needed. - switch (VA.getLocInfo()) { - default: - llvm_unreachable("Unknown loc info!"); - case CCValAssign::Full: - if (VA.isRegLoc()) { - if ((ValVT == MVT::f32 && LocVT == MVT::i32) || - (ValVT == MVT::f64 && LocVT == MVT::i64) || - (ValVT == MVT::i64 && LocVT == MVT::f64)) - Arg = DAG.getNode(ISD::BITCAST, DL, LocVT, Arg); - else if (ValVT == MVT::f64 && LocVT == MVT::i32) { - SDValue Lo = DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32, - Arg, DAG.getConstant(0, DL, MVT::i32)); - SDValue Hi = DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32, - Arg, DAG.getConstant(1, DL, MVT::i32)); - if (!Subtarget.isLittle()) - std::swap(Lo, Hi); - unsigned LocRegLo = VA.getLocReg(); - unsigned LocRegHigh = getNextIntArgReg(LocRegLo); - RegsToPass.push_back(std::make_pair(LocRegLo, Lo)); - RegsToPass.push_back(std::make_pair(LocRegHigh, Hi)); - continue; - } - } - break; - case CCValAssign::BCvt: - Arg = DAG.getNode(ISD::BITCAST, DL, LocVT, Arg); - break; - case CCValAssign::SExtUpper: - UseUpperBits = true; - LLVM_FALLTHROUGH; - case CCValAssign::SExt: - Arg = DAG.getNode(ISD::SIGN_EXTEND, DL, LocVT, Arg); - break; - case CCValAssign::ZExtUpper: - UseUpperBits = true; - LLVM_FALLTHROUGH; - case CCValAssign::ZExt: - Arg = DAG.getNode(ISD::ZERO_EXTEND, DL, LocVT, Arg); - break; - case CCValAssign::AExtUpper: - UseUpperBits = true; - LLVM_FALLTHROUGH; - case CCValAssign::AExt: - Arg = DAG.getNode(ISD::ANY_EXTEND, DL, LocVT, Arg); - break; - } - - if (UseUpperBits) { - unsigned ValSizeInBits = Outs[i].ArgVT.getSizeInBits(); - unsigned LocSizeInBits = VA.getLocVT().getSizeInBits(); - Arg = DAG.getNode( - ISD::SHL, DL, VA.getLocVT(), Arg, - DAG.getConstant(LocSizeInBits - ValSizeInBits, DL, VA.getLocVT())); - } - - // Arguments that can be passed on register must be kept at - // RegsToPass vector - if (VA.isRegLoc()) { - RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); - continue; - } - - // Register can't get to this point... - assert(VA.isMemLoc()); - - // emit ISD::STORE whichs stores the - // parameter value to a stack Location - MemOpChains.push_back(passArgOnStack(StackPtr, VA.getLocMemOffset(), - Chain, Arg, DL, IsTailCall, DAG)); - } - - // Transform all store nodes into one single node because all store - // nodes are independent of each other. - if (!MemOpChains.empty()) - Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOpChains); - - // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every - // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol - // node so that legalize doesn't hack it. - - EVT Ty = Callee.getValueType(); - bool GlobalOrExternal = false, IsCallReloc = false; - - // The long-calls feature is ignored in case of PIC. - // While we do not support -mshared / -mno-shared properly, - // ignore long-calls in case of -mabicalls too. - if (!Subtarget.isABICalls() && !IsPIC) { - // If the function should be called using "long call", - // get its address into a register to prevent using - // of the `jal` instruction for the direct call. - if (auto *N = dyn_cast<ExternalSymbolSDNode>(Callee)) { - if (Subtarget.useLongCalls()) - Callee = Subtarget.hasSym32() - ? getAddrNonPIC(N, SDLoc(N), Ty, DAG) - : getAddrNonPICSym64(N, SDLoc(N), Ty, DAG); - } else if (auto *N = dyn_cast<GlobalAddressSDNode>(Callee)) { - bool UseLongCalls = Subtarget.useLongCalls(); - // If the function has long-call/far/near attribute - // it overrides command line switch pased to the backend. - if (auto *F = dyn_cast<Function>(N->getGlobal())) { - if (F->hasFnAttribute("long-call")) - UseLongCalls = true; - else if (F->hasFnAttribute("short-call")) - UseLongCalls = false; - } - if (UseLongCalls) - Callee = Subtarget.hasSym32() - ? getAddrNonPIC(N, SDLoc(N), Ty, DAG) - : getAddrNonPICSym64(N, SDLoc(N), Ty, DAG); - } - } - - if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) { - if (IsPIC) { - const GlobalValue *Val = G->getGlobal(); - InternalLinkage = Val->hasInternalLinkage(); - - if (InternalLinkage) - Callee = getAddrLocal(G, DL, Ty, DAG, ABI.IsN32() || ABI.IsN64()); - else if (LargeGOT) { - Callee = getAddrGlobalLargeGOT(G, DL, Ty, DAG, MipsII::MO_CALL_HI16, - MipsII::MO_CALL_LO16, Chain, - FuncInfo->callPtrInfo(Val)); - IsCallReloc = true; - } else { - Callee = getAddrGlobal(G, DL, Ty, DAG, MipsII::MO_GOT_CALL, Chain, - FuncInfo->callPtrInfo(Val)); - IsCallReloc = true; - } - } else - Callee = DAG.getTargetGlobalAddress(G->getGlobal(), DL, - getPointerTy(DAG.getDataLayout()), 0, - MipsII::MO_NO_FLAG); - GlobalOrExternal = true; - } - else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) { - const char *Sym = S->getSymbol(); - - if (!IsPIC) // static - Callee = DAG.getTargetExternalSymbol( - Sym, getPointerTy(DAG.getDataLayout()), MipsII::MO_NO_FLAG); - else if (LargeGOT) { - Callee = getAddrGlobalLargeGOT(S, DL, Ty, DAG, MipsII::MO_CALL_HI16, - MipsII::MO_CALL_LO16, Chain, - FuncInfo->callPtrInfo(Sym)); - IsCallReloc = true; - } else { // PIC - Callee = getAddrGlobal(S, DL, Ty, DAG, MipsII::MO_GOT_CALL, Chain, - FuncInfo->callPtrInfo(Sym)); - IsCallReloc = true; - } - - GlobalOrExternal = true; - } - - SmallVector<SDValue, 8> Ops(1, Chain); - SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); - - getOpndList(Ops, RegsToPass, IsPIC, GlobalOrExternal, InternalLinkage, - IsCallReloc, CLI, Callee, Chain); - - if (IsTailCall) { - MF.getFrameInfo().setHasTailCall(); - return DAG.getNode(MipsISD::TailCall, DL, MVT::Other, Ops); - } - - Chain = DAG.getNode(MipsISD::JmpLink, DL, NodeTys, Ops); - SDValue InFlag = Chain.getValue(1); - - // Create the CALLSEQ_END node in the case of where it is not a call to - // memcpy. - if (!(MemcpyInByVal)) { - Chain = DAG.getCALLSEQ_END(Chain, NextStackOffsetVal, - DAG.getIntPtrConstant(0, DL, true), InFlag, DL); - InFlag = Chain.getValue(1); - } - - // Handle result values, copying them out of physregs into vregs that we - // return. - return LowerCallResult(Chain, InFlag, CallConv, IsVarArg, Ins, DL, DAG, - InVals, CLI); -} - -/// LowerCallResult - Lower the result values of a call into the -/// appropriate copies out of appropriate physical registers. -SDValue MipsTargetLowering::LowerCallResult( - SDValue Chain, SDValue InFlag, CallingConv::ID CallConv, bool IsVarArg, - const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL, - SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals, - TargetLowering::CallLoweringInfo &CLI) const { - // Assign locations to each value returned by this call. - SmallVector<CCValAssign, 16> RVLocs; - MipsCCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs, - *DAG.getContext()); - - const ExternalSymbolSDNode *ES = - dyn_cast_or_null<const ExternalSymbolSDNode>(CLI.Callee.getNode()); - CCInfo.AnalyzeCallResult(Ins, RetCC_Mips, CLI.RetTy, - ES ? ES->getSymbol() : nullptr); - - // Copy all of the result registers out of their specified physreg. - for (unsigned i = 0; i != RVLocs.size(); ++i) { - CCValAssign &VA = RVLocs[i]; - assert(VA.isRegLoc() && "Can only return in registers!"); - - SDValue Val = DAG.getCopyFromReg(Chain, DL, RVLocs[i].getLocReg(), - RVLocs[i].getLocVT(), InFlag); - Chain = Val.getValue(1); - InFlag = Val.getValue(2); - - if (VA.isUpperBitsInLoc()) { - unsigned ValSizeInBits = Ins[i].ArgVT.getSizeInBits(); - unsigned LocSizeInBits = VA.getLocVT().getSizeInBits(); - unsigned Shift = - VA.getLocInfo() == CCValAssign::ZExtUpper ? ISD::SRL : ISD::SRA; - Val = DAG.getNode( - Shift, DL, VA.getLocVT(), Val, - DAG.getConstant(LocSizeInBits - ValSizeInBits, DL, VA.getLocVT())); - } - - switch (VA.getLocInfo()) { - default: - llvm_unreachable("Unknown loc info!"); - case CCValAssign::Full: - break; - case CCValAssign::BCvt: - Val = DAG.getNode(ISD::BITCAST, DL, VA.getValVT(), Val); - break; - case CCValAssign::AExt: - case CCValAssign::AExtUpper: - Val = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Val); - break; - case CCValAssign::ZExt: - case CCValAssign::ZExtUpper: - Val = DAG.getNode(ISD::AssertZext, DL, VA.getLocVT(), Val, - DAG.getValueType(VA.getValVT())); - Val = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Val); - break; - case CCValAssign::SExt: - case CCValAssign::SExtUpper: - Val = DAG.getNode(ISD::AssertSext, DL, VA.getLocVT(), Val, - DAG.getValueType(VA.getValVT())); - Val = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Val); - break; - } - - InVals.push_back(Val); - } - - return Chain; -} - -static SDValue UnpackFromArgumentSlot(SDValue Val, const CCValAssign &VA, - EVT ArgVT, const SDLoc &DL, - SelectionDAG &DAG) { - MVT LocVT = VA.getLocVT(); - EVT ValVT = VA.getValVT(); - - // Shift into the upper bits if necessary. - switch (VA.getLocInfo()) { - default: - break; - case CCValAssign::AExtUpper: - case CCValAssign::SExtUpper: - case CCValAssign::ZExtUpper: { - unsigned ValSizeInBits = ArgVT.getSizeInBits(); - unsigned LocSizeInBits = VA.getLocVT().getSizeInBits(); - unsigned Opcode = - VA.getLocInfo() == CCValAssign::ZExtUpper ? ISD::SRL : ISD::SRA; - Val = DAG.getNode( - Opcode, DL, VA.getLocVT(), Val, - DAG.getConstant(LocSizeInBits - ValSizeInBits, DL, VA.getLocVT())); - break; - } - } - - // If this is an value smaller than the argument slot size (32-bit for O32, - // 64-bit for N32/N64), it has been promoted in some way to the argument slot - // size. Extract the value and insert any appropriate assertions regarding - // sign/zero extension. - switch (VA.getLocInfo()) { - default: - llvm_unreachable("Unknown loc info!"); - case CCValAssign::Full: - break; - case CCValAssign::AExtUpper: - case CCValAssign::AExt: - Val = DAG.getNode(ISD::TRUNCATE, DL, ValVT, Val); - break; - case CCValAssign::SExtUpper: - case CCValAssign::SExt: - Val = DAG.getNode(ISD::AssertSext, DL, LocVT, Val, DAG.getValueType(ValVT)); - Val = DAG.getNode(ISD::TRUNCATE, DL, ValVT, Val); - break; - case CCValAssign::ZExtUpper: - case CCValAssign::ZExt: - Val = DAG.getNode(ISD::AssertZext, DL, LocVT, Val, DAG.getValueType(ValVT)); - Val = DAG.getNode(ISD::TRUNCATE, DL, ValVT, Val); - break; - case CCValAssign::BCvt: - Val = DAG.getNode(ISD::BITCAST, DL, ValVT, Val); - break; - } - - return Val; -} - -//===----------------------------------------------------------------------===// -// Formal Arguments Calling Convention Implementation -//===----------------------------------------------------------------------===// -/// LowerFormalArguments - transform physical registers into virtual registers -/// and generate load operations for arguments places on the stack. -SDValue MipsTargetLowering::LowerFormalArguments( - SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, - const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL, - SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { - MachineFunction &MF = DAG.getMachineFunction(); - MachineFrameInfo &MFI = MF.getFrameInfo(); - MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); - - MipsFI->setVarArgsFrameIndex(0); - - // Used with vargs to acumulate store chains. - std::vector<SDValue> OutChains; - - // Assign locations to all of the incoming arguments. - SmallVector<CCValAssign, 16> ArgLocs; - MipsCCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs, - *DAG.getContext()); - CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(CallConv), 1); - const Function &Func = DAG.getMachineFunction().getFunction(); - Function::const_arg_iterator FuncArg = Func.arg_begin(); - - if (Func.hasFnAttribute("interrupt") && !Func.arg_empty()) - report_fatal_error( - "Functions with the interrupt attribute cannot have arguments!"); - - CCInfo.AnalyzeFormalArguments(Ins, CC_Mips_FixedArg); - MipsFI->setFormalArgInfo(CCInfo.getNextStackOffset(), - CCInfo.getInRegsParamsCount() > 0); - - unsigned CurArgIdx = 0; - CCInfo.rewindByValRegsInfo(); - - for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { - CCValAssign &VA = ArgLocs[i]; - if (Ins[i].isOrigArg()) { - std::advance(FuncArg, Ins[i].getOrigArgIndex() - CurArgIdx); - CurArgIdx = Ins[i].getOrigArgIndex(); - } - EVT ValVT = VA.getValVT(); - ISD::ArgFlagsTy Flags = Ins[i].Flags; - bool IsRegLoc = VA.isRegLoc(); - - if (Flags.isByVal()) { - assert(Ins[i].isOrigArg() && "Byval arguments cannot be implicit"); - unsigned FirstByValReg, LastByValReg; - unsigned ByValIdx = CCInfo.getInRegsParamsProcessed(); - CCInfo.getInRegsParamInfo(ByValIdx, FirstByValReg, LastByValReg); - - assert(Flags.getByValSize() && - "ByVal args of size 0 should have been ignored by front-end."); - assert(ByValIdx < CCInfo.getInRegsParamsCount()); - copyByValRegs(Chain, DL, OutChains, DAG, Flags, InVals, &*FuncArg, - FirstByValReg, LastByValReg, VA, CCInfo); - CCInfo.nextInRegsParam(); - continue; - } - - // Arguments stored on registers - if (IsRegLoc) { - MVT RegVT = VA.getLocVT(); - unsigned ArgReg = VA.getLocReg(); - const TargetRegisterClass *RC = getRegClassFor(RegVT); - - // Transform the arguments stored on - // physical registers into virtual ones - unsigned Reg = addLiveIn(DAG.getMachineFunction(), ArgReg, RC); - SDValue ArgValue = DAG.getCopyFromReg(Chain, DL, Reg, RegVT); - - ArgValue = UnpackFromArgumentSlot(ArgValue, VA, Ins[i].ArgVT, DL, DAG); - - // Handle floating point arguments passed in integer registers and - // long double arguments passed in floating point registers. - if ((RegVT == MVT::i32 && ValVT == MVT::f32) || - (RegVT == MVT::i64 && ValVT == MVT::f64) || - (RegVT == MVT::f64 && ValVT == MVT::i64)) - ArgValue = DAG.getNode(ISD::BITCAST, DL, ValVT, ArgValue); - else if (ABI.IsO32() && RegVT == MVT::i32 && - ValVT == MVT::f64) { - unsigned Reg2 = addLiveIn(DAG.getMachineFunction(), - getNextIntArgReg(ArgReg), RC); - SDValue ArgValue2 = DAG.getCopyFromReg(Chain, DL, Reg2, RegVT); - if (!Subtarget.isLittle()) - std::swap(ArgValue, ArgValue2); - ArgValue = DAG.getNode(MipsISD::BuildPairF64, DL, MVT::f64, - ArgValue, ArgValue2); - } - - InVals.push_back(ArgValue); - } else { // VA.isRegLoc() - MVT LocVT = VA.getLocVT(); - - if (ABI.IsO32()) { - // We ought to be able to use LocVT directly but O32 sets it to i32 - // when allocating floating point values to integer registers. - // This shouldn't influence how we load the value into registers unless - // we are targeting softfloat. - if (VA.getValVT().isFloatingPoint() && !Subtarget.useSoftFloat()) - LocVT = VA.getValVT(); - } - - // sanity check - assert(VA.isMemLoc()); - - // The stack pointer offset is relative to the caller stack frame. - int FI = MFI.CreateFixedObject(LocVT.getSizeInBits() / 8, - VA.getLocMemOffset(), true); - - // Create load nodes to retrieve arguments from the stack - SDValue FIN = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout())); - SDValue ArgValue = DAG.getLoad( - LocVT, DL, Chain, FIN, - MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI)); - OutChains.push_back(ArgValue.getValue(1)); - - ArgValue = UnpackFromArgumentSlot(ArgValue, VA, Ins[i].ArgVT, DL, DAG); - - InVals.push_back(ArgValue); - } - } - - for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { - // The mips ABIs for returning structs by value requires that we copy - // the sret argument into $v0 for the return. Save the argument into - // a virtual register so that we can access it from the return points. - if (Ins[i].Flags.isSRet()) { - unsigned Reg = MipsFI->getSRetReturnReg(); - if (!Reg) { - Reg = MF.getRegInfo().createVirtualRegister( - getRegClassFor(ABI.IsN64() ? MVT::i64 : MVT::i32)); - MipsFI->setSRetReturnReg(Reg); - } - SDValue Copy = DAG.getCopyToReg(DAG.getEntryNode(), DL, Reg, InVals[i]); - Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Copy, Chain); - break; - } - } - - if (IsVarArg) - writeVarArgRegs(OutChains, Chain, DL, DAG, CCInfo); - - // All stores are grouped in one node to allow the matching between - // the size of Ins and InVals. This only happens when on varg functions - if (!OutChains.empty()) { - OutChains.push_back(Chain); - Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains); - } - - return Chain; -} - -//===----------------------------------------------------------------------===// -// Return Value Calling Convention Implementation -//===----------------------------------------------------------------------===// - -bool -MipsTargetLowering::CanLowerReturn(CallingConv::ID CallConv, - MachineFunction &MF, bool IsVarArg, - const SmallVectorImpl<ISD::OutputArg> &Outs, - LLVMContext &Context) const { - SmallVector<CCValAssign, 16> RVLocs; - MipsCCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context); - return CCInfo.CheckReturn(Outs, RetCC_Mips); -} - -bool -MipsTargetLowering::shouldSignExtendTypeInLibCall(EVT Type, bool IsSigned) const { - if ((ABI.IsN32() || ABI.IsN64()) && Type == MVT::i32) - return true; - - return IsSigned; -} - -SDValue -MipsTargetLowering::LowerInterruptReturn(SmallVectorImpl<SDValue> &RetOps, - const SDLoc &DL, - SelectionDAG &DAG) const { - MachineFunction &MF = DAG.getMachineFunction(); - MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); - - MipsFI->setISR(); - - return DAG.getNode(MipsISD::ERet, DL, MVT::Other, RetOps); -} - -SDValue -MipsTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, - bool IsVarArg, - const SmallVectorImpl<ISD::OutputArg> &Outs, - const SmallVectorImpl<SDValue> &OutVals, - const SDLoc &DL, SelectionDAG &DAG) const { - // CCValAssign - represent the assignment of - // the return value to a location - SmallVector<CCValAssign, 16> RVLocs; - MachineFunction &MF = DAG.getMachineFunction(); - - // CCState - Info about the registers and stack slot. - MipsCCState CCInfo(CallConv, IsVarArg, MF, RVLocs, *DAG.getContext()); - - // Analyze return values. - CCInfo.AnalyzeReturn(Outs, RetCC_Mips); - - SDValue Flag; - SmallVector<SDValue, 4> RetOps(1, Chain); - - // Copy the result values into the output registers. - for (unsigned i = 0; i != RVLocs.size(); ++i) { - SDValue Val = OutVals[i]; - CCValAssign &VA = RVLocs[i]; - assert(VA.isRegLoc() && "Can only return in registers!"); - bool UseUpperBits = false; - - switch (VA.getLocInfo()) { - default: - llvm_unreachable("Unknown loc info!"); - case CCValAssign::Full: - break; - case CCValAssign::BCvt: - Val = DAG.getNode(ISD::BITCAST, DL, VA.getLocVT(), Val); - break; - case CCValAssign::AExtUpper: - UseUpperBits = true; - LLVM_FALLTHROUGH; - case CCValAssign::AExt: - Val = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), Val); - break; - case CCValAssign::ZExtUpper: - UseUpperBits = true; - LLVM_FALLTHROUGH; - case CCValAssign::ZExt: - Val = DAG.getNode(ISD::ZERO_EXTEND, DL, VA.getLocVT(), Val); - break; - case CCValAssign::SExtUpper: - UseUpperBits = true; - LLVM_FALLTHROUGH; - case CCValAssign::SExt: - Val = DAG.getNode(ISD::SIGN_EXTEND, DL, VA.getLocVT(), Val); - break; - } - - if (UseUpperBits) { - unsigned ValSizeInBits = Outs[i].ArgVT.getSizeInBits(); - unsigned LocSizeInBits = VA.getLocVT().getSizeInBits(); - Val = DAG.getNode( - ISD::SHL, DL, VA.getLocVT(), Val, - DAG.getConstant(LocSizeInBits - ValSizeInBits, DL, VA.getLocVT())); - } - - Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Val, Flag); - - // Guarantee that all emitted copies are stuck together with flags. - Flag = Chain.getValue(1); - RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); - } - - // The mips ABIs for returning structs by value requires that we copy - // the sret argument into $v0 for the return. We saved the argument into - // a virtual register in the entry block, so now we copy the value out - // and into $v0. - if (MF.getFunction().hasStructRetAttr()) { - MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); - unsigned Reg = MipsFI->getSRetReturnReg(); - - if (!Reg) - llvm_unreachable("sret virtual register not created in the entry block"); - SDValue Val = - DAG.getCopyFromReg(Chain, DL, Reg, getPointerTy(DAG.getDataLayout())); - unsigned V0 = ABI.IsN64() ? Mips::V0_64 : Mips::V0; - - Chain = DAG.getCopyToReg(Chain, DL, V0, Val, Flag); - Flag = Chain.getValue(1); - RetOps.push_back(DAG.getRegister(V0, getPointerTy(DAG.getDataLayout()))); - } - - RetOps[0] = Chain; // Update chain. - - // Add the flag if we have it. - if (Flag.getNode()) - RetOps.push_back(Flag); - - // ISRs must use "eret". - if (DAG.getMachineFunction().getFunction().hasFnAttribute("interrupt")) - return LowerInterruptReturn(RetOps, DL, DAG); - - // Standard return on Mips is a "jr $ra" - return DAG.getNode(MipsISD::Ret, DL, MVT::Other, RetOps); -} - -//===----------------------------------------------------------------------===// -// Mips Inline Assembly Support -//===----------------------------------------------------------------------===// - -/// getConstraintType - Given a constraint letter, return the type of -/// constraint it is for this target. -MipsTargetLowering::ConstraintType -MipsTargetLowering::getConstraintType(StringRef Constraint) const { - // Mips specific constraints - // GCC config/mips/constraints.md - // - // 'd' : An address register. Equivalent to r - // unless generating MIPS16 code. - // 'y' : Equivalent to r; retained for - // backwards compatibility. - // 'c' : A register suitable for use in an indirect - // jump. This will always be $25 for -mabicalls. - // 'l' : The lo register. 1 word storage. - // 'x' : The hilo register pair. Double word storage. - if (Constraint.size() == 1) { - switch (Constraint[0]) { - default : break; - case 'd': - case 'y': - case 'f': - case 'c': - case 'l': - case 'x': - return C_RegisterClass; - case 'R': - return C_Memory; - } - } - - if (Constraint == "ZC") - return C_Memory; - - return TargetLowering::getConstraintType(Constraint); -} - -/// Examine constraint type and operand type and determine a weight value. -/// This object must already have been set up with the operand type -/// and the current alternative constraint selected. -TargetLowering::ConstraintWeight -MipsTargetLowering::getSingleConstraintMatchWeight( - AsmOperandInfo &info, const char *constraint) const { - ConstraintWeight weight = CW_Invalid; - Value *CallOperandVal = info.CallOperandVal; - // If we don't have a value, we can't do a match, - // but allow it at the lowest weight. - if (!CallOperandVal) - return CW_Default; - Type *type = CallOperandVal->getType(); - // Look at the constraint type. - switch (*constraint) { - default: - weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint); - break; - case 'd': - case 'y': - if (type->isIntegerTy()) - weight = CW_Register; - break; - case 'f': // FPU or MSA register - if (Subtarget.hasMSA() && type->isVectorTy() && - cast<VectorType>(type)->getBitWidth() == 128) - weight = CW_Register; - else if (type->isFloatTy()) - weight = CW_Register; - break; - case 'c': // $25 for indirect jumps - case 'l': // lo register - case 'x': // hilo register pair - if (type->isIntegerTy()) - weight = CW_SpecificReg; - break; - case 'I': // signed 16 bit immediate - case 'J': // integer zero - case 'K': // unsigned 16 bit immediate - case 'L': // signed 32 bit immediate where lower 16 bits are 0 - case 'N': // immediate in the range of -65535 to -1 (inclusive) - case 'O': // signed 15 bit immediate (+- 16383) - case 'P': // immediate in the range of 65535 to 1 (inclusive) - if (isa<ConstantInt>(CallOperandVal)) - weight = CW_Constant; - break; - case 'R': - weight = CW_Memory; - break; - } - return weight; -} - -/// This is a helper function to parse a physical register string and split it -/// into non-numeric and numeric parts (Prefix and Reg). The first boolean flag -/// that is returned indicates whether parsing was successful. The second flag -/// is true if the numeric part exists. -static std::pair<bool, bool> parsePhysicalReg(StringRef C, StringRef &Prefix, - unsigned long long &Reg) { - if (C.front() != '{' || C.back() != '}') - return std::make_pair(false, false); - - // Search for the first numeric character. - StringRef::const_iterator I, B = C.begin() + 1, E = C.end() - 1; - I = std::find_if(B, E, isdigit); - - Prefix = StringRef(B, I - B); - - // The second flag is set to false if no numeric characters were found. - if (I == E) - return std::make_pair(true, false); - - // Parse the numeric characters. - return std::make_pair(!getAsUnsignedInteger(StringRef(I, E - I), 10, Reg), - true); -} - -EVT MipsTargetLowering::getTypeForExtReturn(LLVMContext &Context, EVT VT, - ISD::NodeType) const { - bool Cond = !Subtarget.isABI_O32() && VT.getSizeInBits() == 32; - EVT MinVT = getRegisterType(Context, Cond ? MVT::i64 : MVT::i32); - return VT.bitsLT(MinVT) ? MinVT : VT; -} - -std::pair<unsigned, const TargetRegisterClass *> MipsTargetLowering:: -parseRegForInlineAsmConstraint(StringRef C, MVT VT) const { - const TargetRegisterInfo *TRI = - Subtarget.getRegisterInfo(); - const TargetRegisterClass *RC; - StringRef Prefix; - unsigned long long Reg; - - std::pair<bool, bool> R = parsePhysicalReg(C, Prefix, Reg); - - if (!R.first) - return std::make_pair(0U, nullptr); - - if ((Prefix == "hi" || Prefix == "lo")) { // Parse hi/lo. - // No numeric characters follow "hi" or "lo". - if (R.second) - return std::make_pair(0U, nullptr); - - RC = TRI->getRegClass(Prefix == "hi" ? - Mips::HI32RegClassID : Mips::LO32RegClassID); - return std::make_pair(*(RC->begin()), RC); - } else if (Prefix.startswith("$msa")) { - // Parse $msa(ir|csr|access|save|modify|request|map|unmap) - - // No numeric characters follow the name. - if (R.second) - return std::make_pair(0U, nullptr); - - Reg = StringSwitch<unsigned long long>(Prefix) - .Case("$msair", Mips::MSAIR) - .Case("$msacsr", Mips::MSACSR) - .Case("$msaaccess", Mips::MSAAccess) - .Case("$msasave", Mips::MSASave) - .Case("$msamodify", Mips::MSAModify) - .Case("$msarequest", Mips::MSARequest) - .Case("$msamap", Mips::MSAMap) - .Case("$msaunmap", Mips::MSAUnmap) - .Default(0); - - if (!Reg) - return std::make_pair(0U, nullptr); - - RC = TRI->getRegClass(Mips::MSACtrlRegClassID); - return std::make_pair(Reg, RC); - } - - if (!R.second) - return std::make_pair(0U, nullptr); - - if (Prefix == "$f") { // Parse $f0-$f31. - // If the size of FP registers is 64-bit or Reg is an even number, select - // the 64-bit register class. Otherwise, select the 32-bit register class. - if (VT == MVT::Other) - VT = (Subtarget.isFP64bit() || !(Reg % 2)) ? MVT::f64 : MVT::f32; - - RC = getRegClassFor(VT); - - if (RC == &Mips::AFGR64RegClass) { - assert(Reg % 2 == 0); - Reg >>= 1; - } - } else if (Prefix == "$fcc") // Parse $fcc0-$fcc7. - RC = TRI->getRegClass(Mips::FCCRegClassID); - else if (Prefix == "$w") { // Parse $w0-$w31. - RC = getRegClassFor((VT == MVT::Other) ? MVT::v16i8 : VT); - } else { // Parse $0-$31. - assert(Prefix == "$"); - RC = getRegClassFor((VT == MVT::Other) ? MVT::i32 : VT); - } - - assert(Reg < RC->getNumRegs()); - return std::make_pair(*(RC->begin() + Reg), RC); -} - -/// Given a register class constraint, like 'r', if this corresponds directly -/// to an LLVM register class, return a register of 0 and the register class -/// pointer. -std::pair<unsigned, const TargetRegisterClass *> -MipsTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, - StringRef Constraint, - MVT VT) const { - if (Constraint.size() == 1) { - switch (Constraint[0]) { - case 'd': // Address register. Same as 'r' unless generating MIPS16 code. - case 'y': // Same as 'r'. Exists for compatibility. - case 'r': - if (VT == MVT::i32 || VT == MVT::i16 || VT == MVT::i8) { - if (Subtarget.inMips16Mode()) - return std::make_pair(0U, &Mips::CPU16RegsRegClass); - return std::make_pair(0U, &Mips::GPR32RegClass); - } - if (VT == MVT::i64 && !Subtarget.isGP64bit()) - return std::make_pair(0U, &Mips::GPR32RegClass); - if (VT == MVT::i64 && Subtarget.isGP64bit()) - return std::make_pair(0U, &Mips::GPR64RegClass); - // This will generate an error message - return std::make_pair(0U, nullptr); - case 'f': // FPU or MSA register - if (VT == MVT::v16i8) - return std::make_pair(0U, &Mips::MSA128BRegClass); - else if (VT == MVT::v8i16 || VT == MVT::v8f16) - return std::make_pair(0U, &Mips::MSA128HRegClass); - else if (VT == MVT::v4i32 || VT == MVT::v4f32) - return std::make_pair(0U, &Mips::MSA128WRegClass); - else if (VT == MVT::v2i64 || VT == MVT::v2f64) - return std::make_pair(0U, &Mips::MSA128DRegClass); - else if (VT == MVT::f32) - return std::make_pair(0U, &Mips::FGR32RegClass); - else if ((VT == MVT::f64) && (!Subtarget.isSingleFloat())) { - if (Subtarget.isFP64bit()) - return std::make_pair(0U, &Mips::FGR64RegClass); - return std::make_pair(0U, &Mips::AFGR64RegClass); - } - break; - case 'c': // register suitable for indirect jump - if (VT == MVT::i32) - return std::make_pair((unsigned)Mips::T9, &Mips::GPR32RegClass); - if (VT == MVT::i64) - return std::make_pair((unsigned)Mips::T9_64, &Mips::GPR64RegClass); - // This will generate an error message - return std::make_pair(0U, nullptr); - case 'l': // use the `lo` register to store values - // that are no bigger than a word - if (VT == MVT::i32 || VT == MVT::i16 || VT == MVT::i8) - return std::make_pair((unsigned)Mips::LO0, &Mips::LO32RegClass); - return std::make_pair((unsigned)Mips::LO0_64, &Mips::LO64RegClass); - case 'x': // use the concatenated `hi` and `lo` registers - // to store doubleword values - // Fixme: Not triggering the use of both hi and low - // This will generate an error message - return std::make_pair(0U, nullptr); - } - } - - std::pair<unsigned, const TargetRegisterClass *> R; - R = parseRegForInlineAsmConstraint(Constraint, VT); - - if (R.second) - return R; - - return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT); -} - -/// LowerAsmOperandForConstraint - Lower the specified operand into the Ops -/// vector. If it is invalid, don't add anything to Ops. -void MipsTargetLowering::LowerAsmOperandForConstraint(SDValue Op, - std::string &Constraint, - std::vector<SDValue>&Ops, - SelectionDAG &DAG) const { - SDLoc DL(Op); - SDValue Result; - - // Only support length 1 constraints for now. - if (Constraint.length() > 1) return; - - char ConstraintLetter = Constraint[0]; - switch (ConstraintLetter) { - default: break; // This will fall through to the generic implementation - case 'I': // Signed 16 bit constant - // If this fails, the parent routine will give an error - if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) { - EVT Type = Op.getValueType(); - int64_t Val = C->getSExtValue(); - if (isInt<16>(Val)) { - Result = DAG.getTargetConstant(Val, DL, Type); - break; - } - } - return; - case 'J': // integer zero - if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) { - EVT Type = Op.getValueType(); - int64_t Val = C->getZExtValue(); - if (Val == 0) { - Result = DAG.getTargetConstant(0, DL, Type); - break; - } - } - return; - case 'K': // unsigned 16 bit immediate - if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) { - EVT Type = Op.getValueType(); - uint64_t Val = (uint64_t)C->getZExtValue(); - if (isUInt<16>(Val)) { - Result = DAG.getTargetConstant(Val, DL, Type); - break; - } - } - return; - case 'L': // signed 32 bit immediate where lower 16 bits are 0 - if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) { - EVT Type = Op.getValueType(); - int64_t Val = C->getSExtValue(); - if ((isInt<32>(Val)) && ((Val & 0xffff) == 0)){ - Result = DAG.getTargetConstant(Val, DL, Type); - break; - } - } - return; - case 'N': // immediate in the range of -65535 to -1 (inclusive) - if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) { - EVT Type = Op.getValueType(); - int64_t Val = C->getSExtValue(); - if ((Val >= -65535) && (Val <= -1)) { - Result = DAG.getTargetConstant(Val, DL, Type); - break; - } - } - return; - case 'O': // signed 15 bit immediate - if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) { - EVT Type = Op.getValueType(); - int64_t Val = C->getSExtValue(); - if ((isInt<15>(Val))) { - Result = DAG.getTargetConstant(Val, DL, Type); - break; - } - } - return; - case 'P': // immediate in the range of 1 to 65535 (inclusive) - if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) { - EVT Type = Op.getValueType(); - int64_t Val = C->getSExtValue(); - if ((Val <= 65535) && (Val >= 1)) { - Result = DAG.getTargetConstant(Val, DL, Type); - break; - } - } - return; - } - - if (Result.getNode()) { - Ops.push_back(Result); - return; - } - - TargetLowering::LowerAsmOperandForConstraint(Op, Constraint, Ops, DAG); -} - -bool MipsTargetLowering::isLegalAddressingMode(const DataLayout &DL, - const AddrMode &AM, Type *Ty, - unsigned AS, Instruction *I) const { - // No global is ever allowed as a base. - if (AM.BaseGV) - return false; - - switch (AM.Scale) { - case 0: // "r+i" or just "i", depending on HasBaseReg. - break; - case 1: - if (!AM.HasBaseReg) // allow "r+i". - break; - return false; // disallow "r+r" or "r+r+i". - default: - return false; - } - - return true; -} - -bool -MipsTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const { - // The Mips target isn't yet aware of offsets. - return false; -} - -EVT MipsTargetLowering::getOptimalMemOpType( - uint64_t Size, unsigned DstAlign, unsigned SrcAlign, bool IsMemset, - bool ZeroMemset, bool MemcpyStrSrc, - const AttributeList &FuncAttributes) const { - if (Subtarget.hasMips64()) - return MVT::i64; - - return MVT::i32; -} - -bool MipsTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT, - bool ForCodeSize) const { - if (VT != MVT::f32 && VT != MVT::f64) - return false; - if (Imm.isNegZero()) - return false; - return Imm.isZero(); -} - -unsigned MipsTargetLowering::getJumpTableEncoding() const { - - // FIXME: For space reasons this should be: EK_GPRel32BlockAddress. - if (ABI.IsN64() && isPositionIndependent()) - return MachineJumpTableInfo::EK_GPRel64BlockAddress; - - return TargetLowering::getJumpTableEncoding(); -} - -bool MipsTargetLowering::useSoftFloat() const { - return Subtarget.useSoftFloat(); -} - -void MipsTargetLowering::copyByValRegs( - SDValue Chain, const SDLoc &DL, std::vector<SDValue> &OutChains, - SelectionDAG &DAG, const ISD::ArgFlagsTy &Flags, - SmallVectorImpl<SDValue> &InVals, const Argument *FuncArg, - unsigned FirstReg, unsigned LastReg, const CCValAssign &VA, - MipsCCState &State) const { - MachineFunction &MF = DAG.getMachineFunction(); - MachineFrameInfo &MFI = MF.getFrameInfo(); - unsigned GPRSizeInBytes = Subtarget.getGPRSizeInBytes(); - unsigned NumRegs = LastReg - FirstReg; - unsigned RegAreaSize = NumRegs * GPRSizeInBytes; - unsigned FrameObjSize = std::max(Flags.getByValSize(), RegAreaSize); - int FrameObjOffset; - ArrayRef<MCPhysReg> ByValArgRegs = ABI.GetByValArgRegs(); - - if (RegAreaSize) - FrameObjOffset = - (int)ABI.GetCalleeAllocdArgSizeInBytes(State.getCallingConv()) - - (int)((ByValArgRegs.size() - FirstReg) * GPRSizeInBytes); - else - FrameObjOffset = VA.getLocMemOffset(); - - // Create frame object. - EVT PtrTy = getPointerTy(DAG.getDataLayout()); - // Make the fixed object stored to mutable so that the load instructions - // referencing it have their memory dependencies added. - // Set the frame object as isAliased which clears the underlying objects - // vector in ScheduleDAGInstrs::buildSchedGraph() resulting in addition of all - // stores as dependencies for loads referencing this fixed object. - int FI = MFI.CreateFixedObject(FrameObjSize, FrameObjOffset, false, true); - SDValue FIN = DAG.getFrameIndex(FI, PtrTy); - InVals.push_back(FIN); - - if (!NumRegs) - return; - - // Copy arg registers. - MVT RegTy = MVT::getIntegerVT(GPRSizeInBytes * 8); - const TargetRegisterClass *RC = getRegClassFor(RegTy); - - for (unsigned I = 0; I < NumRegs; ++I) { - unsigned ArgReg = ByValArgRegs[FirstReg + I]; - unsigned VReg = addLiveIn(MF, ArgReg, RC); - unsigned Offset = I * GPRSizeInBytes; - SDValue StorePtr = DAG.getNode(ISD::ADD, DL, PtrTy, FIN, - DAG.getConstant(Offset, DL, PtrTy)); - SDValue Store = DAG.getStore(Chain, DL, DAG.getRegister(VReg, RegTy), - StorePtr, MachinePointerInfo(FuncArg, Offset)); - OutChains.push_back(Store); - } -} - -// Copy byVal arg to registers and stack. -void MipsTargetLowering::passByValArg( - SDValue Chain, const SDLoc &DL, - std::deque<std::pair<unsigned, SDValue>> &RegsToPass, - SmallVectorImpl<SDValue> &MemOpChains, SDValue StackPtr, - MachineFrameInfo &MFI, SelectionDAG &DAG, SDValue Arg, unsigned FirstReg, - unsigned LastReg, const ISD::ArgFlagsTy &Flags, bool isLittle, - const CCValAssign &VA) const { - unsigned ByValSizeInBytes = Flags.getByValSize(); - unsigned OffsetInBytes = 0; // From beginning of struct - unsigned RegSizeInBytes = Subtarget.getGPRSizeInBytes(); - unsigned Alignment = std::min(Flags.getByValAlign(), RegSizeInBytes); - EVT PtrTy = getPointerTy(DAG.getDataLayout()), - RegTy = MVT::getIntegerVT(RegSizeInBytes * 8); - unsigned NumRegs = LastReg - FirstReg; - - if (NumRegs) { - ArrayRef<MCPhysReg> ArgRegs = ABI.GetByValArgRegs(); - bool LeftoverBytes = (NumRegs * RegSizeInBytes > ByValSizeInBytes); - unsigned I = 0; - - // Copy words to registers. - for (; I < NumRegs - LeftoverBytes; ++I, OffsetInBytes += RegSizeInBytes) { - SDValue LoadPtr = DAG.getNode(ISD::ADD, DL, PtrTy, Arg, - DAG.getConstant(OffsetInBytes, DL, PtrTy)); - SDValue LoadVal = DAG.getLoad(RegTy, DL, Chain, LoadPtr, - MachinePointerInfo(), Alignment); - MemOpChains.push_back(LoadVal.getValue(1)); - unsigned ArgReg = ArgRegs[FirstReg + I]; - RegsToPass.push_back(std::make_pair(ArgReg, LoadVal)); - } - - // Return if the struct has been fully copied. - if (ByValSizeInBytes == OffsetInBytes) - return; - - // Copy the remainder of the byval argument with sub-word loads and shifts. - if (LeftoverBytes) { - SDValue Val; - - for (unsigned LoadSizeInBytes = RegSizeInBytes / 2, TotalBytesLoaded = 0; - OffsetInBytes < ByValSizeInBytes; LoadSizeInBytes /= 2) { - unsigned RemainingSizeInBytes = ByValSizeInBytes - OffsetInBytes; - - if (RemainingSizeInBytes < LoadSizeInBytes) - continue; - - // Load subword. - SDValue LoadPtr = DAG.getNode(ISD::ADD, DL, PtrTy, Arg, - DAG.getConstant(OffsetInBytes, DL, - PtrTy)); - SDValue LoadVal = DAG.getExtLoad( - ISD::ZEXTLOAD, DL, RegTy, Chain, LoadPtr, MachinePointerInfo(), - MVT::getIntegerVT(LoadSizeInBytes * 8), Alignment); - MemOpChains.push_back(LoadVal.getValue(1)); - - // Shift the loaded value. - unsigned Shamt; - - if (isLittle) - Shamt = TotalBytesLoaded * 8; - else - Shamt = (RegSizeInBytes - (TotalBytesLoaded + LoadSizeInBytes)) * 8; - - SDValue Shift = DAG.getNode(ISD::SHL, DL, RegTy, LoadVal, - DAG.getConstant(Shamt, DL, MVT::i32)); - - if (Val.getNode()) - Val = DAG.getNode(ISD::OR, DL, RegTy, Val, Shift); - else - Val = Shift; - - OffsetInBytes += LoadSizeInBytes; - TotalBytesLoaded += LoadSizeInBytes; - Alignment = std::min(Alignment, LoadSizeInBytes); - } - - unsigned ArgReg = ArgRegs[FirstReg + I]; - RegsToPass.push_back(std::make_pair(ArgReg, Val)); - return; - } - } - - // Copy remainder of byval arg to it with memcpy. - unsigned MemCpySize = ByValSizeInBytes - OffsetInBytes; - SDValue Src = DAG.getNode(ISD::ADD, DL, PtrTy, Arg, - DAG.getConstant(OffsetInBytes, DL, PtrTy)); - SDValue Dst = DAG.getNode(ISD::ADD, DL, PtrTy, StackPtr, - DAG.getIntPtrConstant(VA.getLocMemOffset(), DL)); - Chain = DAG.getMemcpy(Chain, DL, Dst, Src, - DAG.getConstant(MemCpySize, DL, PtrTy), - Alignment, /*isVolatile=*/false, /*AlwaysInline=*/false, - /*isTailCall=*/false, - MachinePointerInfo(), MachinePointerInfo()); - MemOpChains.push_back(Chain); -} - -void MipsTargetLowering::writeVarArgRegs(std::vector<SDValue> &OutChains, - SDValue Chain, const SDLoc &DL, - SelectionDAG &DAG, - CCState &State) const { - ArrayRef<MCPhysReg> ArgRegs = ABI.GetVarArgRegs(); - unsigned Idx = State.getFirstUnallocated(ArgRegs); - unsigned RegSizeInBytes = Subtarget.getGPRSizeInBytes(); - MVT RegTy = MVT::getIntegerVT(RegSizeInBytes * 8); - const TargetRegisterClass *RC = getRegClassFor(RegTy); - MachineFunction &MF = DAG.getMachineFunction(); - MachineFrameInfo &MFI = MF.getFrameInfo(); - MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); - - // Offset of the first variable argument from stack pointer. - int VaArgOffset; - - if (ArgRegs.size() == Idx) - VaArgOffset = alignTo(State.getNextStackOffset(), RegSizeInBytes); - else { - VaArgOffset = - (int)ABI.GetCalleeAllocdArgSizeInBytes(State.getCallingConv()) - - (int)(RegSizeInBytes * (ArgRegs.size() - Idx)); - } - - // Record the frame index of the first variable argument - // which is a value necessary to VASTART. - int FI = MFI.CreateFixedObject(RegSizeInBytes, VaArgOffset, true); - MipsFI->setVarArgsFrameIndex(FI); - - // Copy the integer registers that have not been used for argument passing - // to the argument register save area. For O32, the save area is allocated - // in the caller's stack frame, while for N32/64, it is allocated in the - // callee's stack frame. - for (unsigned I = Idx; I < ArgRegs.size(); - ++I, VaArgOffset += RegSizeInBytes) { - unsigned Reg = addLiveIn(MF, ArgRegs[I], RC); - SDValue ArgValue = DAG.getCopyFromReg(Chain, DL, Reg, RegTy); - FI = MFI.CreateFixedObject(RegSizeInBytes, VaArgOffset, true); - SDValue PtrOff = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout())); - SDValue Store = - DAG.getStore(Chain, DL, ArgValue, PtrOff, MachinePointerInfo()); - cast<StoreSDNode>(Store.getNode())->getMemOperand()->setValue( - (Value *)nullptr); - OutChains.push_back(Store); - } -} - -void MipsTargetLowering::HandleByVal(CCState *State, unsigned &Size, - unsigned Align) const { - const TargetFrameLowering *TFL = Subtarget.getFrameLowering(); - - assert(Size && "Byval argument's size shouldn't be 0."); - - Align = std::min(Align, TFL->getStackAlignment()); - - unsigned FirstReg = 0; - unsigned NumRegs = 0; - - if (State->getCallingConv() != CallingConv::Fast) { - unsigned RegSizeInBytes = Subtarget.getGPRSizeInBytes(); - ArrayRef<MCPhysReg> IntArgRegs = ABI.GetByValArgRegs(); - // FIXME: The O32 case actually describes no shadow registers. - const MCPhysReg *ShadowRegs = - ABI.IsO32() ? IntArgRegs.data() : Mips64DPRegs; - - // We used to check the size as well but we can't do that anymore since - // CCState::HandleByVal() rounds up the size after calling this function. - assert(!(Align % RegSizeInBytes) && - "Byval argument's alignment should be a multiple of" - "RegSizeInBytes."); - - FirstReg = State->getFirstUnallocated(IntArgRegs); - - // If Align > RegSizeInBytes, the first arg register must be even. - // FIXME: This condition happens to do the right thing but it's not the - // right way to test it. We want to check that the stack frame offset - // of the register is aligned. - if ((Align > RegSizeInBytes) && (FirstReg % 2)) { - State->AllocateReg(IntArgRegs[FirstReg], ShadowRegs[FirstReg]); - ++FirstReg; - } - - // Mark the registers allocated. - Size = alignTo(Size, RegSizeInBytes); - for (unsigned I = FirstReg; Size > 0 && (I < IntArgRegs.size()); - Size -= RegSizeInBytes, ++I, ++NumRegs) - State->AllocateReg(IntArgRegs[I], ShadowRegs[I]); - } - - State->addInRegsParamInfo(FirstReg, FirstReg + NumRegs); -} - -MachineBasicBlock *MipsTargetLowering::emitPseudoSELECT(MachineInstr &MI, - MachineBasicBlock *BB, - bool isFPCmp, - unsigned Opc) const { - assert(!(Subtarget.hasMips4() || Subtarget.hasMips32()) && - "Subtarget already supports SELECT nodes with the use of" - "conditional-move instructions."); - - const TargetInstrInfo *TII = - Subtarget.getInstrInfo(); - DebugLoc DL = MI.getDebugLoc(); - - // To "insert" a SELECT instruction, we actually have to insert the - // diamond control-flow pattern. The incoming instruction knows the - // destination vreg to set, the condition code register to branch on, the - // true/false values to select between, and a branch opcode to use. - const BasicBlock *LLVM_BB = BB->getBasicBlock(); - MachineFunction::iterator It = ++BB->getIterator(); - - // thisMBB: - // ... - // TrueVal = ... - // setcc r1, r2, r3 - // bNE r1, r0, copy1MBB - // fallthrough --> copy0MBB - MachineBasicBlock *thisMBB = BB; - MachineFunction *F = BB->getParent(); - MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB); - MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB); - F->insert(It, copy0MBB); - F->insert(It, sinkMBB); - - // Transfer the remainder of BB and its successor edges to sinkMBB. - sinkMBB->splice(sinkMBB->begin(), BB, - std::next(MachineBasicBlock::iterator(MI)), BB->end()); - sinkMBB->transferSuccessorsAndUpdatePHIs(BB); - - // Next, add the true and fallthrough blocks as its successors. - BB->addSuccessor(copy0MBB); - BB->addSuccessor(sinkMBB); - - if (isFPCmp) { - // bc1[tf] cc, sinkMBB - BuildMI(BB, DL, TII->get(Opc)) - .addReg(MI.getOperand(1).getReg()) - .addMBB(sinkMBB); - } else { - // bne rs, $0, sinkMBB - BuildMI(BB, DL, TII->get(Opc)) - .addReg(MI.getOperand(1).getReg()) - .addReg(Mips::ZERO) - .addMBB(sinkMBB); - } - - // copy0MBB: - // %FalseValue = ... - // # fallthrough to sinkMBB - BB = copy0MBB; - - // Update machine-CFG edges - BB->addSuccessor(sinkMBB); - - // sinkMBB: - // %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copy0MBB ] - // ... - BB = sinkMBB; - - BuildMI(*BB, BB->begin(), DL, TII->get(Mips::PHI), MI.getOperand(0).getReg()) - .addReg(MI.getOperand(2).getReg()) - .addMBB(thisMBB) - .addReg(MI.getOperand(3).getReg()) - .addMBB(copy0MBB); - - MI.eraseFromParent(); // The pseudo instruction is gone now. - - return BB; -} - -MachineBasicBlock *MipsTargetLowering::emitPseudoD_SELECT(MachineInstr &MI, - MachineBasicBlock *BB) const { - assert(!(Subtarget.hasMips4() || Subtarget.hasMips32()) && - "Subtarget already supports SELECT nodes with the use of" - "conditional-move instructions."); - - const TargetInstrInfo *TII = Subtarget.getInstrInfo(); - DebugLoc DL = MI.getDebugLoc(); - - // D_SELECT substitutes two SELECT nodes that goes one after another and - // have the same condition operand. On machines which don't have - // conditional-move instruction, it reduces unnecessary branch instructions - // which are result of using two diamond patterns that are result of two - // SELECT pseudo instructions. - const BasicBlock *LLVM_BB = BB->getBasicBlock(); - MachineFunction::iterator It = ++BB->getIterator(); - - // thisMBB: - // ... - // TrueVal = ... - // setcc r1, r2, r3 - // bNE r1, r0, copy1MBB - // fallthrough --> copy0MBB - MachineBasicBlock *thisMBB = BB; - MachineFunction *F = BB->getParent(); - MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB); - MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB); - F->insert(It, copy0MBB); - F->insert(It, sinkMBB); - - // Transfer the remainder of BB and its successor edges to sinkMBB. - sinkMBB->splice(sinkMBB->begin(), BB, - std::next(MachineBasicBlock::iterator(MI)), BB->end()); - sinkMBB->transferSuccessorsAndUpdatePHIs(BB); - - // Next, add the true and fallthrough blocks as its successors. - BB->addSuccessor(copy0MBB); - BB->addSuccessor(sinkMBB); - - // bne rs, $0, sinkMBB - BuildMI(BB, DL, TII->get(Mips::BNE)) - .addReg(MI.getOperand(2).getReg()) - .addReg(Mips::ZERO) - .addMBB(sinkMBB); - - // copy0MBB: - // %FalseValue = ... - // # fallthrough to sinkMBB - BB = copy0MBB; - - // Update machine-CFG edges - BB->addSuccessor(sinkMBB); - - // sinkMBB: - // %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copy0MBB ] - // ... - BB = sinkMBB; - - // Use two PHI nodes to select two reults - BuildMI(*BB, BB->begin(), DL, TII->get(Mips::PHI), MI.getOperand(0).getReg()) - .addReg(MI.getOperand(3).getReg()) - .addMBB(thisMBB) - .addReg(MI.getOperand(5).getReg()) - .addMBB(copy0MBB); - BuildMI(*BB, BB->begin(), DL, TII->get(Mips::PHI), MI.getOperand(1).getReg()) - .addReg(MI.getOperand(4).getReg()) - .addMBB(thisMBB) - .addReg(MI.getOperand(6).getReg()) - .addMBB(copy0MBB); - - MI.eraseFromParent(); // The pseudo instruction is gone now. - - return BB; -} - -// FIXME? Maybe this could be a TableGen attribute on some registers and -// this table could be generated automatically from RegInfo. -unsigned MipsTargetLowering::getRegisterByName(const char* RegName, EVT VT, - SelectionDAG &DAG) const { - // Named registers is expected to be fairly rare. For now, just support $28 - // since the linux kernel uses it. - if (Subtarget.isGP64bit()) { - unsigned Reg = StringSwitch<unsigned>(RegName) - .Case("$28", Mips::GP_64) - .Default(0); - if (Reg) - return Reg; - } else { - unsigned Reg = StringSwitch<unsigned>(RegName) - .Case("$28", Mips::GP) - .Default(0); - if (Reg) - return Reg; - } - report_fatal_error("Invalid register name global variable"); -} diff --git a/contrib/llvm/lib/Target/Mips/MipsISelLowering.h b/contrib/llvm/lib/Target/Mips/MipsISelLowering.h deleted file mode 100644 index 2db60e9801f1..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsISelLowering.h +++ /dev/null @@ -1,730 +0,0 @@ -//===- MipsISelLowering.h - Mips DAG Lowering Interface ---------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the interfaces that Mips uses to lower LLVM code into a -// selection DAG. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_MIPS_MIPSISELLOWERING_H -#define LLVM_LIB_TARGET_MIPS_MIPSISELLOWERING_H - -#include "MCTargetDesc/MipsABIInfo.h" -#include "MCTargetDesc/MipsBaseInfo.h" -#include "MCTargetDesc/MipsMCTargetDesc.h" -#include "Mips.h" -#include "llvm/CodeGen/CallingConvLower.h" -#include "llvm/CodeGen/ISDOpcodes.h" -#include "llvm/CodeGen/MachineMemOperand.h" -#include "llvm/CodeGen/SelectionDAG.h" -#include "llvm/CodeGen/SelectionDAGNodes.h" -#include "llvm/CodeGen/TargetLowering.h" -#include "llvm/CodeGen/ValueTypes.h" -#include "llvm/IR/CallingConv.h" -#include "llvm/IR/InlineAsm.h" -#include "llvm/IR/Type.h" -#include "llvm/Support/MachineValueType.h" -#include "llvm/Target/TargetMachine.h" -#include <algorithm> -#include <cassert> -#include <deque> -#include <string> -#include <utility> -#include <vector> - -namespace llvm { - -class Argument; -class CCState; -class CCValAssign; -class FastISel; -class FunctionLoweringInfo; -class MachineBasicBlock; -class MachineFrameInfo; -class MachineInstr; -class MipsCCState; -class MipsFunctionInfo; -class MipsSubtarget; -class MipsTargetMachine; -class TargetLibraryInfo; -class TargetRegisterClass; - - namespace MipsISD { - - enum NodeType : unsigned { - // Start the numbering from where ISD NodeType finishes. - FIRST_NUMBER = ISD::BUILTIN_OP_END, - - // Jump and link (call) - JmpLink, - - // Tail call - TailCall, - - // Get the Highest (63-48) 16 bits from a 64-bit immediate - Highest, - - // Get the Higher (47-32) 16 bits from a 64-bit immediate - Higher, - - // Get the High 16 bits from a 32/64-bit immediate - // No relation with Mips Hi register - Hi, - - // Get the Lower 16 bits from a 32/64-bit immediate - // No relation with Mips Lo register - Lo, - - // Get the High 16 bits from a 32 bit immediate for accessing the GOT. - GotHi, - - // Get the High 16 bits from a 32-bit immediate for accessing TLS. - TlsHi, - - // Handle gp_rel (small data/bss sections) relocation. - GPRel, - - // Thread Pointer - ThreadPointer, - - // Vector Floating Point Multiply and Subtract - FMS, - - // Floating Point Branch Conditional - FPBrcond, - - // Floating Point Compare - FPCmp, - - // Floating point select - FSELECT, - - // Node used to generate an MTC1 i32 to f64 instruction - MTC1_D64, - - // Floating Point Conditional Moves - CMovFP_T, - CMovFP_F, - - // FP-to-int truncation node. - TruncIntFP, - - // Return - Ret, - - // Interrupt, exception, error trap Return - ERet, - - // Software Exception Return. - EH_RETURN, - - // Node used to extract integer from accumulator. - MFHI, - MFLO, - - // Node used to insert integers to accumulator. - MTLOHI, - - // Mult nodes. - Mult, - Multu, - - // MAdd/Sub nodes - MAdd, - MAddu, - MSub, - MSubu, - - // DivRem(u) - DivRem, - DivRemU, - DivRem16, - DivRemU16, - - BuildPairF64, - ExtractElementF64, - - Wrapper, - - DynAlloc, - - Sync, - - Ext, - Ins, - CIns, - - // EXTR.W instrinsic nodes. - EXTP, - EXTPDP, - EXTR_S_H, - EXTR_W, - EXTR_R_W, - EXTR_RS_W, - SHILO, - MTHLIP, - - // DPA.W intrinsic nodes. - MULSAQ_S_W_PH, - MAQ_S_W_PHL, - MAQ_S_W_PHR, - MAQ_SA_W_PHL, - MAQ_SA_W_PHR, - DPAU_H_QBL, - DPAU_H_QBR, - DPSU_H_QBL, - DPSU_H_QBR, - DPAQ_S_W_PH, - DPSQ_S_W_PH, - DPAQ_SA_L_W, - DPSQ_SA_L_W, - DPA_W_PH, - DPS_W_PH, - DPAQX_S_W_PH, - DPAQX_SA_W_PH, - DPAX_W_PH, - DPSX_W_PH, - DPSQX_S_W_PH, - DPSQX_SA_W_PH, - MULSA_W_PH, - - MULT, - MULTU, - MADD_DSP, - MADDU_DSP, - MSUB_DSP, - MSUBU_DSP, - - // DSP shift nodes. - SHLL_DSP, - SHRA_DSP, - SHRL_DSP, - - // DSP setcc and select_cc nodes. - SETCC_DSP, - SELECT_CC_DSP, - - // Vector comparisons. - // These take a vector and return a boolean. - VALL_ZERO, - VANY_ZERO, - VALL_NONZERO, - VANY_NONZERO, - - // These take a vector and return a vector bitmask. - VCEQ, - VCLE_S, - VCLE_U, - VCLT_S, - VCLT_U, - - // Vector Shuffle with mask as an operand - VSHF, // Generic shuffle - SHF, // 4-element set shuffle. - ILVEV, // Interleave even elements - ILVOD, // Interleave odd elements - ILVL, // Interleave left elements - ILVR, // Interleave right elements - PCKEV, // Pack even elements - PCKOD, // Pack odd elements - - // Vector Lane Copy - INSVE, // Copy element from one vector to another - - // Combined (XOR (OR $a, $b), -1) - VNOR, - - // Extended vector element extraction - VEXTRACT_SEXT_ELT, - VEXTRACT_ZEXT_ELT, - - // Load/Store Left/Right nodes. - LWL = ISD::FIRST_TARGET_MEMORY_OPCODE, - LWR, - SWL, - SWR, - LDL, - LDR, - SDL, - SDR - }; - - } // ene namespace MipsISD - - //===--------------------------------------------------------------------===// - // TargetLowering Implementation - //===--------------------------------------------------------------------===// - - class MipsTargetLowering : public TargetLowering { - bool isMicroMips; - - public: - explicit MipsTargetLowering(const MipsTargetMachine &TM, - const MipsSubtarget &STI); - - static const MipsTargetLowering *create(const MipsTargetMachine &TM, - const MipsSubtarget &STI); - - /// createFastISel - This method returns a target specific FastISel object, - /// or null if the target does not support "fast" ISel. - FastISel *createFastISel(FunctionLoweringInfo &funcInfo, - const TargetLibraryInfo *libInfo) const override; - - MVT getScalarShiftAmountTy(const DataLayout &, EVT) const override { - return MVT::i32; - } - - EVT getTypeForExtReturn(LLVMContext &Context, EVT VT, - ISD::NodeType) const override; - - bool isCheapToSpeculateCttz() const override; - bool isCheapToSpeculateCtlz() const override; - bool shouldFoldConstantShiftPairToMask(const SDNode *N, - CombineLevel Level) const override; - - /// Return the register type for a given MVT, ensuring vectors are treated - /// as a series of gpr sized integers. - MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, - EVT VT) const override; - - /// Return the number of registers for a given MVT, ensuring vectors are - /// treated as a series of gpr sized integers. - unsigned getNumRegistersForCallingConv(LLVMContext &Context, - CallingConv::ID CC, - EVT VT) const override; - - /// Break down vectors to the correct number of gpr sized integers. - unsigned getVectorTypeBreakdownForCallingConv( - LLVMContext &Context, CallingConv::ID CC, EVT VT, EVT &IntermediateVT, - unsigned &NumIntermediates, MVT &RegisterVT) const override; - - /// Return the correct alignment for the current calling convention. - unsigned getABIAlignmentForCallingConv(Type *ArgTy, - DataLayout DL) const override { - if (ArgTy->isVectorTy()) - return std::min(DL.getABITypeAlignment(ArgTy), 8U); - return DL.getABITypeAlignment(ArgTy); - } - - ISD::NodeType getExtendForAtomicOps() const override { - return ISD::SIGN_EXTEND; - } - - void LowerOperationWrapper(SDNode *N, - SmallVectorImpl<SDValue> &Results, - SelectionDAG &DAG) const override; - - /// LowerOperation - Provide custom lowering hooks for some operations. - SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override; - - /// ReplaceNodeResults - Replace the results of node with an illegal result - /// type with new values built out of custom code. - /// - void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue>&Results, - SelectionDAG &DAG) const override; - - /// getTargetNodeName - This method returns the name of a target specific - // DAG node. - const char *getTargetNodeName(unsigned Opcode) const override; - - /// getSetCCResultType - get the ISD::SETCC result ValueType - EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, - EVT VT) const override; - - SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override; - - MachineBasicBlock * - EmitInstrWithCustomInserter(MachineInstr &MI, - MachineBasicBlock *MBB) const override; - - void AdjustInstrPostInstrSelection(MachineInstr &MI, - SDNode *Node) const override; - - void HandleByVal(CCState *, unsigned &, unsigned) const override; - - unsigned getRegisterByName(const char* RegName, EVT VT, - SelectionDAG &DAG) const override; - - /// If a physical register, this returns the register that receives the - /// exception address on entry to an EH pad. - unsigned - getExceptionPointerRegister(const Constant *PersonalityFn) const override { - return ABI.IsN64() ? Mips::A0_64 : Mips::A0; - } - - /// If a physical register, this returns the register that receives the - /// exception typeid on entry to a landing pad. - unsigned - getExceptionSelectorRegister(const Constant *PersonalityFn) const override { - return ABI.IsN64() ? Mips::A1_64 : Mips::A1; - } - - /// Returns true if a cast between SrcAS and DestAS is a noop. - bool isNoopAddrSpaceCast(unsigned SrcAS, unsigned DestAS) const override { - // Mips doesn't have any special address spaces so we just reserve - // the first 256 for software use (e.g. OpenCL) and treat casts - // between them as noops. - return SrcAS < 256 && DestAS < 256; - } - - bool isJumpTableRelative() const override { - return getTargetMachine().isPositionIndependent(); - } - - CCAssignFn *CCAssignFnForCall() const; - - CCAssignFn *CCAssignFnForReturn() const; - - protected: - SDValue getGlobalReg(SelectionDAG &DAG, EVT Ty) const; - - // This method creates the following nodes, which are necessary for - // computing a local symbol's address: - // - // (add (load (wrapper $gp, %got(sym)), %lo(sym)) - template <class NodeTy> - SDValue getAddrLocal(NodeTy *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG, - bool IsN32OrN64) const { - unsigned GOTFlag = IsN32OrN64 ? MipsII::MO_GOT_PAGE : MipsII::MO_GOT; - SDValue GOT = DAG.getNode(MipsISD::Wrapper, DL, Ty, getGlobalReg(DAG, Ty), - getTargetNode(N, Ty, DAG, GOTFlag)); - SDValue Load = - DAG.getLoad(Ty, DL, DAG.getEntryNode(), GOT, - MachinePointerInfo::getGOT(DAG.getMachineFunction())); - unsigned LoFlag = IsN32OrN64 ? MipsII::MO_GOT_OFST : MipsII::MO_ABS_LO; - SDValue Lo = DAG.getNode(MipsISD::Lo, DL, Ty, - getTargetNode(N, Ty, DAG, LoFlag)); - return DAG.getNode(ISD::ADD, DL, Ty, Load, Lo); - } - - // This method creates the following nodes, which are necessary for - // computing a global symbol's address: - // - // (load (wrapper $gp, %got(sym))) - template <class NodeTy> - SDValue getAddrGlobal(NodeTy *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG, - unsigned Flag, SDValue Chain, - const MachinePointerInfo &PtrInfo) const { - SDValue Tgt = DAG.getNode(MipsISD::Wrapper, DL, Ty, getGlobalReg(DAG, Ty), - getTargetNode(N, Ty, DAG, Flag)); - return DAG.getLoad(Ty, DL, Chain, Tgt, PtrInfo); - } - - // This method creates the following nodes, which are necessary for - // computing a global symbol's address in large-GOT mode: - // - // (load (wrapper (add %hi(sym), $gp), %lo(sym))) - template <class NodeTy> - SDValue getAddrGlobalLargeGOT(NodeTy *N, const SDLoc &DL, EVT Ty, - SelectionDAG &DAG, unsigned HiFlag, - unsigned LoFlag, SDValue Chain, - const MachinePointerInfo &PtrInfo) const { - SDValue Hi = DAG.getNode(MipsISD::GotHi, DL, Ty, - getTargetNode(N, Ty, DAG, HiFlag)); - Hi = DAG.getNode(ISD::ADD, DL, Ty, Hi, getGlobalReg(DAG, Ty)); - SDValue Wrapper = DAG.getNode(MipsISD::Wrapper, DL, Ty, Hi, - getTargetNode(N, Ty, DAG, LoFlag)); - return DAG.getLoad(Ty, DL, Chain, Wrapper, PtrInfo); - } - - // This method creates the following nodes, which are necessary for - // computing a symbol's address in non-PIC mode: - // - // (add %hi(sym), %lo(sym)) - // - // This method covers O32, N32 and N64 in sym32 mode. - template <class NodeTy> - SDValue getAddrNonPIC(NodeTy *N, const SDLoc &DL, EVT Ty, - SelectionDAG &DAG) const { - SDValue Hi = getTargetNode(N, Ty, DAG, MipsII::MO_ABS_HI); - SDValue Lo = getTargetNode(N, Ty, DAG, MipsII::MO_ABS_LO); - return DAG.getNode(ISD::ADD, DL, Ty, - DAG.getNode(MipsISD::Hi, DL, Ty, Hi), - DAG.getNode(MipsISD::Lo, DL, Ty, Lo)); - } - - // This method creates the following nodes, which are necessary for - // computing a symbol's address in non-PIC mode for N64. - // - // (add (shl (add (shl (add %highest(sym), %higher(sim)), 16), %high(sym)), - // 16), %lo(%sym)) - // - // FIXME: This method is not efficent for (micro)MIPS64R6. - template <class NodeTy> - SDValue getAddrNonPICSym64(NodeTy *N, const SDLoc &DL, EVT Ty, - SelectionDAG &DAG) const { - SDValue Hi = getTargetNode(N, Ty, DAG, MipsII::MO_ABS_HI); - SDValue Lo = getTargetNode(N, Ty, DAG, MipsII::MO_ABS_LO); - - SDValue Highest = - DAG.getNode(MipsISD::Highest, DL, Ty, - getTargetNode(N, Ty, DAG, MipsII::MO_HIGHEST)); - SDValue Higher = getTargetNode(N, Ty, DAG, MipsII::MO_HIGHER); - SDValue HigherPart = - DAG.getNode(ISD::ADD, DL, Ty, Highest, - DAG.getNode(MipsISD::Higher, DL, Ty, Higher)); - SDValue Cst = DAG.getConstant(16, DL, MVT::i32); - SDValue Shift = DAG.getNode(ISD::SHL, DL, Ty, HigherPart, Cst); - SDValue Add = DAG.getNode(ISD::ADD, DL, Ty, Shift, - DAG.getNode(MipsISD::Hi, DL, Ty, Hi)); - SDValue Shift2 = DAG.getNode(ISD::SHL, DL, Ty, Add, Cst); - - return DAG.getNode(ISD::ADD, DL, Ty, Shift2, - DAG.getNode(MipsISD::Lo, DL, Ty, Lo)); - } - - // This method creates the following nodes, which are necessary for - // computing a symbol's address using gp-relative addressing: - // - // (add $gp, %gp_rel(sym)) - template <class NodeTy> - SDValue getAddrGPRel(NodeTy *N, const SDLoc &DL, EVT Ty, - SelectionDAG &DAG, bool IsN64) const { - SDValue GPRel = getTargetNode(N, Ty, DAG, MipsII::MO_GPREL); - return DAG.getNode( - ISD::ADD, DL, Ty, - DAG.getRegister(IsN64 ? Mips::GP_64 : Mips::GP, Ty), - DAG.getNode(MipsISD::GPRel, DL, DAG.getVTList(Ty), GPRel)); - } - - /// This function fills Ops, which is the list of operands that will later - /// be used when a function call node is created. It also generates - /// copyToReg nodes to set up argument registers. - virtual void - getOpndList(SmallVectorImpl<SDValue> &Ops, - std::deque<std::pair<unsigned, SDValue>> &RegsToPass, - bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage, - bool IsCallReloc, CallLoweringInfo &CLI, SDValue Callee, - SDValue Chain) const; - - protected: - SDValue lowerLOAD(SDValue Op, SelectionDAG &DAG) const; - SDValue lowerSTORE(SDValue Op, SelectionDAG &DAG) const; - - // Subtarget Info - const MipsSubtarget &Subtarget; - // Cache the ABI from the TargetMachine, we use it everywhere. - const MipsABIInfo &ABI; - - private: - // Create a TargetGlobalAddress node. - SDValue getTargetNode(GlobalAddressSDNode *N, EVT Ty, SelectionDAG &DAG, - unsigned Flag) const; - - // Create a TargetExternalSymbol node. - SDValue getTargetNode(ExternalSymbolSDNode *N, EVT Ty, SelectionDAG &DAG, - unsigned Flag) const; - - // Create a TargetBlockAddress node. - SDValue getTargetNode(BlockAddressSDNode *N, EVT Ty, SelectionDAG &DAG, - unsigned Flag) const; - - // Create a TargetJumpTable node. - SDValue getTargetNode(JumpTableSDNode *N, EVT Ty, SelectionDAG &DAG, - unsigned Flag) const; - - // Create a TargetConstantPool node. - SDValue getTargetNode(ConstantPoolSDNode *N, EVT Ty, SelectionDAG &DAG, - unsigned Flag) const; - - // Lower Operand helpers - SDValue LowerCallResult(SDValue Chain, SDValue InFlag, - CallingConv::ID CallConv, bool isVarArg, - const SmallVectorImpl<ISD::InputArg> &Ins, - const SDLoc &dl, SelectionDAG &DAG, - SmallVectorImpl<SDValue> &InVals, - TargetLowering::CallLoweringInfo &CLI) const; - - // Lower Operand specifics - SDValue lowerBRCOND(SDValue Op, SelectionDAG &DAG) const; - SDValue lowerConstantPool(SDValue Op, SelectionDAG &DAG) const; - SDValue lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const; - SDValue lowerBlockAddress(SDValue Op, SelectionDAG &DAG) const; - SDValue lowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const; - SDValue lowerJumpTable(SDValue Op, SelectionDAG &DAG) const; - SDValue lowerSELECT(SDValue Op, SelectionDAG &DAG) const; - SDValue lowerSETCC(SDValue Op, SelectionDAG &DAG) const; - SDValue lowerVASTART(SDValue Op, SelectionDAG &DAG) const; - SDValue lowerVAARG(SDValue Op, SelectionDAG &DAG) const; - SDValue lowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const; - SDValue lowerFABS(SDValue Op, SelectionDAG &DAG) const; - SDValue lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const; - SDValue lowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const; - SDValue lowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const; - SDValue lowerATOMIC_FENCE(SDValue Op, SelectionDAG& DAG) const; - SDValue lowerShiftLeftParts(SDValue Op, SelectionDAG& DAG) const; - SDValue lowerShiftRightParts(SDValue Op, SelectionDAG& DAG, - bool IsSRA) const; - SDValue lowerEH_DWARF_CFA(SDValue Op, SelectionDAG &DAG) const; - SDValue lowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) const; - - /// isEligibleForTailCallOptimization - Check whether the call is eligible - /// for tail call optimization. - virtual bool - isEligibleForTailCallOptimization(const CCState &CCInfo, - unsigned NextStackOffset, - const MipsFunctionInfo &FI) const = 0; - - /// copyByValArg - Copy argument registers which were used to pass a byval - /// argument to the stack. Create a stack frame object for the byval - /// argument. - void copyByValRegs(SDValue Chain, const SDLoc &DL, - std::vector<SDValue> &OutChains, SelectionDAG &DAG, - const ISD::ArgFlagsTy &Flags, - SmallVectorImpl<SDValue> &InVals, - const Argument *FuncArg, unsigned FirstReg, - unsigned LastReg, const CCValAssign &VA, - MipsCCState &State) const; - - /// passByValArg - Pass a byval argument in registers or on stack. - void passByValArg(SDValue Chain, const SDLoc &DL, - std::deque<std::pair<unsigned, SDValue>> &RegsToPass, - SmallVectorImpl<SDValue> &MemOpChains, SDValue StackPtr, - MachineFrameInfo &MFI, SelectionDAG &DAG, SDValue Arg, - unsigned FirstReg, unsigned LastReg, - const ISD::ArgFlagsTy &Flags, bool isLittle, - const CCValAssign &VA) const; - - /// writeVarArgRegs - Write variable function arguments passed in registers - /// to the stack. Also create a stack frame object for the first variable - /// argument. - void writeVarArgRegs(std::vector<SDValue> &OutChains, SDValue Chain, - const SDLoc &DL, SelectionDAG &DAG, - CCState &State) const; - - SDValue - LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, - const SmallVectorImpl<ISD::InputArg> &Ins, - const SDLoc &dl, SelectionDAG &DAG, - SmallVectorImpl<SDValue> &InVals) const override; - - SDValue passArgOnStack(SDValue StackPtr, unsigned Offset, SDValue Chain, - SDValue Arg, const SDLoc &DL, bool IsTailCall, - SelectionDAG &DAG) const; - - SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI, - SmallVectorImpl<SDValue> &InVals) const override; - - bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, - bool isVarArg, - const SmallVectorImpl<ISD::OutputArg> &Outs, - LLVMContext &Context) const override; - - SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, - const SmallVectorImpl<ISD::OutputArg> &Outs, - const SmallVectorImpl<SDValue> &OutVals, - const SDLoc &dl, SelectionDAG &DAG) const override; - - SDValue LowerInterruptReturn(SmallVectorImpl<SDValue> &RetOps, - const SDLoc &DL, SelectionDAG &DAG) const; - - bool shouldSignExtendTypeInLibCall(EVT Type, bool IsSigned) const override; - - // Inline asm support - ConstraintType getConstraintType(StringRef Constraint) const override; - - /// Examine constraint string and operand type and determine a weight value. - /// The operand object must already have been set up with the operand type. - ConstraintWeight getSingleConstraintMatchWeight( - AsmOperandInfo &info, const char *constraint) const override; - - /// This function parses registers that appear in inline-asm constraints. - /// It returns pair (0, 0) on failure. - std::pair<unsigned, const TargetRegisterClass *> - parseRegForInlineAsmConstraint(StringRef C, MVT VT) const; - - std::pair<unsigned, const TargetRegisterClass *> - getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, - StringRef Constraint, MVT VT) const override; - - /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops - /// vector. If it is invalid, don't add anything to Ops. If hasMemory is - /// true it means one of the asm constraint of the inline asm instruction - /// being processed is 'm'. - void LowerAsmOperandForConstraint(SDValue Op, - std::string &Constraint, - std::vector<SDValue> &Ops, - SelectionDAG &DAG) const override; - - unsigned - getInlineAsmMemConstraint(StringRef ConstraintCode) const override { - if (ConstraintCode == "o") - return InlineAsm::Constraint_o; - if (ConstraintCode == "R") - return InlineAsm::Constraint_R; - if (ConstraintCode == "ZC") - return InlineAsm::Constraint_ZC; - return TargetLowering::getInlineAsmMemConstraint(ConstraintCode); - } - - bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, - Type *Ty, unsigned AS, - Instruction *I = nullptr) const override; - - bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override; - - EVT getOptimalMemOpType(uint64_t Size, unsigned DstAlign, - unsigned SrcAlign, - bool IsMemset, bool ZeroMemset, - bool MemcpyStrSrc, - const AttributeList &FuncAttributes) const override; - - /// isFPImmLegal - Returns true if the target can instruction select the - /// specified FP immediate natively. If false, the legalizer will - /// materialize the FP immediate as a load from a constant pool. - bool isFPImmLegal(const APFloat &Imm, EVT VT, - bool ForCodeSize) const override; - - unsigned getJumpTableEncoding() const override; - bool useSoftFloat() const override; - - bool shouldInsertFencesForAtomic(const Instruction *I) const override { - return true; - } - - /// Emit a sign-extension using sll/sra, seb, or seh appropriately. - MachineBasicBlock *emitSignExtendToI32InReg(MachineInstr &MI, - MachineBasicBlock *BB, - unsigned Size, unsigned DstReg, - unsigned SrcRec) const; - - MachineBasicBlock *emitAtomicBinary(MachineInstr &MI, - MachineBasicBlock *BB) const; - MachineBasicBlock *emitAtomicBinaryPartword(MachineInstr &MI, - MachineBasicBlock *BB, - unsigned Size) const; - MachineBasicBlock *emitAtomicCmpSwap(MachineInstr &MI, - MachineBasicBlock *BB) const; - MachineBasicBlock *emitAtomicCmpSwapPartword(MachineInstr &MI, - MachineBasicBlock *BB, - unsigned Size) const; - MachineBasicBlock *emitSEL_D(MachineInstr &MI, MachineBasicBlock *BB) const; - MachineBasicBlock *emitPseudoSELECT(MachineInstr &MI, MachineBasicBlock *BB, - bool isFPCmp, unsigned Opc) const; - MachineBasicBlock *emitPseudoD_SELECT(MachineInstr &MI, - MachineBasicBlock *BB) const; - }; - - /// Create MipsTargetLowering objects. - const MipsTargetLowering * - createMips16TargetLowering(const MipsTargetMachine &TM, - const MipsSubtarget &STI); - const MipsTargetLowering * - createMipsSETargetLowering(const MipsTargetMachine &TM, - const MipsSubtarget &STI); - -namespace Mips { - -FastISel *createFastISel(FunctionLoweringInfo &funcInfo, - const TargetLibraryInfo *libInfo); - -} // end namespace Mips - -} // end namespace llvm - -#endif // LLVM_LIB_TARGET_MIPS_MIPSISELLOWERING_H diff --git a/contrib/llvm/lib/Target/Mips/MipsInstrFPU.td b/contrib/llvm/lib/Target/Mips/MipsInstrFPU.td deleted file mode 100644 index e94e107e64c2..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsInstrFPU.td +++ /dev/null @@ -1,970 +0,0 @@ -//===-- MipsInstrFPU.td - Mips FPU Instruction Information -*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file describes the Mips FPU instruction set. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// Floating Point Instructions -// ------------------------ -// * 64bit fp: -// - 32 64-bit registers (default mode) -// - 16 even 32-bit registers (32-bit compatible mode) for -// single and double access. -// * 32bit fp: -// - 16 even 32-bit registers - single and double (aliased) -// - 32 32-bit registers (within single-only mode) -//===----------------------------------------------------------------------===// - -// Floating Point Compare and Branch -def SDT_MipsFPBrcond : SDTypeProfile<0, 3, [SDTCisInt<0>, - SDTCisVT<1, i32>, - SDTCisVT<2, OtherVT>]>; -def SDT_MipsFPCmp : SDTypeProfile<0, 3, [SDTCisSameAs<0, 1>, SDTCisFP<1>, - SDTCisVT<2, i32>]>; -def SDT_MipsCMovFP : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisVT<2, i32>, - SDTCisSameAs<1, 3>]>; -def SDT_MipsTruncIntFP : SDTypeProfile<1, 1, [SDTCisFP<0>, SDTCisFP<1>]>; -def SDT_MipsBuildPairF64 : SDTypeProfile<1, 2, [SDTCisVT<0, f64>, - SDTCisVT<1, i32>, - SDTCisSameAs<1, 2>]>; -def SDT_MipsExtractElementF64 : SDTypeProfile<1, 2, [SDTCisVT<0, i32>, - SDTCisVT<1, f64>, - SDTCisVT<2, i32>]>; - -def SDT_MipsMTC1_D64 : SDTypeProfile<1, 1, [SDTCisVT<0, f64>, - SDTCisVT<1, i32>]>; - -def MipsFPCmp : SDNode<"MipsISD::FPCmp", SDT_MipsFPCmp, [SDNPOutGlue]>; -def MipsCMovFP_T : SDNode<"MipsISD::CMovFP_T", SDT_MipsCMovFP, [SDNPInGlue]>; -def MipsCMovFP_F : SDNode<"MipsISD::CMovFP_F", SDT_MipsCMovFP, [SDNPInGlue]>; -def MipsFPBrcond : SDNode<"MipsISD::FPBrcond", SDT_MipsFPBrcond, - [SDNPHasChain, SDNPOptInGlue]>; -def MipsTruncIntFP : SDNode<"MipsISD::TruncIntFP", SDT_MipsTruncIntFP>; -def MipsBuildPairF64 : SDNode<"MipsISD::BuildPairF64", SDT_MipsBuildPairF64>; -def MipsExtractElementF64 : SDNode<"MipsISD::ExtractElementF64", - SDT_MipsExtractElementF64>; - -def MipsMTC1_D64 : SDNode<"MipsISD::MTC1_D64", SDT_MipsMTC1_D64>; - -// Operand for printing out a condition code. -let PrintMethod = "printFCCOperand", DecoderMethod = "DecodeCondCode" in - def condcode : Operand<i32>; - -//===----------------------------------------------------------------------===// -// Feature predicates. -//===----------------------------------------------------------------------===// - -def IsFP64bit : Predicate<"Subtarget->isFP64bit()">, - AssemblerPredicate<"FeatureFP64Bit">; -def NotFP64bit : Predicate<"!Subtarget->isFP64bit()">, - AssemblerPredicate<"!FeatureFP64Bit">; -def IsSingleFloat : Predicate<"Subtarget->isSingleFloat()">, - AssemblerPredicate<"FeatureSingleFloat">; -def IsNotSingleFloat : Predicate<"!Subtarget->isSingleFloat()">, - AssemblerPredicate<"!FeatureSingleFloat">; -def IsNotSoftFloat : Predicate<"!Subtarget->useSoftFloat()">, - AssemblerPredicate<"!FeatureSoftFloat">; - -//===----------------------------------------------------------------------===// -// Mips FGR size adjectives. -// They are mutually exclusive. -//===----------------------------------------------------------------------===// - -class FGR_32 { list<Predicate> FGRPredicates = [NotFP64bit]; } -class FGR_64 { list<Predicate> FGRPredicates = [IsFP64bit]; } -class HARDFLOAT { list<Predicate> HardFloatPredicate = [IsNotSoftFloat]; } - -//===----------------------------------------------------------------------===// - -// FP immediate patterns. -def fpimm0 : PatLeaf<(fpimm), [{ - return N->isExactlyValue(+0.0); -}]>; - -def fpimm0neg : PatLeaf<(fpimm), [{ - return N->isExactlyValue(-0.0); -}]>; - -//===----------------------------------------------------------------------===// -// Instruction Class Templates -// -// A set of multiclasses is used to address the register usage. -// -// S32 - single precision in 16 32bit even fp registers -// single precision in 32 32bit fp registers in SingleOnly mode -// S64 - single precision in 32 64bit fp registers (In64BitMode) -// D32 - double precision in 16 32bit even fp registers -// D64 - double precision in 32 64bit fp registers (In64BitMode) -// -// Only S32 and D32 are supported right now. -//===----------------------------------------------------------------------===// -class ADDS_FT<string opstr, RegisterOperand RC, InstrItinClass Itin, bit IsComm, - SDPatternOperator OpNode= null_frag> : - InstSE<(outs RC:$fd), (ins RC:$fs, RC:$ft), - !strconcat(opstr, "\t$fd, $fs, $ft"), - [(set RC:$fd, (OpNode RC:$fs, RC:$ft))], Itin, FrmFR, opstr>, - HARDFLOAT { - let isCommutable = IsComm; -} - -multiclass ADDS_M<string opstr, InstrItinClass Itin, bit IsComm, - SDPatternOperator OpNode = null_frag> { - def _D32 : MMRel, ADDS_FT<opstr, AFGR64Opnd, Itin, IsComm, OpNode>, FGR_32; - def _D64 : ADDS_FT<opstr, FGR64Opnd, Itin, IsComm, OpNode>, FGR_64 { - string DecoderNamespace = "MipsFP64"; - } -} - -class ABSS_FT<string opstr, RegisterOperand DstRC, RegisterOperand SrcRC, - InstrItinClass Itin, SDPatternOperator OpNode= null_frag> : - InstSE<(outs DstRC:$fd), (ins SrcRC:$fs), !strconcat(opstr, "\t$fd, $fs"), - [(set DstRC:$fd, (OpNode SrcRC:$fs))], Itin, FrmFR, opstr>, - HARDFLOAT, - NeverHasSideEffects; - -class CVT_PS_S_FT<string opstr, RegisterOperand DstRC, RegisterOperand SrcRC, InstrItinClass Itin, bit IsComm, - SDPatternOperator OpNode= null_frag> : - InstSE<(outs DstRC:$fd), (ins SrcRC:$fs, SrcRC:$ft), - !strconcat(opstr, "\t$fd, $fs, $ft"), - [(set DstRC:$fd, (OpNode SrcRC:$fs, SrcRC:$ft))], Itin, FrmFR, opstr>, - HARDFLOAT { - let isCommutable = IsComm; -} - -multiclass ABSS_M<string opstr, InstrItinClass Itin, - SDPatternOperator OpNode= null_frag> { - def _D32 : MMRel, ABSS_FT<opstr, AFGR64Opnd, AFGR64Opnd, Itin, OpNode>, - FGR_32; - def _D64 : StdMMR6Rel, ABSS_FT<opstr, FGR64Opnd, FGR64Opnd, Itin, OpNode>, FGR_64 { - string DecoderNamespace = "MipsFP64"; - } -} - -multiclass ROUND_M<string opstr, InstrItinClass Itin> { - def _D32 : MMRel, ABSS_FT<opstr, FGR32Opnd, AFGR64Opnd, Itin>, FGR_32; - def _D64 : StdMMR6Rel, ABSS_FT<opstr, FGR32Opnd, FGR64Opnd, Itin>, FGR_64 { - let DecoderNamespace = "MipsFP64"; - } -} - -class MFC1_FT<string opstr, RegisterOperand DstRC, RegisterOperand SrcRC, - InstrItinClass Itin, SDPatternOperator OpNode= null_frag> : - InstSE<(outs DstRC:$rt), (ins SrcRC:$fs), !strconcat(opstr, "\t$rt, $fs"), - [(set DstRC:$rt, (OpNode SrcRC:$fs))], Itin, FrmFR, opstr>, HARDFLOAT { - let isMoveReg = 1; -} - -class MTC1_FT<string opstr, RegisterOperand DstRC, RegisterOperand SrcRC, - InstrItinClass Itin, SDPatternOperator OpNode= null_frag> : - InstSE<(outs DstRC:$fs), (ins SrcRC:$rt), !strconcat(opstr, "\t$rt, $fs"), - [(set DstRC:$fs, (OpNode SrcRC:$rt))], Itin, FrmFR, opstr>, HARDFLOAT { - let isMoveReg = 1; -} - -class MTC1_64_FT<string opstr, RegisterOperand DstRC, RegisterOperand SrcRC, - InstrItinClass Itin> : - InstSE<(outs DstRC:$fs), (ins DstRC:$fs_in, SrcRC:$rt), - !strconcat(opstr, "\t$rt, $fs"), [], Itin, FrmFR, opstr>, HARDFLOAT { - // $fs_in is part of a white lie to work around a widespread bug in the FPU - // implementation. See expandBuildPairF64 for details. - let Constraints = "$fs = $fs_in"; -} - -class LW_FT<string opstr, RegisterOperand RC, DAGOperand MO, - InstrItinClass Itin, SDPatternOperator OpNode = null_frag> : - InstSE<(outs RC:$rt), (ins MO:$addr), !strconcat(opstr, "\t$rt, $addr"), - [(set RC:$rt, (OpNode addrDefault:$addr))], Itin, FrmFI, opstr>, - HARDFLOAT { - let DecoderMethod = "DecodeFMem"; - let mayLoad = 1; -} - -class SW_FT<string opstr, RegisterOperand RC, DAGOperand MO, - InstrItinClass Itin, SDPatternOperator OpNode = null_frag> : - InstSE<(outs), (ins RC:$rt, MO:$addr), !strconcat(opstr, "\t$rt, $addr"), - [(OpNode RC:$rt, addrDefault:$addr)], Itin, FrmFI, opstr>, HARDFLOAT { - let DecoderMethod = "DecodeFMem"; - let mayStore = 1; -} - -class MADDS_FT<string opstr, RegisterOperand RC, InstrItinClass Itin, - SDPatternOperator OpNode = null_frag> : - InstSE<(outs RC:$fd), (ins RC:$fr, RC:$fs, RC:$ft), - !strconcat(opstr, "\t$fd, $fr, $fs, $ft"), - [(set RC:$fd, (OpNode (fmul RC:$fs, RC:$ft), RC:$fr))], Itin, - FrmFR, opstr>, HARDFLOAT; - -class NMADDS_FT<string opstr, RegisterOperand RC, InstrItinClass Itin, - SDPatternOperator OpNode = null_frag> : - InstSE<(outs RC:$fd), (ins RC:$fr, RC:$fs, RC:$ft), - !strconcat(opstr, "\t$fd, $fr, $fs, $ft"), - [(set RC:$fd, (fsub fpimm0, (OpNode (fmul RC:$fs, RC:$ft), RC:$fr)))], - Itin, FrmFR, opstr>, HARDFLOAT; - -class LWXC1_FT<string opstr, RegisterOperand DRC, - InstrItinClass Itin, SDPatternOperator OpNode = null_frag> : - InstSE<(outs DRC:$fd), (ins PtrRC:$base, PtrRC:$index), - !strconcat(opstr, "\t$fd, ${index}(${base})"), - [(set DRC:$fd, (OpNode (add iPTR:$base, iPTR:$index)))], Itin, - FrmFI, opstr>, HARDFLOAT { - let AddedComplexity = 20; -} - -class SWXC1_FT<string opstr, RegisterOperand DRC, - InstrItinClass Itin, SDPatternOperator OpNode = null_frag> : - InstSE<(outs), (ins DRC:$fs, PtrRC:$base, PtrRC:$index), - !strconcat(opstr, "\t$fs, ${index}(${base})"), - [(OpNode DRC:$fs, (add iPTR:$base, iPTR:$index))], Itin, - FrmFI, opstr>, HARDFLOAT { - let AddedComplexity = 20; -} - -class BC1F_FT<string opstr, DAGOperand opnd, InstrItinClass Itin, - SDPatternOperator Op = null_frag> : - InstSE<(outs), (ins FCCRegsOpnd:$fcc, opnd:$offset), - !strconcat(opstr, "\t$fcc, $offset"), - [(MipsFPBrcond Op, FCCRegsOpnd:$fcc, bb:$offset)], Itin, - FrmFI, opstr>, HARDFLOAT { - let isBranch = 1; - let isTerminator = 1; - let hasDelaySlot = 1; - let Defs = [AT]; - let hasFCCRegOperand = 1; -} - -class BC1XL_FT<string opstr, DAGOperand opnd, InstrItinClass Itin> : - InstSE<(outs), (ins FCCRegsOpnd:$fcc, opnd:$offset), - !strconcat(opstr, "\t$fcc, $offset"), [], Itin, - FrmFI, opstr>, HARDFLOAT { - let isBranch = 1; - let isTerminator = 1; - let hasDelaySlot = 1; - let Defs = [AT]; - let hasFCCRegOperand = 1; -} - -class CEQS_FT<string typestr, RegisterClass RC, InstrItinClass Itin, - SDPatternOperator OpNode = null_frag> : - InstSE<(outs), (ins RC:$fs, RC:$ft, condcode:$cond), - !strconcat("c.$cond.", typestr, "\t$fs, $ft"), - [(OpNode RC:$fs, RC:$ft, imm:$cond)], Itin, FrmFR, - !strconcat("c.$cond.", typestr)>, HARDFLOAT { - let Defs = [FCC0]; - let isCodeGenOnly = 1; - let hasFCCRegOperand = 1; -} - - -// Note: MIPS-IV introduced $fcc1-$fcc7 and renamed FCSR31[23] $fcc0. Rather -// duplicating the instruction definition for MIPS1 - MIPS3, we expand -// c.cond.ft if necessary, and reject it after constructing the -// instruction if the ISA doesn't support it. -class C_COND_FT<string CondStr, string Typestr, RegisterOperand RC, - InstrItinClass itin> : - InstSE<(outs FCCRegsOpnd:$fcc), (ins RC:$fs, RC:$ft), - !strconcat("c.", CondStr, ".", Typestr, "\t$fcc, $fs, $ft"), [], itin, - FrmFR>, HARDFLOAT { - let isCompare = 1; - let hasFCCRegOperand = 1; -} - - -multiclass C_COND_M<string TypeStr, RegisterOperand RC, bits<5> fmt, - InstrItinClass itin> { - def C_F_#NAME : MMRel, C_COND_FT<"f", TypeStr, RC, itin>, - C_COND_FM<fmt, 0> { - let BaseOpcode = "c.f."#NAME; - let isCommutable = 1; - } - def C_UN_#NAME : MMRel, C_COND_FT<"un", TypeStr, RC, itin>, - C_COND_FM<fmt, 1> { - let BaseOpcode = "c.un."#NAME; - let isCommutable = 1; - } - def C_EQ_#NAME : MMRel, C_COND_FT<"eq", TypeStr, RC, itin>, - C_COND_FM<fmt, 2> { - let BaseOpcode = "c.eq."#NAME; - let isCommutable = 1; - } - def C_UEQ_#NAME : MMRel, C_COND_FT<"ueq", TypeStr, RC, itin>, - C_COND_FM<fmt, 3> { - let BaseOpcode = "c.ueq."#NAME; - let isCommutable = 1; - } - def C_OLT_#NAME : MMRel, C_COND_FT<"olt", TypeStr, RC, itin>, - C_COND_FM<fmt, 4> { - let BaseOpcode = "c.olt."#NAME; - } - def C_ULT_#NAME : MMRel, C_COND_FT<"ult", TypeStr, RC, itin>, - C_COND_FM<fmt, 5> { - let BaseOpcode = "c.ult."#NAME; - } - def C_OLE_#NAME : MMRel, C_COND_FT<"ole", TypeStr, RC, itin>, - C_COND_FM<fmt, 6> { - let BaseOpcode = "c.ole."#NAME; - } - def C_ULE_#NAME : MMRel, C_COND_FT<"ule", TypeStr, RC, itin>, - C_COND_FM<fmt, 7> { - let BaseOpcode = "c.ule."#NAME; - } - def C_SF_#NAME : MMRel, C_COND_FT<"sf", TypeStr, RC, itin>, - C_COND_FM<fmt, 8> { - let BaseOpcode = "c.sf."#NAME; - let isCommutable = 1; - } - def C_NGLE_#NAME : MMRel, C_COND_FT<"ngle", TypeStr, RC, itin>, - C_COND_FM<fmt, 9> { - let BaseOpcode = "c.ngle."#NAME; - } - def C_SEQ_#NAME : MMRel, C_COND_FT<"seq", TypeStr, RC, itin>, - C_COND_FM<fmt, 10> { - let BaseOpcode = "c.seq."#NAME; - let isCommutable = 1; - } - def C_NGL_#NAME : MMRel, C_COND_FT<"ngl", TypeStr, RC, itin>, - C_COND_FM<fmt, 11> { - let BaseOpcode = "c.ngl."#NAME; - } - def C_LT_#NAME : MMRel, C_COND_FT<"lt", TypeStr, RC, itin>, - C_COND_FM<fmt, 12> { - let BaseOpcode = "c.lt."#NAME; - } - def C_NGE_#NAME : MMRel, C_COND_FT<"nge", TypeStr, RC, itin>, - C_COND_FM<fmt, 13> { - let BaseOpcode = "c.nge."#NAME; - } - def C_LE_#NAME : MMRel, C_COND_FT<"le", TypeStr, RC, itin>, - C_COND_FM<fmt, 14> { - let BaseOpcode = "c.le."#NAME; - } - def C_NGT_#NAME : MMRel, C_COND_FT<"ngt", TypeStr, RC, itin>, - C_COND_FM<fmt, 15> { - let BaseOpcode = "c.ngt."#NAME; - } -} - -let AdditionalPredicates = [NotInMicroMips] in { -defm S : C_COND_M<"s", FGR32Opnd, 16, II_C_CC_S>, ISA_MIPS1_NOT_32R6_64R6; -defm D32 : C_COND_M<"d", AFGR64Opnd, 17, II_C_CC_D>, ISA_MIPS1_NOT_32R6_64R6, - FGR_32; -let DecoderNamespace = "MipsFP64" in -defm D64 : C_COND_M<"d", FGR64Opnd, 17, II_C_CC_D>, ISA_MIPS1_NOT_32R6_64R6, - FGR_64; -} -//===----------------------------------------------------------------------===// -// Floating Point Instructions -//===----------------------------------------------------------------------===// -let AdditionalPredicates = [NotInMicroMips] in { - def ROUND_W_S : MMRel, StdMMR6Rel, ABSS_FT<"round.w.s", FGR32Opnd, FGR32Opnd, II_ROUND>, - ABSS_FM<0xc, 16>, ISA_MIPS2; - defm ROUND_W : ROUND_M<"round.w.d", II_ROUND>, ABSS_FM<0xc, 17>, ISA_MIPS2; - def TRUNC_W_S : MMRel, StdMMR6Rel, ABSS_FT<"trunc.w.s", FGR32Opnd, FGR32Opnd, II_TRUNC>, - ABSS_FM<0xd, 16>, ISA_MIPS2; - def CEIL_W_S : MMRel, StdMMR6Rel, ABSS_FT<"ceil.w.s", FGR32Opnd, FGR32Opnd, II_CEIL>, - ABSS_FM<0xe, 16>, ISA_MIPS2; - def FLOOR_W_S : MMRel, StdMMR6Rel, ABSS_FT<"floor.w.s", FGR32Opnd, FGR32Opnd, II_FLOOR>, - ABSS_FM<0xf, 16>, ISA_MIPS2; - def CVT_W_S : MMRel, ABSS_FT<"cvt.w.s", FGR32Opnd, FGR32Opnd, II_CVT>, - ABSS_FM<0x24, 16>, ISA_MIPS1; - - defm TRUNC_W : ROUND_M<"trunc.w.d", II_TRUNC>, ABSS_FM<0xd, 17>, ISA_MIPS2; - defm CEIL_W : ROUND_M<"ceil.w.d", II_CEIL>, ABSS_FM<0xe, 17>, ISA_MIPS2; - defm FLOOR_W : ROUND_M<"floor.w.d", II_FLOOR>, ABSS_FM<0xf, 17>, ISA_MIPS2; - defm CVT_W : ROUND_M<"cvt.w.d", II_CVT>, ABSS_FM<0x24, 17>, ISA_MIPS1; -} - -let AdditionalPredicates = [NotInMicroMips] in { - def RECIP_S : MMRel, ABSS_FT<"recip.s", FGR32Opnd, FGR32Opnd, II_RECIP_S>, - ABSS_FM<0b010101, 0x10>, INSN_MIPS4_32R2; - def RECIP_D32 : MMRel, ABSS_FT<"recip.d", AFGR64Opnd, AFGR64Opnd, II_RECIP_D>, - ABSS_FM<0b010101, 0x11>, INSN_MIPS4_32R2, FGR_32 { - let BaseOpcode = "RECIP_D32"; - } - let DecoderNamespace = "MipsFP64" in - def RECIP_D64 : MMRel, ABSS_FT<"recip.d", FGR64Opnd, FGR64Opnd, - II_RECIP_D>, ABSS_FM<0b010101, 0x11>, - INSN_MIPS4_32R2, FGR_64; - def RSQRT_S : MMRel, ABSS_FT<"rsqrt.s", FGR32Opnd, FGR32Opnd, II_RSQRT_S>, - ABSS_FM<0b010110, 0x10>, INSN_MIPS4_32R2; - def RSQRT_D32 : MMRel, ABSS_FT<"rsqrt.d", AFGR64Opnd, AFGR64Opnd, II_RSQRT_D>, - ABSS_FM<0b010110, 0x11>, INSN_MIPS4_32R2, FGR_32 { - let BaseOpcode = "RSQRT_D32"; - } - let DecoderNamespace = "MipsFP64" in - def RSQRT_D64 : MMRel, ABSS_FT<"rsqrt.d", FGR64Opnd, FGR64Opnd, - II_RSQRT_D>, ABSS_FM<0b010110, 0x11>, - INSN_MIPS4_32R2, FGR_64; -} -let DecoderNamespace = "MipsFP64" in { - let AdditionalPredicates = [NotInMicroMips] in { - def ROUND_L_S : ABSS_FT<"round.l.s", FGR64Opnd, FGR32Opnd, II_ROUND>, - ABSS_FM<0x8, 16>, ISA_MIPS2, FGR_64; - def ROUND_L_D64 : ABSS_FT<"round.l.d", FGR64Opnd, FGR64Opnd, II_ROUND>, - ABSS_FM<0x8, 17>, INSN_MIPS3_32, FGR_64; - def TRUNC_L_S : ABSS_FT<"trunc.l.s", FGR64Opnd, FGR32Opnd, II_TRUNC>, - ABSS_FM<0x9, 16>, ISA_MIPS2, FGR_64; - def TRUNC_L_D64 : ABSS_FT<"trunc.l.d", FGR64Opnd, FGR64Opnd, II_TRUNC>, - ABSS_FM<0x9, 17>, INSN_MIPS3_32, FGR_64; - def CEIL_L_S : ABSS_FT<"ceil.l.s", FGR64Opnd, FGR32Opnd, II_CEIL>, - ABSS_FM<0xa, 16>, ISA_MIPS2, FGR_64; - def CEIL_L_D64 : ABSS_FT<"ceil.l.d", FGR64Opnd, FGR64Opnd, II_CEIL>, - ABSS_FM<0xa, 17>, INSN_MIPS3_32, FGR_64; - def FLOOR_L_S : ABSS_FT<"floor.l.s", FGR64Opnd, FGR32Opnd, II_FLOOR>, - ABSS_FM<0xb, 16>, ISA_MIPS2, FGR_64; - def FLOOR_L_D64 : ABSS_FT<"floor.l.d", FGR64Opnd, FGR64Opnd, II_FLOOR>, - ABSS_FM<0xb, 17>, INSN_MIPS3_32, FGR_64; - } -} - -let AdditionalPredicates = [NotInMicroMips] in{ - def CVT_S_W : MMRel, ABSS_FT<"cvt.s.w", FGR32Opnd, FGR32Opnd, II_CVT>, - ABSS_FM<0x20, 20>, ISA_MIPS1; - def CVT_L_S : MMRel, ABSS_FT<"cvt.l.s", FGR64Opnd, FGR32Opnd, II_CVT>, - ABSS_FM<0x25, 16>, INSN_MIPS3_32R2; - def CVT_L_D64: MMRel, ABSS_FT<"cvt.l.d", FGR64Opnd, FGR64Opnd, II_CVT>, - ABSS_FM<0x25, 17>, INSN_MIPS3_32R2; -} - -let AdditionalPredicates = [NotInMicroMips] in { - def CVT_S_D32 : MMRel, ABSS_FT<"cvt.s.d", FGR32Opnd, AFGR64Opnd, II_CVT>, - ABSS_FM<0x20, 17>, ISA_MIPS1, FGR_32; - def CVT_D32_S : MMRel, ABSS_FT<"cvt.d.s", AFGR64Opnd, FGR32Opnd, II_CVT>, - ABSS_FM<0x21, 16>, ISA_MIPS1, FGR_32; - def CVT_D32_W : MMRel, ABSS_FT<"cvt.d.w", AFGR64Opnd, FGR32Opnd, II_CVT>, - ABSS_FM<0x21, 20>, ISA_MIPS1, FGR_32; -} - -let DecoderNamespace = "MipsFP64" in { - let AdditionalPredicates = [NotInMicroMips] in { - def PLL_PS64 : ADDS_FT<"pll.ps", FGR64Opnd, II_CVT, 0>, - ADDS_FM<0x2C, 22>, - ISA_MIPS32R2_NOT_32R6_64R6, FGR_64; - def PLU_PS64 : ADDS_FT<"plu.ps", FGR64Opnd, II_CVT, 0>, - ADDS_FM<0x2D, 22>, - ISA_MIPS32R2_NOT_32R6_64R6, FGR_64; - - def CVT_S_PU64 : ABSS_FT<"cvt.s.pu", FGR32Opnd, FGR64Opnd, II_CVT>, - ABSS_FM<0x20, 22>, - ISA_MIPS32R2_NOT_32R6_64R6, FGR_64; - def CVT_S_PL64 : ABSS_FT<"cvt.s.pl", FGR32Opnd, FGR64Opnd, II_CVT>, - ABSS_FM<0x28, 22>, - ISA_MIPS32R2_NOT_32R6_64R6, FGR_64; - - def CVT_PS_S64 : CVT_PS_S_FT<"cvt.ps.s", FGR64Opnd, FGR32Opnd, II_CVT, 0>, - ADDS_FM<0x26, 16>, - ISA_MIPS32R2_NOT_32R6_64R6, FGR_64; - } -} - -let DecoderNamespace = "MipsFP64" in { - let AdditionalPredicates = [NotInMicroMips] in { - def CVT_S_L : ABSS_FT<"cvt.s.l", FGR32Opnd, FGR64Opnd, II_CVT>, - ABSS_FM<0x20, 21>, INSN_MIPS3_32R2, FGR_64; - def CVT_S_D64 : ABSS_FT<"cvt.s.d", FGR32Opnd, FGR64Opnd, II_CVT>, - ABSS_FM<0x20, 17>, ISA_MIPS1, FGR_64; - def CVT_D64_W : ABSS_FT<"cvt.d.w", FGR64Opnd, FGR32Opnd, II_CVT>, - ABSS_FM<0x21, 20>, ISA_MIPS1, FGR_64; - def CVT_D64_S : ABSS_FT<"cvt.d.s", FGR64Opnd, FGR32Opnd, II_CVT>, - ABSS_FM<0x21, 16>, ISA_MIPS1, FGR_64; - def CVT_D64_L : ABSS_FT<"cvt.d.l", FGR64Opnd, FGR64Opnd, II_CVT>, - ABSS_FM<0x21, 21>, INSN_MIPS3_32R2, FGR_64; - } -} - -let isPseudo = 1, isCodeGenOnly = 1 in { - def PseudoCVT_S_W : ABSS_FT<"", FGR32Opnd, GPR32Opnd, II_CVT>; - def PseudoCVT_D32_W : ABSS_FT<"", AFGR64Opnd, GPR32Opnd, II_CVT>; - def PseudoCVT_S_L : ABSS_FT<"", FGR64Opnd, GPR64Opnd, II_CVT>; - def PseudoCVT_D64_W : ABSS_FT<"", FGR64Opnd, GPR32Opnd, II_CVT>; - def PseudoCVT_D64_L : ABSS_FT<"", FGR64Opnd, GPR64Opnd, II_CVT>; -} - -let AdditionalPredicates = [NotInMicroMips, UseAbs] in { - def FABS_S : MMRel, ABSS_FT<"abs.s", FGR32Opnd, FGR32Opnd, II_ABS, fabs>, - ABSS_FM<0x5, 16>, ISA_MIPS1; - defm FABS : ABSS_M<"abs.d", II_ABS, fabs>, ABSS_FM<0x5, 17>, ISA_MIPS1; -} - -def FNEG_S : MMRel, ABSS_FT<"neg.s", FGR32Opnd, FGR32Opnd, II_NEG, fneg>, - ABSS_FM<0x7, 16>, ISA_MIPS1; -let AdditionalPredicates = [NotInMicroMips] in { - defm FNEG : ABSS_M<"neg.d", II_NEG, fneg>, ABSS_FM<0x7, 17>, ISA_MIPS1; -} - -let AdditionalPredicates = [NotInMicroMips] in { - def FSQRT_S : MMRel, StdMMR6Rel, ABSS_FT<"sqrt.s", FGR32Opnd, FGR32Opnd, - II_SQRT_S, fsqrt>, ABSS_FM<0x4, 16>, ISA_MIPS2; - defm FSQRT : ABSS_M<"sqrt.d", II_SQRT_D, fsqrt>, ABSS_FM<0x4, 17>, ISA_MIPS2; -} - -// The odd-numbered registers are only referenced when doing loads, -// stores, and moves between floating-point and integer registers. -// When defining instructions, we reference all 32-bit registers, -// regardless of register aliasing. - -/// Move Control Registers From/To CPU Registers -let AdditionalPredicates = [NotInMicroMips] in { - def CFC1 : MMRel, MFC1_FT<"cfc1", GPR32Opnd, CCROpnd, II_CFC1>, MFC1_FM<2>, - ISA_MIPS1; - def CTC1 : MMRel, MTC1_FT<"ctc1", CCROpnd, GPR32Opnd, II_CTC1>, MFC1_FM<6>, - ISA_MIPS1; - - def MFC1 : MMRel, StdMMR6Rel, MFC1_FT<"mfc1", GPR32Opnd, FGR32Opnd, II_MFC1, - bitconvert>, MFC1_FM<0>, ISA_MIPS1; - def MFC1_D64 : MFC1_FT<"mfc1", GPR32Opnd, FGR64Opnd, II_MFC1>, MFC1_FM<0>, - ISA_MIPS1, FGR_64 { - let DecoderNamespace = "MipsFP64"; - } - def MTC1 : MMRel, StdMMR6Rel, MTC1_FT<"mtc1", FGR32Opnd, GPR32Opnd, II_MTC1, - bitconvert>, MFC1_FM<4>, ISA_MIPS1; - def MTC1_D64 : MTC1_FT<"mtc1", FGR64Opnd, GPR32Opnd, II_MTC1>, MFC1_FM<4>, - ISA_MIPS1, FGR_64 { - let DecoderNamespace = "MipsFP64"; - } - - def MFHC1_D32 : MMRel, MFC1_FT<"mfhc1", GPR32Opnd, AFGR64Opnd, II_MFHC1>, - MFC1_FM<3>, ISA_MIPS32R2, FGR_32; - def MFHC1_D64 : MFC1_FT<"mfhc1", GPR32Opnd, FGR64Opnd, II_MFHC1>, - MFC1_FM<3>, ISA_MIPS32R2, FGR_64 { - let DecoderNamespace = "MipsFP64"; - } - - def MTHC1_D32 : MMRel, StdMMR6Rel, MTC1_64_FT<"mthc1", AFGR64Opnd, GPR32Opnd, II_MTHC1>, - MFC1_FM<7>, ISA_MIPS32R2, FGR_32; - def MTHC1_D64 : MTC1_64_FT<"mthc1", FGR64Opnd, GPR32Opnd, II_MTHC1>, - MFC1_FM<7>, ISA_MIPS32R2, FGR_64 { - let DecoderNamespace = "MipsFP64"; - } - - def DMTC1 : MTC1_FT<"dmtc1", FGR64Opnd, GPR64Opnd, II_DMTC1, - bitconvert>, MFC1_FM<5>, ISA_MIPS3; - def DMFC1 : MFC1_FT<"dmfc1", GPR64Opnd, FGR64Opnd, II_DMFC1, - bitconvert>, MFC1_FM<1>, ISA_MIPS3; - let isMoveReg = 1 in { - def FMOV_S : MMRel, ABSS_FT<"mov.s", FGR32Opnd, FGR32Opnd, II_MOV_S>, - ABSS_FM<0x6, 16>, ISA_MIPS1; - defm FMOV : ABSS_M<"mov.d", II_MOV_D>, ABSS_FM<0x6, 17>, ISA_MIPS1; - } // isMoveReg -} - -/// Floating Point Memory Instructions -let AdditionalPredicates = [NotInMicroMips] in { - def LWC1 : MMRel, LW_FT<"lwc1", FGR32Opnd, mem_simm16, II_LWC1, load>, - LW_FM<0x31>, ISA_MIPS1; - def SWC1 : MMRel, SW_FT<"swc1", FGR32Opnd, mem_simm16, II_SWC1, store>, - LW_FM<0x39>, ISA_MIPS1; -} - -let DecoderNamespace = "MipsFP64", AdditionalPredicates = [NotInMicroMips] in { - def LDC164 : StdMMR6Rel, LW_FT<"ldc1", FGR64Opnd, mem_simm16, II_LDC1, load>, - LW_FM<0x35>, ISA_MIPS2, FGR_64 { - let BaseOpcode = "LDC164"; - } - def SDC164 : StdMMR6Rel, SW_FT<"sdc1", FGR64Opnd, mem_simm16, II_SDC1, store>, - LW_FM<0x3d>, ISA_MIPS2, FGR_64; -} - -let AdditionalPredicates = [NotInMicroMips] in { - def LDC1 : MMRel, StdMMR6Rel, LW_FT<"ldc1", AFGR64Opnd, mem_simm16, II_LDC1, - load>, LW_FM<0x35>, ISA_MIPS2, FGR_32 { - let BaseOpcode = "LDC132"; - } - def SDC1 : MMRel, SW_FT<"sdc1", AFGR64Opnd, mem_simm16, II_SDC1, store>, - LW_FM<0x3d>, ISA_MIPS2, FGR_32; -} - -// Indexed loads and stores. -// Base register + offset register addressing mode (indicated by "x" in the -// instruction mnemonic) is disallowed under NaCl. -let AdditionalPredicates = [IsNotNaCl] in { - def LWXC1 : MMRel, LWXC1_FT<"lwxc1", FGR32Opnd, II_LWXC1, load>, LWXC1_FM<0>, - INSN_MIPS4_32R2_NOT_32R6_64R6; - def SWXC1 : MMRel, SWXC1_FT<"swxc1", FGR32Opnd, II_SWXC1, store>, SWXC1_FM<8>, - INSN_MIPS4_32R2_NOT_32R6_64R6; -} - -let AdditionalPredicates = [NotInMicroMips, IsNotNaCl] in { - def LDXC1 : LWXC1_FT<"ldxc1", AFGR64Opnd, II_LDXC1, load>, LWXC1_FM<1>, - INSN_MIPS4_32R2_NOT_32R6_64R6, FGR_32; - def SDXC1 : SWXC1_FT<"sdxc1", AFGR64Opnd, II_SDXC1, store>, SWXC1_FM<9>, - INSN_MIPS4_32R2_NOT_32R6_64R6, FGR_32; -} - -let DecoderNamespace="MipsFP64" in { - def LDXC164 : LWXC1_FT<"ldxc1", FGR64Opnd, II_LDXC1, load>, LWXC1_FM<1>, - INSN_MIPS4_32R2_NOT_32R6_64R6, FGR_64; - def SDXC164 : SWXC1_FT<"sdxc1", FGR64Opnd, II_SDXC1, store>, SWXC1_FM<9>, - INSN_MIPS4_32R2_NOT_32R6_64R6, FGR_64; -} - -// Load/store doubleword indexed unaligned. -// FIXME: This instruction should not be defined for FGR_32. -let AdditionalPredicates = [IsNotNaCl, NotInMicroMips] in { - def LUXC1 : MMRel, LWXC1_FT<"luxc1", AFGR64Opnd, II_LUXC1>, LWXC1_FM<0x5>, - INSN_MIPS5_32R2_NOT_32R6_64R6, FGR_32; - def SUXC1 : MMRel, SWXC1_FT<"suxc1", AFGR64Opnd, II_SUXC1>, SWXC1_FM<0xd>, - INSN_MIPS5_32R2_NOT_32R6_64R6, FGR_32; -} - -let AdditionalPredicates = [IsNotNaCl, NotInMicroMips], - DecoderNamespace="MipsFP64" in { - def LUXC164 : LWXC1_FT<"luxc1", FGR64Opnd, II_LUXC1>, LWXC1_FM<0x5>, - INSN_MIPS5_32R2_NOT_32R6_64R6, FGR_64; - def SUXC164 : SWXC1_FT<"suxc1", FGR64Opnd, II_SUXC1>, SWXC1_FM<0xd>, - INSN_MIPS5_32R2_NOT_32R6_64R6, FGR_64; -} - -/// Floating-point Aritmetic -let AdditionalPredicates = [NotInMicroMips] in { - def FADD_S : MMRel, ADDS_FT<"add.s", FGR32Opnd, II_ADD_S, 1, fadd>, - ADDS_FM<0x00, 16>, ISA_MIPS1; - defm FADD : ADDS_M<"add.d", II_ADD_D, 1, fadd>, ADDS_FM<0x00, 17>, - ISA_MIPS1; - def FDIV_S : MMRel, ADDS_FT<"div.s", FGR32Opnd, II_DIV_S, 0, fdiv>, - ADDS_FM<0x03, 16>, ISA_MIPS1; - defm FDIV : ADDS_M<"div.d", II_DIV_D, 0, fdiv>, ADDS_FM<0x03, 17>, - ISA_MIPS1; - def FMUL_S : MMRel, ADDS_FT<"mul.s", FGR32Opnd, II_MUL_S, 1, fmul>, - ADDS_FM<0x02, 16>, ISA_MIPS1; - defm FMUL : ADDS_M<"mul.d", II_MUL_D, 1, fmul>, ADDS_FM<0x02, 17>, - ISA_MIPS1; - def FSUB_S : MMRel, ADDS_FT<"sub.s", FGR32Opnd, II_SUB_S, 0, fsub>, - ADDS_FM<0x01, 16>, ISA_MIPS1; - defm FSUB : ADDS_M<"sub.d", II_SUB_D, 0, fsub>, ADDS_FM<0x01, 17>, - ISA_MIPS1; -} - -let AdditionalPredicates = [NotInMicroMips, HasMadd4] in { - def MADD_S : MMRel, MADDS_FT<"madd.s", FGR32Opnd, II_MADD_S, fadd>, - MADDS_FM<4, 0>, INSN_MIPS4_32R2_NOT_32R6_64R6; - def MSUB_S : MMRel, MADDS_FT<"msub.s", FGR32Opnd, II_MSUB_S, fsub>, - MADDS_FM<5, 0>, INSN_MIPS4_32R2_NOT_32R6_64R6; - - def MADD_D32 : MMRel, MADDS_FT<"madd.d", AFGR64Opnd, II_MADD_D, fadd>, - MADDS_FM<4, 1>, INSN_MIPS4_32R2_NOT_32R6_64R6, FGR_32; - def MSUB_D32 : MMRel, MADDS_FT<"msub.d", AFGR64Opnd, II_MSUB_D, fsub>, - MADDS_FM<5, 1>, INSN_MIPS4_32R2_NOT_32R6_64R6, FGR_32; - - let DecoderNamespace = "MipsFP64" in { - def MADD_D64 : MADDS_FT<"madd.d", FGR64Opnd, II_MADD_D, fadd>, - MADDS_FM<4, 1>, INSN_MIPS4_32R2_NOT_32R6_64R6, FGR_64; - def MSUB_D64 : MADDS_FT<"msub.d", FGR64Opnd, II_MSUB_D, fsub>, - MADDS_FM<5, 1>, INSN_MIPS4_32R2_NOT_32R6_64R6, FGR_64; - } -} - -let AdditionalPredicates = [NoNaNsFPMath, HasMadd4, NotInMicroMips] in { - def NMADD_S : MMRel, NMADDS_FT<"nmadd.s", FGR32Opnd, II_NMADD_S, fadd>, - MADDS_FM<6, 0>, INSN_MIPS4_32R2_NOT_32R6_64R6; - def NMSUB_S : MMRel, NMADDS_FT<"nmsub.s", FGR32Opnd, II_NMSUB_S, fsub>, - MADDS_FM<7, 0>, INSN_MIPS4_32R2_NOT_32R6_64R6; - - def NMADD_D32 : MMRel, NMADDS_FT<"nmadd.d", AFGR64Opnd, II_NMADD_D, fadd>, - MADDS_FM<6, 1>, INSN_MIPS4_32R2_NOT_32R6_64R6, FGR_32; - def NMSUB_D32 : MMRel, NMADDS_FT<"nmsub.d", AFGR64Opnd, II_NMSUB_D, fsub>, - MADDS_FM<7, 1>, INSN_MIPS4_32R2_NOT_32R6_64R6, FGR_32; - - let DecoderNamespace = "MipsFP64" in { - def NMADD_D64 : NMADDS_FT<"nmadd.d", FGR64Opnd, II_NMADD_D, fadd>, - MADDS_FM<6, 1>, INSN_MIPS4_32R2_NOT_32R6_64R6, FGR_64; - def NMSUB_D64 : NMADDS_FT<"nmsub.d", FGR64Opnd, II_NMSUB_D, fsub>, - MADDS_FM<7, 1>, INSN_MIPS4_32R2_NOT_32R6_64R6, FGR_64; - } -} -//===----------------------------------------------------------------------===// -// Floating Point Branch Codes -//===----------------------------------------------------------------------===// -// Mips branch codes. These correspond to condcode in MipsInstrInfo.h. -// They must be kept in synch. -def MIPS_BRANCH_F : PatLeaf<(i32 0)>; -def MIPS_BRANCH_T : PatLeaf<(i32 1)>; - -let AdditionalPredicates = [NotInMicroMips] in { - def BC1F : MMRel, BC1F_FT<"bc1f", brtarget, II_BC1F, MIPS_BRANCH_F>, - BC1F_FM<0, 0>, ISA_MIPS1_NOT_32R6_64R6; - def BC1FL : MMRel, BC1XL_FT<"bc1fl", brtarget, II_BC1FL>, - BC1F_FM<1, 0>, ISA_MIPS2_NOT_32R6_64R6; - def BC1T : MMRel, BC1F_FT<"bc1t", brtarget, II_BC1T, MIPS_BRANCH_T>, - BC1F_FM<0, 1>, ISA_MIPS1_NOT_32R6_64R6; - def BC1TL : MMRel, BC1XL_FT<"bc1tl", brtarget, II_BC1TL>, - BC1F_FM<1, 1>, ISA_MIPS2_NOT_32R6_64R6; - -/// Floating Point Compare - def FCMP_S32 : MMRel, CEQS_FT<"s", FGR32, II_C_CC_S, MipsFPCmp>, CEQS_FM<16>, - ISA_MIPS1_NOT_32R6_64R6 { - - // FIXME: This is a required to work around the fact that these instructions - // only use $fcc0. Ideally, MipsFPCmp nodes could be removed and the - // fcc register set is used directly. - bits<3> fcc = 0; - } - def FCMP_D32 : MMRel, CEQS_FT<"d", AFGR64, II_C_CC_D, MipsFPCmp>, CEQS_FM<17>, - ISA_MIPS1_NOT_32R6_64R6, FGR_32 { - // FIXME: This is a required to work around the fact that these instructions - // only use $fcc0. Ideally, MipsFPCmp nodes could be removed and the - // fcc register set is used directly. - bits<3> fcc = 0; - } -} -let DecoderNamespace = "MipsFP64" in -def FCMP_D64 : CEQS_FT<"d", FGR64, II_C_CC_D, MipsFPCmp>, CEQS_FM<17>, - ISA_MIPS1_NOT_32R6_64R6, FGR_64 { - // FIXME: This is a required to work around the fact that thiese instructions - // only use $fcc0. Ideally, MipsFPCmp nodes could be removed and the - // fcc register set is used directly. - bits<3> fcc = 0; -} - -//===----------------------------------------------------------------------===// -// Floating Point Pseudo-Instructions -//===----------------------------------------------------------------------===// - -// This pseudo instr gets expanded into 2 mtc1 instrs after register -// allocation. -class BuildPairF64Base<RegisterOperand RO> : - PseudoSE<(outs RO:$dst), (ins GPR32Opnd:$lo, GPR32Opnd:$hi), - [(set RO:$dst, (MipsBuildPairF64 GPR32Opnd:$lo, GPR32Opnd:$hi))], - II_MTC1>; - -def BuildPairF64 : BuildPairF64Base<AFGR64Opnd>, FGR_32, HARDFLOAT; -def BuildPairF64_64 : BuildPairF64Base<FGR64Opnd>, FGR_64, HARDFLOAT; - -// This pseudo instr gets expanded into 2 mfc1 instrs after register -// allocation. -// if n is 0, lower part of src is extracted. -// if n is 1, higher part of src is extracted. -// This node has associated scheduling information as the pre RA scheduler -// asserts otherwise. -class ExtractElementF64Base<RegisterOperand RO> : - PseudoSE<(outs GPR32Opnd:$dst), (ins RO:$src, i32imm:$n), - [(set GPR32Opnd:$dst, (MipsExtractElementF64 RO:$src, imm:$n))], - II_MFC1>; - -def ExtractElementF64 : ExtractElementF64Base<AFGR64Opnd>, FGR_32, HARDFLOAT; -def ExtractElementF64_64 : ExtractElementF64Base<FGR64Opnd>, FGR_64, HARDFLOAT; - -def PseudoTRUNC_W_S : MipsAsmPseudoInst<(outs FGR32Opnd:$fd), - (ins FGR32Opnd:$fs, GPR32Opnd:$rs), - "trunc.w.s\t$fd, $fs, $rs">; - -def PseudoTRUNC_W_D32 : MipsAsmPseudoInst<(outs FGR32Opnd:$fd), - (ins AFGR64Opnd:$fs, GPR32Opnd:$rs), - "trunc.w.d\t$fd, $fs, $rs">, - FGR_32, HARDFLOAT; - -def PseudoTRUNC_W_D : MipsAsmPseudoInst<(outs FGR32Opnd:$fd), - (ins FGR64Opnd:$fs, GPR32Opnd:$rs), - "trunc.w.d\t$fd, $fs, $rs">, - FGR_64, HARDFLOAT; - -def LoadImmSingleGPR : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), - (ins imm64:$fpimm), - "li.s\t$rd, $fpimm">; - -def LoadImmSingleFGR : MipsAsmPseudoInst<(outs StrictlyFGR32Opnd:$rd), - (ins imm64:$fpimm), - "li.s\t$rd, $fpimm">, - HARDFLOAT; - -def LoadImmDoubleGPR : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), - (ins imm64:$fpimm), - "li.d\t$rd, $fpimm">; - -def LoadImmDoubleFGR_32 : MipsAsmPseudoInst<(outs StrictlyAFGR64Opnd:$rd), - (ins imm64:$fpimm), - "li.d\t$rd, $fpimm">, - FGR_32, HARDFLOAT; - -def LoadImmDoubleFGR : MipsAsmPseudoInst<(outs StrictlyFGR64Opnd:$rd), - (ins imm64:$fpimm), - "li.d\t$rd, $fpimm">, - FGR_64, HARDFLOAT; - -def SDC1_M1 : MipsAsmPseudoInst<(outs AFGR64Opnd:$fd), - (ins mem_simm16:$addr), - "s.d\t$fd, $addr">, - FGR_32, ISA_MIPS1, HARDFLOAT; - -//===----------------------------------------------------------------------===// -// InstAliases. -//===----------------------------------------------------------------------===// -def : MipsInstAlias - <"s.s $fd, $addr", (SWC1 FGR32Opnd:$fd, mem_simm16:$addr), 0>, - ISA_MIPS2, HARDFLOAT; -def : MipsInstAlias - <"s.d $fd, $addr", (SDC1 AFGR64Opnd:$fd, mem_simm16:$addr), 0>, - FGR_32, ISA_MIPS2, HARDFLOAT; -def : MipsInstAlias - <"s.d $fd, $addr", (SDC164 FGR64Opnd:$fd, mem_simm16:$addr), 0>, - FGR_64, ISA_MIPS2, HARDFLOAT; -def : MipsInstAlias - <"s.d $fd, $addr", (SDC1_M1 AFGR64Opnd:$fd, mem_simm16:$addr), 0>, - FGR_32, ISA_MIPS1, HARDFLOAT; - -def : MipsInstAlias - <"l.s $fd, $addr", (LWC1 FGR32Opnd:$fd, mem_simm16:$addr), 0>, - ISA_MIPS2, HARDFLOAT; -def : MipsInstAlias - <"l.d $fd, $addr", (LDC1 AFGR64Opnd:$fd, mem_simm16:$addr), 0>, - FGR_32, ISA_MIPS2, HARDFLOAT; -def : MipsInstAlias - <"l.d $fd, $addr", (LDC164 FGR64Opnd:$fd, mem_simm16:$addr), 0>, - FGR_64, ISA_MIPS2, HARDFLOAT; - -multiclass C_COND_ALIASES<string TypeStr, RegisterOperand RC> { - def : MipsInstAlias<!strconcat("c.f.", TypeStr, " $fs, $ft"), - (!cast<Instruction>("C_F_"#NAME) FCC0, - RC:$fs, RC:$ft), 1>; - def : MipsInstAlias<!strconcat("c.un.", TypeStr, " $fs, $ft"), - (!cast<Instruction>("C_UN_"#NAME) FCC0, - RC:$fs, RC:$ft), 1>; - def : MipsInstAlias<!strconcat("c.eq.", TypeStr, " $fs, $ft"), - (!cast<Instruction>("C_EQ_"#NAME) FCC0, - RC:$fs, RC:$ft), 1>; - def : MipsInstAlias<!strconcat("c.ueq.", TypeStr, " $fs, $ft"), - (!cast<Instruction>("C_UEQ_"#NAME) FCC0, - RC:$fs, RC:$ft), 1>; - def : MipsInstAlias<!strconcat("c.olt.", TypeStr, " $fs, $ft"), - (!cast<Instruction>("C_OLT_"#NAME) FCC0, - RC:$fs, RC:$ft), 1>; - def : MipsInstAlias<!strconcat("c.ult.", TypeStr, " $fs, $ft"), - (!cast<Instruction>("C_ULT_"#NAME) FCC0, - RC:$fs, RC:$ft), 1>; - def : MipsInstAlias<!strconcat("c.ole.", TypeStr, " $fs, $ft"), - (!cast<Instruction>("C_OLE_"#NAME) FCC0, - RC:$fs, RC:$ft), 1>; - def : MipsInstAlias<!strconcat("c.ule.", TypeStr, " $fs, $ft"), - (!cast<Instruction>("C_ULE_"#NAME) FCC0, - RC:$fs, RC:$ft), 1>; - def : MipsInstAlias<!strconcat("c.sf.", TypeStr, " $fs, $ft"), - (!cast<Instruction>("C_SF_"#NAME) FCC0, - RC:$fs, RC:$ft), 1>; - def : MipsInstAlias<!strconcat("c.ngle.", TypeStr, " $fs, $ft"), - (!cast<Instruction>("C_NGLE_"#NAME) FCC0, - RC:$fs, RC:$ft), 1>; - def : MipsInstAlias<!strconcat("c.seq.", TypeStr, " $fs, $ft"), - (!cast<Instruction>("C_SEQ_"#NAME) FCC0, - RC:$fs, RC:$ft), 1>; - def : MipsInstAlias<!strconcat("c.ngl.", TypeStr, " $fs, $ft"), - (!cast<Instruction>("C_NGL_"#NAME) FCC0, - RC:$fs, RC:$ft), 1>; - def : MipsInstAlias<!strconcat("c.lt.", TypeStr, " $fs, $ft"), - (!cast<Instruction>("C_LT_"#NAME) FCC0, - RC:$fs, RC:$ft), 1>; - def : MipsInstAlias<!strconcat("c.nge.", TypeStr, " $fs, $ft"), - (!cast<Instruction>("C_NGE_"#NAME) FCC0, - RC:$fs, RC:$ft), 1>; - def : MipsInstAlias<!strconcat("c.le.", TypeStr, " $fs, $ft"), - (!cast<Instruction>("C_LE_"#NAME) FCC0, - RC:$fs, RC:$ft), 1>; - def : MipsInstAlias<!strconcat("c.ngt.", TypeStr, " $fs, $ft"), - (!cast<Instruction>("C_NGT_"#NAME) FCC0, - RC:$fs, RC:$ft), 1>; -} - -multiclass BC1_ALIASES<Instruction BCTrue, string BCTrueString, - Instruction BCFalse, string BCFalseString> { - def : MipsInstAlias<!strconcat(BCTrueString, " $offset"), - (BCTrue FCC0, brtarget:$offset), 1>; - - def : MipsInstAlias<!strconcat(BCFalseString, " $offset"), - (BCFalse FCC0, brtarget:$offset), 1>; -} - -let AdditionalPredicates = [NotInMicroMips] in { - defm S : C_COND_ALIASES<"s", FGR32Opnd>, HARDFLOAT, - ISA_MIPS1_NOT_32R6_64R6; - defm D32 : C_COND_ALIASES<"d", AFGR64Opnd>, HARDFLOAT, - ISA_MIPS1_NOT_32R6_64R6, FGR_32; - defm D64 : C_COND_ALIASES<"d", FGR64Opnd>, HARDFLOAT, - ISA_MIPS1_NOT_32R6_64R6, FGR_64; - - defm : BC1_ALIASES<BC1T, "bc1t", BC1F, "bc1f">, ISA_MIPS1_NOT_32R6_64R6, - HARDFLOAT; - defm : BC1_ALIASES<BC1TL, "bc1tl", BC1FL, "bc1fl">, ISA_MIPS2_NOT_32R6_64R6, - HARDFLOAT; -} -//===----------------------------------------------------------------------===// -// Floating Point Patterns -//===----------------------------------------------------------------------===// -def : MipsPat<(f32 fpimm0), (MTC1 ZERO)>, ISA_MIPS1; -def : MipsPat<(f32 fpimm0neg), (FNEG_S (MTC1 ZERO))>, ISA_MIPS1; - -def : MipsPat<(f32 (sint_to_fp GPR32Opnd:$src)), - (PseudoCVT_S_W GPR32Opnd:$src)>; -def : MipsPat<(MipsTruncIntFP FGR32Opnd:$src), - (TRUNC_W_S FGR32Opnd:$src)>, ISA_MIPS1; - -def : MipsPat<(MipsMTC1_D64 GPR32Opnd:$src), - (MTC1_D64 GPR32Opnd:$src)>, ISA_MIPS1, FGR_64; - -def : MipsPat<(f64 (sint_to_fp GPR32Opnd:$src)), - (PseudoCVT_D32_W GPR32Opnd:$src)>, FGR_32; -let AdditionalPredicates = [NotInMicroMips] in { - def : MipsPat<(MipsTruncIntFP AFGR64Opnd:$src), - (TRUNC_W_D32 AFGR64Opnd:$src)>, ISA_MIPS2, FGR_32; - def : MipsPat<(f32 (fpround AFGR64Opnd:$src)), - (CVT_S_D32 AFGR64Opnd:$src)>, ISA_MIPS1, FGR_32; - def : MipsPat<(f64 (fpextend FGR32Opnd:$src)), - (CVT_D32_S FGR32Opnd:$src)>, ISA_MIPS1, FGR_32; -} - -def : MipsPat<(f64 fpimm0), (DMTC1 ZERO_64)>, ISA_MIPS3, GPR_64, FGR_64; -def : MipsPat<(f64 fpimm0neg), (FNEG_D64 (DMTC1 ZERO_64))>, ISA_MIPS3, GPR_64, - FGR_64; - -def : MipsPat<(f64 (sint_to_fp GPR32Opnd:$src)), - (PseudoCVT_D64_W GPR32Opnd:$src)>, FGR_64; -def : MipsPat<(f32 (sint_to_fp GPR64Opnd:$src)), - (EXTRACT_SUBREG (PseudoCVT_S_L GPR64Opnd:$src), sub_lo)>, FGR_64; -def : MipsPat<(f64 (sint_to_fp GPR64Opnd:$src)), - (PseudoCVT_D64_L GPR64Opnd:$src)>, FGR_64; - -def : MipsPat<(MipsTruncIntFP FGR64Opnd:$src), - (TRUNC_W_D64 FGR64Opnd:$src)>, ISA_MIPS2, FGR_64; -def : MipsPat<(MipsTruncIntFP FGR32Opnd:$src), - (TRUNC_L_S FGR32Opnd:$src)>, ISA_MIPS2, FGR_64; -def : MipsPat<(MipsTruncIntFP FGR64Opnd:$src), - (TRUNC_L_D64 FGR64Opnd:$src)>, ISA_MIPS2, FGR_64; - -let AdditionalPredicates = [NotInMicroMips] in { - def : MipsPat<(f32 (fpround FGR64Opnd:$src)), - (CVT_S_D64 FGR64Opnd:$src)>, ISA_MIPS1, FGR_64; - def : MipsPat<(f64 (fpextend FGR32Opnd:$src)), - (CVT_D64_S FGR32Opnd:$src)>, ISA_MIPS1, FGR_64; -} - -// To generate NMADD and NMSUB instructions when fneg node is present -multiclass NMADD_NMSUB<Instruction Nmadd, Instruction Nmsub, RegisterOperand RC> { - def : MipsPat<(fneg (fadd (fmul RC:$fs, RC:$ft), RC:$fr)), - (Nmadd RC:$fr, RC:$fs, RC:$ft)>; - def : MipsPat<(fneg (fsub (fmul RC:$fs, RC:$ft), RC:$fr)), - (Nmsub RC:$fr, RC:$fs, RC:$ft)>; -} - -let AdditionalPredicates = [NoNaNsFPMath, HasMadd4, NotInMicroMips] in { - defm : NMADD_NMSUB<NMADD_S, NMSUB_S, FGR32Opnd>, INSN_MIPS4_32R2_NOT_32R6_64R6; - defm : NMADD_NMSUB<NMADD_D32, NMSUB_D32, AFGR64Opnd>, FGR_32, INSN_MIPS4_32R2_NOT_32R6_64R6; - defm : NMADD_NMSUB<NMADD_D64, NMSUB_D64, FGR64Opnd>, FGR_64, INSN_MIPS4_32R2_NOT_32R6_64R6; -} - -// Patterns for loads/stores with a reg+imm operand. -let AdditionalPredicates = [NotInMicroMips] in { - let AddedComplexity = 40 in { - def : LoadRegImmPat<LWC1, f32, load>, ISA_MIPS1; - def : StoreRegImmPat<SWC1, f32>, ISA_MIPS1; - - def : LoadRegImmPat<LDC164, f64, load>, ISA_MIPS1, FGR_64; - def : StoreRegImmPat<SDC164, f64>, ISA_MIPS1, FGR_64; - - def : LoadRegImmPat<LDC1, f64, load>, ISA_MIPS1, FGR_32; - def : StoreRegImmPat<SDC1, f64>, ISA_MIPS1, FGR_32; - } -} diff --git a/contrib/llvm/lib/Target/Mips/MipsInstrFormats.td b/contrib/llvm/lib/Target/Mips/MipsInstrFormats.td deleted file mode 100644 index af7cdbe5d609..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsInstrFormats.td +++ /dev/null @@ -1,998 +0,0 @@ -//===-- MipsInstrFormats.td - Mips Instruction Formats -----*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// Describe MIPS instructions format -// -// CPU INSTRUCTION FORMATS -// -// opcode - operation code. -// rs - src reg. -// rt - dst reg (on a 2 regs instr) or src reg (on a 3 reg instr). -// rd - dst reg, only used on 3 regs instr. -// shamt - only used on shift instructions, contains the shift amount. -// funct - combined with opcode field give us an operation code. -// -//===----------------------------------------------------------------------===// - -// Format specifies the encoding used by the instruction. This is part of the -// ad-hoc solution used to emit machine instruction encodings by our machine -// code emitter. -class Format<bits<4> val> { - bits<4> Value = val; -} - -def Pseudo : Format<0>; -def FrmR : Format<1>; -def FrmI : Format<2>; -def FrmJ : Format<3>; -def FrmFR : Format<4>; -def FrmFI : Format<5>; -def FrmOther : Format<6>; // Instruction w/ a custom format - -class MMRel; - -def Std2MicroMips : InstrMapping { - let FilterClass = "MMRel"; - // Instructions with the same BaseOpcode and isNVStore values form a row. - let RowFields = ["BaseOpcode"]; - // Instructions with the same predicate sense form a column. - let ColFields = ["Arch"]; - // The key column is the unpredicated instructions. - let KeyCol = ["se"]; - // Value columns are PredSense=true and PredSense=false - let ValueCols = [["se"], ["micromips"]]; -} - -class StdMMR6Rel; - -def Std2MicroMipsR6 : InstrMapping { - let FilterClass = "StdMMR6Rel"; - // Instructions with the same BaseOpcode and isNVStore values form a row. - let RowFields = ["BaseOpcode"]; - // Instructions with the same predicate sense form a column. - let ColFields = ["Arch"]; - // The key column is the unpredicated instructions. - let KeyCol = ["se"]; - // Value columns are PredSense=true and PredSense=false - let ValueCols = [["se"], ["micromipsr6"]]; -} - -class StdArch { - string Arch = "se"; -} - -// Generic Mips Format -class MipsInst<dag outs, dag ins, string asmstr, list<dag> pattern, - InstrItinClass itin, Format f>: Instruction, PredicateControl -{ - field bits<32> Inst; - Format Form = f; - - let Namespace = "Mips"; - - let Size = 4; - - bits<6> Opcode = 0; - - // Top 6 bits are the 'opcode' field - let Inst{31-26} = Opcode; - - let OutOperandList = outs; - let InOperandList = ins; - - let AsmString = asmstr; - let Pattern = pattern; - let Itinerary = itin; - - // - // Attributes specific to Mips instructions... - // - bits<4> FormBits = Form.Value; - bit isCTI = 0; // Any form of Control Transfer Instruction. - // Required for MIPSR6 - bit hasForbiddenSlot = 0; // Instruction has a forbidden slot. - bit IsPCRelativeLoad = 0; // Load instruction with implicit source register - // ($pc) and with explicit offset and destination - // register - bit hasFCCRegOperand = 0; // Instruction uses $fcc<X> register and is - // present in MIPS-I to MIPS-III. - - // TSFlags layout should be kept in sync with MCTargetDesc/MipsBaseInfo.h. - let TSFlags{3-0} = FormBits; - let TSFlags{4} = isCTI; - let TSFlags{5} = hasForbiddenSlot; - let TSFlags{6} = IsPCRelativeLoad; - let TSFlags{7} = hasFCCRegOperand; - - let DecoderNamespace = "Mips"; - - field bits<32> SoftFail = 0; -} - -// Mips32/64 Instruction Format -class InstSE<dag outs, dag ins, string asmstr, list<dag> pattern, - InstrItinClass itin, Format f, string opstr = ""> : - MipsInst<outs, ins, asmstr, pattern, itin, f> { - let EncodingPredicates = [NotInMips16Mode]; - string BaseOpcode = opstr; - string Arch; -} - -// Mips Pseudo Instructions Format -class MipsPseudo<dag outs, dag ins, list<dag> pattern, - InstrItinClass itin = IIPseudo> : - MipsInst<outs, ins, "", pattern, itin, Pseudo> { - let isCodeGenOnly = 1; - let isPseudo = 1; -} - -// Mips32/64 Pseudo Instruction Format -class PseudoSE<dag outs, dag ins, list<dag> pattern, - InstrItinClass itin = IIPseudo> : - MipsPseudo<outs, ins, pattern, itin> { - let EncodingPredicates = [NotInMips16Mode]; -} - -// Pseudo-instructions for alternate assembly syntax (never used by codegen). -// These are aliases that require C++ handling to convert to the target -// instruction, while InstAliases can be handled directly by tblgen. -class MipsAsmPseudoInst<dag outs, dag ins, string asmstr>: - MipsInst<outs, ins, asmstr, [], IIPseudo, Pseudo> { - let isPseudo = 1; - let hasNoSchedulingInfo = 1; - let Pattern = []; -} -//===----------------------------------------------------------------------===// -// Format R instruction class in Mips : <|opcode|rs|rt|rd|shamt|funct|> -//===----------------------------------------------------------------------===// - -class FR<bits<6> op, bits<6> _funct, dag outs, dag ins, string asmstr, - list<dag> pattern, InstrItinClass itin>: - InstSE<outs, ins, asmstr, pattern, itin, FrmR> -{ - bits<5> rd; - bits<5> rs; - bits<5> rt; - bits<5> shamt; - bits<6> funct; - - let Opcode = op; - let funct = _funct; - - let Inst{25-21} = rs; - let Inst{20-16} = rt; - let Inst{15-11} = rd; - let Inst{10-6} = shamt; - let Inst{5-0} = funct; -} - -//===----------------------------------------------------------------------===// -// Format I instruction class in Mips : <|opcode|rs|rt|immediate|> -//===----------------------------------------------------------------------===// - -class FI<bits<6> op, dag outs, dag ins, string asmstr, list<dag> pattern, - InstrItinClass itin>: InstSE<outs, ins, asmstr, pattern, itin, FrmI> -{ - bits<5> rt; - bits<5> rs; - bits<16> imm16; - - let Opcode = op; - - let Inst{25-21} = rs; - let Inst{20-16} = rt; - let Inst{15-0} = imm16; -} - -class BranchBase<bits<6> op, dag outs, dag ins, string asmstr, - list<dag> pattern, InstrItinClass itin>: - InstSE<outs, ins, asmstr, pattern, itin, FrmI> -{ - bits<5> rs; - bits<5> rt; - bits<16> imm16; - - let Opcode = op; - - let Inst{25-21} = rs; - let Inst{20-16} = rt; - let Inst{15-0} = imm16; -} - -//===----------------------------------------------------------------------===// -// Format J instruction class in Mips : <|opcode|address|> -//===----------------------------------------------------------------------===// - -class FJ<bits<6> op> : StdArch -{ - bits<26> target; - - bits<32> Inst; - - let Inst{31-26} = op; - let Inst{25-0} = target; -} - -//===----------------------------------------------------------------------===// -// MFC instruction class in Mips : <|op|mf|rt|rd|gst|0000|sel|> -//===----------------------------------------------------------------------===// -class MFC3OP_FM<bits<6> op, bits<5> mfmt, bits<3> guest> : StdArch { - bits<5> rt; - bits<5> rd; - bits<3> sel; - - bits<32> Inst; - - let Inst{31-26} = op; - let Inst{25-21} = mfmt; - let Inst{20-16} = rt; - let Inst{15-11} = rd; - let Inst{10-8} = guest; - let Inst{7-3} = 0; - let Inst{2-0} = sel; -} - -class MFC2OP_FM<bits<6> op, bits<5> mfmt> : StdArch { - bits<5> rt; - bits<16> imm16; - - bits<32> Inst; - - let Inst{31-26} = op; - let Inst{25-21} = mfmt; - let Inst{20-16} = rt; - let Inst{15-0} = imm16; -} - -class ADD_FM<bits<6> op, bits<6> funct> : StdArch { - bits<5> rd; - bits<5> rs; - bits<5> rt; - - bits<32> Inst; - - let Inst{31-26} = op; - let Inst{25-21} = rs; - let Inst{20-16} = rt; - let Inst{15-11} = rd; - let Inst{10-6} = 0; - let Inst{5-0} = funct; -} - -class ADDI_FM<bits<6> op> : StdArch { - bits<5> rs; - bits<5> rt; - bits<16> imm16; - - bits<32> Inst; - - let Inst{31-26} = op; - let Inst{25-21} = rs; - let Inst{20-16} = rt; - let Inst{15-0} = imm16; -} - -class SRA_FM<bits<6> funct, bit rotate> : StdArch { - bits<5> rd; - bits<5> rt; - bits<5> shamt; - - bits<32> Inst; - - let Inst{31-26} = 0; - let Inst{25-22} = 0; - let Inst{21} = rotate; - let Inst{20-16} = rt; - let Inst{15-11} = rd; - let Inst{10-6} = shamt; - let Inst{5-0} = funct; -} - -class SRLV_FM<bits<6> funct, bit rotate> : StdArch { - bits<5> rd; - bits<5> rt; - bits<5> rs; - - bits<32> Inst; - - let Inst{31-26} = 0; - let Inst{25-21} = rs; - let Inst{20-16} = rt; - let Inst{15-11} = rd; - let Inst{10-7} = 0; - let Inst{6} = rotate; - let Inst{5-0} = funct; -} - -class BEQ_FM<bits<6> op> : StdArch { - bits<5> rs; - bits<5> rt; - bits<16> offset; - - bits<32> Inst; - - let Inst{31-26} = op; - let Inst{25-21} = rs; - let Inst{20-16} = rt; - let Inst{15-0} = offset; -} - -class BGEZ_FM<bits<6> op, bits<5> funct> : StdArch { - bits<5> rs; - bits<16> offset; - - bits<32> Inst; - - let Inst{31-26} = op; - let Inst{25-21} = rs; - let Inst{20-16} = funct; - let Inst{15-0} = offset; -} - -class BBIT_FM<bits<6> op> : StdArch { - bits<5> rs; - bits<5> p; - bits<16> offset; - - bits<32> Inst; - - let Inst{31-26} = op; - let Inst{25-21} = rs; - let Inst{20-16} = p; - let Inst{15-0} = offset; -} - -class SLTI_FM<bits<6> op> : StdArch { - bits<5> rt; - bits<5> rs; - bits<16> imm16; - - bits<32> Inst; - - let Inst{31-26} = op; - let Inst{25-21} = rs; - let Inst{20-16} = rt; - let Inst{15-0} = imm16; -} - -class MFLO_FM<bits<6> funct> : StdArch { - bits<5> rd; - - bits<32> Inst; - - let Inst{31-26} = 0; - let Inst{25-16} = 0; - let Inst{15-11} = rd; - let Inst{10-6} = 0; - let Inst{5-0} = funct; -} - -class MTLO_FM<bits<6> funct> : StdArch { - bits<5> rs; - - bits<32> Inst; - - let Inst{31-26} = 0; - let Inst{25-21} = rs; - let Inst{20-6} = 0; - let Inst{5-0} = funct; -} - -class SEB_FM<bits<5> funct, bits<6> funct2> : StdArch { - bits<5> rd; - bits<5> rt; - - bits<32> Inst; - - let Inst{31-26} = 0x1f; - let Inst{25-21} = 0; - let Inst{20-16} = rt; - let Inst{15-11} = rd; - let Inst{10-6} = funct; - let Inst{5-0} = funct2; -} - -class CLO_FM<bits<6> funct> : StdArch { - bits<5> rd; - bits<5> rs; - bits<5> rt; - - bits<32> Inst; - - let Inst{31-26} = 0x1c; - let Inst{25-21} = rs; - let Inst{20-16} = rt; - let Inst{15-11} = rd; - let Inst{10-6} = 0; - let Inst{5-0} = funct; - let rt = rd; -} - -class LUI_FM : StdArch { - bits<5> rt; - bits<16> imm16; - - bits<32> Inst; - - let Inst{31-26} = 0xf; - let Inst{25-21} = 0; - let Inst{20-16} = rt; - let Inst{15-0} = imm16; -} - -class JALR_FM { - bits<5> rd; - bits<5> rs; - - bits<32> Inst; - - let Inst{31-26} = 0; - let Inst{25-21} = rs; - let Inst{20-16} = 0; - let Inst{15-11} = rd; - let Inst{10-6} = 0; - let Inst{5-0} = 9; -} - -class BGEZAL_FM<bits<5> funct> : StdArch { - bits<5> rs; - bits<16> offset; - - bits<32> Inst; - - let Inst{31-26} = 1; - let Inst{25-21} = rs; - let Inst{20-16} = funct; - let Inst{15-0} = offset; -} - -class SYNC_FM : StdArch { - bits<5> stype; - - bits<32> Inst; - - let Inst{31-26} = 0; - let Inst{10-6} = stype; - let Inst{5-0} = 0xf; -} - -class SYNCI_FM : StdArch { - // Produced by the mem_simm16 address as reg << 16 | imm (see getMemEncoding). - bits<21> addr; - bits<5> rs = addr{20-16}; - bits<16> offset = addr{15-0}; - - bits<32> Inst; - - let Inst{31-26} = 0b000001; - let Inst{25-21} = rs; - let Inst{20-16} = 0b11111; - let Inst{15-0} = offset; -} - -class MULT_FM<bits<6> op, bits<6> funct> : StdArch { - bits<5> rs; - bits<5> rt; - - bits<32> Inst; - - let Inst{31-26} = op; - let Inst{25-21} = rs; - let Inst{20-16} = rt; - let Inst{15-6} = 0; - let Inst{5-0} = funct; -} - -class EXT_FM<bits<6> funct> : StdArch { - bits<5> rt; - bits<5> rs; - bits<5> pos; - bits<5> size; - - bits<32> Inst; - - let Inst{31-26} = 0x1f; - let Inst{25-21} = rs; - let Inst{20-16} = rt; - let Inst{15-11} = size; - let Inst{10-6} = pos; - let Inst{5-0} = funct; -} - -class RDHWR_FM : StdArch { - bits<5> rt; - bits<5> rd; - bits<3> sel; - - bits<32> Inst; - - let Inst{31-26} = 0x1f; - let Inst{25-21} = 0; - let Inst{20-16} = rt; - let Inst{15-11} = rd; - let Inst{10-9} = 0b00; - let Inst{8-6} = sel; - let Inst{5-0} = 0x3b; -} - -class TEQ_FM<bits<6> funct> : StdArch { - bits<5> rs; - bits<5> rt; - bits<10> code_; - - bits<32> Inst; - - let Inst{31-26} = 0; - let Inst{25-21} = rs; - let Inst{20-16} = rt; - let Inst{15-6} = code_; - let Inst{5-0} = funct; -} - -class TEQI_FM<bits<5> funct> : StdArch { - bits<5> rs; - bits<16> imm16; - - bits<32> Inst; - - let Inst{31-26} = 1; - let Inst{25-21} = rs; - let Inst{20-16} = funct; - let Inst{15-0} = imm16; -} - -class WAIT_FM : StdArch { - bits<32> Inst; - - let Inst{31-26} = 0x10; - let Inst{25} = 1; - let Inst{24-6} = 0; - let Inst{5-0} = 0x20; -} - -class EXTS_FM<bits<6> funct> : StdArch { - bits<5> rt; - bits<5> rs; - bits<5> pos; - bits<5> lenm1; - - bits<32> Inst; - - let Inst{31-26} = 0x1c; - let Inst{25-21} = rs; - let Inst{20-16} = rt; - let Inst{15-11} = lenm1; - let Inst{10-6} = pos; - let Inst{5-0} = funct; -} - -class MTMR_FM<bits<6> funct> : StdArch { - bits<5> rs; - - bits<32> Inst; - - let Inst{31-26} = 0x1c; - let Inst{25-21} = rs; - let Inst{20-6} = 0; - let Inst{5-0} = funct; -} - -class POP_FM<bits<6> funct> : StdArch { - bits<5> rd; - bits<5> rs; - - bits<32> Inst; - - let Inst{31-26} = 0x1c; - let Inst{25-21} = rs; - let Inst{20-16} = 0; - let Inst{15-11} = rd; - let Inst{10-6} = 0; - let Inst{5-0} = funct; -} - -class SEQ_FM<bits<6> funct> : StdArch { - bits<5> rd; - bits<5> rs; - bits<5> rt; - - bits<32> Inst; - - let Inst{31-26} = 0x1c; - let Inst{25-21} = rs; - let Inst{20-16} = rt; - let Inst{15-11} = rd; - let Inst{10-6} = 0; - let Inst{5-0} = funct; -} - -class SEQI_FM<bits<6> funct> : StdArch { - bits<5> rs; - bits<5> rt; - bits<10> imm10; - - bits<32> Inst; - - let Inst{31-26} = 0x1c; - let Inst{25-21} = rs; - let Inst{20-16} = rt; - let Inst{15-6} = imm10; - let Inst{5-0} = funct; -} - -class SAA_FM<bits<6> funct> : StdArch { - bits<5> rt; - bits<5> rs; - - bits<32> Inst; - - let Inst{31-26} = 0x1c; - let Inst{25-21} = rs; - let Inst{20-16} = rt; - let Inst{15-6} = 0; - let Inst{5-0} = funct; -} - -//===----------------------------------------------------------------------===// -// System calls format <op|code_|funct> -//===----------------------------------------------------------------------===// - -class SYS_FM<bits<6> funct> : StdArch -{ - bits<20> code_; - bits<32> Inst; - let Inst{31-26} = 0x0; - let Inst{25-6} = code_; - let Inst{5-0} = funct; -} - -//===----------------------------------------------------------------------===// -// Break instruction format <op|code_1|funct> -//===----------------------------------------------------------------------===// - -class BRK_FM<bits<6> funct> : StdArch -{ - bits<10> code_1; - bits<10> code_2; - bits<32> Inst; - let Inst{31-26} = 0x0; - let Inst{25-16} = code_1; - let Inst{15-6} = code_2; - let Inst{5-0} = funct; -} - -//===----------------------------------------------------------------------===// -// Exception return format <Cop0|1|0|funct> -//===----------------------------------------------------------------------===// - -class ER_FM<bits<6> funct, bit LLBit> : StdArch -{ - bits<32> Inst; - let Inst{31-26} = 0x10; - let Inst{25} = 1; - let Inst{24-7} = 0; - let Inst{6} = LLBit; - let Inst{5-0} = funct; -} - -//===----------------------------------------------------------------------===// -// Enable/disable interrupt instruction format <Cop0|MFMC0|rt|12|0|sc|0|0> -//===----------------------------------------------------------------------===// - -class EI_FM<bits<1> sc> : StdArch -{ - bits<32> Inst; - bits<5> rt; - let Inst{31-26} = 0x10; - let Inst{25-21} = 0xb; - let Inst{20-16} = rt; - let Inst{15-11} = 0xc; - let Inst{10-6} = 0; - let Inst{5} = sc; - let Inst{4-0} = 0; -} - -//===----------------------------------------------------------------------===// -// -// FLOATING POINT INSTRUCTION FORMATS -// -// opcode - operation code. -// fs - src reg. -// ft - dst reg (on a 2 regs instr) or src reg (on a 3 reg instr). -// fd - dst reg, only used on 3 regs instr. -// fmt - double or single precision. -// funct - combined with opcode field give us an operation code. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// Format FI instruction class in Mips : <|opcode|base|ft|immediate|> -//===----------------------------------------------------------------------===// - -class FFI<bits<6> op, dag outs, dag ins, string asmstr, list<dag> pattern>: - InstSE<outs, ins, asmstr, pattern, NoItinerary, FrmFI> -{ - bits<5> ft; - bits<5> base; - bits<16> imm16; - - let Opcode = op; - - let Inst{25-21} = base; - let Inst{20-16} = ft; - let Inst{15-0} = imm16; -} - -class ADDS_FM<bits<6> funct, bits<5> fmt> : StdArch { - bits<5> fd; - bits<5> fs; - bits<5> ft; - - bits<32> Inst; - - let Inst{31-26} = 0x11; - let Inst{25-21} = fmt; - let Inst{20-16} = ft; - let Inst{15-11} = fs; - let Inst{10-6} = fd; - let Inst{5-0} = funct; -} - -class ABSS_FM<bits<6> funct, bits<5> fmt> : StdArch { - bits<5> fd; - bits<5> fs; - - bits<32> Inst; - - let Inst{31-26} = 0x11; - let Inst{25-21} = fmt; - let Inst{20-16} = 0; - let Inst{15-11} = fs; - let Inst{10-6} = fd; - let Inst{5-0} = funct; -} - -class MFC1_FM<bits<5> funct> : StdArch { - bits<5> rt; - bits<5> fs; - - bits<32> Inst; - - let Inst{31-26} = 0x11; - let Inst{25-21} = funct; - let Inst{20-16} = rt; - let Inst{15-11} = fs; - let Inst{10-0} = 0; -} - -class LW_FM<bits<6> op> : StdArch { - bits<5> rt; - bits<21> addr; - - bits<32> Inst; - - let Inst{31-26} = op; - let Inst{25-21} = addr{20-16}; - let Inst{20-16} = rt; - let Inst{15-0} = addr{15-0}; -} - -class MADDS_FM<bits<3> funct, bits<3> fmt> : StdArch { - bits<5> fd; - bits<5> fr; - bits<5> fs; - bits<5> ft; - - bits<32> Inst; - - let Inst{31-26} = 0x13; - let Inst{25-21} = fr; - let Inst{20-16} = ft; - let Inst{15-11} = fs; - let Inst{10-6} = fd; - let Inst{5-3} = funct; - let Inst{2-0} = fmt; -} - -class LWXC1_FM<bits<6> funct> : StdArch { - bits<5> fd; - bits<5> base; - bits<5> index; - - bits<32> Inst; - - let Inst{31-26} = 0x13; - let Inst{25-21} = base; - let Inst{20-16} = index; - let Inst{15-11} = 0; - let Inst{10-6} = fd; - let Inst{5-0} = funct; -} - -class SWXC1_FM<bits<6> funct> : StdArch { - bits<5> fs; - bits<5> base; - bits<5> index; - - bits<32> Inst; - - let Inst{31-26} = 0x13; - let Inst{25-21} = base; - let Inst{20-16} = index; - let Inst{15-11} = fs; - let Inst{10-6} = 0; - let Inst{5-0} = funct; -} - -class BC1F_FM<bit nd, bit tf> : StdArch { - bits<3> fcc; - bits<16> offset; - - bits<32> Inst; - - let Inst{31-26} = 0x11; - let Inst{25-21} = 0x8; - let Inst{20-18} = fcc; - let Inst{17} = nd; - let Inst{16} = tf; - let Inst{15-0} = offset; -} - -class CEQS_FM<bits<5> fmt> : StdArch { - bits<5> fs; - bits<5> ft; - bits<3> fcc; - bits<4> cond; - - bits<32> Inst; - - let Inst{31-26} = 0x11; - let Inst{25-21} = fmt; - let Inst{20-16} = ft; - let Inst{15-11} = fs; - let Inst{10-8} = fcc; - let Inst{7-4} = 0x3; - let Inst{3-0} = cond; -} - -class C_COND_FM<bits<5> fmt, bits<4> c> : CEQS_FM<fmt> { - let cond = c; -} - -class CMov_I_F_FM<bits<6> funct, bits<5> fmt> : StdArch { - bits<5> fd; - bits<5> fs; - bits<5> rt; - - bits<32> Inst; - - let Inst{31-26} = 0x11; - let Inst{25-21} = fmt; - let Inst{20-16} = rt; - let Inst{15-11} = fs; - let Inst{10-6} = fd; - let Inst{5-0} = funct; -} - -class CMov_F_I_FM<bit tf> : StdArch { - bits<5> rd; - bits<5> rs; - bits<3> fcc; - - bits<32> Inst; - - let Inst{31-26} = 0; - let Inst{25-21} = rs; - let Inst{20-18} = fcc; - let Inst{17} = 0; - let Inst{16} = tf; - let Inst{15-11} = rd; - let Inst{10-6} = 0; - let Inst{5-0} = 1; -} - -class CMov_F_F_FM<bits<5> fmt, bit tf> : StdArch { - bits<5> fd; - bits<5> fs; - bits<3> fcc; - - bits<32> Inst; - - let Inst{31-26} = 0x11; - let Inst{25-21} = fmt; - let Inst{20-18} = fcc; - let Inst{17} = 0; - let Inst{16} = tf; - let Inst{15-11} = fs; - let Inst{10-6} = fd; - let Inst{5-0} = 0x11; -} - -class BARRIER_FM<bits<5> op> : StdArch { - bits<32> Inst; - - let Inst{31-26} = 0; // SPECIAL - let Inst{25-21} = 0; - let Inst{20-16} = 0; // rt = 0 - let Inst{15-11} = 0; // rd = 0 - let Inst{10-6} = op; // Operation - let Inst{5-0} = 0; // SLL -} - -class SDBBP_FM : StdArch { - bits<20> code_; - - bits<32> Inst; - - let Inst{31-26} = 0b011100; // SPECIAL2 - let Inst{25-6} = code_; - let Inst{5-0} = 0b111111; // SDBBP -} - -class JR_HB_FM<bits<6> op> : StdArch{ - bits<5> rs; - - bits<32> Inst; - - let Inst{31-26} = 0; // SPECIAL - let Inst{25-21} = rs; - let Inst{20-11} = 0; - let Inst{10} = 1; - let Inst{9-6} = 0; - let Inst{5-0} = op; -} - -class JALR_HB_FM<bits<6> op> : StdArch { - bits<5> rd; - bits<5> rs; - - bits<32> Inst; - - let Inst{31-26} = 0; // SPECIAL - let Inst{25-21} = rs; - let Inst{20-16} = 0; - let Inst{15-11} = rd; - let Inst{10} = 1; - let Inst{9-6} = 0; - let Inst{5-0} = op; -} - -class COP0_TLB_FM<bits<6> op> : StdArch { - bits<32> Inst; - - let Inst{31-26} = 0x10; // COP0 - let Inst{25} = 1; // CO - let Inst{24-6} = 0; - let Inst{5-0} = op; // Operation -} - -class CACHEOP_FM<bits<6> op> : StdArch { - bits<21> addr; - bits<5> hint; - bits<5> base = addr{20-16}; - bits<16> offset = addr{15-0}; - - bits<32> Inst; - - let Inst{31-26} = op; - let Inst{25-21} = base; - let Inst{20-16} = hint; - let Inst{15-0} = offset; -} - -class HYPCALL_FM<bits<6> op> : StdArch { - bits<10> code_; - - bits<32> Inst; - - let Inst{31-26} = 0b010000; - let Inst{25} = 1; - let Inst{20-11} = code_; - let Inst{5-0} = op; -} diff --git a/contrib/llvm/lib/Target/Mips/MipsInstrInfo.cpp b/contrib/llvm/lib/Target/Mips/MipsInstrInfo.cpp deleted file mode 100644 index fbd56206b249..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsInstrInfo.cpp +++ /dev/null @@ -1,842 +0,0 @@ -//===- MipsInstrInfo.cpp - Mips Instruction Information -------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains the Mips implementation of the TargetInstrInfo class. -// -//===----------------------------------------------------------------------===// - -#include "MipsInstrInfo.h" -#include "MCTargetDesc/MipsBaseInfo.h" -#include "MCTargetDesc/MipsMCTargetDesc.h" -#include "MipsSubtarget.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/MachineOperand.h" -#include "llvm/CodeGen/TargetOpcodes.h" -#include "llvm/CodeGen/TargetSubtargetInfo.h" -#include "llvm/IR/DebugLoc.h" -#include "llvm/MC/MCInstrDesc.h" -#include "llvm/Target/TargetMachine.h" -#include <cassert> - -using namespace llvm; - -#define GET_INSTRINFO_CTOR_DTOR -#include "MipsGenInstrInfo.inc" - -// Pin the vtable to this file. -void MipsInstrInfo::anchor() {} - -MipsInstrInfo::MipsInstrInfo(const MipsSubtarget &STI, unsigned UncondBr) - : MipsGenInstrInfo(Mips::ADJCALLSTACKDOWN, Mips::ADJCALLSTACKUP), - Subtarget(STI), UncondBrOpc(UncondBr) {} - -const MipsInstrInfo *MipsInstrInfo::create(MipsSubtarget &STI) { - if (STI.inMips16Mode()) - return createMips16InstrInfo(STI); - - return createMipsSEInstrInfo(STI); -} - -bool MipsInstrInfo::isZeroImm(const MachineOperand &op) const { - return op.isImm() && op.getImm() == 0; -} - -/// insertNoop - If data hazard condition is found insert the target nop -/// instruction. -// FIXME: This appears to be dead code. -void MipsInstrInfo:: -insertNoop(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const -{ - DebugLoc DL; - BuildMI(MBB, MI, DL, get(Mips::NOP)); -} - -MachineMemOperand * -MipsInstrInfo::GetMemOperand(MachineBasicBlock &MBB, int FI, - MachineMemOperand::Flags Flags) const { - MachineFunction &MF = *MBB.getParent(); - MachineFrameInfo &MFI = MF.getFrameInfo(); - unsigned Align = MFI.getObjectAlignment(FI); - - return MF.getMachineMemOperand(MachinePointerInfo::getFixedStack(MF, FI), - Flags, MFI.getObjectSize(FI), Align); -} - -//===----------------------------------------------------------------------===// -// Branch Analysis -//===----------------------------------------------------------------------===// - -void MipsInstrInfo::AnalyzeCondBr(const MachineInstr *Inst, unsigned Opc, - MachineBasicBlock *&BB, - SmallVectorImpl<MachineOperand> &Cond) const { - assert(getAnalyzableBrOpc(Opc) && "Not an analyzable branch"); - int NumOp = Inst->getNumExplicitOperands(); - - // for both int and fp branches, the last explicit operand is the - // MBB. - BB = Inst->getOperand(NumOp-1).getMBB(); - Cond.push_back(MachineOperand::CreateImm(Opc)); - - for (int i = 0; i < NumOp-1; i++) - Cond.push_back(Inst->getOperand(i)); -} - -bool MipsInstrInfo::analyzeBranch(MachineBasicBlock &MBB, - MachineBasicBlock *&TBB, - MachineBasicBlock *&FBB, - SmallVectorImpl<MachineOperand> &Cond, - bool AllowModify) const { - SmallVector<MachineInstr*, 2> BranchInstrs; - BranchType BT = analyzeBranch(MBB, TBB, FBB, Cond, AllowModify, BranchInstrs); - - return (BT == BT_None) || (BT == BT_Indirect); -} - -void MipsInstrInfo::BuildCondBr(MachineBasicBlock &MBB, MachineBasicBlock *TBB, - const DebugLoc &DL, - ArrayRef<MachineOperand> Cond) const { - unsigned Opc = Cond[0].getImm(); - const MCInstrDesc &MCID = get(Opc); - MachineInstrBuilder MIB = BuildMI(&MBB, DL, MCID); - - for (unsigned i = 1; i < Cond.size(); ++i) { - assert((Cond[i].isImm() || Cond[i].isReg()) && - "Cannot copy operand for conditional branch!"); - MIB.add(Cond[i]); - } - MIB.addMBB(TBB); -} - -unsigned MipsInstrInfo::insertBranch(MachineBasicBlock &MBB, - MachineBasicBlock *TBB, - MachineBasicBlock *FBB, - ArrayRef<MachineOperand> Cond, - const DebugLoc &DL, - int *BytesAdded) const { - // Shouldn't be a fall through. - assert(TBB && "insertBranch must not be told to insert a fallthrough"); - assert(!BytesAdded && "code size not handled"); - - // # of condition operands: - // Unconditional branches: 0 - // Floating point branches: 1 (opc) - // Int BranchZero: 2 (opc, reg) - // Int Branch: 3 (opc, reg0, reg1) - assert((Cond.size() <= 3) && - "# of Mips branch conditions must be <= 3!"); - - // Two-way Conditional branch. - if (FBB) { - BuildCondBr(MBB, TBB, DL, Cond); - BuildMI(&MBB, DL, get(UncondBrOpc)).addMBB(FBB); - return 2; - } - - // One way branch. - // Unconditional branch. - if (Cond.empty()) - BuildMI(&MBB, DL, get(UncondBrOpc)).addMBB(TBB); - else // Conditional branch. - BuildCondBr(MBB, TBB, DL, Cond); - return 1; -} - -unsigned MipsInstrInfo::removeBranch(MachineBasicBlock &MBB, - int *BytesRemoved) const { - assert(!BytesRemoved && "code size not handled"); - - MachineBasicBlock::reverse_iterator I = MBB.rbegin(), REnd = MBB.rend(); - unsigned removed = 0; - - // Up to 2 branches are removed. - // Note that indirect branches are not removed. - while (I != REnd && removed < 2) { - // Skip past debug instructions. - if (I->isDebugInstr()) { - ++I; - continue; - } - if (!getAnalyzableBrOpc(I->getOpcode())) - break; - // Remove the branch. - I->eraseFromParent(); - I = MBB.rbegin(); - ++removed; - } - - return removed; -} - -/// reverseBranchCondition - Return the inverse opcode of the -/// specified Branch instruction. -bool MipsInstrInfo::reverseBranchCondition( - SmallVectorImpl<MachineOperand> &Cond) const { - assert( (Cond.size() && Cond.size() <= 3) && - "Invalid Mips branch condition!"); - Cond[0].setImm(getOppositeBranchOpc(Cond[0].getImm())); - return false; -} - -MipsInstrInfo::BranchType MipsInstrInfo::analyzeBranch( - MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, - SmallVectorImpl<MachineOperand> &Cond, bool AllowModify, - SmallVectorImpl<MachineInstr *> &BranchInstrs) const { - MachineBasicBlock::reverse_iterator I = MBB.rbegin(), REnd = MBB.rend(); - - // Skip all the debug instructions. - while (I != REnd && I->isDebugInstr()) - ++I; - - if (I == REnd || !isUnpredicatedTerminator(*I)) { - // This block ends with no branches (it just falls through to its succ). - // Leave TBB/FBB null. - TBB = FBB = nullptr; - return BT_NoBranch; - } - - MachineInstr *LastInst = &*I; - unsigned LastOpc = LastInst->getOpcode(); - BranchInstrs.push_back(LastInst); - - // Not an analyzable branch (e.g., indirect jump). - if (!getAnalyzableBrOpc(LastOpc)) - return LastInst->isIndirectBranch() ? BT_Indirect : BT_None; - - // Get the second to last instruction in the block. - unsigned SecondLastOpc = 0; - MachineInstr *SecondLastInst = nullptr; - - // Skip past any debug instruction to see if the second last actual - // is a branch. - ++I; - while (I != REnd && I->isDebugInstr()) - ++I; - - if (I != REnd) { - SecondLastInst = &*I; - SecondLastOpc = getAnalyzableBrOpc(SecondLastInst->getOpcode()); - - // Not an analyzable branch (must be an indirect jump). - if (isUnpredicatedTerminator(*SecondLastInst) && !SecondLastOpc) - return BT_None; - } - - // If there is only one terminator instruction, process it. - if (!SecondLastOpc) { - // Unconditional branch. - if (LastInst->isUnconditionalBranch()) { - TBB = LastInst->getOperand(0).getMBB(); - return BT_Uncond; - } - - // Conditional branch - AnalyzeCondBr(LastInst, LastOpc, TBB, Cond); - return BT_Cond; - } - - // If we reached here, there are two branches. - // If there are three terminators, we don't know what sort of block this is. - if (++I != REnd && isUnpredicatedTerminator(*I)) - return BT_None; - - BranchInstrs.insert(BranchInstrs.begin(), SecondLastInst); - - // If second to last instruction is an unconditional branch, - // analyze it and remove the last instruction. - if (SecondLastInst->isUnconditionalBranch()) { - // Return if the last instruction cannot be removed. - if (!AllowModify) - return BT_None; - - TBB = SecondLastInst->getOperand(0).getMBB(); - LastInst->eraseFromParent(); - BranchInstrs.pop_back(); - return BT_Uncond; - } - - // Conditional branch followed by an unconditional branch. - // The last one must be unconditional. - if (!LastInst->isUnconditionalBranch()) - return BT_None; - - AnalyzeCondBr(SecondLastInst, SecondLastOpc, TBB, Cond); - FBB = LastInst->getOperand(0).getMBB(); - - return BT_CondUncond; -} - -bool MipsInstrInfo::isBranchOffsetInRange(unsigned BranchOpc, int64_t BrOffset) const { - switch (BranchOpc) { - case Mips::B: - case Mips::BAL: - case Mips::BAL_BR: - case Mips::BAL_BR_MM: - case Mips::BC1F: - case Mips::BC1FL: - case Mips::BC1T: - case Mips::BC1TL: - case Mips::BEQ: case Mips::BEQ64: - case Mips::BEQL: - case Mips::BGEZ: case Mips::BGEZ64: - case Mips::BGEZL: - case Mips::BGEZAL: - case Mips::BGEZALL: - case Mips::BGTZ: case Mips::BGTZ64: - case Mips::BGTZL: - case Mips::BLEZ: case Mips::BLEZ64: - case Mips::BLEZL: - case Mips::BLTZ: case Mips::BLTZ64: - case Mips::BLTZL: - case Mips::BLTZAL: - case Mips::BLTZALL: - case Mips::BNE: case Mips::BNE64: - case Mips::BNEL: - return isInt<18>(BrOffset); - - // microMIPSr3 branches - case Mips::B_MM: - case Mips::BC1F_MM: - case Mips::BC1T_MM: - case Mips::BEQ_MM: - case Mips::BGEZ_MM: - case Mips::BGEZAL_MM: - case Mips::BGTZ_MM: - case Mips::BLEZ_MM: - case Mips::BLTZ_MM: - case Mips::BLTZAL_MM: - case Mips::BNE_MM: - case Mips::BEQZC_MM: - case Mips::BNEZC_MM: - return isInt<17>(BrOffset); - - // microMIPSR3 short branches. - case Mips::B16_MM: - return isInt<11>(BrOffset); - - case Mips::BEQZ16_MM: - case Mips::BNEZ16_MM: - return isInt<8>(BrOffset); - - // MIPSR6 branches. - case Mips::BALC: - case Mips::BC: - return isInt<28>(BrOffset); - - case Mips::BC1EQZ: - case Mips::BC1NEZ: - case Mips::BC2EQZ: - case Mips::BC2NEZ: - case Mips::BEQC: case Mips::BEQC64: - case Mips::BNEC: case Mips::BNEC64: - case Mips::BGEC: case Mips::BGEC64: - case Mips::BGEUC: case Mips::BGEUC64: - case Mips::BGEZC: case Mips::BGEZC64: - case Mips::BGTZC: case Mips::BGTZC64: - case Mips::BLEZC: case Mips::BLEZC64: - case Mips::BLTC: case Mips::BLTC64: - case Mips::BLTUC: case Mips::BLTUC64: - case Mips::BLTZC: case Mips::BLTZC64: - case Mips::BNVC: - case Mips::BOVC: - case Mips::BGEZALC: - case Mips::BEQZALC: - case Mips::BGTZALC: - case Mips::BLEZALC: - case Mips::BLTZALC: - case Mips::BNEZALC: - return isInt<18>(BrOffset); - - case Mips::BEQZC: case Mips::BEQZC64: - case Mips::BNEZC: case Mips::BNEZC64: - return isInt<23>(BrOffset); - - // microMIPSR6 branches - case Mips::BC16_MMR6: - return isInt<11>(BrOffset); - - case Mips::BEQZC16_MMR6: - case Mips::BNEZC16_MMR6: - return isInt<8>(BrOffset); - - case Mips::BALC_MMR6: - case Mips::BC_MMR6: - return isInt<27>(BrOffset); - - case Mips::BC1EQZC_MMR6: - case Mips::BC1NEZC_MMR6: - case Mips::BC2EQZC_MMR6: - case Mips::BC2NEZC_MMR6: - case Mips::BGEZALC_MMR6: - case Mips::BEQZALC_MMR6: - case Mips::BGTZALC_MMR6: - case Mips::BLEZALC_MMR6: - case Mips::BLTZALC_MMR6: - case Mips::BNEZALC_MMR6: - case Mips::BNVC_MMR6: - case Mips::BOVC_MMR6: - return isInt<17>(BrOffset); - - case Mips::BEQC_MMR6: - case Mips::BNEC_MMR6: - case Mips::BGEC_MMR6: - case Mips::BGEUC_MMR6: - case Mips::BGEZC_MMR6: - case Mips::BGTZC_MMR6: - case Mips::BLEZC_MMR6: - case Mips::BLTC_MMR6: - case Mips::BLTUC_MMR6: - case Mips::BLTZC_MMR6: - return isInt<18>(BrOffset); - - case Mips::BEQZC_MMR6: - case Mips::BNEZC_MMR6: - return isInt<23>(BrOffset); - - // DSP branches. - case Mips::BPOSGE32: - return isInt<18>(BrOffset); - case Mips::BPOSGE32_MM: - case Mips::BPOSGE32C_MMR3: - return isInt<17>(BrOffset); - - // cnMIPS branches. - case Mips::BBIT0: - case Mips::BBIT032: - case Mips::BBIT1: - case Mips::BBIT132: - return isInt<18>(BrOffset); - - // MSA branches. - case Mips::BZ_B: - case Mips::BZ_H: - case Mips::BZ_W: - case Mips::BZ_D: - case Mips::BZ_V: - case Mips::BNZ_B: - case Mips::BNZ_H: - case Mips::BNZ_W: - case Mips::BNZ_D: - case Mips::BNZ_V: - return isInt<18>(BrOffset); - } - - llvm_unreachable("Unknown branch instruction!"); -} - - -/// Return the corresponding compact (no delay slot) form of a branch. -unsigned MipsInstrInfo::getEquivalentCompactForm( - const MachineBasicBlock::iterator I) const { - unsigned Opcode = I->getOpcode(); - bool canUseShortMicroMipsCTI = false; - - if (Subtarget.inMicroMipsMode()) { - switch (Opcode) { - case Mips::BNE: - case Mips::BNE_MM: - case Mips::BEQ: - case Mips::BEQ_MM: - // microMIPS has NE,EQ branches that do not have delay slots provided one - // of the operands is zero. - if (I->getOperand(1).getReg() == Subtarget.getABI().GetZeroReg()) - canUseShortMicroMipsCTI = true; - break; - // For microMIPS the PseudoReturn and PseudoIndirectBranch are always - // expanded to JR_MM, so they can be replaced with JRC16_MM. - case Mips::JR: - case Mips::PseudoReturn: - case Mips::PseudoIndirectBranch: - canUseShortMicroMipsCTI = true; - break; - } - } - - // MIPSR6 forbids both operands being the zero register. - if (Subtarget.hasMips32r6() && (I->getNumOperands() > 1) && - (I->getOperand(0).isReg() && - (I->getOperand(0).getReg() == Mips::ZERO || - I->getOperand(0).getReg() == Mips::ZERO_64)) && - (I->getOperand(1).isReg() && - (I->getOperand(1).getReg() == Mips::ZERO || - I->getOperand(1).getReg() == Mips::ZERO_64))) - return 0; - - if (Subtarget.hasMips32r6() || canUseShortMicroMipsCTI) { - switch (Opcode) { - case Mips::B: - return Mips::BC; - case Mips::BAL: - return Mips::BALC; - case Mips::BEQ: - case Mips::BEQ_MM: - if (canUseShortMicroMipsCTI) - return Mips::BEQZC_MM; - else if (I->getOperand(0).getReg() == I->getOperand(1).getReg()) - return 0; - return Mips::BEQC; - case Mips::BNE: - case Mips::BNE_MM: - if (canUseShortMicroMipsCTI) - return Mips::BNEZC_MM; - else if (I->getOperand(0).getReg() == I->getOperand(1).getReg()) - return 0; - return Mips::BNEC; - case Mips::BGE: - if (I->getOperand(0).getReg() == I->getOperand(1).getReg()) - return 0; - return Mips::BGEC; - case Mips::BGEU: - if (I->getOperand(0).getReg() == I->getOperand(1).getReg()) - return 0; - return Mips::BGEUC; - case Mips::BGEZ: - return Mips::BGEZC; - case Mips::BGTZ: - return Mips::BGTZC; - case Mips::BLEZ: - return Mips::BLEZC; - case Mips::BLT: - if (I->getOperand(0).getReg() == I->getOperand(1).getReg()) - return 0; - return Mips::BLTC; - case Mips::BLTU: - if (I->getOperand(0).getReg() == I->getOperand(1).getReg()) - return 0; - return Mips::BLTUC; - case Mips::BLTZ: - return Mips::BLTZC; - case Mips::BEQ64: - if (I->getOperand(0).getReg() == I->getOperand(1).getReg()) - return 0; - return Mips::BEQC64; - case Mips::BNE64: - if (I->getOperand(0).getReg() == I->getOperand(1).getReg()) - return 0; - return Mips::BNEC64; - case Mips::BGTZ64: - return Mips::BGTZC64; - case Mips::BGEZ64: - return Mips::BGEZC64; - case Mips::BLTZ64: - return Mips::BLTZC64; - case Mips::BLEZ64: - return Mips::BLEZC64; - // For MIPSR6, the instruction 'jic' can be used for these cases. Some - // tools will accept 'jrc reg' as an alias for 'jic 0, $reg'. - case Mips::JR: - case Mips::PseudoIndirectBranchR6: - case Mips::PseudoReturn: - case Mips::TAILCALLR6REG: - if (canUseShortMicroMipsCTI) - return Mips::JRC16_MM; - return Mips::JIC; - case Mips::JALRPseudo: - return Mips::JIALC; - case Mips::JR64: - case Mips::PseudoIndirectBranch64R6: - case Mips::PseudoReturn64: - case Mips::TAILCALL64R6REG: - return Mips::JIC64; - case Mips::JALR64Pseudo: - return Mips::JIALC64; - default: - return 0; - } - } - - return 0; -} - -/// Predicate for distingushing between control transfer instructions and all -/// other instructions for handling forbidden slots. Consider inline assembly -/// as unsafe as well. -bool MipsInstrInfo::SafeInForbiddenSlot(const MachineInstr &MI) const { - if (MI.isInlineAsm()) - return false; - - return (MI.getDesc().TSFlags & MipsII::IsCTI) == 0; -} - -/// Predicate for distingushing instructions that have forbidden slots. -bool MipsInstrInfo::HasForbiddenSlot(const MachineInstr &MI) const { - return (MI.getDesc().TSFlags & MipsII::HasForbiddenSlot) != 0; -} - -/// Return the number of bytes of code the specified instruction may be. -unsigned MipsInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const { - switch (MI.getOpcode()) { - default: - return MI.getDesc().getSize(); - case TargetOpcode::INLINEASM: - case TargetOpcode::INLINEASM_BR: { // Inline Asm: Variable size. - const MachineFunction *MF = MI.getParent()->getParent(); - const char *AsmStr = MI.getOperand(0).getSymbolName(); - return getInlineAsmLength(AsmStr, *MF->getTarget().getMCAsmInfo()); - } - case Mips::CONSTPOOL_ENTRY: - // If this machine instr is a constant pool entry, its size is recorded as - // operand #2. - return MI.getOperand(2).getImm(); - } -} - -MachineInstrBuilder -MipsInstrInfo::genInstrWithNewOpc(unsigned NewOpc, - MachineBasicBlock::iterator I) const { - MachineInstrBuilder MIB; - - // Certain branches have two forms: e.g beq $1, $zero, dest vs beqz $1, dest - // Pick the zero form of the branch for readable assembly and for greater - // branch distance in non-microMIPS mode. - // Additional MIPSR6 does not permit the use of register $zero for compact - // branches. - // FIXME: Certain atomic sequences on mips64 generate 32bit references to - // Mips::ZERO, which is incorrect. This test should be updated to use - // Subtarget.getABI().GetZeroReg() when those atomic sequences and others - // are fixed. - int ZeroOperandPosition = -1; - bool BranchWithZeroOperand = false; - if (I->isBranch() && !I->isPseudo()) { - auto TRI = I->getParent()->getParent()->getSubtarget().getRegisterInfo(); - ZeroOperandPosition = I->findRegisterUseOperandIdx(Mips::ZERO, false, TRI); - BranchWithZeroOperand = ZeroOperandPosition != -1; - } - - if (BranchWithZeroOperand) { - switch (NewOpc) { - case Mips::BEQC: - NewOpc = Mips::BEQZC; - break; - case Mips::BNEC: - NewOpc = Mips::BNEZC; - break; - case Mips::BGEC: - NewOpc = Mips::BGEZC; - break; - case Mips::BLTC: - NewOpc = Mips::BLTZC; - break; - case Mips::BEQC64: - NewOpc = Mips::BEQZC64; - break; - case Mips::BNEC64: - NewOpc = Mips::BNEZC64; - break; - } - } - - MIB = BuildMI(*I->getParent(), I, I->getDebugLoc(), get(NewOpc)); - - // For MIPSR6 JI*C requires an immediate 0 as an operand, JIALC(64) an - // immediate 0 as an operand and requires the removal of it's implicit-def %ra - // implicit operand as copying the implicit operations of the instructio we're - // looking at will give us the correct flags. - if (NewOpc == Mips::JIC || NewOpc == Mips::JIALC || NewOpc == Mips::JIC64 || - NewOpc == Mips::JIALC64) { - - if (NewOpc == Mips::JIALC || NewOpc == Mips::JIALC64) - MIB->RemoveOperand(0); - - for (unsigned J = 0, E = I->getDesc().getNumOperands(); J < E; ++J) { - MIB.add(I->getOperand(J)); - } - - MIB.addImm(0); - - // If I has an MCSymbol operand (used by asm printer, to emit R_MIPS_JALR), - // add it to the new instruction. - for (unsigned J = I->getDesc().getNumOperands(), E = I->getNumOperands(); - J < E; ++J) { - const MachineOperand &MO = I->getOperand(J); - if (MO.isMCSymbol() && (MO.getTargetFlags() & MipsII::MO_JALR)) - MIB.addSym(MO.getMCSymbol(), MipsII::MO_JALR); - } - - - } else { - for (unsigned J = 0, E = I->getDesc().getNumOperands(); J < E; ++J) { - if (BranchWithZeroOperand && (unsigned)ZeroOperandPosition == J) - continue; - - MIB.add(I->getOperand(J)); - } - } - - MIB.copyImplicitOps(*I); - MIB.cloneMemRefs(*I); - return MIB; -} - -bool MipsInstrInfo::findCommutedOpIndices(MachineInstr &MI, unsigned &SrcOpIdx1, - unsigned &SrcOpIdx2) const { - assert(!MI.isBundle() && - "TargetInstrInfo::findCommutedOpIndices() can't handle bundles"); - - const MCInstrDesc &MCID = MI.getDesc(); - if (!MCID.isCommutable()) - return false; - - switch (MI.getOpcode()) { - case Mips::DPADD_U_H: - case Mips::DPADD_U_W: - case Mips::DPADD_U_D: - case Mips::DPADD_S_H: - case Mips::DPADD_S_W: - case Mips::DPADD_S_D: - // The first operand is both input and output, so it should not commute - if (!fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 2, 3)) - return false; - - if (!MI.getOperand(SrcOpIdx1).isReg() || !MI.getOperand(SrcOpIdx2).isReg()) - return false; - return true; - } - return TargetInstrInfo::findCommutedOpIndices(MI, SrcOpIdx1, SrcOpIdx2); -} - -// ins, ext, dext*, dins have the following constraints: -// X <= pos < Y -// X < size <= Y -// X < pos+size <= Y -// -// dinsm and dinsu have the following constraints: -// X <= pos < Y -// X <= size <= Y -// X < pos+size <= Y -// -// The callee of verifyInsExtInstruction however gives the bounds of -// dins[um] like the other (d)ins (d)ext(um) instructions, so that this -// function doesn't have to vary it's behaviour based on the instruction -// being checked. -static bool verifyInsExtInstruction(const MachineInstr &MI, StringRef &ErrInfo, - const int64_t PosLow, const int64_t PosHigh, - const int64_t SizeLow, - const int64_t SizeHigh, - const int64_t BothLow, - const int64_t BothHigh) { - MachineOperand MOPos = MI.getOperand(2); - if (!MOPos.isImm()) { - ErrInfo = "Position is not an immediate!"; - return false; - } - int64_t Pos = MOPos.getImm(); - if (!((PosLow <= Pos) && (Pos < PosHigh))) { - ErrInfo = "Position operand is out of range!"; - return false; - } - - MachineOperand MOSize = MI.getOperand(3); - if (!MOSize.isImm()) { - ErrInfo = "Size operand is not an immediate!"; - return false; - } - int64_t Size = MOSize.getImm(); - if (!((SizeLow < Size) && (Size <= SizeHigh))) { - ErrInfo = "Size operand is out of range!"; - return false; - } - - if (!((BothLow < (Pos + Size)) && ((Pos + Size) <= BothHigh))) { - ErrInfo = "Position + Size is out of range!"; - return false; - } - - return true; -} - -// Perform target specific instruction verification. -bool MipsInstrInfo::verifyInstruction(const MachineInstr &MI, - StringRef &ErrInfo) const { - // Verify that ins and ext instructions are well formed. - switch (MI.getOpcode()) { - case Mips::EXT: - case Mips::EXT_MM: - case Mips::INS: - case Mips::INS_MM: - case Mips::DINS: - return verifyInsExtInstruction(MI, ErrInfo, 0, 32, 0, 32, 0, 32); - case Mips::DINSM: - // The ISA spec has a subtle difference between dinsm and dextm - // in that it says: - // 2 <= size <= 64 for 'dinsm' but 'dextm' has 32 < size <= 64. - // To make the bounds checks similar, the range 1 < size <= 64 is checked - // for 'dinsm'. - return verifyInsExtInstruction(MI, ErrInfo, 0, 32, 1, 64, 32, 64); - case Mips::DINSU: - // The ISA spec has a subtle difference between dinsu and dextu in that - // the size range of dinsu is specified as 1 <= size <= 32 whereas size - // for dextu is 0 < size <= 32. The range checked for dinsu here is - // 0 < size <= 32, which is equivalent and similar to dextu. - return verifyInsExtInstruction(MI, ErrInfo, 32, 64, 0, 32, 32, 64); - case Mips::DEXT: - return verifyInsExtInstruction(MI, ErrInfo, 0, 32, 0, 32, 0, 63); - case Mips::DEXTM: - return verifyInsExtInstruction(MI, ErrInfo, 0, 32, 32, 64, 32, 64); - case Mips::DEXTU: - return verifyInsExtInstruction(MI, ErrInfo, 32, 64, 0, 32, 32, 64); - case Mips::TAILCALLREG: - case Mips::PseudoIndirectBranch: - case Mips::JR: - case Mips::JR64: - case Mips::JALR: - case Mips::JALR64: - case Mips::JALRPseudo: - if (!Subtarget.useIndirectJumpsHazard()) - return true; - - ErrInfo = "invalid instruction when using jump guards!"; - return false; - default: - return true; - } - - return true; -} - -std::pair<unsigned, unsigned> -MipsInstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const { - return std::make_pair(TF, 0u); -} - -ArrayRef<std::pair<unsigned, const char*>> -MipsInstrInfo::getSerializableDirectMachineOperandTargetFlags() const { - using namespace MipsII; - - static const std::pair<unsigned, const char*> Flags[] = { - {MO_GOT, "mips-got"}, - {MO_GOT_CALL, "mips-got-call"}, - {MO_GPREL, "mips-gprel"}, - {MO_ABS_HI, "mips-abs-hi"}, - {MO_ABS_LO, "mips-abs-lo"}, - {MO_TLSGD, "mips-tlsgd"}, - {MO_TLSLDM, "mips-tlsldm"}, - {MO_DTPREL_HI, "mips-dtprel-hi"}, - {MO_DTPREL_LO, "mips-dtprel-lo"}, - {MO_GOTTPREL, "mips-gottprel"}, - {MO_TPREL_HI, "mips-tprel-hi"}, - {MO_TPREL_LO, "mips-tprel-lo"}, - {MO_GPOFF_HI, "mips-gpoff-hi"}, - {MO_GPOFF_LO, "mips-gpoff-lo"}, - {MO_GOT_DISP, "mips-got-disp"}, - {MO_GOT_PAGE, "mips-got-page"}, - {MO_GOT_OFST, "mips-got-ofst"}, - {MO_HIGHER, "mips-higher"}, - {MO_HIGHEST, "mips-highest"}, - {MO_GOT_HI16, "mips-got-hi16"}, - {MO_GOT_LO16, "mips-got-lo16"}, - {MO_CALL_HI16, "mips-call-hi16"}, - {MO_CALL_LO16, "mips-call-lo16"}, - {MO_JALR, "mips-jalr"} - }; - return makeArrayRef(Flags); -} diff --git a/contrib/llvm/lib/Target/Mips/MipsInstrInfo.h b/contrib/llvm/lib/Target/Mips/MipsInstrInfo.h deleted file mode 100644 index a626c0c3fdb8..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsInstrInfo.h +++ /dev/null @@ -1,187 +0,0 @@ -//===- MipsInstrInfo.h - Mips Instruction Information -----------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains the Mips implementation of the TargetInstrInfo class. -// -// FIXME: We need to override TargetInstrInfo::getInlineAsmLength method in -// order for MipsLongBranch pass to work correctly when the code has inline -// assembly. The returned value doesn't have to be the asm instruction's exact -// size in bytes; MipsLongBranch only expects it to be the correct upper bound. -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_MIPS_MIPSINSTRINFO_H -#define LLVM_LIB_TARGET_MIPS_MIPSINSTRINFO_H - -#include "MCTargetDesc/MipsMCTargetDesc.h" -#include "Mips.h" -#include "MipsRegisterInfo.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/MachineMemOperand.h" -#include "llvm/CodeGen/TargetInstrInfo.h" -#include <cstdint> - -#define GET_INSTRINFO_HEADER -#include "MipsGenInstrInfo.inc" - -namespace llvm { - -class MachineInstr; -class MachineOperand; -class MipsSubtarget; -class TargetRegisterClass; -class TargetRegisterInfo; - -class MipsInstrInfo : public MipsGenInstrInfo { - virtual void anchor(); - -protected: - const MipsSubtarget &Subtarget; - unsigned UncondBrOpc; - -public: - enum BranchType { - BT_None, // Couldn't analyze branch. - BT_NoBranch, // No branches found. - BT_Uncond, // One unconditional branch. - BT_Cond, // One conditional branch. - BT_CondUncond, // A conditional branch followed by an unconditional branch. - BT_Indirect // One indirct branch. - }; - - explicit MipsInstrInfo(const MipsSubtarget &STI, unsigned UncondBrOpc); - - static const MipsInstrInfo *create(MipsSubtarget &STI); - - /// Branch Analysis - bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, - MachineBasicBlock *&FBB, - SmallVectorImpl<MachineOperand> &Cond, - bool AllowModify) const override; - - unsigned removeBranch(MachineBasicBlock &MBB, - int *BytesRemoved = nullptr) const override; - - unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, - MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond, - const DebugLoc &DL, - int *BytesAdded = nullptr) const override; - - bool - reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const override; - - BranchType analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, - MachineBasicBlock *&FBB, - SmallVectorImpl<MachineOperand> &Cond, - bool AllowModify, - SmallVectorImpl<MachineInstr *> &BranchInstrs) const; - - /// Determine the opcode of a non-delay slot form for a branch if one exists. - unsigned getEquivalentCompactForm(const MachineBasicBlock::iterator I) const; - - /// Determine if the branch target is in range. - bool isBranchOffsetInRange(unsigned BranchOpc, - int64_t BrOffset) const override; - - /// Predicate to determine if an instruction can go in a forbidden slot. - bool SafeInForbiddenSlot(const MachineInstr &MI) const; - - /// Predicate to determine if an instruction has a forbidden slot. - bool HasForbiddenSlot(const MachineInstr &MI) const; - - /// Insert nop instruction when hazard condition is found - void insertNoop(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI) const override; - - /// getRegisterInfo - TargetInstrInfo is a superset of MRegister info. As - /// such, whenever a client has an instance of instruction info, it should - /// always be able to get register info as well (through this method). - virtual const MipsRegisterInfo &getRegisterInfo() const = 0; - - virtual unsigned getOppositeBranchOpc(unsigned Opc) const = 0; - - /// Return the number of bytes of code the specified instruction may be. - unsigned getInstSizeInBytes(const MachineInstr &MI) const override; - - void storeRegToStackSlot(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI, - unsigned SrcReg, bool isKill, int FrameIndex, - const TargetRegisterClass *RC, - const TargetRegisterInfo *TRI) const override { - storeRegToStack(MBB, MBBI, SrcReg, isKill, FrameIndex, RC, TRI, 0); - } - - void loadRegFromStackSlot(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI, - unsigned DestReg, int FrameIndex, - const TargetRegisterClass *RC, - const TargetRegisterInfo *TRI) const override { - loadRegFromStack(MBB, MBBI, DestReg, FrameIndex, RC, TRI, 0); - } - - virtual void storeRegToStack(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - unsigned SrcReg, bool isKill, int FrameIndex, - const TargetRegisterClass *RC, - const TargetRegisterInfo *TRI, - int64_t Offset) const = 0; - - virtual void loadRegFromStack(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - unsigned DestReg, int FrameIndex, - const TargetRegisterClass *RC, - const TargetRegisterInfo *TRI, - int64_t Offset) const = 0; - - virtual void adjustStackPtr(unsigned SP, int64_t Amount, - MachineBasicBlock &MBB, - MachineBasicBlock::iterator I) const = 0; - - /// Create an instruction which has the same operands and memory operands - /// as MI but has a new opcode. - MachineInstrBuilder genInstrWithNewOpc(unsigned NewOpc, - MachineBasicBlock::iterator I) const; - - bool findCommutedOpIndices(MachineInstr &MI, unsigned &SrcOpIdx1, - unsigned &SrcOpIdx2) const override; - - /// Perform target specific instruction verification. - bool verifyInstruction(const MachineInstr &MI, - StringRef &ErrInfo) const override; - - std::pair<unsigned, unsigned> - decomposeMachineOperandsTargetFlags(unsigned TF) const override; - - ArrayRef<std::pair<unsigned, const char *>> - getSerializableDirectMachineOperandTargetFlags() const override; - -protected: - bool isZeroImm(const MachineOperand &op) const; - - MachineMemOperand *GetMemOperand(MachineBasicBlock &MBB, int FI, - MachineMemOperand::Flags Flags) const; - -private: - virtual unsigned getAnalyzableBrOpc(unsigned Opc) const = 0; - - void AnalyzeCondBr(const MachineInstr *Inst, unsigned Opc, - MachineBasicBlock *&BB, - SmallVectorImpl<MachineOperand> &Cond) const; - - void BuildCondBr(MachineBasicBlock &MBB, MachineBasicBlock *TBB, - const DebugLoc &DL, ArrayRef<MachineOperand> Cond) const; -}; - -/// Create MipsInstrInfo objects. -const MipsInstrInfo *createMips16InstrInfo(const MipsSubtarget &STI); -const MipsInstrInfo *createMipsSEInstrInfo(const MipsSubtarget &STI); - -} // end namespace llvm - -#endif // LLVM_LIB_TARGET_MIPS_MIPSINSTRINFO_H diff --git a/contrib/llvm/lib/Target/Mips/MipsInstrInfo.td b/contrib/llvm/lib/Target/Mips/MipsInstrInfo.td deleted file mode 100644 index bf9bb1122f74..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsInstrInfo.td +++ /dev/null @@ -1,3383 +0,0 @@ -//===- MipsInstrInfo.td - Target Description for Mips Target -*- tablegen -*-=// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains the Mips implementation of the TargetInstrInfo class. -// -//===----------------------------------------------------------------------===// - - -//===----------------------------------------------------------------------===// -// Mips profiles and nodes -//===----------------------------------------------------------------------===// - -def SDT_MipsJmpLink : SDTypeProfile<0, 1, [SDTCisVT<0, iPTR>]>; -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_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>, - SDTCisInt<1>, SDTCisSameAs<1, 2>]>; -def SDT_MipsMultDiv : SDTypeProfile<1, 2, [SDTCisVT<0, untyped>, SDTCisInt<1>, - SDTCisSameAs<1, 2>]>; -def SDT_MipsMAddMSub : SDTypeProfile<1, 3, - [SDTCisVT<0, untyped>, SDTCisSameAs<0, 3>, - SDTCisVT<1, i32>, SDTCisSameAs<1, 2>]>; -def SDT_MipsDivRem16 : SDTypeProfile<0, 2, [SDTCisInt<0>, SDTCisSameAs<0, 1>]>; - -def SDT_MipsThreadPointer : SDTypeProfile<1, 0, [SDTCisPtrTy<0>]>; - -def SDT_Sync : SDTypeProfile<0, 1, [SDTCisVT<0, i32>]>; - -def SDT_Ext : SDTypeProfile<1, 3, [SDTCisInt<0>, SDTCisSameAs<0, 1>, - SDTCisVT<2, i32>, SDTCisSameAs<2, 3>]>; -def SDT_Ins : SDTypeProfile<1, 4, [SDTCisInt<0>, SDTCisSameAs<0, 1>, - SDTCisVT<2, i32>, SDTCisSameAs<2, 3>, - SDTCisSameAs<0, 4>]>; - -def SDTMipsLoadLR : SDTypeProfile<1, 2, - [SDTCisInt<0>, SDTCisPtrTy<1>, - SDTCisSameAs<0, 2>]>; - -// Call -def MipsJmpLink : SDNode<"MipsISD::JmpLink",SDT_MipsJmpLink, - [SDNPHasChain, SDNPOutGlue, SDNPOptInGlue, - SDNPVariadic]>; - -// Tail call -def MipsTailCall : SDNode<"MipsISD::TailCall", SDT_MipsJmpLink, - [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; - -// 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>; - -// Hi node for handling TLS offsets -def MipsTlsHi : SDNode<"MipsISD::TlsHi", SDTIntUnaryOp>; - -// Thread pointer -def MipsThreadPointer: SDNode<"MipsISD::ThreadPointer", SDT_MipsThreadPointer>; - -// Return -def MipsRet : SDNode<"MipsISD::Ret", SDTNone, - [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; - -def MipsERet : SDNode<"MipsISD::ERet", SDTNone, - [SDNPHasChain, SDNPOptInGlue, SDNPSideEffect]>; - -// These are target-independent nodes, but have target-specific formats. -def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_MipsCallSeqStart, - [SDNPHasChain, SDNPSideEffect, SDNPOutGlue]>; -def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_MipsCallSeqEnd, - [SDNPHasChain, SDNPSideEffect, - SDNPOptInGlue, SDNPOutGlue]>; - -// Nodes used to extract LO/HI registers. -def MipsMFHI : SDNode<"MipsISD::MFHI", SDT_MFLOHI>; -def MipsMFLO : SDNode<"MipsISD::MFLO", SDT_MFLOHI>; - -// Node used to insert 32-bit integers to LOHI register pair. -def MipsMTLOHI : SDNode<"MipsISD::MTLOHI", SDT_MTLOHI>; - -// Mult nodes. -def MipsMult : SDNode<"MipsISD::Mult", SDT_MipsMultDiv>; -def MipsMultu : SDNode<"MipsISD::Multu", SDT_MipsMultDiv>; - -// MAdd*/MSub* nodes -def MipsMAdd : SDNode<"MipsISD::MAdd", SDT_MipsMAddMSub>; -def MipsMAddu : SDNode<"MipsISD::MAddu", SDT_MipsMAddMSub>; -def MipsMSub : SDNode<"MipsISD::MSub", SDT_MipsMAddMSub>; -def MipsMSubu : SDNode<"MipsISD::MSubu", SDT_MipsMAddMSub>; - -// DivRem(u) nodes -def MipsDivRem : SDNode<"MipsISD::DivRem", SDT_MipsMultDiv>; -def MipsDivRemU : SDNode<"MipsISD::DivRemU", SDT_MipsMultDiv>; -def MipsDivRem16 : SDNode<"MipsISD::DivRem16", SDT_MipsDivRem16, - [SDNPOutGlue]>; -def MipsDivRemU16 : SDNode<"MipsISD::DivRemU16", SDT_MipsDivRem16, - [SDNPOutGlue]>; - -// Target constant nodes that are not part of any isel patterns and remain -// unchanged can cause instructions with illegal operands to be emitted. -// Wrapper node patterns give the instruction selector a chance to replace -// target constant nodes that would otherwise remain unchanged with ADDiu -// nodes. Without these wrapper node patterns, the following conditional move -// instruction is emitted when function cmov2 in test/CodeGen/Mips/cmov.ll is -// compiled: -// movn %got(d)($gp), %got(c)($gp), $4 -// This instruction is illegal since movn can take only register operands. - -def MipsWrapper : SDNode<"MipsISD::Wrapper", SDTIntBinOp>; - -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]>; -def MipsLWR : SDNode<"MipsISD::LWR", SDTMipsLoadLR, - [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; -def MipsSWL : SDNode<"MipsISD::SWL", SDTStore, - [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; -def MipsSWR : SDNode<"MipsISD::SWR", SDTStore, - [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; -def MipsLDL : SDNode<"MipsISD::LDL", SDTMipsLoadLR, - [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; -def MipsLDR : SDNode<"MipsISD::LDR", SDTMipsLoadLR, - [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; -def MipsSDL : SDNode<"MipsISD::SDL", SDTStore, - [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; -def MipsSDR : SDNode<"MipsISD::SDR", SDTStore, - [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; - -//===----------------------------------------------------------------------===// -// Mips Instruction Predicate Definitions. -//===----------------------------------------------------------------------===// -def HasMips2 : Predicate<"Subtarget->hasMips2()">, - AssemblerPredicate<"FeatureMips2">; -def HasMips3_32 : Predicate<"Subtarget->hasMips3_32()">, - AssemblerPredicate<"FeatureMips3_32">; -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()">, - AssemblerPredicate<"!FeatureMips4_32">; -def HasMips4_32r2 : Predicate<"Subtarget->hasMips4_32r2()">, - AssemblerPredicate<"FeatureMips4_32r2">; -def HasMips5_32r2 : Predicate<"Subtarget->hasMips5_32r2()">, - AssemblerPredicate<"FeatureMips5_32r2">; -def HasMips32 : Predicate<"Subtarget->hasMips32()">, - AssemblerPredicate<"FeatureMips32">; -def HasMips32r2 : Predicate<"Subtarget->hasMips32r2()">, - AssemblerPredicate<"FeatureMips32r2">; -def HasMips32r5 : Predicate<"Subtarget->hasMips32r5()">, - AssemblerPredicate<"FeatureMips32r5">; -def HasMips32r6 : Predicate<"Subtarget->hasMips32r6()">, - AssemblerPredicate<"FeatureMips32r6">; -def NotMips32r6 : Predicate<"!Subtarget->hasMips32r6()">, - AssemblerPredicate<"!FeatureMips32r6">; -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 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 HasCnMipsP : Predicate<"Subtarget->hasCnMipsP()">, - AssemblerPredicate<"FeatureCnMipsP">; -def NotCnMipsP : Predicate<"!Subtarget->hasCnMipsP()">, - AssemblerPredicate<"!FeatureCnMipsP">; -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 NoNaNsFPMath : Predicate<"TM.Options.NoNaNsFPMath">; -def UseAbs : Predicate<"Subtarget->inAbs2008Mode() ||" - "TM.Options.NoNaNsFPMath">; -def HasStdEnc : Predicate<"Subtarget->hasStandardEncoding()">, - AssemblerPredicate<"!FeatureMips16">; -def NotDSP : Predicate<"!Subtarget->hasDSP()">; -def InMicroMips : Predicate<"Subtarget->inMicroMipsMode()">, - AssemblerPredicate<"FeatureMicroMips">; -def NotInMicroMips : Predicate<"!Subtarget->inMicroMipsMode()">, - AssemblerPredicate<"!FeatureMicroMips">; -def IsLE : Predicate<"Subtarget->isLittle()">; -def IsBE : Predicate<"!Subtarget->isLittle()">; -def IsNotNaCl : Predicate<"!Subtarget->isTargetNaCl()">; -def UseTCCInDIV : AssemblerPredicate<"FeatureUseTCCInDIV">; -def HasEVA : Predicate<"Subtarget->hasEVA()">, - AssemblerPredicate<"FeatureEVA">; -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. -//===----------------------------------------------------------------------===// - -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. -//===----------------------------------------------------------------------===// - -// FIXME: I'd prefer to use additive predicates to build the instruction sets -// but we are short on assembler feature bits at the moment. Using a -// 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_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_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_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_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_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_MICROMIPS32R6 { - list<Predicate> InsnPredicates = [HasMips32r6]; - list<Predicate> EncodingPredicates = [InMicroMips]; -} -class ISA_MICROMIPS64R6 { - list<Predicate> InsnPredicates = [HasMips64r6]; - list<Predicate> EncodingPredicates = [InMicroMips]; -} -class ISA_MICROMIPS32_NOT_MIPS32R6 { - list<Predicate> InsnPredicates = [NotMips32r6]; - list<Predicate> EncodingPredicates = [InMicroMips]; -} -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]; -} - -// 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]; -} - -// 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_CNMIPSP { - list<Predicate> ASEPredicate = [HasCnMipsP]; -} - -class NOT_ASE_CNMIPSP { - list<Predicate> ASEPredicate = [NotCnMipsP]; -} - -class ASE_MIPS64_CNMIPS { - list<Predicate> ASEPredicate = [HasMips64, HasCnMips]; -} - -class ASE_MSA { - list<Predicate> ASEPredicate = [HasMSA]; -} - -class ASE_MSA_NOT_MSA64 { - list<Predicate> ASEPredicate = [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]; -} - -// 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 MipsPat<dag pattern, dag result> : Pat<pattern, result>, PredicateControl; - -class MipsInstAlias<string Asm, dag Result, bit Emit = 0b1> : - InstAlias<Asm, Result, Emit>, PredicateControl; - -class IsCommutable { - bit isCommutable = 1; -} - -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 { - bit isCall = 1; - bit isTerminator = 1; - bit isReturn = 1; - bit isBarrier = 1; - bit hasExtraSrcRegAllocReq = 1; - bit isCodeGenOnly = 1; - bit isCTI = 1; -} - -class IsAsCheapAsAMove { - bit isAsCheapAsAMove = 1; -} - -class NeverHasSideEffects { - bit hasSideEffects = 0; -} - -//===----------------------------------------------------------------------===// -// Instruction format superclass -//===----------------------------------------------------------------------===// - -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; - let RenderMethod = "addImmOperands"; - let PredicateMethod = "isScaledSImm<" # Bits # ", " # Shift # ">"; - let SuperClasses = Supers; - let DiagnosticType = "SImm" # Bits # "_Lsl" # Shift; -} - -class ConstantUImmAsmOperandClass<int Bits, list<AsmOperandClass> Supers = [], - int Offset = 0> : AsmOperandClass { - let Name = "ConstantUImm" # Bits # "_" # Offset; - let RenderMethod = "addConstantUImmOperands<" # Bits # ", " # Offset # ">"; - let PredicateMethod = "isConstantUImm<" # Bits # ", " # Offset # ">"; - let SuperClasses = 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"; -} -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"; -} -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"; -} -def ConstantUImm6AsmOperandClass - : ConstantUImmAsmOperandClass<6, [ConstantUImm6Lsl2AsmOperandClass]>; -def ConstantSImm6AsmOperandClass - : ConstantSImmAsmOperandClass<6, [ConstantUImm6AsmOperandClass]>; -def ConstantUImm5Lsl2AsmOperandClass : AsmOperandClass { - let Name = "UImm5Lsl2"; - let RenderMethod = "addImmOperands"; - let PredicateMethod = "isScaledUImm<5, 2>"; - let SuperClasses = [ConstantSImm6AsmOperandClass]; - 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]> { - 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]>; -def ConstantUImm4AsmOperandClass - : ConstantUImmAsmOperandClass<4, [ConstantSImm5AsmOperandClass]>; -def ConstantSImm4AsmOperandClass - : ConstantSImmAsmOperandClass<4, [ConstantUImm4AsmOperandClass]>; -def ConstantUImm3AsmOperandClass - : ConstantUImmAsmOperandClass<3, [ConstantSImm4AsmOperandClass]>; -def ConstantUImm2Plus1AsmOperandClass - : ConstantUImmAsmOperandClass<2, [ConstantUImm3AsmOperandClass], 1>; -def ConstantUImm2AsmOperandClass - : ConstantUImmAsmOperandClass<2, [ConstantUImm3AsmOperandClass]>; -def ConstantUImm1AsmOperandClass - : ConstantUImmAsmOperandClass<1, [ConstantUImm2AsmOperandClass]>; -def ConstantImmzAsmOperandClass : AsmOperandClass { - let Name = "ConstantImmz"; - let RenderMethod = "addConstantUImmOperands<1>"; - let PredicateMethod = "isConstantImmz"; - let SuperClasses = [ConstantUImm1AsmOperandClass]; - let DiagnosticType = "Immz"; -} - -def Simm19Lsl2AsmOperand - : SimmLslAsmOperandClass<19, [], 2>; - -def MipsJumpTargetAsmOperand : AsmOperandClass { - let Name = "JumpTarget"; - let ParserMethod = "parseJumpTarget"; - let PredicateMethod = "isImm"; - let RenderMethod = "addImmOperands"; -} - -// Instruction operand types -def jmptarget : Operand<OtherVT> { - let EncoderMethod = "getJumpTargetOpValue"; - let ParserMatchClass = MipsJumpTargetAsmOperand; -} -def brtarget : Operand<OtherVT> { - let EncoderMethod = "getBranchTargetOpValue"; - let OperandType = "OPERAND_PCREL"; - let DecoderMethod = "DecodeBranchTarget"; - let ParserMatchClass = MipsJumpTargetAsmOperand; -} -def 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; -} - -def imm64: Operand<i64>; - -def simm19_lsl2 : Operand<i32> { - let EncoderMethod = "getSimm19Lsl2Encoding"; - let DecoderMethod = "DecodeSimm19Lsl2"; - let ParserMatchClass = Simm19Lsl2AsmOperand; -} - -def simm18_lsl3 : Operand<i32> { - let EncoderMethod = "getSimm18Lsl3Encoding"; - let DecoderMethod = "DecodeSimm18Lsl3"; - let ParserMatchClass = MipsJumpTargetAsmOperand; -} - -// Zero -def uimmz : Operand<i32> { - let PrintMethod = "printUImm<0>"; - 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 - def uimm # I : Operand<i32> { - let PrintMethod = "printUImm<" # I # ">"; - let ParserMatchClass = - !cast<AsmOperandClass>("ConstantUImm" # I # "AsmOperandClass"); - } - -def uimm2_plus1 : Operand<i32> { - let PrintMethod = "printUImm<2, 1>"; - let EncoderMethod = "getUImmWithOffsetEncoding<2, 1>"; - let DecoderMethod = "DecodeUImmWithOffset<2, 1>"; - let ParserMatchClass = ConstantUImm2Plus1AsmOperandClass; -} - -def uimm5_plus1 : Operand<i32> { - let PrintMethod = "printUImm<5, 1>"; - 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 ParserMatchClass = ConstantUImm5Plus32AsmOperandClass; -} - -def uimm5_plus33 : Operand<i32> { - let PrintMethod = "printUImm<5, 33>"; - 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 ParserMatchClass = ConstantUImm5Plus32NormalizeAsmOperandClass; -} - -def uimm5_lsl2 : Operand<OtherVT> { - let EncoderMethod = "getUImm5Lsl2Encoding"; - let DecoderMethod = "DecodeUImmWithOffsetAndScale<5, 0, 4>"; - let ParserMatchClass = ConstantUImm5Lsl2AsmOperandClass; -} - -def uimm5_plus32_normalize_64 : Operand<i64> { - let PrintMethod = "printUImm<5>"; - 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 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 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; -} - -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 MipsMemAsmOperand : AsmOperandClass { - let Name = "Mem"; - let ParserMethod = "parseMemOperand"; -} - -def MipsMemSimm9AsmOperand : AsmOperandClass { - let Name = "MemOffsetSimm9"; - let SuperClasses = [MipsMemAsmOperand]; - let RenderMethod = "addMemOperands"; - let ParserMethod = "parseMemOperand"; - let PredicateMethod = "isMemWithSimmOffset<9>"; - let DiagnosticType = "MemSImm9"; -} - -def MipsMemSimm10AsmOperand : AsmOperandClass { - let Name = "MemOffsetSimm10"; - let SuperClasses = [MipsMemAsmOperand]; - let RenderMethod = "addMemOperands"; - let ParserMethod = "parseMemOperand"; - let PredicateMethod = "isMemWithSimmOffset<10>"; - let DiagnosticType = "MemSImm10"; -} - -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 { - let Name = "MemOffsetSimm16"; - let SuperClasses = [MipsMemAsmOperand]; - 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 { - let Name = "InvNum"; - let RenderMethod = "addImmOperands"; - let ParserMethod = "parseInvNum"; -} - -def InvertedImOperand : Operand<i32> { - let ParserMatchClass = MipsInvertedImmoperand; -} - -def InvertedImOperand64 : Operand<i64> { - let ParserMatchClass = MipsInvertedImmoperand; -} - -class mem_generic : Operand<iPTR> { - let PrintMethod = "printMemOperand"; - let MIOperandInfo = (ops ptr_rc, simm16); - let EncoderMethod = "getMemEncoding"; - let ParserMatchClass = MipsMemAsmOperand; - let OperandType = "OPERAND_MEMORY"; -} - -// Address operand -def mem : mem_generic; - -// MSA specific address operand -def mem_msa : mem_generic { - let MIOperandInfo = (ops ptr_rc, simm10); - 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); - let EncoderMethod = "getMemEncoding"; - let ParserMatchClass = MipsMemSimm10AsmOperand; -} - -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); - let EncoderMethod = "getMemEncoding"; - let OperandType = "OPERAND_MEMORY"; -} - -def PtrRC : Operand<iPTR> { - let MIOperandInfo = (ops ptr_rc); - let DecoderMethod = "DecodePtrRegisterClass"; - let ParserMatchClass = GPR32AsmOperand; -} - -// size operand of ins instruction -def size_ins : Operand<i32> { - let EncoderMethod = "getSizeInsEncoding"; - let DecoderMethod = "DecodeInsSize"; -} - -// Transformation Function - get the lower 16 bits. -def LO16 : SDNodeXForm<imm, [{ - return getImm(N, N->getZExtValue() & 0xFFFF); -}]>; - -// Transformation Function - get the higher 16 bits. -def HI16 : SDNodeXForm<imm, [{ - return getImm(N, (N->getZExtValue() >> 16) & 0xFFFF); -}]>; - -// Plus 1. -def Plus1 : SDNodeXForm<imm, [{ return getImm(N, N->getSExtValue() + 1); }]>; - -// Node immediate is zero (e.g. insve.d) -def immz : PatLeaf<(imm), [{ return N->getSExtValue() == 0; }]>; - -// Node immediate fits as 16-bit sign extended on target immediate. -// e.g. addi, andi -def immSExt8 : PatLeaf<(imm), [{ return isInt<8>(N->getSExtValue()); }]>; - -// Node immediate fits as 16-bit sign extended on target immediate. -// 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 16-bit zero extended on target immediate. -// The LO16 param means that only the lower 16 bits of the node -// immediate are caught. -// e.g. addiu, sltiu -def immZExt16 : PatLeaf<(imm), [{ - if (N->getValueType(0) == MVT::i32) - return (uint32_t)N->getZExtValue() == (unsigned short)N->getZExtValue(); - else - return (uint64_t)N->getZExtValue() == (unsigned short)N->getZExtValue(); -}], LO16>; - -// Immediate can be loaded with LUi (32-bit int with lower 16-bit cleared). -def immSExt32Low16Zero : 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 : - ComplexPattern<iPTR, 2, "selectIntAddr", [frameindex]>; - -def addrRegImm : - ComplexPattern<iPTR, 2, "selectAddrRegImm", [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]>; - -//===----------------------------------------------------------------------===// -// Instructions specific format -//===----------------------------------------------------------------------===// - -// Arithmetic and logical instructions with 3 register operands. -class ArithLogicR<string opstr, RegisterOperand RO, bit isComm = 0, - InstrItinClass Itin = NoItinerary, - SDPatternOperator OpNode = null_frag>: - InstSE<(outs RO:$rd), (ins RO:$rs, RO:$rt), - !strconcat(opstr, "\t$rd, $rs, $rt"), - [(set RO:$rd, (OpNode RO:$rs, RO:$rt))], Itin, FrmR, opstr> { - let isCommutable = isComm; - let isReMaterializable = 1; - let TwoOperandAliasConstraint = "$rd = $rs"; -} - -// Arithmetic and logical instructions with 2 register operands. -class ArithLogicI<string opstr, Operand Od, RegisterOperand RO, - InstrItinClass Itin = NoItinerary, - SDPatternOperator imm_type = null_frag, - SDPatternOperator OpNode = null_frag> : - InstSE<(outs RO:$rt), (ins RO:$rs, Od:$imm16), - !strconcat(opstr, "\t$rt, $rs, $imm16"), - [(set RO:$rt, (OpNode RO:$rs, imm_type:$imm16))], - Itin, FrmI, opstr> { - let isReMaterializable = 1; - let TwoOperandAliasConstraint = "$rs = $rt"; -} - -// Arithmetic Multiply ADD/SUB -class MArithR<string opstr, InstrItinClass itin, bit isComm = 0> : - InstSE<(outs), (ins GPR32Opnd:$rs, GPR32Opnd:$rt), - !strconcat(opstr, "\t$rs, $rt"), [], itin, FrmR, opstr> { - let Defs = [HI0, LO0]; - let Uses = [HI0, LO0]; - let isCommutable = isComm; -} - -// Logical -class LogicNOR<string opstr, RegisterOperand RO>: - InstSE<(outs RO:$rd), (ins RO:$rs, RO:$rt), - !strconcat(opstr, "\t$rd, $rs, $rt"), - [(set RO:$rd, (not (or RO:$rs, RO:$rt)))], II_NOR, FrmR, opstr> { - let isCommutable = 1; -} - -// Shifts -class shift_rotate_imm<string opstr, Operand ImmOpnd, - RegisterOperand RO, InstrItinClass itin, - SDPatternOperator OpNode = null_frag, - SDPatternOperator PF = null_frag> : - InstSE<(outs RO:$rd), (ins RO:$rt, ImmOpnd:$shamt), - !strconcat(opstr, "\t$rd, $rt, $shamt"), - [(set RO:$rd, (OpNode RO:$rt, PF:$shamt))], itin, FrmR, opstr> { - let TwoOperandAliasConstraint = "$rt = $rd"; -} - -class shift_rotate_reg<string opstr, RegisterOperand RO, InstrItinClass itin, - SDPatternOperator OpNode = null_frag>: - InstSE<(outs RO:$rd), (ins RO:$rt, GPR32Opnd:$rs), - !strconcat(opstr, "\t$rd, $rt, $rs"), - [(set RO:$rd, (OpNode RO:$rt, GPR32Opnd:$rs))], itin, FrmR, - opstr>; - -// Load Upper Immediate -class LoadUpper<string opstr, RegisterOperand RO, Operand Imm>: - InstSE<(outs RO:$rt), (ins Imm:$imm16), !strconcat(opstr, "\t$rt, $imm16"), - [], II_LUI, FrmI, opstr>, IsAsCheapAsAMove { - let hasSideEffects = 0; - let isReMaterializable = 1; -} - -// 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"), - [(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>; - -// Load/Store Left/Right -let canFoldAsLoad = 1 in -class LoadLeftRight<string opstr, SDNode OpNode, RegisterOperand RO, - InstrItinClass Itin> : - InstSE<(outs RO:$rt), (ins mem:$addr, RO:$src), - !strconcat(opstr, "\t$rt, $addr"), - [(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, - InstrItinClass Itin> : - 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"), - [(set RC:$rt, (OpNode addrDefault:$addr))], Itin, FrmFI, opstr> { - let DecoderMethod = "DecodeFMem2"; - let mayLoad = 1; -} - -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"), - [(OpNode RC:$rt, addrDefault:$addr)], Itin, FrmFI, opstr> { - let DecoderMethod = "DecodeFMem2"; - let mayStore = 1; -} - -// COP3 Load/Store -class LW_FT3<string opstr, RegisterOperand RC, InstrItinClass Itin, - SDPatternOperator OpNode= null_frag> : - InstSE<(outs RC:$rt), (ins mem:$addr), !strconcat(opstr, "\t$rt, $addr"), - [(set RC:$rt, (OpNode addrDefault:$addr))], Itin, FrmFI, opstr> { - let DecoderMethod = "DecodeFMem3"; - let mayLoad = 1; -} - -class SW_FT3<string opstr, RegisterOperand RC, InstrItinClass Itin, - SDPatternOperator OpNode= null_frag> : - InstSE<(outs), (ins RC:$rt, mem:$addr), !strconcat(opstr, "\t$rt, $addr"), - [(OpNode RC:$rt, addrDefault:$addr)], Itin, FrmFI, opstr> { - let DecoderMethod = "DecodeFMem3"; - let mayStore = 1; -} - -// Conditional Branch -class CBranch<string opstr, DAGOperand opnd, PatFrag cond_op, - RegisterOperand RO> : - 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 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> : - 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 Defs = [AT]; - bit isCTI = 1; -} - -// SetCC -class SetCC_R<string opstr, PatFrag cond_op, RegisterOperand RO> : - InstSE<(outs GPR32Opnd:$rd), (ins RO:$rs, RO:$rt), - !strconcat(opstr, "\t$rd, $rs, $rt"), - [(set GPR32Opnd:$rd, (cond_op RO:$rs, RO:$rt))], - II_SLT_SLTU, FrmR, opstr>; - -class SetCC_I<string opstr, PatFrag cond_op, Operand Od, PatLeaf imm_type, - RegisterOperand RO>: - InstSE<(outs GPR32Opnd:$rt), (ins RO:$rs, Od:$imm16), - !strconcat(opstr, "\t$rt, $rs, $imm16"), - [(set GPR32Opnd:$rt, (cond_op RO:$rs, imm_type:$imm16))], - II_SLTI_SLTIU, FrmI, opstr>; - -// Jump -class JumpFJ<DAGOperand opnd, string opstr, SDPatternOperator operator, - SDPatternOperator targetoperator, string bopstr> : - InstSE<(outs), (ins opnd:$target), !strconcat(opstr, "\t$target"), - [(operator targetoperator:$target)], II_J, FrmJ, bopstr> { - let isTerminator=1; - let isBarrier=1; - let hasDelaySlot = 1; - let DecoderMethod = "DecodeJumpTarget"; - let Defs = [AT]; - bit isCTI = 1; -} - -// Unconditional branch -class UncondBranch<Instruction BEQInst, DAGOperand opnd> : - PseudoSE<(outs), (ins brtarget:$offset), [(br bb:$offset)], II_B>, - PseudoInstExpansion<(BEQInst ZERO, ZERO, opnd:$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 -class JumpFR<string opstr, RegisterOperand RO, - SDPatternOperator operator = null_frag>: - InstSE<(outs), (ins RO:$rs), "jr\t$rs", [(operator RO:$rs)], II_JR, - FrmR, opstr>; - -// Indirect branch -class IndirectBranch<string opstr, RegisterOperand RO> : JumpFR<opstr, RO> { - let isBranch = 1; - let isIndirectBranch = 1; -} - -// Jump and Link (Call) -let isCall=1, hasDelaySlot=1, isCTI=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> { - let DecoderMethod = "DecodeJumpTarget"; - } - - 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; - } - - 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; - } - - class BGEZAL_FT<string opstr, DAGOperand opnd, - RegisterOperand RO> : - InstSE<(outs), (ins RO:$rs, opnd:$offset), - !strconcat(opstr, "\t$rs, $offset"), [], II_BCCZAL, FrmI, opstr> { - let hasDelaySlot = 1; - } - -} - -let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, hasDelaySlot = 1, - hasExtraSrcRegAllocReq = 1, isCTI = 1, Defs = [AT] in { - class TailCall<Instruction JumpInst, DAGOperand Opnd> : - PseudoSE<(outs), (ins calltarget:$target), [], II_J>, - PseudoInstExpansion<(JumpInst Opnd:$target)>; - - class TailCallReg<Instruction JumpInst, RegisterOperand RO> : - PseudoSE<(outs), (ins RO:$rs), [(MipsTailCall RO:$rs)], II_JR>, - PseudoInstExpansion<(JumpInst RO:$rs)> { - let hasPostISelHook = 1; - } -} - -class BAL_BR_Pseudo<Instruction RealInst, DAGOperand opnd> : - PseudoSE<(outs), (ins opnd:$offset), [], II_BCCZAL>, - PseudoInstExpansion<(RealInst ZERO, opnd:$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>; -// Break -class BRK_FT<string opstr> : - InstSE<(outs), (ins uimm10:$code_1, uimm10:$code_2), - !strconcat(opstr, "\t$code_1, $code_2"), [], II_BREAK, - FrmOther, opstr>; - -// (D)Eret -class ER_FT<string opstr, InstrItinClass itin = NoItinerary> : - InstSE<(outs), (ins), - opstr, [], itin, FrmOther, opstr>; - -// Wait -class WAIT_FT<string opstr> : - InstSE<(outs), (ins), opstr, [], II_WAIT, FrmOther, opstr>; -} - -// Interrupts -class DEI_FT<string opstr, RegisterOperand RO, - InstrItinClass itin = NoItinerary> : - InstSE<(outs RO:$rt), (ins), - !strconcat(opstr, "\t$rt"), [], itin, 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>; - -class SYNCI_FT<string opstr, DAGOperand MO> : - InstSE<(outs), (ins MO:$addr), !strconcat(opstr, "\t$addr"), [], - II_SYNCI, 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>; -} - -// Mul, Div -class Mult<string opstr, InstrItinClass itin, RegisterOperand RO, - list<Register> DefRegs> : - InstSE<(outs), (ins RO:$rs, RO:$rt), !strconcat(opstr, "\t$rs, $rt"), [], - itin, FrmR, opstr> { - let isCommutable = 1; - let Defs = DefRegs; - let hasSideEffects = 0; -} - -// Pseudo multiply/divide instruction with explicit accumulator register -// operands. -class MultDivPseudo<Instruction RealInst, RegisterClass R0, RegisterOperand R1, - SDPatternOperator OpNode, InstrItinClass Itin, - bit IsComm = 1, bit HasSideEffects = 0, - bit UsesCustomInserter = 0> : - PseudoSE<(outs R0:$ac), (ins R1:$rs, R1:$rt), - [(set R0:$ac, (OpNode R1:$rs, R1:$rt))], Itin>, - PseudoInstExpansion<(RealInst R1:$rs, R1:$rt)> { - let isCommutable = IsComm; - let hasSideEffects = HasSideEffects; - let usesCustomInserter = UsesCustomInserter; -} - -// Pseudo multiply add/sub instruction with explicit accumulator register -// operands. -class MAddSubPseudo<Instruction RealInst, SDPatternOperator OpNode, - InstrItinClass itin> - : PseudoSE<(outs ACC64:$ac), - (ins GPR32Opnd:$rs, GPR32Opnd:$rt, ACC64:$acin), - [(set ACC64:$ac, - (OpNode GPR32Opnd:$rs, GPR32Opnd:$rt, ACC64:$acin))], - itin>, - PseudoInstExpansion<(RealInst GPR32Opnd:$rs, GPR32Opnd:$rt)> { - string Constraints = "$acin = $ac"; -} - -class Div<string opstr, InstrItinClass itin, RegisterOperand RO, - list<Register> DefRegs> : - InstSE<(outs), (ins RO:$rs, RO:$rt), !strconcat(opstr, "\t$$zero, $rs, $rt"), - [], itin, FrmR, opstr> { - let Defs = DefRegs; -} - -// Move from Hi/Lo -class PseudoMFLOHI<RegisterClass DstRC, RegisterClass SrcRC, SDNode OpNode> - : PseudoSE<(outs DstRC:$rd), (ins SrcRC:$hilo), - [(set DstRC:$rd, (OpNode SrcRC:$hilo))], II_MFHI_MFLO>; - -class MoveFromLOHI<string opstr, RegisterOperand RO, Register UseReg>: - InstSE<(outs RO:$rd), (ins), !strconcat(opstr, "\t$rd"), [], II_MFHI_MFLO, - FrmR, opstr> { - let Uses = [UseReg]; - let hasSideEffects = 0; - let isMoveReg = 1; -} - -class PseudoMTLOHI<RegisterClass DstRC, RegisterClass SrcRC> - : PseudoSE<(outs DstRC:$lohi), (ins SrcRC:$lo, SrcRC:$hi), - [(set DstRC:$lohi, (MipsMTLOHI SrcRC:$lo, SrcRC:$hi))], - II_MTHI_MTLO>; - -class MoveToLOHI<string opstr, RegisterOperand RO, list<Register> DefRegs>: - InstSE<(outs), (ins RO:$rs), !strconcat(opstr, "\t$rs"), [], II_MTHI_MTLO, - 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, - !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>: - InstSE<(outs RO:$rd), (ins RO:$rs), !strconcat(opstr, "\t$rd, $rs"), - [(set RO:$rd, (ctlz RO:$rs))], itin, FrmR, opstr>; - -class CountLeading1<string opstr, RegisterOperand RO, - InstrItinClass itin = NoItinerary>: - InstSE<(outs RO:$rd), (ins RO:$rs), !strconcat(opstr, "\t$rd, $rs"), - [(set RO:$rd, (ctlz (not RO:$rs)))], itin, FrmR, opstr>; - -// Sign Extend in Register. -class SignExtInReg<string opstr, ValueType vt, RegisterOperand RO, - InstrItinClass itin> : - InstSE<(outs RO:$rd), (ins RO:$rt), !strconcat(opstr, "\t$rd, $rt"), - [(set RO:$rd, (sext_inreg RO:$rt, vt))], itin, FrmR, opstr>; - -// Subword Swap -class SubwordSwap<string opstr, RegisterOperand RO, - InstrItinClass itin = NoItinerary>: - InstSE<(outs RO:$rd), (ins RO:$rt), !strconcat(opstr, "\t$rd, $rt"), [], itin, - FrmR, opstr> { - let hasSideEffects = 0; -} - -// 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">; - -// Ext and Ins -class ExtBase<string opstr, RegisterOperand RO, Operand PosOpnd, - Operand SizeOpnd, PatFrag PosImm, PatFrag SizeImm, - 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>; - -// '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> { - let Constraints = "$src = $rt"; -} - -// Atomic instructions with 2 source operands (ATOMIC_SWAP & ATOMIC_LOAD_*). -class Atomic2Ops<PatFrag Op, RegisterClass DRC> : - PseudoSE<(outs DRC:$dst), (ins PtrRC:$ptr, DRC:$incr), - [(set DRC:$dst, (Op iPTR:$ptr, DRC:$incr))]> { - let hasNoSchedulingInfo = 1; -} - -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))]> { - let hasNoSchedulingInfo = 1; -} - -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> { - 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> { - 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 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 TrapBase<Instruction RealInst> - : PseudoSE<(outs), (ins), [(trap)], II_TRAP>, - PseudoInstExpansion<(RealInst 0, 0)> { - let isBarrier = 1; - let isTerminator = 1; - let isCodeGenOnly = 1; - let isCTI = 1; -} - -//===----------------------------------------------------------------------===// -// Pseudo instructions -//===----------------------------------------------------------------------===// - -// 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 hasSideEffects=1 in - def ERet : PseudoSE<(outs), (ins), [(MipsERet)]>; -} - -let Defs = [SP], Uses = [SP], hasSideEffects = 1, hasNoSchedulingInfo = 1 in { -def ADJCALLSTACKDOWN : MipsPseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), - [(callseq_start timm:$amt1, timm:$amt2)]>; -def ADJCALLSTACKUP : MipsPseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), - [(callseq_end timm:$amt1, timm:$amt2)]>; -} - -let usesCustomInserter = 1 in { - def ATOMIC_LOAD_ADD_I8 : Atomic2Ops<atomic_load_add_8, GPR32>; - def ATOMIC_LOAD_ADD_I16 : Atomic2Ops<atomic_load_add_16, GPR32>; - def ATOMIC_LOAD_ADD_I32 : Atomic2Ops<atomic_load_add_32, GPR32>; - def ATOMIC_LOAD_SUB_I8 : Atomic2Ops<atomic_load_sub_8, GPR32>; - def ATOMIC_LOAD_SUB_I16 : Atomic2Ops<atomic_load_sub_16, GPR32>; - def ATOMIC_LOAD_SUB_I32 : Atomic2Ops<atomic_load_sub_32, GPR32>; - def ATOMIC_LOAD_AND_I8 : Atomic2Ops<atomic_load_and_8, GPR32>; - def ATOMIC_LOAD_AND_I16 : Atomic2Ops<atomic_load_and_16, GPR32>; - def ATOMIC_LOAD_AND_I32 : Atomic2Ops<atomic_load_and_32, GPR32>; - def ATOMIC_LOAD_OR_I8 : Atomic2Ops<atomic_load_or_8, GPR32>; - def ATOMIC_LOAD_OR_I16 : Atomic2Ops<atomic_load_or_16, GPR32>; - def ATOMIC_LOAD_OR_I32 : Atomic2Ops<atomic_load_or_32, GPR32>; - def ATOMIC_LOAD_XOR_I8 : Atomic2Ops<atomic_load_xor_8, GPR32>; - def ATOMIC_LOAD_XOR_I16 : Atomic2Ops<atomic_load_xor_16, GPR32>; - def ATOMIC_LOAD_XOR_I32 : Atomic2Ops<atomic_load_xor_32, GPR32>; - def ATOMIC_LOAD_NAND_I8 : Atomic2Ops<atomic_load_nand_8, GPR32>; - def ATOMIC_LOAD_NAND_I16 : Atomic2Ops<atomic_load_nand_16, GPR32>; - def ATOMIC_LOAD_NAND_I32 : Atomic2Ops<atomic_load_nand_32, GPR32>; - - def ATOMIC_SWAP_I8 : Atomic2Ops<atomic_swap_8, GPR32>; - def ATOMIC_SWAP_I16 : Atomic2Ops<atomic_swap_16, GPR32>; - def ATOMIC_SWAP_I32 : Atomic2Ops<atomic_swap_32, GPR32>; - - 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 { - def LOAD_ACC64 : Load<"", ACC64>; - def STORE_ACC64 : Store<"", ACC64>; -} - -// We need these two pseudo instructions 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 - $baltgt) -def LONG_BRANCH_LUi : PseudoSE<(outs GPR32Opnd:$dst), - (ins brtarget:$tgt, brtarget:$baltgt), []> { - bit hasNoSchedulingInfo = 1; -} -// Expands to: lui $dst, highest/%higher/%hi/%lo($tgt) -def LONG_BRANCH_LUi2Op : PseudoSE<(outs GPR32Opnd:$dst), - (ins brtarget:$tgt), []> { - bit hasNoSchedulingInfo = 1; -} - -// Expands to: addiu $dst, $src, %highest/%higher/%hi/%lo($tgt - $baltgt) -def LONG_BRANCH_ADDiu : PseudoSE<(outs GPR32Opnd:$dst), - (ins GPR32Opnd:$src, brtarget:$tgt, brtarget:$baltgt), []> { - bit hasNoSchedulingInfo = 1; -} -// Expands to: addiu $dst, $src, %highest/%higher/%hi/%lo($tgt) -def LONG_BRANCH_ADDiu2Op : PseudoSE<(outs GPR32Opnd:$dst), - (ins GPR32Opnd:$src, brtarget:$tgt), []> { - bit hasNoSchedulingInfo = 1; -} - -//===----------------------------------------------------------------------===// -// Instruction definition -//===----------------------------------------------------------------------===// -//===----------------------------------------------------------------------===// -// MipsI Instructions -//===----------------------------------------------------------------------===// - -/// 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; -} - -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; -} - -/// Load and Store Instructions -/// aligned -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 : StdMMR6Rel, Store<"sw", GPR32Opnd, store, II_SW>, MMRel, LW_FM<0x2b>, ISA_MIPS1; -} - -/// load/store left/right -let AdditionalPredicates = [NotInMicroMips] in { -def LWL : MMRel, 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>, - ISA_MIPS1_NOT_32R6_64R6; -def SWL : MMRel, 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>, - ISA_MIPS1_NOT_32R6_64R6; - -// COP2 Memory Instructions -def LWC2 : StdMMR6Rel, LW_FT2<"lwc2", COP2Opnd, II_LWC2, load>, LW_FM<0x32>, - 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>, - 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 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; -} - -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 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 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; - - def WAIT : MMRel, StdMMR6Rel, WAIT_FT<"wait">, WAIT_FM, INSN_MIPS3_32; -} - -let AdditionalPredicates = [NotInMicroMips] in { -/// 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; -} -/// 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>, - 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>, - 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, 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<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<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, 2>, ISA_MIPS2_NOT_32R6_64R6; -def B : UncondBranch<BEQ, brtarget>, ISA_MIPS1; - -def JAL : MMRel, JumpLink<"jal", calltarget>, FJ<3>, ISA_MIPS1; - -} - -let AdditionalPredicates = [NotInMicroMips, NoIndirectJumpGuards] in { - def JALR : JumpLinkReg<"jalr", GPR32Opnd>, JALR_FM, ISA_MIPS1; - def JALRPseudo : JumpLinkRegPseudo<GPR32Opnd, JALR, RA>, ISA_MIPS1; -} - -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; - -// 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> : - MipsPseudo<(outs), (ins RO:$rs), [(brind RO:$rs)], - II_IndirectBranchPseudo>, - PseudoInstExpansion<(JumpInst RO:$rs)> { - 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; - -// Return instructions are matched as a RetRA instruction, then are expanded -// into PseudoReturn/PseudoReturn64 after register allocation. Finally, -// MipsAsmPrinter expands this into JR, JR64, JALR, or JALR64 depending on the -// ISA. -class PseudoReturnBase<RegisterOperand RO> : MipsPseudo<(outs), (ins RO:$rs), - [], II_ReturnPseudo> { - let isTerminator = 1; - let isBarrier = 1; - let hasDelaySlot = 1; - let isReturn = 1; - let isCodeGenOnly = 1; - let hasCtrlDep = 1; - let hasExtraSrcRegAllocReq = 1; - bit isCTI = 1; -} - -def PseudoReturn : PseudoReturnBase<GPR32Opnd>; - -// Exception handling related node and instructions. -// The conversion sequence is: -// ISD::EH_RETURN -> MipsISD::EH_RETURN -> -// MIPSeh_return -> (stack change + indirect branch) -// -// MIPSeh_return takes the place of regular return instruction -// but takes two arguments (V1, V0) which are used for storing -// the offset and return address respectively. -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, hasNoSchedulingInfo = 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, GPR64:$dst), - [(MIPSehret GPR64:$spoff, GPR64:$dst)]>; -} - -/// 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; - - /// 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; - - /// 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; - - // 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; - - // 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>, - ISA_MIPS1_NOT_32R6_64R6; -def PseudoMULTu : MultDivPseudo<MULTu, ACC64, GPR32Opnd, MipsMultu, II_MULTU>, - ISA_MIPS1_NOT_32R6_64R6; -def PseudoMFHI : PseudoMFLOHI<GPR32, ACC64, MipsMFHI>, ISA_MIPS1_NOT_32R6_64R6; -def PseudoMFLO : PseudoMFLOHI<GPR32, ACC64, MipsMFLO>, ISA_MIPS1_NOT_32R6_64R6; -def PseudoMTLOHI : PseudoMTLOHI<ACC64, GPR32>, ISA_MIPS1_NOT_32R6_64R6; -def PseudoMADD : MAddSubPseudo<MADD, MipsMAdd, II_MADD>, - ISA_MIPS32_NOT_32R6_64R6; -def PseudoMADDU : MAddSubPseudo<MADDU, MipsMAddu, II_MADDU>, - ISA_MIPS32_NOT_32R6_64R6; -def PseudoMSUB : MAddSubPseudo<MSUB, MipsMSub, II_MSUB>, - ISA_MIPS32_NOT_32R6_64R6; -def PseudoMSUBU : MAddSubPseudo<MSUBU, MipsMSubu, II_MSUBU>, - ISA_MIPS32_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; -} -/// 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; - - let isCTI = 1 in - def PAUSE : MMRel, StdMMR6Rel, Barrier<"pause", II_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 -// and because of that it doesn't follow the naming convention of the -// rest of the file. To avoid a mixture of old vs new style, the new -// style was chosen. -class JR_HB_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> { - dag OutOperandList = (outs); - dag InOperandList = (ins GPROpnd:$rs); - string AsmString = !strconcat(instr_asm, "\t$rs"); - list<dag> Pattern = []; -} - -class JALR_HB_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> { - dag OutOperandList = (outs GPROpnd:$rd); - dag InOperandList = (ins GPROpnd:$rs); - string AsmString = !strconcat(instr_asm, "\t$rd, $rs"); - list<dag> Pattern = []; -} - -class JR_HB_DESC<RegisterOperand RO> : - InstSE<(outs), (ins), "", [], II_JR_HB, FrmJ>, JR_HB_DESC_BASE<"jr.hb", RO> { - 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> { - 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; - -let AdditionalPredicates = [NotInMicroMips, UseIndirectJumpsHazard] in - def JALRHBPseudo : JumpLinkRegPseudo<GPR32Opnd, JALR_HB, RA>; - - -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> : - InstSE<(outs), (ins MemOpnd:$addr, uimm5:$hint), - !strconcat(instr_asm, "\t$hint, $addr"), [], itin, 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 ROL : MipsAsmPseudoInst<(outs), - (ins GPR32Opnd:$rs, GPR32Opnd:$rt, GPR32Opnd:$rd), - "rol\t$rs, $rt, $rd">; -def ROLImm : MipsAsmPseudoInst<(outs), - (ins GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), - "rol\t$rs, $rt, $imm">; -def : MipsInstAlias<"rol $rd, $rs", - (ROL GPR32Opnd:$rd, GPR32Opnd:$rd, GPR32Opnd:$rs), 0>; -def : MipsInstAlias<"rol $rd, $imm", - (ROLImm GPR32Opnd:$rd, GPR32Opnd:$rd, simm16:$imm), 0>; - -def ROR : MipsAsmPseudoInst<(outs), - (ins GPR32Opnd:$rs, GPR32Opnd:$rt, GPR32Opnd:$rd), - "ror\t$rs, $rt, $rd">; -def RORImm : MipsAsmPseudoInst<(outs), - (ins GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), - "ror\t$rs, $rt, $imm">; -def : MipsInstAlias<"ror $rd, $rs", - (ROR GPR32Opnd:$rd, GPR32Opnd:$rd, GPR32Opnd:$rs), 0>; -def : MipsInstAlias<"ror $rd, $imm", - (RORImm GPR32Opnd:$rd, GPR32Opnd:$rd, simm16:$imm), 0>; - -def DROL : MipsAsmPseudoInst<(outs), - (ins GPR32Opnd:$rs, GPR32Opnd:$rt, GPR32Opnd:$rd), - "drol\t$rs, $rt, $rd">, ISA_MIPS64; -def DROLImm : MipsAsmPseudoInst<(outs), - (ins GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), - "drol\t$rs, $rt, $imm">, ISA_MIPS64; -def : MipsInstAlias<"drol $rd, $rs", - (DROL GPR32Opnd:$rd, GPR32Opnd:$rd, GPR32Opnd:$rs), 0>, ISA_MIPS64; -def : MipsInstAlias<"drol $rd, $imm", - (DROLImm GPR32Opnd:$rd, GPR32Opnd:$rd, simm16:$imm), 0>, ISA_MIPS64; - -def DROR : MipsAsmPseudoInst<(outs), - (ins GPR32Opnd:$rs, GPR32Opnd:$rt, GPR32Opnd:$rd), - "dror\t$rs, $rt, $rd">, ISA_MIPS64; -def DRORImm : MipsAsmPseudoInst<(outs), - (ins GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), - "dror\t$rs, $rt, $imm">, ISA_MIPS64; -def : MipsInstAlias<"dror $rd, $rs", - (DROR GPR32Opnd:$rd, GPR32Opnd:$rd, GPR32Opnd:$rs), 0>, ISA_MIPS64; -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>; -} - -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 SGE : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), - (ins GPR32Opnd:$rs, GPR32Opnd:$rt), - "sge\t$rd, $rs, $rt">, ISA_MIPS1; - def : MipsInstAlias<"sge $rs, $rt", - (SGE GPR32Opnd:$rs, GPR32Opnd:$rs, GPR32Opnd:$rt), 0>, - ISA_MIPS1; - def SGEImm : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), - (ins GPR32Opnd:$rs, simm32:$imm), - "sge\t$rd, $rs, $imm">, GPR_32; - def : MipsInstAlias<"sge $rs, $imm", (SGEImm GPR32Opnd:$rs, - GPR32Opnd:$rs, - simm32:$imm), 0>, - GPR_32; - - def SGEU : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), - (ins GPR32Opnd:$rs, GPR32Opnd:$rt), - "sgeu\t$rd, $rs, $rt">, ISA_MIPS1; - def : MipsInstAlias<"sgeu $rs, $rt", - (SGEU GPR32Opnd:$rs, GPR32Opnd:$rs, GPR32Opnd:$rt), 0>, - ISA_MIPS1; - def SGEUImm : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), - (ins GPR32Opnd:$rs, uimm32_coerced:$imm), - "sgeu\t$rd, $rs, $imm">, GPR_32; - def : MipsInstAlias<"sgeu $rs, $imm", (SGEUImm GPR32Opnd:$rs, - GPR32Opnd:$rs, - uimm32_coerced:$imm), 0>, - GPR_32; - - 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 SGTImm : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), - (ins GPR32Opnd:$rs, simm32:$imm), - "sgt\t$rd, $rs, $imm">, GPR_32; - def : MipsInstAlias<"sgt $rs, $imm", (SGTImm GPR32Opnd:$rs, - GPR32Opnd:$rs, - simm32:$imm), 0>, - GPR_32; - 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 SGTUImm : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), - (ins GPR32Opnd:$rs, uimm32_coerced:$imm), - "sgtu\t$rd, $rs, $imm">, GPR_32; - def : MipsInstAlias<"sgtu $rs, $imm", (SGTUImm GPR32Opnd:$rs, - GPR32Opnd:$rs, - uimm32_coerced:$imm), 0>, - GPR_32; - - 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), 1>, - 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), 1>, - 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; - - def : MipsInstAlias<"teq $rs, $rt", - (TEQ GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>, ISA_MIPS2; - def : MipsInstAlias<"tge $rs, $rt", - (TGE GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>, ISA_MIPS2; - def : MipsInstAlias<"tgeu $rs, $rt", - (TGEU GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>, ISA_MIPS2; - def : MipsInstAlias<"tlt $rs, $rt", - (TLT GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>, ISA_MIPS2; - def : MipsInstAlias<"tltu $rs, $rt", - (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<"sub, $rd, $rs, $imm", - (ADDi GPR32Opnd:$rd, GPR32Opnd:$rs, - InvertedImOperand:$imm), 0>, ISA_MIPS1_NOT_32R6_64R6; -def : MipsInstAlias<"sub $rs, $imm", - (ADDi GPR32Opnd:$rs, GPR32Opnd:$rs, InvertedImOperand:$imm), - 0>, ISA_MIPS1_NOT_32R6_64R6; -def : MipsInstAlias<"subu, $rd, $rs, $imm", - (ADDiu GPR32Opnd:$rd, GPR32Opnd:$rs, - 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<"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; - -//===----------------------------------------------------------------------===// -// 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>; - -class LoadAddressFromReg32<string instr_asm, Operand MemOpnd, - RegisterOperand RO> : - MipsAsmPseudoInst<(outs RO:$rt), (ins MemOpnd:$addr), - !strconcat(instr_asm, "\t$rt, $addr")> ; -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 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; - -let hasDelaySlot = 1, isCTI = 1 in { -def BneImm : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), - (ins imm64:$imm64, brtarget:$offset), - "bne\t$rt, $imm64, $offset">; -def BeqImm : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), - (ins imm64:$imm64, brtarget:$offset), - "beq\t$rt, $imm64, $offset">; - -class CondBranchPseudo<string instr_asm> : - MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, GPR32Opnd:$rt, - brtarget:$offset), - !strconcat(instr_asm, "\t$rs, $rt, $offset")>; -} - -def BLT : CondBranchPseudo<"blt">; -def BLE : CondBranchPseudo<"ble">; -def BGE : CondBranchPseudo<"bge">; -def BGT : CondBranchPseudo<"bgt">; -def BLTU : CondBranchPseudo<"bltu">; -def BLEU : CondBranchPseudo<"bleu">; -def BGEU : CondBranchPseudo<"bgeu">; -def BGTU : CondBranchPseudo<"bgtu">; -def BLTL : CondBranchPseudo<"bltl">, ISA_MIPS2_NOT_32R6_64R6; -def BLEL : CondBranchPseudo<"blel">, ISA_MIPS2_NOT_32R6_64R6; -def BGEL : CondBranchPseudo<"bgel">, ISA_MIPS2_NOT_32R6_64R6; -def BGTL : CondBranchPseudo<"bgtl">, ISA_MIPS2_NOT_32R6_64R6; -def BLTUL: CondBranchPseudo<"bltul">, ISA_MIPS2_NOT_32R6_64R6; -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">; -def BGTImmMacro : CondBranchImmPseudo<"bgt">; -def BLTUImmMacro : CondBranchImmPseudo<"bltu">; -def BLEUImmMacro : CondBranchImmPseudo<"bleu">; -def BGEUImmMacro : CondBranchImmPseudo<"bgeu">; -def BGTUImmMacro : CondBranchImmPseudo<"bgtu">; -def BLTLImmMacro : CondBranchImmPseudo<"bltl">, ISA_MIPS2_NOT_32R6_64R6; -def BLELImmMacro : CondBranchImmPseudo<"blel">, ISA_MIPS2_NOT_32R6_64R6; -def BGELImmMacro : CondBranchImmPseudo<"bgel">, ISA_MIPS2_NOT_32R6_64R6; -def BGTLImmMacro : CondBranchImmPseudo<"bgtl">, ISA_MIPS2_NOT_32R6_64R6; -def BLTULImmMacro : CondBranchImmPseudo<"bltul">, ISA_MIPS2_NOT_32R6_64R6; -def BLEULImmMacro : CondBranchImmPseudo<"bleul">, ISA_MIPS2_NOT_32R6_64R6; -def BGEULImmMacro : CondBranchImmPseudo<"bgeul">, ISA_MIPS2_NOT_32R6_64R6; -def BGTULImmMacro : CondBranchImmPseudo<"bgtul">, ISA_MIPS2_NOT_32R6_64R6; - -// FIXME: Predicates are removed because instructions are matched regardless of -// predicates, because PredicateControl was not in the hierarchy. This was -// done to emit more precise error message from expansion function. -// 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 : 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 : MipsInstAlias<"divu $rd, $imm", (UDivIMacro GPR32Opnd:$rd, GPR32Opnd:$rd, - simm32:$imm), 0>, - ISA_MIPS1_NOT_32R6_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 Ulh : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), (ins mem:$addr), - "ulh\t$rt, $addr">; //, ISA_MIPS1_NOT_32R6_64R6; - -def Ulhu : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), (ins mem:$addr), - "ulhu\t$rt, $addr">; //, ISA_MIPS1_NOT_32R6_64R6; - -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 -//===----------------------------------------------------------------------===// - -// Load/store pattern templates. -class LoadRegImmPat<Instruction LoadInst, ValueType ValTy, PatFrag Node> : - MipsPat<(ValTy (Node addrRegImm:$a)), (LoadInst addrRegImm:$a)>; - -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 - defm : MaterializeImms<i32, ZERO, ADDiu, LUi, ORi>, ISA_MIPS1; - -// Carry MipsPatterns -let AdditionalPredicates = [NotInMicroMips] in { - def : MipsPat<(subc GPR32:$lhs, GPR32:$rhs), - (SUBu GPR32:$lhs, GPR32:$rhs)>, ISA_MIPS1; -} -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. -def : MipsPat<(mul GPR32:$lhs, GPR32:$rhs), - (PseudoMFLO (PseudoMULT GPR32:$lhs, GPR32:$rhs))>, - ISA_MIPS1_NOT_32R6_64R6; - -// SYNC -def : MipsPat<(MipsSync (i32 immz)), - (SYNC 0)>, ISA_MIPS2; - -// Call -def : MipsPat<(MipsJmpLink (i32 texternalsym:$dst)), - (JAL texternalsym:$dst)>, ISA_MIPS1; -//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; -} -// 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)>; -} - -// 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; - - def : MipsPat<(MipsTlsHi tglobaltlsaddr:$in), (LUi tglobaltlsaddr:$in)>, - ISA_MIPS1; - - // 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; -} - -// 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; - - // peepholes - def : MipsPat<(store (i32 0), addr:$dst), (SW ZERO, addr:$dst)>, ISA_MIPS1; -} - -// brcond patterns -multiclass BrcondPats<RegisterClass RC, Instruction BEQOp, Instruction BEQOp1, - 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)>; -def : MipsPat<(brcond (i32 (setuge RC:$lhs, RC:$rhs)), bb:$dst), - (BEQOp1 (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)>; -def : MipsPat<(brcond (i32 (setuge RC:$lhs, immSExt16:$rhs)), bb:$dst), - (BEQOp1 (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)>; -def : MipsPat<(brcond (i32 (setugt RC:$lhs, immSExt16Plus1:$rhs)), bb:$dst), - (BEQOp1 (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)>; -def : MipsPat<(brcond (i32 (setule RC:$lhs, RC:$rhs)), bb:$dst), - (BEQOp1 (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; -} - -// setcc patterns -multiclass SeteqPats<RegisterClass RC, Instruction SLTiuOp, Instruction XOROp, - Instruction SLTuOp, Register ZEROReg> { - def : MipsPat<(seteq RC:$lhs, 0), - (SLTiuOp RC:$lhs, 1)>; - def : MipsPat<(setne RC:$lhs, 0), - (SLTuOp ZEROReg, RC:$lhs)>; - def : MipsPat<(seteq RC:$lhs, RC:$rhs), - (SLTiuOp (XOROp RC:$lhs, RC:$rhs), 1)>; - def : MipsPat<(setne RC:$lhs, RC:$rhs), - (SLTuOp ZEROReg, (XOROp RC:$lhs, RC:$rhs))>; -} - -multiclass SetlePats<RegisterClass RC, Instruction XORiOp, Instruction SLTOp, - Instruction SLTuOp> { - def : MipsPat<(setle RC:$lhs, RC:$rhs), - (XORiOp (SLTOp RC:$rhs, RC:$lhs), 1)>; - def : MipsPat<(setule RC:$lhs, RC:$rhs), - (XORiOp (SLTuOp RC:$rhs, RC:$lhs), 1)>; -} - -multiclass SetgtPats<RegisterClass RC, Instruction SLTOp, Instruction SLTuOp> { - def : MipsPat<(setgt RC:$lhs, RC:$rhs), - (SLTOp RC:$rhs, RC:$lhs)>; - def : MipsPat<(setugt RC:$lhs, RC:$rhs), - (SLTuOp RC:$rhs, RC:$lhs)>; -} - -multiclass SetgePats<RegisterClass RC, Instruction XORiOp, Instruction SLTOp, - Instruction SLTuOp> { - def : MipsPat<(setge RC:$lhs, RC:$rhs), - (XORiOp (SLTOp RC:$lhs, RC:$rhs), 1)>; - def : MipsPat<(setuge RC:$lhs, RC:$rhs), - (XORiOp (SLTuOp RC:$lhs, RC:$rhs), 1)>; -} - -multiclass SetgeImmPats<RegisterClass RC, Instruction XORiOp, - Instruction SLTiOp, Instruction SLTiuOp> { - def : MipsPat<(setge RC:$lhs, immSExt16:$rhs), - (XORiOp (SLTiOp RC:$lhs, immSExt16:$rhs), 1)>; - def : MipsPat<(setuge RC:$lhs, immSExt16:$rhs), - (XORiOp (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; - - // bswap pattern - def : MipsPat<(bswap GPR32:$rt), (ROTR (WSBH GPR32:$rt), 16)>, ISA_MIPS32R2; -} - -// 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; - } - - // 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 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; -} - -//===----------------------------------------------------------------------===// -// Floating Point Support -//===----------------------------------------------------------------------===// - -include "MipsInstrFPU.td" -include "Mips64InstrInfo.td" -include "MipsCondMov.td" - -include "Mips32r6InstrInfo.td" -include "Mips64r6InstrInfo.td" - -// -// Mips16 - -include "Mips16InstrFormats.td" -include "Mips16InstrInfo.td" - -// DSP -include "MipsDSPInstrFormats.td" -include "MipsDSPInstrInfo.td" - -// MSA -include "MipsMSAInstrFormats.td" -include "MipsMSAInstrInfo.td" - -// EVA -include "MipsEVAInstrFormats.td" -include "MipsEVAInstrInfo.td" - -// MT -include "MipsMTInstrFormats.td" -include "MipsMTInstrInfo.td" - -// Micromips -include "MicroMipsInstrFormats.td" -include "MicroMipsInstrInfo.td" -include "MicroMipsInstrFPU.td" - -// Micromips r6 -include "MicroMips32r6InstrFormats.td" -include "MicroMips32r6InstrInfo.td" - -// Micromips DSP -include "MicroMipsDSPInstrFormats.td" -include "MicroMipsDSPInstrInfo.td" diff --git a/contrib/llvm/lib/Target/Mips/MipsInstructionSelector.cpp b/contrib/llvm/lib/Target/Mips/MipsInstructionSelector.cpp deleted file mode 100644 index 45a47ad3c087..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsInstructionSelector.cpp +++ /dev/null @@ -1,671 +0,0 @@ -//===- MipsInstructionSelector.cpp ------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// \file -/// This file implements the targeting of the InstructionSelector class for -/// Mips. -/// \todo This should be generated by TableGen. -//===----------------------------------------------------------------------===// - -#include "MCTargetDesc/MipsInstPrinter.h" -#include "MipsMachineFunction.h" -#include "MipsRegisterBankInfo.h" -#include "MipsTargetMachine.h" -#include "llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h" -#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" - -#define DEBUG_TYPE "mips-isel" - -using namespace llvm; - -namespace { - -#define GET_GLOBALISEL_PREDICATE_BITSET -#include "MipsGenGlobalISel.inc" -#undef GET_GLOBALISEL_PREDICATE_BITSET - -class MipsInstructionSelector : public InstructionSelector { -public: - MipsInstructionSelector(const MipsTargetMachine &TM, const MipsSubtarget &STI, - const MipsRegisterBankInfo &RBI); - - bool select(MachineInstr &I, CodeGenCoverage &CoverageInfo) const override; - static const char *getName() { return DEBUG_TYPE; } - -private: - bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const; - bool materialize32BitImm(Register DestReg, APInt Imm, - MachineIRBuilder &B) const; - bool selectCopy(MachineInstr &I, MachineRegisterInfo &MRI) const; - const TargetRegisterClass * - getRegClassForTypeOnBank(unsigned OpSize, const RegisterBank &RB, - const RegisterBankInfo &RBI) const; - - const MipsTargetMachine &TM; - const MipsSubtarget &STI; - const MipsInstrInfo &TII; - const MipsRegisterInfo &TRI; - const MipsRegisterBankInfo &RBI; - -#define GET_GLOBALISEL_PREDICATES_DECL -#include "MipsGenGlobalISel.inc" -#undef GET_GLOBALISEL_PREDICATES_DECL - -#define GET_GLOBALISEL_TEMPORARIES_DECL -#include "MipsGenGlobalISel.inc" -#undef GET_GLOBALISEL_TEMPORARIES_DECL -}; - -} // end anonymous namespace - -#define GET_GLOBALISEL_IMPL -#include "MipsGenGlobalISel.inc" -#undef GET_GLOBALISEL_IMPL - -MipsInstructionSelector::MipsInstructionSelector( - const MipsTargetMachine &TM, const MipsSubtarget &STI, - const MipsRegisterBankInfo &RBI) - : InstructionSelector(), TM(TM), STI(STI), TII(*STI.getInstrInfo()), - TRI(*STI.getRegisterInfo()), RBI(RBI), - -#define GET_GLOBALISEL_PREDICATES_INIT -#include "MipsGenGlobalISel.inc" -#undef GET_GLOBALISEL_PREDICATES_INIT -#define GET_GLOBALISEL_TEMPORARIES_INIT -#include "MipsGenGlobalISel.inc" -#undef GET_GLOBALISEL_TEMPORARIES_INIT -{ -} - -bool MipsInstructionSelector::selectCopy(MachineInstr &I, - MachineRegisterInfo &MRI) const { - Register DstReg = I.getOperand(0).getReg(); - if (TargetRegisterInfo::isPhysicalRegister(DstReg)) - return true; - - const RegisterBank *RegBank = RBI.getRegBank(DstReg, MRI, TRI); - const unsigned DstSize = MRI.getType(DstReg).getSizeInBits(); - - const TargetRegisterClass *RC = &Mips::GPR32RegClass; - if (RegBank->getID() == Mips::FPRBRegBankID) { - if (DstSize == 32) - RC = &Mips::FGR32RegClass; - else if (DstSize == 64) - RC = STI.isFP64bit() ? &Mips::FGR64RegClass : &Mips::AFGR64RegClass; - else - llvm_unreachable("Unsupported destination size"); - } - if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) { - LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode()) - << " operand\n"); - return false; - } - return true; -} - -const TargetRegisterClass *MipsInstructionSelector::getRegClassForTypeOnBank( - unsigned OpSize, const RegisterBank &RB, - const RegisterBankInfo &RBI) const { - if (RB.getID() == Mips::GPRBRegBankID) - return &Mips::GPR32RegClass; - - if (RB.getID() == Mips::FPRBRegBankID) - return OpSize == 32 - ? &Mips::FGR32RegClass - : STI.hasMips32r6() || STI.isFP64bit() ? &Mips::FGR64RegClass - : &Mips::AFGR64RegClass; - - llvm_unreachable("getRegClassForTypeOnBank can't find register class."); - return nullptr; -} - -bool MipsInstructionSelector::materialize32BitImm(Register DestReg, APInt Imm, - MachineIRBuilder &B) const { - assert(Imm.getBitWidth() == 32 && "Unsupported immediate size."); - // Ori zero extends immediate. Used for values with zeros in high 16 bits. - if (Imm.getHiBits(16).isNullValue()) { - MachineInstr *Inst = B.buildInstr(Mips::ORi, {DestReg}, {Register(Mips::ZERO)}) - .addImm(Imm.getLoBits(16).getLimitedValue()); - return constrainSelectedInstRegOperands(*Inst, TII, TRI, RBI); - } - // Lui places immediate in high 16 bits and sets low 16 bits to zero. - if (Imm.getLoBits(16).isNullValue()) { - MachineInstr *Inst = B.buildInstr(Mips::LUi, {DestReg}, {}) - .addImm(Imm.getHiBits(16).getLimitedValue()); - return constrainSelectedInstRegOperands(*Inst, TII, TRI, RBI); - } - // ADDiu sign extends immediate. Used for values with 1s in high 17 bits. - if (Imm.isSignedIntN(16)) { - MachineInstr *Inst = B.buildInstr(Mips::ADDiu, {DestReg}, {Register(Mips::ZERO)}) - .addImm(Imm.getLoBits(16).getLimitedValue()); - return constrainSelectedInstRegOperands(*Inst, TII, TRI, RBI); - } - // Values that cannot be materialized with single immediate instruction. - Register LUiReg = B.getMRI()->createVirtualRegister(&Mips::GPR32RegClass); - MachineInstr *LUi = B.buildInstr(Mips::LUi, {LUiReg}, {}) - .addImm(Imm.getHiBits(16).getLimitedValue()); - MachineInstr *ORi = B.buildInstr(Mips::ORi, {DestReg}, {LUiReg}) - .addImm(Imm.getLoBits(16).getLimitedValue()); - if (!constrainSelectedInstRegOperands(*LUi, TII, TRI, RBI)) - return false; - if (!constrainSelectedInstRegOperands(*ORi, TII, TRI, RBI)) - return false; - return true; -} - -/// Returning Opc indicates that we failed to select MIPS instruction opcode. -static unsigned selectLoadStoreOpCode(unsigned Opc, unsigned MemSizeInBytes, - unsigned RegBank, bool isFP64) { - bool isStore = Opc == TargetOpcode::G_STORE; - if (RegBank == Mips::GPRBRegBankID) { - if (isStore) - switch (MemSizeInBytes) { - case 4: - return Mips::SW; - case 2: - return Mips::SH; - case 1: - return Mips::SB; - default: - return Opc; - } - else - // Unspecified extending load is selected into zeroExtending load. - switch (MemSizeInBytes) { - case 4: - return Mips::LW; - case 2: - return Opc == TargetOpcode::G_SEXTLOAD ? Mips::LH : Mips::LHu; - case 1: - return Opc == TargetOpcode::G_SEXTLOAD ? Mips::LB : Mips::LBu; - default: - return Opc; - } - } - - if (RegBank == Mips::FPRBRegBankID) { - switch (MemSizeInBytes) { - case 4: - return isStore ? Mips::SWC1 : Mips::LWC1; - case 8: - if (isFP64) - return isStore ? Mips::SDC164 : Mips::LDC164; - else - return isStore ? Mips::SDC1 : Mips::LDC1; - default: - return Opc; - } - } - return Opc; -} - -bool MipsInstructionSelector::select(MachineInstr &I, - CodeGenCoverage &CoverageInfo) const { - - MachineBasicBlock &MBB = *I.getParent(); - MachineFunction &MF = *MBB.getParent(); - MachineRegisterInfo &MRI = MF.getRegInfo(); - - if (!isPreISelGenericOpcode(I.getOpcode())) { - if (I.isCopy()) - return selectCopy(I, MRI); - - return true; - } - - if (I.getOpcode() == Mips::G_MUL) { - MachineInstr *Mul = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::MUL)) - .add(I.getOperand(0)) - .add(I.getOperand(1)) - .add(I.getOperand(2)); - if (!constrainSelectedInstRegOperands(*Mul, TII, TRI, RBI)) - return false; - Mul->getOperand(3).setIsDead(true); - Mul->getOperand(4).setIsDead(true); - - I.eraseFromParent(); - return true; - } - - if (selectImpl(I, CoverageInfo)) - return true; - - MachineInstr *MI = nullptr; - using namespace TargetOpcode; - - switch (I.getOpcode()) { - case G_UMULH: { - Register PseudoMULTuReg = MRI.createVirtualRegister(&Mips::ACC64RegClass); - MachineInstr *PseudoMULTu, *PseudoMove; - - PseudoMULTu = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::PseudoMULTu)) - .addDef(PseudoMULTuReg) - .add(I.getOperand(1)) - .add(I.getOperand(2)); - if (!constrainSelectedInstRegOperands(*PseudoMULTu, TII, TRI, RBI)) - return false; - - PseudoMove = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::PseudoMFHI)) - .addDef(I.getOperand(0).getReg()) - .addUse(PseudoMULTuReg); - if (!constrainSelectedInstRegOperands(*PseudoMove, TII, TRI, RBI)) - return false; - - I.eraseFromParent(); - return true; - } - case G_GEP: { - MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDu)) - .add(I.getOperand(0)) - .add(I.getOperand(1)) - .add(I.getOperand(2)); - break; - } - case G_FRAME_INDEX: { - MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu)) - .add(I.getOperand(0)) - .add(I.getOperand(1)) - .addImm(0); - break; - } - case G_BRCOND: { - MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::BNE)) - .add(I.getOperand(0)) - .addUse(Mips::ZERO) - .add(I.getOperand(1)); - break; - } - case G_PHI: { - const Register DestReg = I.getOperand(0).getReg(); - const unsigned OpSize = MRI.getType(DestReg).getSizeInBits(); - - const TargetRegisterClass *DefRC = nullptr; - if (TargetRegisterInfo::isPhysicalRegister(DestReg)) - DefRC = TRI.getRegClass(DestReg); - else - DefRC = getRegClassForTypeOnBank(OpSize, - *RBI.getRegBank(DestReg, MRI, TRI), RBI); - - I.setDesc(TII.get(TargetOpcode::PHI)); - return RBI.constrainGenericRegister(DestReg, *DefRC, MRI); - } - case G_STORE: - case G_LOAD: - case G_ZEXTLOAD: - case G_SEXTLOAD: { - const Register DestReg = I.getOperand(0).getReg(); - const unsigned DestRegBank = RBI.getRegBank(DestReg, MRI, TRI)->getID(); - const unsigned OpSize = MRI.getType(DestReg).getSizeInBits(); - const unsigned OpMemSizeInBytes = (*I.memoperands_begin())->getSize(); - - if (DestRegBank == Mips::GPRBRegBankID && OpSize != 32) - return false; - - if (DestRegBank == Mips::FPRBRegBankID && OpSize != 32 && OpSize != 64) - return false; - - const unsigned NewOpc = selectLoadStoreOpCode( - I.getOpcode(), OpMemSizeInBytes, DestRegBank, STI.isFP64bit()); - if (NewOpc == I.getOpcode()) - return false; - - MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(NewOpc)) - .add(I.getOperand(0)) - .add(I.getOperand(1)) - .addImm(0) - .addMemOperand(*I.memoperands_begin()); - break; - } - case G_UDIV: - case G_UREM: - case G_SDIV: - case G_SREM: { - Register HILOReg = MRI.createVirtualRegister(&Mips::ACC64RegClass); - bool IsSigned = I.getOpcode() == G_SREM || I.getOpcode() == G_SDIV; - bool IsDiv = I.getOpcode() == G_UDIV || I.getOpcode() == G_SDIV; - - MachineInstr *PseudoDIV, *PseudoMove; - PseudoDIV = BuildMI(MBB, I, I.getDebugLoc(), - TII.get(IsSigned ? Mips::PseudoSDIV : Mips::PseudoUDIV)) - .addDef(HILOReg) - .add(I.getOperand(1)) - .add(I.getOperand(2)); - if (!constrainSelectedInstRegOperands(*PseudoDIV, TII, TRI, RBI)) - return false; - - PseudoMove = BuildMI(MBB, I, I.getDebugLoc(), - TII.get(IsDiv ? Mips::PseudoMFLO : Mips::PseudoMFHI)) - .addDef(I.getOperand(0).getReg()) - .addUse(HILOReg); - if (!constrainSelectedInstRegOperands(*PseudoMove, TII, TRI, RBI)) - return false; - - I.eraseFromParent(); - return true; - } - case G_SELECT: { - // Handle operands with pointer type. - MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::MOVN_I_I)) - .add(I.getOperand(0)) - .add(I.getOperand(2)) - .add(I.getOperand(1)) - .add(I.getOperand(3)); - break; - } - case G_CONSTANT: { - MachineIRBuilder B(I); - if (!materialize32BitImm(I.getOperand(0).getReg(), - I.getOperand(1).getCImm()->getValue(), B)) - return false; - - I.eraseFromParent(); - return true; - } - case G_FCONSTANT: { - const APFloat &FPimm = I.getOperand(1).getFPImm()->getValueAPF(); - APInt APImm = FPimm.bitcastToAPInt(); - unsigned Size = MRI.getType(I.getOperand(0).getReg()).getSizeInBits(); - - if (Size == 32) { - Register GPRReg = MRI.createVirtualRegister(&Mips::GPR32RegClass); - MachineIRBuilder B(I); - if (!materialize32BitImm(GPRReg, APImm, B)) - return false; - - MachineInstrBuilder MTC1 = - B.buildInstr(Mips::MTC1, {I.getOperand(0).getReg()}, {GPRReg}); - if (!MTC1.constrainAllUses(TII, TRI, RBI)) - return false; - } - if (Size == 64) { - Register GPRRegHigh = MRI.createVirtualRegister(&Mips::GPR32RegClass); - Register GPRRegLow = MRI.createVirtualRegister(&Mips::GPR32RegClass); - MachineIRBuilder B(I); - if (!materialize32BitImm(GPRRegHigh, APImm.getHiBits(32).trunc(32), B)) - return false; - if (!materialize32BitImm(GPRRegLow, APImm.getLoBits(32).trunc(32), B)) - return false; - - MachineInstrBuilder PairF64 = B.buildInstr( - STI.isFP64bit() ? Mips::BuildPairF64_64 : Mips::BuildPairF64, - {I.getOperand(0).getReg()}, {GPRRegLow, GPRRegHigh}); - if (!PairF64.constrainAllUses(TII, TRI, RBI)) - return false; - } - - I.eraseFromParent(); - return true; - } - case G_FABS: { - unsigned Size = MRI.getType(I.getOperand(0).getReg()).getSizeInBits(); - unsigned FABSOpcode = - Size == 32 ? Mips::FABS_S - : STI.isFP64bit() ? Mips::FABS_D64 : Mips::FABS_D32; - MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(FABSOpcode)) - .add(I.getOperand(0)) - .add(I.getOperand(1)); - break; - } - case G_FPTOSI: { - unsigned FromSize = MRI.getType(I.getOperand(1).getReg()).getSizeInBits(); - unsigned ToSize = MRI.getType(I.getOperand(0).getReg()).getSizeInBits(); - (void)ToSize; - assert((ToSize == 32) && "Unsupported integer size for G_FPTOSI"); - assert((FromSize == 32 || FromSize == 64) && - "Unsupported floating point size for G_FPTOSI"); - - unsigned Opcode; - if (FromSize == 32) - Opcode = Mips::TRUNC_W_S; - else - Opcode = STI.isFP64bit() ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32; - unsigned ResultInFPR = MRI.createVirtualRegister(&Mips::FGR32RegClass); - MachineInstr *Trunc = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Opcode)) - .addDef(ResultInFPR) - .addUse(I.getOperand(1).getReg()); - if (!constrainSelectedInstRegOperands(*Trunc, TII, TRI, RBI)) - return false; - - MachineInstr *Move = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::MFC1)) - .addDef(I.getOperand(0).getReg()) - .addUse(ResultInFPR); - if (!constrainSelectedInstRegOperands(*Move, TII, TRI, RBI)) - return false; - - I.eraseFromParent(); - return true; - } - case G_GLOBAL_VALUE: { - const llvm::GlobalValue *GVal = I.getOperand(1).getGlobal(); - if (MF.getTarget().isPositionIndependent()) { - MachineInstr *LWGOT = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LW)) - .addDef(I.getOperand(0).getReg()) - .addReg(MF.getInfo<MipsFunctionInfo>() - ->getGlobalBaseRegForGlobalISel()) - .addGlobalAddress(GVal); - // Global Values that don't have local linkage are handled differently - // when they are part of call sequence. MipsCallLowering::lowerCall - // creates G_GLOBAL_VALUE instruction as part of call sequence and adds - // MO_GOT_CALL flag when Callee doesn't have local linkage. - if (I.getOperand(1).getTargetFlags() == MipsII::MO_GOT_CALL) - LWGOT->getOperand(2).setTargetFlags(MipsII::MO_GOT_CALL); - else - LWGOT->getOperand(2).setTargetFlags(MipsII::MO_GOT); - LWGOT->addMemOperand( - MF, MF.getMachineMemOperand(MachinePointerInfo::getGOT(MF), - MachineMemOperand::MOLoad, 4, 4)); - if (!constrainSelectedInstRegOperands(*LWGOT, TII, TRI, RBI)) - return false; - - if (GVal->hasLocalLinkage()) { - Register LWGOTDef = MRI.createVirtualRegister(&Mips::GPR32RegClass); - LWGOT->getOperand(0).setReg(LWGOTDef); - - MachineInstr *ADDiu = - BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu)) - .addDef(I.getOperand(0).getReg()) - .addReg(LWGOTDef) - .addGlobalAddress(GVal); - ADDiu->getOperand(2).setTargetFlags(MipsII::MO_ABS_LO); - if (!constrainSelectedInstRegOperands(*ADDiu, TII, TRI, RBI)) - return false; - } - } else { - Register LUiReg = MRI.createVirtualRegister(&Mips::GPR32RegClass); - - MachineInstr *LUi = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LUi)) - .addDef(LUiReg) - .addGlobalAddress(GVal); - LUi->getOperand(1).setTargetFlags(MipsII::MO_ABS_HI); - if (!constrainSelectedInstRegOperands(*LUi, TII, TRI, RBI)) - return false; - - MachineInstr *ADDiu = - BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu)) - .addDef(I.getOperand(0).getReg()) - .addUse(LUiReg) - .addGlobalAddress(GVal); - ADDiu->getOperand(2).setTargetFlags(MipsII::MO_ABS_LO); - if (!constrainSelectedInstRegOperands(*ADDiu, TII, TRI, RBI)) - return false; - } - I.eraseFromParent(); - return true; - } - case G_ICMP: { - struct Instr { - unsigned Opcode; - Register Def, LHS, RHS; - Instr(unsigned Opcode, Register Def, Register LHS, Register RHS) - : Opcode(Opcode), Def(Def), LHS(LHS), RHS(RHS){}; - - bool hasImm() const { - if (Opcode == Mips::SLTiu || Opcode == Mips::XORi) - return true; - return false; - } - }; - - SmallVector<struct Instr, 2> Instructions; - Register ICMPReg = I.getOperand(0).getReg(); - Register Temp = MRI.createVirtualRegister(&Mips::GPR32RegClass); - Register LHS = I.getOperand(2).getReg(); - Register RHS = I.getOperand(3).getReg(); - CmpInst::Predicate Cond = - static_cast<CmpInst::Predicate>(I.getOperand(1).getPredicate()); - - switch (Cond) { - case CmpInst::ICMP_EQ: // LHS == RHS -> (LHS ^ RHS) < 1 - Instructions.emplace_back(Mips::XOR, Temp, LHS, RHS); - Instructions.emplace_back(Mips::SLTiu, ICMPReg, Temp, 1); - break; - case CmpInst::ICMP_NE: // LHS != RHS -> 0 < (LHS ^ RHS) - Instructions.emplace_back(Mips::XOR, Temp, LHS, RHS); - Instructions.emplace_back(Mips::SLTu, ICMPReg, Mips::ZERO, Temp); - break; - case CmpInst::ICMP_UGT: // LHS > RHS -> RHS < LHS - Instructions.emplace_back(Mips::SLTu, ICMPReg, RHS, LHS); - break; - case CmpInst::ICMP_UGE: // LHS >= RHS -> !(LHS < RHS) - Instructions.emplace_back(Mips::SLTu, Temp, LHS, RHS); - Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1); - break; - case CmpInst::ICMP_ULT: // LHS < RHS -> LHS < RHS - Instructions.emplace_back(Mips::SLTu, ICMPReg, LHS, RHS); - break; - case CmpInst::ICMP_ULE: // LHS <= RHS -> !(RHS < LHS) - Instructions.emplace_back(Mips::SLTu, Temp, RHS, LHS); - Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1); - break; - case CmpInst::ICMP_SGT: // LHS > RHS -> RHS < LHS - Instructions.emplace_back(Mips::SLT, ICMPReg, RHS, LHS); - break; - case CmpInst::ICMP_SGE: // LHS >= RHS -> !(LHS < RHS) - Instructions.emplace_back(Mips::SLT, Temp, LHS, RHS); - Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1); - break; - case CmpInst::ICMP_SLT: // LHS < RHS -> LHS < RHS - Instructions.emplace_back(Mips::SLT, ICMPReg, LHS, RHS); - break; - case CmpInst::ICMP_SLE: // LHS <= RHS -> !(RHS < LHS) - Instructions.emplace_back(Mips::SLT, Temp, RHS, LHS); - Instructions.emplace_back(Mips::XORi, ICMPReg, Temp, 1); - break; - default: - return false; - } - - MachineIRBuilder B(I); - for (const struct Instr &Instruction : Instructions) { - MachineInstrBuilder MIB = B.buildInstr( - Instruction.Opcode, {Instruction.Def}, {Instruction.LHS}); - - if (Instruction.hasImm()) - MIB.addImm(Instruction.RHS); - else - MIB.addUse(Instruction.RHS); - - if (!MIB.constrainAllUses(TII, TRI, RBI)) - return false; - } - - I.eraseFromParent(); - return true; - } - case G_FCMP: { - unsigned MipsFCMPCondCode; - bool isLogicallyNegated; - switch (CmpInst::Predicate Cond = static_cast<CmpInst::Predicate>( - I.getOperand(1).getPredicate())) { - case CmpInst::FCMP_UNO: // Unordered - case CmpInst::FCMP_ORD: // Ordered (OR) - MipsFCMPCondCode = Mips::FCOND_UN; - isLogicallyNegated = Cond != CmpInst::FCMP_UNO; - break; - case CmpInst::FCMP_OEQ: // Equal - case CmpInst::FCMP_UNE: // Not Equal (NEQ) - MipsFCMPCondCode = Mips::FCOND_OEQ; - isLogicallyNegated = Cond != CmpInst::FCMP_OEQ; - break; - case CmpInst::FCMP_UEQ: // Unordered or Equal - case CmpInst::FCMP_ONE: // Ordered or Greater Than or Less Than (OGL) - MipsFCMPCondCode = Mips::FCOND_UEQ; - isLogicallyNegated = Cond != CmpInst::FCMP_UEQ; - break; - case CmpInst::FCMP_OLT: // Ordered or Less Than - case CmpInst::FCMP_UGE: // Unordered or Greater Than or Equal (UGE) - MipsFCMPCondCode = Mips::FCOND_OLT; - isLogicallyNegated = Cond != CmpInst::FCMP_OLT; - break; - case CmpInst::FCMP_ULT: // Unordered or Less Than - case CmpInst::FCMP_OGE: // Ordered or Greater Than or Equal (OGE) - MipsFCMPCondCode = Mips::FCOND_ULT; - isLogicallyNegated = Cond != CmpInst::FCMP_ULT; - break; - case CmpInst::FCMP_OLE: // Ordered or Less Than or Equal - case CmpInst::FCMP_UGT: // Unordered or Greater Than (UGT) - MipsFCMPCondCode = Mips::FCOND_OLE; - isLogicallyNegated = Cond != CmpInst::FCMP_OLE; - break; - case CmpInst::FCMP_ULE: // Unordered or Less Than or Equal - case CmpInst::FCMP_OGT: // Ordered or Greater Than (OGT) - MipsFCMPCondCode = Mips::FCOND_ULE; - isLogicallyNegated = Cond != CmpInst::FCMP_ULE; - break; - default: - return false; - } - - // Default compare result in gpr register will be `true`. - // We will move `false` (MIPS::Zero) to gpr result when fcmp gives false - // using MOVF_I. When orignal predicate (Cond) is logically negated - // MipsFCMPCondCode, result is inverted i.e. MOVT_I is used. - unsigned MoveOpcode = isLogicallyNegated ? Mips::MOVT_I : Mips::MOVF_I; - - unsigned TrueInReg = MRI.createVirtualRegister(&Mips::GPR32RegClass); - BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu)) - .addDef(TrueInReg) - .addUse(Mips::ZERO) - .addImm(1); - - unsigned Size = MRI.getType(I.getOperand(2).getReg()).getSizeInBits(); - unsigned FCMPOpcode = - Size == 32 ? Mips::FCMP_S32 - : STI.isFP64bit() ? Mips::FCMP_D64 : Mips::FCMP_D32; - MachineInstr *FCMP = BuildMI(MBB, I, I.getDebugLoc(), TII.get(FCMPOpcode)) - .addUse(I.getOperand(2).getReg()) - .addUse(I.getOperand(3).getReg()) - .addImm(MipsFCMPCondCode); - if (!constrainSelectedInstRegOperands(*FCMP, TII, TRI, RBI)) - return false; - - MachineInstr *Move = BuildMI(MBB, I, I.getDebugLoc(), TII.get(MoveOpcode)) - .addDef(I.getOperand(0).getReg()) - .addUse(Mips::ZERO) - .addUse(Mips::FCC0) - .addUse(TrueInReg); - if (!constrainSelectedInstRegOperands(*Move, TII, TRI, RBI)) - return false; - - I.eraseFromParent(); - return true; - } - default: - return false; - } - - I.eraseFromParent(); - return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI); -} - -namespace llvm { -InstructionSelector *createMipsInstructionSelector(const MipsTargetMachine &TM, - MipsSubtarget &Subtarget, - MipsRegisterBankInfo &RBI) { - return new MipsInstructionSelector(TM, Subtarget, RBI); -} -} // end namespace llvm diff --git a/contrib/llvm/lib/Target/Mips/MipsLegalizerInfo.cpp b/contrib/llvm/lib/Target/Mips/MipsLegalizerInfo.cpp deleted file mode 100644 index e442a81837ed..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsLegalizerInfo.cpp +++ /dev/null @@ -1,155 +0,0 @@ -//===- MipsLegalizerInfo.cpp ------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// \file -/// This file implements the targeting of the Machinelegalizer class for Mips. -/// \todo This should be generated by TableGen. -//===----------------------------------------------------------------------===// - -#include "MipsLegalizerInfo.h" -#include "MipsTargetMachine.h" -#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h" - -using namespace llvm; - -MipsLegalizerInfo::MipsLegalizerInfo(const MipsSubtarget &ST) { - using namespace TargetOpcode; - - const LLT s1 = LLT::scalar(1); - const LLT s32 = LLT::scalar(32); - const LLT s64 = LLT::scalar(64); - const LLT p0 = LLT::pointer(0, 32); - - getActionDefinitionsBuilder({G_ADD, G_SUB, G_MUL}) - .legalFor({s32}) - .clampScalar(0, s32, s32); - - getActionDefinitionsBuilder({G_UADDO, G_UADDE, G_USUBO, G_USUBE, G_UMULO}) - .lowerFor({{s32, s1}}); - - getActionDefinitionsBuilder(G_UMULH) - .legalFor({s32}) - .maxScalar(0, s32); - - getActionDefinitionsBuilder({G_LOAD, G_STORE}) - .legalForTypesWithMemDesc({{s32, p0, 8, 8}, - {s32, p0, 16, 8}, - {s32, p0, 32, 8}, - {s64, p0, 64, 8}, - {p0, p0, 32, 8}}) - .minScalar(0, s32); - - getActionDefinitionsBuilder(G_UNMERGE_VALUES) - .legalFor({{s32, s64}}); - - getActionDefinitionsBuilder(G_MERGE_VALUES) - .legalFor({{s64, s32}}); - - getActionDefinitionsBuilder({G_ZEXTLOAD, G_SEXTLOAD}) - .legalForTypesWithMemDesc({{s32, p0, 8, 8}, - {s32, p0, 16, 8}}) - .minScalar(0, s32); - - getActionDefinitionsBuilder(G_SELECT) - .legalForCartesianProduct({p0, s32, s64}, {s32}) - .minScalar(0, s32) - .minScalar(1, s32); - - getActionDefinitionsBuilder(G_BRCOND) - .legalFor({s32}) - .minScalar(0, s32); - - getActionDefinitionsBuilder(G_PHI) - .legalFor({p0, s32, s64}) - .minScalar(0, s32); - - getActionDefinitionsBuilder({G_AND, G_OR, G_XOR}) - .legalFor({s32}) - .clampScalar(0, s32, s32); - - getActionDefinitionsBuilder({G_SDIV, G_SREM, G_UREM, G_UDIV}) - .legalFor({s32}) - .minScalar(0, s32) - .libcallFor({s64}); - - getActionDefinitionsBuilder({G_SHL, G_ASHR, G_LSHR}) - .legalFor({s32, s32}) - .minScalar(1, s32); - - getActionDefinitionsBuilder(G_ICMP) - .legalForCartesianProduct({s32}, {s32, p0}) - .clampScalar(1, s32, s32) - .minScalar(0, s32); - - getActionDefinitionsBuilder(G_CONSTANT) - .legalFor({s32}) - .clampScalar(0, s32, s32); - - getActionDefinitionsBuilder(G_GEP) - .legalFor({{p0, s32}}); - - getActionDefinitionsBuilder(G_FRAME_INDEX) - .legalFor({p0}); - - getActionDefinitionsBuilder(G_GLOBAL_VALUE) - .legalFor({p0}); - - // FP instructions - getActionDefinitionsBuilder(G_FCONSTANT) - .legalFor({s32, s64}); - - getActionDefinitionsBuilder({G_FADD, G_FSUB, G_FMUL, G_FDIV, G_FABS, G_FSQRT}) - .legalFor({s32, s64}); - - getActionDefinitionsBuilder(G_FCMP) - .legalFor({{s32, s32}, {s32, s64}}) - .minScalar(0, s32); - - getActionDefinitionsBuilder({G_FCEIL, G_FFLOOR}) - .libcallFor({s32, s64}); - - getActionDefinitionsBuilder(G_FPEXT) - .legalFor({{s64, s32}}); - - getActionDefinitionsBuilder(G_FPTRUNC) - .legalFor({{s32, s64}}); - - // FP to int conversion instructions - getActionDefinitionsBuilder(G_FPTOSI) - .legalForCartesianProduct({s32}, {s64, s32}) - .libcallForCartesianProduct({s64}, {s64, s32}) - .minScalar(0, s32); - - getActionDefinitionsBuilder(G_FPTOUI) - .libcallForCartesianProduct({s64}, {s64, s32}) - .minScalar(0, s32); - - // Int to FP conversion instructions - getActionDefinitionsBuilder(G_SITOFP) - .legalForCartesianProduct({s64, s32}, {s32}) - .libcallForCartesianProduct({s64, s32}, {s64}) - .minScalar(1, s32); - - getActionDefinitionsBuilder(G_UITOFP) - .libcallForCartesianProduct({s64, s32}, {s64}) - .minScalar(1, s32); - - computeTables(); - verify(*ST.getInstrInfo()); -} - -bool MipsLegalizerInfo::legalizeCustom(MachineInstr &MI, - MachineRegisterInfo &MRI, - MachineIRBuilder &MIRBuilder, - GISelChangeObserver &Observer) const { - - using namespace TargetOpcode; - - MIRBuilder.setInstr(MI); - - return false; -} diff --git a/contrib/llvm/lib/Target/Mips/MipsLegalizerInfo.h b/contrib/llvm/lib/Target/Mips/MipsLegalizerInfo.h deleted file mode 100644 index e5021e081890..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsLegalizerInfo.h +++ /dev/null @@ -1,33 +0,0 @@ -//===- MipsLegalizerInfo ----------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// \file -/// This file declares the targeting of the Machinelegalizer class for Mips. -/// \todo This should be generated by TableGen. -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_MIPS_MIPSMACHINELEGALIZER_H -#define LLVM_LIB_TARGET_MIPS_MIPSMACHINELEGALIZER_H - -#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h" -#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h" - -namespace llvm { - -class MipsSubtarget; - -/// This class provides legalization strategies. -class MipsLegalizerInfo : public LegalizerInfo { -public: - MipsLegalizerInfo(const MipsSubtarget &ST); - - bool legalizeCustom(MachineInstr &MI, MachineRegisterInfo &MRI, - MachineIRBuilder &MIRBuilder, - GISelChangeObserver &Observer) const override; -}; -} // end namespace llvm -#endif diff --git a/contrib/llvm/lib/Target/Mips/MipsMCInstLower.cpp b/contrib/llvm/lib/Target/Mips/MipsMCInstLower.cpp deleted file mode 100644 index fd984058a2bf..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsMCInstLower.cpp +++ /dev/null @@ -1,330 +0,0 @@ -//===- MipsMCInstLower.cpp - Convert Mips MachineInstr to MCInst ----------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains code to lower Mips MachineInstrs to their corresponding -// MCInst records. -// -//===----------------------------------------------------------------------===// - -#include "MipsMCInstLower.h" -#include "MCTargetDesc/MipsBaseInfo.h" -#include "MCTargetDesc/MipsMCExpr.h" -#include "MipsAsmPrinter.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/CodeGen/MachineOperand.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCInst.h" -#include "llvm/Support/ErrorHandling.h" -#include <cassert> - -using namespace llvm; - -MipsMCInstLower::MipsMCInstLower(MipsAsmPrinter &asmprinter) - : AsmPrinter(asmprinter) {} - -void MipsMCInstLower::Initialize(MCContext *C) { - Ctx = C; -} - -MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO, - MachineOperandType MOTy, - unsigned Offset) const { - MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None; - MipsMCExpr::MipsExprKind TargetKind = MipsMCExpr::MEK_None; - bool IsGpOff = false; - const MCSymbol *Symbol; - - switch(MO.getTargetFlags()) { - default: - llvm_unreachable("Invalid target flag!"); - case MipsII::MO_NO_FLAG: - break; - case MipsII::MO_GPREL: - TargetKind = MipsMCExpr::MEK_GPREL; - break; - case MipsII::MO_GOT_CALL: - TargetKind = MipsMCExpr::MEK_GOT_CALL; - break; - case MipsII::MO_GOT: - TargetKind = MipsMCExpr::MEK_GOT; - break; - case MipsII::MO_ABS_HI: - TargetKind = MipsMCExpr::MEK_HI; - break; - case MipsII::MO_ABS_LO: - TargetKind = MipsMCExpr::MEK_LO; - break; - case MipsII::MO_TLSGD: - TargetKind = MipsMCExpr::MEK_TLSGD; - break; - case MipsII::MO_TLSLDM: - TargetKind = MipsMCExpr::MEK_TLSLDM; - break; - case MipsII::MO_DTPREL_HI: - TargetKind = MipsMCExpr::MEK_DTPREL_HI; - break; - case MipsII::MO_DTPREL_LO: - TargetKind = MipsMCExpr::MEK_DTPREL_LO; - break; - case MipsII::MO_GOTTPREL: - TargetKind = MipsMCExpr::MEK_GOTTPREL; - break; - case MipsII::MO_TPREL_HI: - TargetKind = MipsMCExpr::MEK_TPREL_HI; - break; - case MipsII::MO_TPREL_LO: - TargetKind = MipsMCExpr::MEK_TPREL_LO; - break; - case MipsII::MO_GPOFF_HI: - TargetKind = MipsMCExpr::MEK_HI; - IsGpOff = true; - break; - case MipsII::MO_GPOFF_LO: - TargetKind = MipsMCExpr::MEK_LO; - IsGpOff = true; - break; - case MipsII::MO_GOT_DISP: - TargetKind = MipsMCExpr::MEK_GOT_DISP; - break; - case MipsII::MO_GOT_HI16: - TargetKind = MipsMCExpr::MEK_GOT_HI16; - break; - case MipsII::MO_GOT_LO16: - TargetKind = MipsMCExpr::MEK_GOT_LO16; - break; - case MipsII::MO_GOT_PAGE: - TargetKind = MipsMCExpr::MEK_GOT_PAGE; - break; - case MipsII::MO_GOT_OFST: - TargetKind = MipsMCExpr::MEK_GOT_OFST; - break; - case MipsII::MO_HIGHER: - TargetKind = MipsMCExpr::MEK_HIGHER; - break; - case MipsII::MO_HIGHEST: - TargetKind = MipsMCExpr::MEK_HIGHEST; - break; - case MipsII::MO_CALL_HI16: - TargetKind = MipsMCExpr::MEK_CALL_HI16; - break; - case MipsII::MO_CALL_LO16: - TargetKind = MipsMCExpr::MEK_CALL_LO16; - break; - case MipsII::MO_JALR: - return MCOperand(); - } - - switch (MOTy) { - case MachineOperand::MO_MachineBasicBlock: - Symbol = MO.getMBB()->getSymbol(); - break; - - case MachineOperand::MO_GlobalAddress: - Symbol = AsmPrinter.getSymbol(MO.getGlobal()); - Offset += MO.getOffset(); - break; - - case MachineOperand::MO_BlockAddress: - Symbol = AsmPrinter.GetBlockAddressSymbol(MO.getBlockAddress()); - Offset += MO.getOffset(); - break; - - case MachineOperand::MO_ExternalSymbol: - Symbol = AsmPrinter.GetExternalSymbolSymbol(MO.getSymbolName()); - Offset += MO.getOffset(); - break; - - case MachineOperand::MO_MCSymbol: - Symbol = MO.getMCSymbol(); - Offset += MO.getOffset(); - break; - - case MachineOperand::MO_JumpTableIndex: - Symbol = AsmPrinter.GetJTISymbol(MO.getIndex()); - break; - - case MachineOperand::MO_ConstantPoolIndex: - Symbol = AsmPrinter.GetCPISymbol(MO.getIndex()); - Offset += MO.getOffset(); - break; - - default: - llvm_unreachable("<unknown operand type>"); - } - - const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, Kind, *Ctx); - - if (Offset) { - // Assume offset is never negative. - assert(Offset > 0); - - Expr = MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(Offset, *Ctx), - *Ctx); - } - - if (IsGpOff) - Expr = MipsMCExpr::createGpOff(TargetKind, Expr, *Ctx); - else if (TargetKind != MipsMCExpr::MEK_None) - Expr = MipsMCExpr::create(TargetKind, Expr, *Ctx); - - return MCOperand::createExpr(Expr); -} - -MCOperand MipsMCInstLower::LowerOperand(const MachineOperand &MO, - unsigned offset) const { - MachineOperandType MOTy = MO.getType(); - - switch (MOTy) { - default: llvm_unreachable("unknown operand type"); - case MachineOperand::MO_Register: - // Ignore all implicit register operands. - if (MO.isImplicit()) break; - return MCOperand::createReg(MO.getReg()); - case MachineOperand::MO_Immediate: - return MCOperand::createImm(MO.getImm() + offset); - case MachineOperand::MO_MachineBasicBlock: - case MachineOperand::MO_GlobalAddress: - case MachineOperand::MO_ExternalSymbol: - case MachineOperand::MO_MCSymbol: - case MachineOperand::MO_JumpTableIndex: - case MachineOperand::MO_ConstantPoolIndex: - case MachineOperand::MO_BlockAddress: - return LowerSymbolOperand(MO, MOTy, offset); - case MachineOperand::MO_RegisterMask: - break; - } - - return MCOperand(); -} - -MCOperand MipsMCInstLower::createSub(MachineBasicBlock *BB1, - MachineBasicBlock *BB2, - MipsMCExpr::MipsExprKind Kind) const { - const MCSymbolRefExpr *Sym1 = MCSymbolRefExpr::create(BB1->getSymbol(), *Ctx); - const MCSymbolRefExpr *Sym2 = MCSymbolRefExpr::create(BB2->getSymbol(), *Ctx); - const MCBinaryExpr *Sub = MCBinaryExpr::createSub(Sym1, Sym2, *Ctx); - - return MCOperand::createExpr(MipsMCExpr::create(Kind, Sub, *Ctx)); -} - -void MipsMCInstLower:: -lowerLongBranchLUi(const MachineInstr *MI, MCInst &OutMI) const { - OutMI.setOpcode(Mips::LUi); - - // Lower register operand. - OutMI.addOperand(LowerOperand(MI->getOperand(0))); - - MipsMCExpr::MipsExprKind Kind; - unsigned TargetFlags = MI->getOperand(1).getTargetFlags(); - switch (TargetFlags) { - case MipsII::MO_HIGHEST: - Kind = MipsMCExpr::MEK_HIGHEST; - break; - case MipsII::MO_HIGHER: - Kind = MipsMCExpr::MEK_HIGHER; - break; - case MipsII::MO_ABS_HI: - Kind = MipsMCExpr::MEK_HI; - break; - case MipsII::MO_ABS_LO: - Kind = MipsMCExpr::MEK_LO; - break; - default: - report_fatal_error("Unexpected flags for lowerLongBranchLUi"); - } - - if (MI->getNumOperands() == 2) { - const MCExpr *Expr = - MCSymbolRefExpr::create(MI->getOperand(1).getMBB()->getSymbol(), *Ctx); - const MipsMCExpr *MipsExpr = MipsMCExpr::create(Kind, Expr, *Ctx); - OutMI.addOperand(MCOperand::createExpr(MipsExpr)); - } else if (MI->getNumOperands() == 3) { - // Create %hi($tgt-$baltgt). - OutMI.addOperand(createSub(MI->getOperand(1).getMBB(), - MI->getOperand(2).getMBB(), Kind)); - } -} - -void MipsMCInstLower::lowerLongBranchADDiu(const MachineInstr *MI, - MCInst &OutMI, int Opcode) const { - OutMI.setOpcode(Opcode); - - MipsMCExpr::MipsExprKind Kind; - unsigned TargetFlags = MI->getOperand(2).getTargetFlags(); - switch (TargetFlags) { - case MipsII::MO_HIGHEST: - Kind = MipsMCExpr::MEK_HIGHEST; - break; - case MipsII::MO_HIGHER: - Kind = MipsMCExpr::MEK_HIGHER; - break; - case MipsII::MO_ABS_HI: - Kind = MipsMCExpr::MEK_HI; - break; - case MipsII::MO_ABS_LO: - Kind = MipsMCExpr::MEK_LO; - break; - default: - report_fatal_error("Unexpected flags for lowerLongBranchADDiu"); - } - - // Lower two register operands. - for (unsigned I = 0, E = 2; I != E; ++I) { - const MachineOperand &MO = MI->getOperand(I); - OutMI.addOperand(LowerOperand(MO)); - } - - if (MI->getNumOperands() == 3) { - // Lower register operand. - const MCExpr *Expr = - MCSymbolRefExpr::create(MI->getOperand(2).getMBB()->getSymbol(), *Ctx); - const MipsMCExpr *MipsExpr = MipsMCExpr::create(Kind, Expr, *Ctx); - OutMI.addOperand(MCOperand::createExpr(MipsExpr)); - } else if (MI->getNumOperands() == 4) { - // Create %lo($tgt-$baltgt) or %hi($tgt-$baltgt). - OutMI.addOperand(createSub(MI->getOperand(2).getMBB(), - MI->getOperand(3).getMBB(), Kind)); - } -} - -bool MipsMCInstLower::lowerLongBranch(const MachineInstr *MI, - MCInst &OutMI) const { - switch (MI->getOpcode()) { - default: - return false; - case Mips::LONG_BRANCH_LUi: - case Mips::LONG_BRANCH_LUi2Op: - case Mips::LONG_BRANCH_LUi2Op_64: - lowerLongBranchLUi(MI, OutMI); - return true; - case Mips::LONG_BRANCH_ADDiu: - case Mips::LONG_BRANCH_ADDiu2Op: - lowerLongBranchADDiu(MI, OutMI, Mips::ADDiu); - return true; - case Mips::LONG_BRANCH_DADDiu: - case Mips::LONG_BRANCH_DADDiu2Op: - lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu); - return true; - } -} - -void MipsMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { - if (lowerLongBranch(MI, OutMI)) - return; - - OutMI.setOpcode(MI->getOpcode()); - - for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { - const MachineOperand &MO = MI->getOperand(i); - MCOperand MCOp = LowerOperand(MO); - - if (MCOp.isValid()) - OutMI.addOperand(MCOp); - } -} diff --git a/contrib/llvm/lib/Target/Mips/MipsMCInstLower.h b/contrib/llvm/lib/Target/Mips/MipsMCInstLower.h deleted file mode 100644 index 29af6f21de82..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsMCInstLower.h +++ /dev/null @@ -1,53 +0,0 @@ -//===- MipsMCInstLower.h - Lower MachineInstr to MCInst --------*- C++ -*--===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_MIPS_MIPSMCINSTLOWER_H -#define LLVM_LIB_TARGET_MIPS_MIPSMCINSTLOWER_H - -#include "MCTargetDesc/MipsMCExpr.h" -#include "llvm/CodeGen/MachineOperand.h" -#include "llvm/Support/Compiler.h" - -namespace llvm { - -class MachineBasicBlock; -class MachineInstr; -class MCContext; -class MCInst; -class MCOperand; -class MipsAsmPrinter; - -/// MipsMCInstLower - This class is used to lower an MachineInstr into an -/// MCInst. -class LLVM_LIBRARY_VISIBILITY MipsMCInstLower { - using MachineOperandType = MachineOperand::MachineOperandType; - - MCContext *Ctx; - MipsAsmPrinter &AsmPrinter; - -public: - MipsMCInstLower(MipsAsmPrinter &asmprinter); - - void Initialize(MCContext *C); - void Lower(const MachineInstr *MI, MCInst &OutMI) const; - MCOperand LowerOperand(const MachineOperand& MO, unsigned offset = 0) const; - -private: - MCOperand LowerSymbolOperand(const MachineOperand &MO, - MachineOperandType MOTy, unsigned Offset) const; - MCOperand createSub(MachineBasicBlock *BB1, MachineBasicBlock *BB2, - MipsMCExpr::MipsExprKind Kind) const; - void lowerLongBranchLUi(const MachineInstr *MI, MCInst &OutMI) const; - void lowerLongBranchADDiu(const MachineInstr *MI, MCInst &OutMI, - int Opcode) const; - bool lowerLongBranch(const MachineInstr *MI, MCInst &OutMI) const; -}; - -} // end namespace llvm - -#endif // LLVM_LIB_TARGET_MIPS_MIPSMCINSTLOWER_H diff --git a/contrib/llvm/lib/Target/Mips/MipsMSAInstrFormats.td b/contrib/llvm/lib/Target/Mips/MipsMSAInstrFormats.td deleted file mode 100644 index 2bfc92c85e96..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsMSAInstrFormats.td +++ /dev/null @@ -1,455 +0,0 @@ -//===- MipsMSAInstrFormats.td - Mips Instruction Formats ---*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -class MSAInst : MipsInst<(outs), (ins), "", [], NoItinerary, FrmOther>, - ASE_MSA { - let EncodingPredicates = [HasStdEnc]; - let Inst{31-26} = 0b011110; -} - -class MSACBranch : MSAInst { - let Inst{31-26} = 0b010001; -} - -class MSASpecial : MSAInst { - let Inst{31-26} = 0b000000; -} - -class MSAPseudo<dag outs, dag ins, list<dag> pattern, - InstrItinClass itin = IIPseudo>: - MipsPseudo<outs, ins, pattern, itin> { - let EncodingPredicates = [HasStdEnc]; - let ASEPredicate = [HasMSA]; -} - -class MSA_BIT_B_FMT<bits<3> major, bits<6> minor>: MSAInst { - bits<5> ws; - bits<5> wd; - bits<3> m; - - let Inst{25-23} = major; - let Inst{22-19} = 0b1110; - let Inst{18-16} = m; - let Inst{15-11} = ws; - let Inst{10-6} = wd; - let Inst{5-0} = minor; -} - -class MSA_BIT_H_FMT<bits<3> major, bits<6> minor>: MSAInst { - bits<5> ws; - bits<5> wd; - bits<4> m; - - let Inst{25-23} = major; - let Inst{22-20} = 0b110; - let Inst{19-16} = m; - let Inst{15-11} = ws; - let Inst{10-6} = wd; - let Inst{5-0} = minor; -} - -class MSA_BIT_W_FMT<bits<3> major, bits<6> minor>: MSAInst { - bits<5> ws; - bits<5> wd; - bits<5> m; - - let Inst{25-23} = major; - let Inst{22-21} = 0b10; - let Inst{20-16} = m; - let Inst{15-11} = ws; - let Inst{10-6} = wd; - let Inst{5-0} = minor; -} - -class MSA_BIT_D_FMT<bits<3> major, bits<6> minor>: MSAInst { - bits<5> ws; - bits<5> wd; - bits<6> m; - - let Inst{25-23} = major; - let Inst{22} = 0b0; - let Inst{21-16} = m; - let Inst{15-11} = ws; - let Inst{10-6} = wd; - let Inst{5-0} = minor; -} - -class MSA_2R_FILL_FMT<bits<8> major, bits<2> df, bits<6> minor>: MSAInst { - bits<5> rs; - bits<5> wd; - - let Inst{25-18} = major; - let Inst{17-16} = df; - let Inst{15-11} = rs; - let Inst{10-6} = wd; - let Inst{5-0} = minor; -} - -class MSA_2R_FILL_D_FMT<bits<8> major, bits<2> df, bits<6> minor>: MSAInst { - bits<5> rs; - bits<5> wd; - - let Inst{25-18} = major; - let Inst{17-16} = df; - let Inst{15-11} = rs; - let Inst{10-6} = wd; - let Inst{5-0} = minor; -} - -class MSA_2R_FMT<bits<8> major, bits<2> df, bits<6> minor>: MSAInst { - bits<5> ws; - bits<5> wd; - - let Inst{25-18} = major; - let Inst{17-16} = df; - let Inst{15-11} = ws; - let Inst{10-6} = wd; - let Inst{5-0} = minor; -} - -class MSA_2RF_FMT<bits<9> major, bits<1> df, bits<6> minor>: MSAInst { - bits<5> ws; - bits<5> wd; - - let Inst{25-17} = major; - let Inst{16} = df; - let Inst{15-11} = ws; - let Inst{10-6} = wd; - let Inst{5-0} = minor; -} - -class MSA_3R_FMT<bits<3> major, bits<2> df, bits<6> minor>: MSAInst { - bits<5> wt; - bits<5> ws; - bits<5> wd; - - let Inst{25-23} = major; - let Inst{22-21} = df; - let Inst{20-16} = wt; - let Inst{15-11} = ws; - let Inst{10-6} = wd; - let Inst{5-0} = minor; -} - -class MSA_3RF_FMT<bits<4> major, bits<1> df, bits<6> minor>: MSAInst { - bits<5> wt; - bits<5> ws; - bits<5> wd; - - let Inst{25-22} = major; - let Inst{21} = df; - let Inst{20-16} = wt; - let Inst{15-11} = ws; - let Inst{10-6} = wd; - let Inst{5-0} = minor; -} - -class MSA_3R_INDEX_FMT<bits<3> major, bits<2> df, bits<6> minor>: MSAInst { - bits<5> rt; - bits<5> ws; - bits<5> wd; - - let Inst{25-23} = major; - let Inst{22-21} = df; - let Inst{20-16} = rt; - let Inst{15-11} = ws; - let Inst{10-6} = wd; - let Inst{5-0} = minor; -} - -class MSA_ELM_FMT<bits<10> major, bits<6> minor>: MSAInst { - bits<5> ws; - bits<5> wd; - - let Inst{25-16} = major; - let Inst{15-11} = ws; - let Inst{10-6} = wd; - let Inst{5-0} = minor; -} - -class MSA_ELM_CFCMSA_FMT<bits<10> major, bits<6> minor>: MSAInst { - bits<5> rd; - bits<5> cs; - - let Inst{25-16} = major; - let Inst{15-11} = cs; - let Inst{10-6} = rd; - let Inst{5-0} = minor; -} - -class MSA_ELM_CTCMSA_FMT<bits<10> major, bits<6> minor>: MSAInst { - bits<5> rs; - bits<5> cd; - - let Inst{25-16} = major; - let Inst{15-11} = rs; - let Inst{10-6} = cd; - let Inst{5-0} = minor; -} - -class MSA_ELM_B_FMT<bits<4> major, bits<6> minor>: MSAInst { - bits<4> n; - bits<5> ws; - bits<5> wd; - - let Inst{25-22} = major; - let Inst{21-20} = 0b00; - let Inst{19-16} = n{3-0}; - let Inst{15-11} = ws; - let Inst{10-6} = wd; - let Inst{5-0} = minor; -} - -class MSA_ELM_H_FMT<bits<4> major, bits<6> minor>: MSAInst { - bits<4> n; - bits<5> ws; - bits<5> wd; - - let Inst{25-22} = major; - let Inst{21-19} = 0b100; - let Inst{18-16} = n{2-0}; - let Inst{15-11} = ws; - let Inst{10-6} = wd; - let Inst{5-0} = minor; -} - -class MSA_ELM_W_FMT<bits<4> major, bits<6> minor>: MSAInst { - bits<4> n; - bits<5> ws; - bits<5> wd; - - let Inst{25-22} = major; - let Inst{21-18} = 0b1100; - let Inst{17-16} = n{1-0}; - let Inst{15-11} = ws; - let Inst{10-6} = wd; - let Inst{5-0} = minor; -} - -class MSA_ELM_D_FMT<bits<4> major, bits<6> minor>: MSAInst { - bits<4> n; - bits<5> ws; - bits<5> wd; - - let Inst{25-22} = major; - let Inst{21-17} = 0b11100; - let Inst{16} = n{0}; - let Inst{15-11} = ws; - let Inst{10-6} = wd; - let Inst{5-0} = minor; -} - -class MSA_ELM_COPY_B_FMT<bits<4> major, bits<6> minor>: MSAInst { - bits<4> n; - bits<5> ws; - bits<5> rd; - - let Inst{25-22} = major; - let Inst{21-20} = 0b00; - let Inst{19-16} = n{3-0}; - let Inst{15-11} = ws; - let Inst{10-6} = rd; - let Inst{5-0} = minor; -} - -class MSA_ELM_COPY_H_FMT<bits<4> major, bits<6> minor>: MSAInst { - bits<4> n; - bits<5> ws; - bits<5> rd; - - let Inst{25-22} = major; - let Inst{21-19} = 0b100; - let Inst{18-16} = n{2-0}; - let Inst{15-11} = ws; - let Inst{10-6} = rd; - let Inst{5-0} = minor; -} - -class MSA_ELM_COPY_W_FMT<bits<4> major, bits<6> minor>: MSAInst { - bits<4> n; - bits<5> ws; - bits<5> rd; - - let Inst{25-22} = major; - let Inst{21-18} = 0b1100; - let Inst{17-16} = n{1-0}; - let Inst{15-11} = ws; - let Inst{10-6} = rd; - let Inst{5-0} = minor; -} - -class MSA_ELM_COPY_D_FMT<bits<4> major, bits<6> minor>: MSAInst { - bits<4> n; - bits<5> ws; - bits<5> rd; - - let Inst{25-22} = major; - let Inst{21-17} = 0b11100; - let Inst{16} = n{0}; - let Inst{15-11} = ws; - let Inst{10-6} = rd; - let Inst{5-0} = minor; -} - -class MSA_ELM_INSERT_B_FMT<bits<4> major, bits<6> minor>: MSAInst { - bits<6> n; - bits<5> rs; - bits<5> wd; - - let Inst{25-22} = major; - let Inst{21-20} = 0b00; - let Inst{19-16} = n{3-0}; - let Inst{15-11} = rs; - let Inst{10-6} = wd; - let Inst{5-0} = minor; -} - -class MSA_ELM_INSERT_H_FMT<bits<4> major, bits<6> minor>: MSAInst { - bits<6> n; - bits<5> rs; - bits<5> wd; - - let Inst{25-22} = major; - let Inst{21-19} = 0b100; - let Inst{18-16} = n{2-0}; - let Inst{15-11} = rs; - let Inst{10-6} = wd; - let Inst{5-0} = minor; -} - -class MSA_ELM_INSERT_W_FMT<bits<4> major, bits<6> minor>: MSAInst { - bits<6> n; - bits<5> rs; - bits<5> wd; - - let Inst{25-22} = major; - let Inst{21-18} = 0b1100; - let Inst{17-16} = n{1-0}; - let Inst{15-11} = rs; - let Inst{10-6} = wd; - let Inst{5-0} = minor; -} - -class MSA_ELM_INSERT_D_FMT<bits<4> major, bits<6> minor>: MSAInst { - bits<6> n; - bits<5> rs; - bits<5> wd; - - let Inst{25-22} = major; - let Inst{21-17} = 0b11100; - let Inst{16} = n{0}; - let Inst{15-11} = rs; - let Inst{10-6} = wd; - let Inst{5-0} = minor; -} - -class MSA_I5_FMT<bits<3> major, bits<2> df, bits<6> minor>: MSAInst { - bits<5> imm; - bits<5> ws; - bits<5> wd; - - let Inst{25-23} = major; - let Inst{22-21} = df; - let Inst{20-16} = imm; - let Inst{15-11} = ws; - let Inst{10-6} = wd; - let Inst{5-0} = minor; -} - -class MSA_I8_FMT<bits<2> major, bits<6> minor>: MSAInst { - bits<8> u8; - bits<5> ws; - bits<5> wd; - - let Inst{25-24} = major; - let Inst{23-16} = u8; - let Inst{15-11} = ws; - let Inst{10-6} = wd; - let Inst{5-0} = minor; -} - -class MSA_I10_FMT<bits<3> major, bits<2> df, bits<6> minor>: MSAInst { - bits<10> s10; - bits<5> wd; - - let Inst{25-23} = major; - let Inst{22-21} = df; - let Inst{20-11} = s10; - let Inst{10-6} = wd; - let Inst{5-0} = minor; -} - -class MSA_MI10_FMT<bits<2> df, bits<4> minor>: MSAInst { - bits<21> addr; - bits<5> wd; - - let Inst{25-16} = addr{9-0}; - let Inst{15-11} = addr{20-16}; - let Inst{10-6} = wd; - let Inst{5-2} = minor; - let Inst{1-0} = df; -} - -class MSA_VEC_FMT<bits<5> major, bits<6> minor>: MSAInst { - bits<5> wt; - bits<5> ws; - bits<5> wd; - - let Inst{25-21} = major; - let Inst{20-16} = wt; - let Inst{15-11} = ws; - let Inst{10-6} = wd; - let Inst{5-0} = minor; -} - -class MSA_CBRANCH_FMT<bits<3> major, bits<2> df>: MSACBranch { - bits<16> offset; - bits<5> wt; - - let Inst{25-23} = major; - let Inst{22-21} = df; - let Inst{20-16} = wt; - let Inst{15-0} = offset; -} - -class MSA_CBRANCH_V_FMT<bits<5> major>: MSACBranch { - bits<16> offset; - bits<5> wt; - - let Inst{25-21} = major; - let Inst{20-16} = wt; - let Inst{15-0} = offset; -} - -class SPECIAL_LSA_FMT<bits<6> minor>: MSASpecial { - bits<5> rs; - bits<5> rt; - bits<5> rd; - bits<2> sa; - - let Inst{25-21} = rs; - let Inst{20-16} = rt; - let Inst{15-11} = rd; - let Inst{10-8} = 0b000; - let Inst{7-6} = sa; - let Inst{5-0} = minor; -} - -class SPECIAL_DLSA_FMT<bits<6> minor>: MSASpecial { - bits<5> rs; - bits<5> rt; - bits<5> rd; - bits<2> sa; - - let Inst{25-21} = rs; - let Inst{20-16} = rt; - let Inst{15-11} = rd; - let Inst{10-8} = 0b000; - let Inst{7-6} = sa; - let Inst{5-0} = minor; -} diff --git a/contrib/llvm/lib/Target/Mips/MipsMSAInstrInfo.td b/contrib/llvm/lib/Target/Mips/MipsMSAInstrInfo.td deleted file mode 100644 index 907ed9ef746f..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsMSAInstrInfo.td +++ /dev/null @@ -1,4057 +0,0 @@ -//===- MipsMSAInstrInfo.td - MSA ASE instructions -*- tablegen ------------*-=// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file describes Mips MSA ASE instructions. -// -//===----------------------------------------------------------------------===// - -def SDT_MipsVecCond : SDTypeProfile<1, 1, [SDTCisInt<0>, SDTCisVec<1>]>; -def SDT_VSetCC : SDTypeProfile<1, 3, [SDTCisInt<0>, - SDTCisInt<1>, - SDTCisSameAs<1, 2>, - SDTCisVT<3, OtherVT>]>; -def SDT_VFSetCC : SDTypeProfile<1, 3, [SDTCisInt<0>, - SDTCisFP<1>, - SDTCisSameAs<1, 2>, - SDTCisVT<3, OtherVT>]>; -def SDT_VSHF : SDTypeProfile<1, 3, [SDTCisInt<0>, SDTCisVec<0>, - SDTCisInt<1>, SDTCisVec<1>, - SDTCisSameAs<0, 2>, SDTCisSameAs<2, 3>]>; -def SDT_SHF : SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisVec<0>, - SDTCisVT<1, i32>, SDTCisSameAs<0, 2>]>; -def SDT_ILV : SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisVec<0>, - SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>]>; -def SDT_INSVE : SDTypeProfile<1, 4, [SDTCisVec<0>, SDTCisSameAs<0, 1>, - SDTCisVT<2, i32>, SDTCisSameAs<0, 3>, - SDTCisVT<4, i32>]>; - -def MipsVAllNonZero : SDNode<"MipsISD::VALL_NONZERO", SDT_MipsVecCond>; -def MipsVAnyNonZero : SDNode<"MipsISD::VANY_NONZERO", SDT_MipsVecCond>; -def MipsVAllZero : SDNode<"MipsISD::VALL_ZERO", SDT_MipsVecCond>; -def MipsVAnyZero : SDNode<"MipsISD::VANY_ZERO", SDT_MipsVecCond>; -def MipsVNOR : SDNode<"MipsISD::VNOR", SDTIntBinOp, - [SDNPCommutative, SDNPAssociative]>; -def MipsVSHF : SDNode<"MipsISD::VSHF", SDT_VSHF>; -def MipsSHF : SDNode<"MipsISD::SHF", SDT_SHF>; -def MipsILVEV : SDNode<"MipsISD::ILVEV", SDT_ILV>; -def MipsILVOD : SDNode<"MipsISD::ILVOD", SDT_ILV>; -def MipsILVL : SDNode<"MipsISD::ILVL", SDT_ILV>; -def MipsILVR : SDNode<"MipsISD::ILVR", SDT_ILV>; -def MipsPCKEV : SDNode<"MipsISD::PCKEV", SDT_ILV>; -def MipsPCKOD : SDNode<"MipsISD::PCKOD", SDT_ILV>; -def MipsINSVE : SDNode<"MipsISD::INSVE", SDT_INSVE>; -def MipsFMS : SDNode<"MipsISD::FMS", SDTFPTernaryOp>; - -def vsetcc : SDNode<"ISD::SETCC", SDT_VSetCC>; -def vfsetcc : SDNode<"ISD::SETCC", SDT_VFSetCC>; - -def MipsVExtractSExt : SDNode<"MipsISD::VEXTRACT_SEXT_ELT", - SDTypeProfile<1, 3, [SDTCisPtrTy<2>]>, []>; -def MipsVExtractZExt : SDNode<"MipsISD::VEXTRACT_ZEXT_ELT", - SDTypeProfile<1, 3, [SDTCisPtrTy<2>]>, []>; - -def immZExt1Ptr : ImmLeaf<iPTR, [{return isUInt<1>(Imm);}]>; -def immZExt2Ptr : ImmLeaf<iPTR, [{return isUInt<2>(Imm);}]>; -def immZExt3Ptr : ImmLeaf<iPTR, [{return isUInt<3>(Imm);}]>; -def immZExt4Ptr : ImmLeaf<iPTR, [{return isUInt<4>(Imm);}]>; - -// Operands - -def immZExt2Lsa : ImmLeaf<i32, [{return isUInt<2>(Imm - 1);}]>; - -// Pattern fragments -def vextract_sext_i8 : PatFrag<(ops node:$vec, node:$idx), - (MipsVExtractSExt node:$vec, node:$idx, i8)>; -def vextract_sext_i16 : PatFrag<(ops node:$vec, node:$idx), - (MipsVExtractSExt node:$vec, node:$idx, i16)>; -def vextract_sext_i32 : PatFrag<(ops node:$vec, node:$idx), - (MipsVExtractSExt node:$vec, node:$idx, i32)>; -def vextract_sext_i64 : PatFrag<(ops node:$vec, node:$idx), - (MipsVExtractSExt node:$vec, node:$idx, i64)>; - -def vextract_zext_i8 : PatFrag<(ops node:$vec, node:$idx), - (MipsVExtractZExt node:$vec, node:$idx, i8)>; -def vextract_zext_i16 : PatFrag<(ops node:$vec, node:$idx), - (MipsVExtractZExt node:$vec, node:$idx, i16)>; -def vextract_zext_i32 : PatFrag<(ops node:$vec, node:$idx), - (MipsVExtractZExt node:$vec, node:$idx, i32)>; -def vextract_zext_i64 : PatFrag<(ops node:$vec, node:$idx), - (MipsVExtractZExt node:$vec, node:$idx, i64)>; - -def vinsert_v16i8 : PatFrag<(ops node:$vec, node:$val, node:$idx), - (v16i8 (vector_insert node:$vec, node:$val, node:$idx))>; -def vinsert_v8i16 : PatFrag<(ops node:$vec, node:$val, node:$idx), - (v8i16 (vector_insert node:$vec, node:$val, node:$idx))>; -def vinsert_v4i32 : PatFrag<(ops node:$vec, node:$val, node:$idx), - (v4i32 (vector_insert node:$vec, node:$val, node:$idx))>; -def vinsert_v2i64 : PatFrag<(ops node:$vec, node:$val, node:$idx), - (v2i64 (vector_insert node:$vec, node:$val, node:$idx))>; - -def insve_v16i8 : PatFrag<(ops node:$v1, node:$i1, node:$v2, node:$i2), - (v16i8 (MipsINSVE node:$v1, node:$i1, node:$v2, node:$i2))>; -def insve_v8i16 : PatFrag<(ops node:$v1, node:$i1, node:$v2, node:$i2), - (v8i16 (MipsINSVE node:$v1, node:$i1, node:$v2, node:$i2))>; -def insve_v4i32 : PatFrag<(ops node:$v1, node:$i1, node:$v2, node:$i2), - (v4i32 (MipsINSVE node:$v1, node:$i1, node:$v2, node:$i2))>; -def insve_v2i64 : PatFrag<(ops node:$v1, node:$i1, node:$v2, node:$i2), - (v2i64 (MipsINSVE node:$v1, node:$i1, node:$v2, node:$i2))>; - -class vfsetcc_type<ValueType ResTy, ValueType OpTy, CondCode CC> : - PatFrag<(ops node:$lhs, node:$rhs), - (ResTy (vfsetcc (OpTy node:$lhs), (OpTy node:$rhs), CC))>; - -// ISD::SETFALSE cannot occur -def vfseteq_v4f32 : vfsetcc_type<v4i32, v4f32, SETEQ>; -def vfseteq_v2f64 : vfsetcc_type<v2i64, v2f64, SETEQ>; -def vfsetge_v4f32 : vfsetcc_type<v4i32, v4f32, SETGE>; -def vfsetge_v2f64 : vfsetcc_type<v2i64, v2f64, SETGE>; -def vfsetgt_v4f32 : vfsetcc_type<v4i32, v4f32, SETGT>; -def vfsetgt_v2f64 : vfsetcc_type<v2i64, v2f64, SETGT>; -def vfsetle_v4f32 : vfsetcc_type<v4i32, v4f32, SETLE>; -def vfsetle_v2f64 : vfsetcc_type<v2i64, v2f64, SETLE>; -def vfsetlt_v4f32 : vfsetcc_type<v4i32, v4f32, SETLT>; -def vfsetlt_v2f64 : vfsetcc_type<v2i64, v2f64, SETLT>; -def vfsetne_v4f32 : vfsetcc_type<v4i32, v4f32, SETNE>; -def vfsetne_v2f64 : vfsetcc_type<v2i64, v2f64, SETNE>; -def vfsetoeq_v4f32 : vfsetcc_type<v4i32, v4f32, SETOEQ>; -def vfsetoeq_v2f64 : vfsetcc_type<v2i64, v2f64, SETOEQ>; -def vfsetoge_v4f32 : vfsetcc_type<v4i32, v4f32, SETOGE>; -def vfsetoge_v2f64 : vfsetcc_type<v2i64, v2f64, SETOGE>; -def vfsetogt_v4f32 : vfsetcc_type<v4i32, v4f32, SETOGT>; -def vfsetogt_v2f64 : vfsetcc_type<v2i64, v2f64, SETOGT>; -def vfsetole_v4f32 : vfsetcc_type<v4i32, v4f32, SETOLE>; -def vfsetole_v2f64 : vfsetcc_type<v2i64, v2f64, SETOLE>; -def vfsetolt_v4f32 : vfsetcc_type<v4i32, v4f32, SETOLT>; -def vfsetolt_v2f64 : vfsetcc_type<v2i64, v2f64, SETOLT>; -def vfsetone_v4f32 : vfsetcc_type<v4i32, v4f32, SETONE>; -def vfsetone_v2f64 : vfsetcc_type<v2i64, v2f64, SETONE>; -def vfsetord_v4f32 : vfsetcc_type<v4i32, v4f32, SETO>; -def vfsetord_v2f64 : vfsetcc_type<v2i64, v2f64, SETO>; -def vfsetun_v4f32 : vfsetcc_type<v4i32, v4f32, SETUO>; -def vfsetun_v2f64 : vfsetcc_type<v2i64, v2f64, SETUO>; -def vfsetueq_v4f32 : vfsetcc_type<v4i32, v4f32, SETUEQ>; -def vfsetueq_v2f64 : vfsetcc_type<v2i64, v2f64, SETUEQ>; -def vfsetuge_v4f32 : vfsetcc_type<v4i32, v4f32, SETUGE>; -def vfsetuge_v2f64 : vfsetcc_type<v2i64, v2f64, SETUGE>; -def vfsetugt_v4f32 : vfsetcc_type<v4i32, v4f32, SETUGT>; -def vfsetugt_v2f64 : vfsetcc_type<v2i64, v2f64, SETUGT>; -def vfsetule_v4f32 : vfsetcc_type<v4i32, v4f32, SETULE>; -def vfsetule_v2f64 : vfsetcc_type<v2i64, v2f64, SETULE>; -def vfsetult_v4f32 : vfsetcc_type<v4i32, v4f32, SETULT>; -def vfsetult_v2f64 : vfsetcc_type<v2i64, v2f64, SETULT>; -def vfsetune_v4f32 : vfsetcc_type<v4i32, v4f32, SETUNE>; -def vfsetune_v2f64 : vfsetcc_type<v2i64, v2f64, SETUNE>; -// ISD::SETTRUE cannot occur -// ISD::SETFALSE2 cannot occur -// ISD::SETTRUE2 cannot occur - -class vsetcc_type<ValueType ResTy, CondCode CC> : - PatFrag<(ops node:$lhs, node:$rhs), - (ResTy (vsetcc node:$lhs, node:$rhs, CC))>; - -def vseteq_v16i8 : vsetcc_type<v16i8, SETEQ>; -def vseteq_v8i16 : vsetcc_type<v8i16, SETEQ>; -def vseteq_v4i32 : vsetcc_type<v4i32, SETEQ>; -def vseteq_v2i64 : vsetcc_type<v2i64, SETEQ>; -def vsetle_v16i8 : vsetcc_type<v16i8, SETLE>; -def vsetle_v8i16 : vsetcc_type<v8i16, SETLE>; -def vsetle_v4i32 : vsetcc_type<v4i32, SETLE>; -def vsetle_v2i64 : vsetcc_type<v2i64, SETLE>; -def vsetlt_v16i8 : vsetcc_type<v16i8, SETLT>; -def vsetlt_v8i16 : vsetcc_type<v8i16, SETLT>; -def vsetlt_v4i32 : vsetcc_type<v4i32, SETLT>; -def vsetlt_v2i64 : vsetcc_type<v2i64, SETLT>; -def vsetule_v16i8 : vsetcc_type<v16i8, SETULE>; -def vsetule_v8i16 : vsetcc_type<v8i16, SETULE>; -def vsetule_v4i32 : vsetcc_type<v4i32, SETULE>; -def vsetule_v2i64 : vsetcc_type<v2i64, SETULE>; -def vsetult_v16i8 : vsetcc_type<v16i8, SETULT>; -def vsetult_v8i16 : vsetcc_type<v8i16, SETULT>; -def vsetult_v4i32 : vsetcc_type<v4i32, SETULT>; -def vsetult_v2i64 : vsetcc_type<v2i64, SETULT>; - -def vsplati8 : PatFrag<(ops node:$e0), - (v16i8 (build_vector node:$e0, node:$e0, - node:$e0, node:$e0, - node:$e0, node:$e0, - node:$e0, node:$e0, - node:$e0, node:$e0, - node:$e0, node:$e0, - node:$e0, node:$e0, - node:$e0, node:$e0))>; -def vsplati16 : PatFrag<(ops node:$e0), - (v8i16 (build_vector node:$e0, node:$e0, - node:$e0, node:$e0, - node:$e0, node:$e0, - node:$e0, node:$e0))>; -def vsplati32 : PatFrag<(ops node:$e0), - (v4i32 (build_vector node:$e0, node:$e0, - node:$e0, node:$e0))>; - -def vsplati64_imm_eq_1 : PatLeaf<(bitconvert (v4i32 (build_vector))), [{ - APInt Imm; - SDNode *BV = N->getOperand(0).getNode(); - EVT EltTy = N->getValueType(0).getVectorElementType(); - - return selectVSplat(BV, Imm, EltTy.getSizeInBits()) && - Imm.getBitWidth() == EltTy.getSizeInBits() && Imm == 1; -}]>; - -def vsplati64 : PatFrag<(ops node:$e0), - (v2i64 (build_vector node:$e0, node:$e0))>; - -def vsplati64_splat_d : PatFrag<(ops node:$e0), - (v2i64 (bitconvert - (v4i32 (and - (v4i32 (build_vector node:$e0, - node:$e0, - node:$e0, - node:$e0)), - vsplati64_imm_eq_1))))>; - -def vsplatf32 : PatFrag<(ops node:$e0), - (v4f32 (build_vector node:$e0, node:$e0, - node:$e0, node:$e0))>; -def vsplatf64 : PatFrag<(ops node:$e0), - (v2f64 (build_vector node:$e0, node:$e0))>; - -def vsplati8_elt : PatFrag<(ops node:$v, node:$i), - (MipsVSHF (vsplati8 node:$i), node:$v, node:$v)>; -def vsplati16_elt : PatFrag<(ops node:$v, node:$i), - (MipsVSHF (vsplati16 node:$i), node:$v, node:$v)>; -def vsplati32_elt : PatFrag<(ops node:$v, node:$i), - (MipsVSHF (vsplati32 node:$i), node:$v, node:$v)>; -def vsplati64_elt : PatFrag<(ops node:$v, node:$i), - (MipsVSHF (vsplati64_splat_d node:$i), - node:$v, node:$v)>; - -class SplatPatLeaf<Operand opclass, dag frag, code pred = [{}], - SDNodeXForm xform = NOOP_SDNodeXForm> - : PatLeaf<frag, pred, xform> { - Operand OpClass = opclass; -} - -class SplatComplexPattern<Operand opclass, ValueType ty, int numops, string fn, - list<SDNode> roots = [], - list<SDNodeProperty> props = []> : - ComplexPattern<ty, numops, fn, roots, props> { - Operand OpClass = opclass; -} - -def vsplati8_uimm3 : SplatComplexPattern<vsplat_uimm3, v16i8, 1, - "selectVSplatUimm3", - [build_vector, bitconvert]>; - -def vsplati8_uimm4 : SplatComplexPattern<vsplat_uimm4, v16i8, 1, - "selectVSplatUimm4", - [build_vector, bitconvert]>; - -def vsplati8_uimm5 : SplatComplexPattern<vsplat_uimm5, v16i8, 1, - "selectVSplatUimm5", - [build_vector, bitconvert]>; - -def vsplati8_uimm8 : SplatComplexPattern<vsplat_uimm8, v16i8, 1, - "selectVSplatUimm8", - [build_vector, bitconvert]>; - -def vsplati8_simm5 : SplatComplexPattern<vsplat_simm5, v16i8, 1, - "selectVSplatSimm5", - [build_vector, bitconvert]>; - -def vsplati16_uimm3 : SplatComplexPattern<vsplat_uimm3, v8i16, 1, - "selectVSplatUimm3", - [build_vector, bitconvert]>; - -def vsplati16_uimm4 : SplatComplexPattern<vsplat_uimm4, v8i16, 1, - "selectVSplatUimm4", - [build_vector, bitconvert]>; - -def vsplati16_uimm5 : SplatComplexPattern<vsplat_uimm5, v8i16, 1, - "selectVSplatUimm5", - [build_vector, bitconvert]>; - -def vsplati16_simm5 : SplatComplexPattern<vsplat_simm5, v8i16, 1, - "selectVSplatSimm5", - [build_vector, bitconvert]>; - -def vsplati32_uimm2 : SplatComplexPattern<vsplat_uimm2, v4i32, 1, - "selectVSplatUimm2", - [build_vector, bitconvert]>; - -def vsplati32_uimm5 : SplatComplexPattern<vsplat_uimm5, v4i32, 1, - "selectVSplatUimm5", - [build_vector, bitconvert]>; - -def vsplati32_simm5 : SplatComplexPattern<vsplat_simm5, v4i32, 1, - "selectVSplatSimm5", - [build_vector, bitconvert]>; - -def vsplati64_uimm1 : SplatComplexPattern<vsplat_uimm1, v2i64, 1, - "selectVSplatUimm1", - [build_vector, bitconvert]>; - -def vsplati64_uimm5 : SplatComplexPattern<vsplat_uimm5, v2i64, 1, - "selectVSplatUimm5", - [build_vector, bitconvert]>; - -def vsplati64_uimm6 : SplatComplexPattern<vsplat_uimm6, v2i64, 1, - "selectVSplatUimm6", - [build_vector, bitconvert]>; - -def vsplati64_simm5 : SplatComplexPattern<vsplat_simm5, v2i64, 1, - "selectVSplatSimm5", - [build_vector, bitconvert]>; - -// Any build_vector that is a constant splat with a value that is an exact -// power of 2 -def vsplat_uimm_pow2 : ComplexPattern<vAny, 1, "selectVSplatUimmPow2", - [build_vector, bitconvert]>; - -// Any build_vector that is a constant splat with a value that is the bitwise -// inverse of an exact power of 2 -def vsplat_uimm_inv_pow2 : ComplexPattern<vAny, 1, "selectVSplatUimmInvPow2", - [build_vector, bitconvert]>; - -// Any build_vector that is a constant splat with only a consecutive sequence -// of left-most bits set. -def vsplat_maskl_bits_uimm3 - : SplatComplexPattern<vsplat_uimm3, vAny, 1, "selectVSplatMaskL", - [build_vector, bitconvert]>; -def vsplat_maskl_bits_uimm4 - : SplatComplexPattern<vsplat_uimm4, vAny, 1, "selectVSplatMaskL", - [build_vector, bitconvert]>; -def vsplat_maskl_bits_uimm5 - : SplatComplexPattern<vsplat_uimm5, vAny, 1, "selectVSplatMaskL", - [build_vector, bitconvert]>; -def vsplat_maskl_bits_uimm6 - : SplatComplexPattern<vsplat_uimm6, vAny, 1, "selectVSplatMaskL", - [build_vector, bitconvert]>; - -// Any build_vector that is a constant splat with only a consecutive sequence -// of right-most bits set. -def vsplat_maskr_bits_uimm3 - : SplatComplexPattern<vsplat_uimm3, vAny, 1, "selectVSplatMaskR", - [build_vector, bitconvert]>; -def vsplat_maskr_bits_uimm4 - : SplatComplexPattern<vsplat_uimm4, vAny, 1, "selectVSplatMaskR", - [build_vector, bitconvert]>; -def vsplat_maskr_bits_uimm5 - : SplatComplexPattern<vsplat_uimm5, vAny, 1, "selectVSplatMaskR", - [build_vector, bitconvert]>; -def vsplat_maskr_bits_uimm6 - : SplatComplexPattern<vsplat_uimm6, vAny, 1, "selectVSplatMaskR", - [build_vector, bitconvert]>; - -// Any build_vector that is a constant splat with a value that equals 1 -// FIXME: These should be a ComplexPattern but we can't use them because the -// ISel generator requires the uses to have a name, but providing a name -// causes other errors ("used in pattern but not operand list") -def vsplat_imm_eq_1 : PatLeaf<(build_vector), [{ - APInt Imm; - EVT EltTy = N->getValueType(0).getVectorElementType(); - - return selectVSplat(N, Imm, EltTy.getSizeInBits()) && - Imm.getBitWidth() == EltTy.getSizeInBits() && Imm == 1; -}]>; - -def vbclr_b : PatFrag<(ops node:$ws, node:$wt), - (and node:$ws, (xor (shl vsplat_imm_eq_1, node:$wt), - immAllOnesV))>; -def vbclr_h : PatFrag<(ops node:$ws, node:$wt), - (and node:$ws, (xor (shl vsplat_imm_eq_1, node:$wt), - immAllOnesV))>; -def vbclr_w : PatFrag<(ops node:$ws, node:$wt), - (and node:$ws, (xor (shl vsplat_imm_eq_1, node:$wt), - immAllOnesV))>; -def vbclr_d : PatFrag<(ops node:$ws, node:$wt), - (and node:$ws, (xor (shl (v2i64 vsplati64_imm_eq_1), - node:$wt), - (bitconvert (v4i32 immAllOnesV))))>; - -def vbneg_b : PatFrag<(ops node:$ws, node:$wt), - (xor node:$ws, (shl vsplat_imm_eq_1, node:$wt))>; -def vbneg_h : PatFrag<(ops node:$ws, node:$wt), - (xor node:$ws, (shl vsplat_imm_eq_1, node:$wt))>; -def vbneg_w : PatFrag<(ops node:$ws, node:$wt), - (xor node:$ws, (shl vsplat_imm_eq_1, node:$wt))>; -def vbneg_d : PatFrag<(ops node:$ws, node:$wt), - (xor node:$ws, (shl (v2i64 vsplati64_imm_eq_1), - node:$wt))>; - -def vbset_b : PatFrag<(ops node:$ws, node:$wt), - (or node:$ws, (shl vsplat_imm_eq_1, node:$wt))>; -def vbset_h : PatFrag<(ops node:$ws, node:$wt), - (or node:$ws, (shl vsplat_imm_eq_1, node:$wt))>; -def vbset_w : PatFrag<(ops node:$ws, node:$wt), - (or node:$ws, (shl vsplat_imm_eq_1, node:$wt))>; -def vbset_d : PatFrag<(ops node:$ws, node:$wt), - (or node:$ws, (shl (v2i64 vsplati64_imm_eq_1), - node:$wt))>; - -def muladd : PatFrag<(ops node:$wd, node:$ws, node:$wt), - (add node:$wd, (mul node:$ws, node:$wt))>; - -def mulsub : PatFrag<(ops node:$wd, node:$ws, node:$wt), - (sub node:$wd, (mul node:$ws, node:$wt))>; - -def mul_fexp2 : PatFrag<(ops node:$ws, node:$wt), - (fmul node:$ws, (fexp2 node:$wt))>; - -// Instruction encoding. -class ADD_A_B_ENC : MSA_3R_FMT<0b000, 0b00, 0b010000>; -class ADD_A_H_ENC : MSA_3R_FMT<0b000, 0b01, 0b010000>; -class ADD_A_W_ENC : MSA_3R_FMT<0b000, 0b10, 0b010000>; -class ADD_A_D_ENC : MSA_3R_FMT<0b000, 0b11, 0b010000>; - -class ADDS_A_B_ENC : MSA_3R_FMT<0b001, 0b00, 0b010000>; -class ADDS_A_H_ENC : MSA_3R_FMT<0b001, 0b01, 0b010000>; -class ADDS_A_W_ENC : MSA_3R_FMT<0b001, 0b10, 0b010000>; -class ADDS_A_D_ENC : MSA_3R_FMT<0b001, 0b11, 0b010000>; - -class ADDS_S_B_ENC : MSA_3R_FMT<0b010, 0b00, 0b010000>; -class ADDS_S_H_ENC : MSA_3R_FMT<0b010, 0b01, 0b010000>; -class ADDS_S_W_ENC : MSA_3R_FMT<0b010, 0b10, 0b010000>; -class ADDS_S_D_ENC : MSA_3R_FMT<0b010, 0b11, 0b010000>; - -class ADDS_U_B_ENC : MSA_3R_FMT<0b011, 0b00, 0b010000>; -class ADDS_U_H_ENC : MSA_3R_FMT<0b011, 0b01, 0b010000>; -class ADDS_U_W_ENC : MSA_3R_FMT<0b011, 0b10, 0b010000>; -class ADDS_U_D_ENC : MSA_3R_FMT<0b011, 0b11, 0b010000>; - -class ADDV_B_ENC : MSA_3R_FMT<0b000, 0b00, 0b001110>; -class ADDV_H_ENC : MSA_3R_FMT<0b000, 0b01, 0b001110>; -class ADDV_W_ENC : MSA_3R_FMT<0b000, 0b10, 0b001110>; -class ADDV_D_ENC : MSA_3R_FMT<0b000, 0b11, 0b001110>; - -class ADDVI_B_ENC : MSA_I5_FMT<0b000, 0b00, 0b000110>; -class ADDVI_H_ENC : MSA_I5_FMT<0b000, 0b01, 0b000110>; -class ADDVI_W_ENC : MSA_I5_FMT<0b000, 0b10, 0b000110>; -class ADDVI_D_ENC : MSA_I5_FMT<0b000, 0b11, 0b000110>; - -class AND_V_ENC : MSA_VEC_FMT<0b00000, 0b011110>; - -class ANDI_B_ENC : MSA_I8_FMT<0b00, 0b000000>; - -class ASUB_S_B_ENC : MSA_3R_FMT<0b100, 0b00, 0b010001>; -class ASUB_S_H_ENC : MSA_3R_FMT<0b100, 0b01, 0b010001>; -class ASUB_S_W_ENC : MSA_3R_FMT<0b100, 0b10, 0b010001>; -class ASUB_S_D_ENC : MSA_3R_FMT<0b100, 0b11, 0b010001>; - -class ASUB_U_B_ENC : MSA_3R_FMT<0b101, 0b00, 0b010001>; -class ASUB_U_H_ENC : MSA_3R_FMT<0b101, 0b01, 0b010001>; -class ASUB_U_W_ENC : MSA_3R_FMT<0b101, 0b10, 0b010001>; -class ASUB_U_D_ENC : MSA_3R_FMT<0b101, 0b11, 0b010001>; - -class AVE_S_B_ENC : MSA_3R_FMT<0b100, 0b00, 0b010000>; -class AVE_S_H_ENC : MSA_3R_FMT<0b100, 0b01, 0b010000>; -class AVE_S_W_ENC : MSA_3R_FMT<0b100, 0b10, 0b010000>; -class AVE_S_D_ENC : MSA_3R_FMT<0b100, 0b11, 0b010000>; - -class AVE_U_B_ENC : MSA_3R_FMT<0b101, 0b00, 0b010000>; -class AVE_U_H_ENC : MSA_3R_FMT<0b101, 0b01, 0b010000>; -class AVE_U_W_ENC : MSA_3R_FMT<0b101, 0b10, 0b010000>; -class AVE_U_D_ENC : MSA_3R_FMT<0b101, 0b11, 0b010000>; - -class AVER_S_B_ENC : MSA_3R_FMT<0b110, 0b00, 0b010000>; -class AVER_S_H_ENC : MSA_3R_FMT<0b110, 0b01, 0b010000>; -class AVER_S_W_ENC : MSA_3R_FMT<0b110, 0b10, 0b010000>; -class AVER_S_D_ENC : MSA_3R_FMT<0b110, 0b11, 0b010000>; - -class AVER_U_B_ENC : MSA_3R_FMT<0b111, 0b00, 0b010000>; -class AVER_U_H_ENC : MSA_3R_FMT<0b111, 0b01, 0b010000>; -class AVER_U_W_ENC : MSA_3R_FMT<0b111, 0b10, 0b010000>; -class AVER_U_D_ENC : MSA_3R_FMT<0b111, 0b11, 0b010000>; - -class BCLR_B_ENC : MSA_3R_FMT<0b011, 0b00, 0b001101>; -class BCLR_H_ENC : MSA_3R_FMT<0b011, 0b01, 0b001101>; -class BCLR_W_ENC : MSA_3R_FMT<0b011, 0b10, 0b001101>; -class BCLR_D_ENC : MSA_3R_FMT<0b011, 0b11, 0b001101>; - -class BCLRI_B_ENC : MSA_BIT_B_FMT<0b011, 0b001001>; -class BCLRI_H_ENC : MSA_BIT_H_FMT<0b011, 0b001001>; -class BCLRI_W_ENC : MSA_BIT_W_FMT<0b011, 0b001001>; -class BCLRI_D_ENC : MSA_BIT_D_FMT<0b011, 0b001001>; - -class BINSL_B_ENC : MSA_3R_FMT<0b110, 0b00, 0b001101>; -class BINSL_H_ENC : MSA_3R_FMT<0b110, 0b01, 0b001101>; -class BINSL_W_ENC : MSA_3R_FMT<0b110, 0b10, 0b001101>; -class BINSL_D_ENC : MSA_3R_FMT<0b110, 0b11, 0b001101>; - -class BINSLI_B_ENC : MSA_BIT_B_FMT<0b110, 0b001001>; -class BINSLI_H_ENC : MSA_BIT_H_FMT<0b110, 0b001001>; -class BINSLI_W_ENC : MSA_BIT_W_FMT<0b110, 0b001001>; -class BINSLI_D_ENC : MSA_BIT_D_FMT<0b110, 0b001001>; - -class BINSR_B_ENC : MSA_3R_FMT<0b111, 0b00, 0b001101>; -class BINSR_H_ENC : MSA_3R_FMT<0b111, 0b01, 0b001101>; -class BINSR_W_ENC : MSA_3R_FMT<0b111, 0b10, 0b001101>; -class BINSR_D_ENC : MSA_3R_FMT<0b111, 0b11, 0b001101>; - -class BINSRI_B_ENC : MSA_BIT_B_FMT<0b111, 0b001001>; -class BINSRI_H_ENC : MSA_BIT_H_FMT<0b111, 0b001001>; -class BINSRI_W_ENC : MSA_BIT_W_FMT<0b111, 0b001001>; -class BINSRI_D_ENC : MSA_BIT_D_FMT<0b111, 0b001001>; - -class BMNZ_V_ENC : MSA_VEC_FMT<0b00100, 0b011110>; - -class BMNZI_B_ENC : MSA_I8_FMT<0b00, 0b000001>; - -class BMZ_V_ENC : MSA_VEC_FMT<0b00101, 0b011110>; - -class BMZI_B_ENC : MSA_I8_FMT<0b01, 0b000001>; - -class BNEG_B_ENC : MSA_3R_FMT<0b101, 0b00, 0b001101>; -class BNEG_H_ENC : MSA_3R_FMT<0b101, 0b01, 0b001101>; -class BNEG_W_ENC : MSA_3R_FMT<0b101, 0b10, 0b001101>; -class BNEG_D_ENC : MSA_3R_FMT<0b101, 0b11, 0b001101>; - -class BNEGI_B_ENC : MSA_BIT_B_FMT<0b101, 0b001001>; -class BNEGI_H_ENC : MSA_BIT_H_FMT<0b101, 0b001001>; -class BNEGI_W_ENC : MSA_BIT_W_FMT<0b101, 0b001001>; -class BNEGI_D_ENC : MSA_BIT_D_FMT<0b101, 0b001001>; - -class BNZ_B_ENC : MSA_CBRANCH_FMT<0b111, 0b00>; -class BNZ_H_ENC : MSA_CBRANCH_FMT<0b111, 0b01>; -class BNZ_W_ENC : MSA_CBRANCH_FMT<0b111, 0b10>; -class BNZ_D_ENC : MSA_CBRANCH_FMT<0b111, 0b11>; - -class BNZ_V_ENC : MSA_CBRANCH_V_FMT<0b01111>; - -class BSEL_V_ENC : MSA_VEC_FMT<0b00110, 0b011110>; - -class BSELI_B_ENC : MSA_I8_FMT<0b10, 0b000001>; - -class BSET_B_ENC : MSA_3R_FMT<0b100, 0b00, 0b001101>; -class BSET_H_ENC : MSA_3R_FMT<0b100, 0b01, 0b001101>; -class BSET_W_ENC : MSA_3R_FMT<0b100, 0b10, 0b001101>; -class BSET_D_ENC : MSA_3R_FMT<0b100, 0b11, 0b001101>; - -class BSETI_B_ENC : MSA_BIT_B_FMT<0b100, 0b001001>; -class BSETI_H_ENC : MSA_BIT_H_FMT<0b100, 0b001001>; -class BSETI_W_ENC : MSA_BIT_W_FMT<0b100, 0b001001>; -class BSETI_D_ENC : MSA_BIT_D_FMT<0b100, 0b001001>; - -class BZ_B_ENC : MSA_CBRANCH_FMT<0b110, 0b00>; -class BZ_H_ENC : MSA_CBRANCH_FMT<0b110, 0b01>; -class BZ_W_ENC : MSA_CBRANCH_FMT<0b110, 0b10>; -class BZ_D_ENC : MSA_CBRANCH_FMT<0b110, 0b11>; - -class BZ_V_ENC : MSA_CBRANCH_V_FMT<0b01011>; - -class CEQ_B_ENC : MSA_3R_FMT<0b000, 0b00, 0b001111>; -class CEQ_H_ENC : MSA_3R_FMT<0b000, 0b01, 0b001111>; -class CEQ_W_ENC : MSA_3R_FMT<0b000, 0b10, 0b001111>; -class CEQ_D_ENC : MSA_3R_FMT<0b000, 0b11, 0b001111>; - -class CEQI_B_ENC : MSA_I5_FMT<0b000, 0b00, 0b000111>; -class CEQI_H_ENC : MSA_I5_FMT<0b000, 0b01, 0b000111>; -class CEQI_W_ENC : MSA_I5_FMT<0b000, 0b10, 0b000111>; -class CEQI_D_ENC : MSA_I5_FMT<0b000, 0b11, 0b000111>; - -class CFCMSA_ENC : MSA_ELM_CFCMSA_FMT<0b0001111110, 0b011001>; - -class CLE_S_B_ENC : MSA_3R_FMT<0b100, 0b00, 0b001111>; -class CLE_S_H_ENC : MSA_3R_FMT<0b100, 0b01, 0b001111>; -class CLE_S_W_ENC : MSA_3R_FMT<0b100, 0b10, 0b001111>; -class CLE_S_D_ENC : MSA_3R_FMT<0b100, 0b11, 0b001111>; - -class CLE_U_B_ENC : MSA_3R_FMT<0b101, 0b00, 0b001111>; -class CLE_U_H_ENC : MSA_3R_FMT<0b101, 0b01, 0b001111>; -class CLE_U_W_ENC : MSA_3R_FMT<0b101, 0b10, 0b001111>; -class CLE_U_D_ENC : MSA_3R_FMT<0b101, 0b11, 0b001111>; - -class CLEI_S_B_ENC : MSA_I5_FMT<0b100, 0b00, 0b000111>; -class CLEI_S_H_ENC : MSA_I5_FMT<0b100, 0b01, 0b000111>; -class CLEI_S_W_ENC : MSA_I5_FMT<0b100, 0b10, 0b000111>; -class CLEI_S_D_ENC : MSA_I5_FMT<0b100, 0b11, 0b000111>; - -class CLEI_U_B_ENC : MSA_I5_FMT<0b101, 0b00, 0b000111>; -class CLEI_U_H_ENC : MSA_I5_FMT<0b101, 0b01, 0b000111>; -class CLEI_U_W_ENC : MSA_I5_FMT<0b101, 0b10, 0b000111>; -class CLEI_U_D_ENC : MSA_I5_FMT<0b101, 0b11, 0b000111>; - -class CLT_S_B_ENC : MSA_3R_FMT<0b010, 0b00, 0b001111>; -class CLT_S_H_ENC : MSA_3R_FMT<0b010, 0b01, 0b001111>; -class CLT_S_W_ENC : MSA_3R_FMT<0b010, 0b10, 0b001111>; -class CLT_S_D_ENC : MSA_3R_FMT<0b010, 0b11, 0b001111>; - -class CLT_U_B_ENC : MSA_3R_FMT<0b011, 0b00, 0b001111>; -class CLT_U_H_ENC : MSA_3R_FMT<0b011, 0b01, 0b001111>; -class CLT_U_W_ENC : MSA_3R_FMT<0b011, 0b10, 0b001111>; -class CLT_U_D_ENC : MSA_3R_FMT<0b011, 0b11, 0b001111>; - -class CLTI_S_B_ENC : MSA_I5_FMT<0b010, 0b00, 0b000111>; -class CLTI_S_H_ENC : MSA_I5_FMT<0b010, 0b01, 0b000111>; -class CLTI_S_W_ENC : MSA_I5_FMT<0b010, 0b10, 0b000111>; -class CLTI_S_D_ENC : MSA_I5_FMT<0b010, 0b11, 0b000111>; - -class CLTI_U_B_ENC : MSA_I5_FMT<0b011, 0b00, 0b000111>; -class CLTI_U_H_ENC : MSA_I5_FMT<0b011, 0b01, 0b000111>; -class CLTI_U_W_ENC : MSA_I5_FMT<0b011, 0b10, 0b000111>; -class CLTI_U_D_ENC : MSA_I5_FMT<0b011, 0b11, 0b000111>; - -class COPY_S_B_ENC : MSA_ELM_COPY_B_FMT<0b0010, 0b011001>; -class COPY_S_H_ENC : MSA_ELM_COPY_H_FMT<0b0010, 0b011001>; -class COPY_S_W_ENC : MSA_ELM_COPY_W_FMT<0b0010, 0b011001>; -class COPY_S_D_ENC : MSA_ELM_COPY_D_FMT<0b0010, 0b011001>; - -class COPY_U_B_ENC : MSA_ELM_COPY_B_FMT<0b0011, 0b011001>; -class COPY_U_H_ENC : MSA_ELM_COPY_H_FMT<0b0011, 0b011001>; -class COPY_U_W_ENC : MSA_ELM_COPY_W_FMT<0b0011, 0b011001>; - -class CTCMSA_ENC : MSA_ELM_CTCMSA_FMT<0b0000111110, 0b011001>; - -class DIV_S_B_ENC : MSA_3R_FMT<0b100, 0b00, 0b010010>; -class DIV_S_H_ENC : MSA_3R_FMT<0b100, 0b01, 0b010010>; -class DIV_S_W_ENC : MSA_3R_FMT<0b100, 0b10, 0b010010>; -class DIV_S_D_ENC : MSA_3R_FMT<0b100, 0b11, 0b010010>; - -class DIV_U_B_ENC : MSA_3R_FMT<0b101, 0b00, 0b010010>; -class DIV_U_H_ENC : MSA_3R_FMT<0b101, 0b01, 0b010010>; -class DIV_U_W_ENC : MSA_3R_FMT<0b101, 0b10, 0b010010>; -class DIV_U_D_ENC : MSA_3R_FMT<0b101, 0b11, 0b010010>; - -class DOTP_S_H_ENC : MSA_3R_FMT<0b000, 0b01, 0b010011>; -class DOTP_S_W_ENC : MSA_3R_FMT<0b000, 0b10, 0b010011>; -class DOTP_S_D_ENC : MSA_3R_FMT<0b000, 0b11, 0b010011>; - -class DOTP_U_H_ENC : MSA_3R_FMT<0b001, 0b01, 0b010011>; -class DOTP_U_W_ENC : MSA_3R_FMT<0b001, 0b10, 0b010011>; -class DOTP_U_D_ENC : MSA_3R_FMT<0b001, 0b11, 0b010011>; - -class DPADD_S_H_ENC : MSA_3R_FMT<0b010, 0b01, 0b010011>; -class DPADD_S_W_ENC : MSA_3R_FMT<0b010, 0b10, 0b010011>; -class DPADD_S_D_ENC : MSA_3R_FMT<0b010, 0b11, 0b010011>; - -class DPADD_U_H_ENC : MSA_3R_FMT<0b011, 0b01, 0b010011>; -class DPADD_U_W_ENC : MSA_3R_FMT<0b011, 0b10, 0b010011>; -class DPADD_U_D_ENC : MSA_3R_FMT<0b011, 0b11, 0b010011>; - -class DPSUB_S_H_ENC : MSA_3R_FMT<0b100, 0b01, 0b010011>; -class DPSUB_S_W_ENC : MSA_3R_FMT<0b100, 0b10, 0b010011>; -class DPSUB_S_D_ENC : MSA_3R_FMT<0b100, 0b11, 0b010011>; - -class DPSUB_U_H_ENC : MSA_3R_FMT<0b101, 0b01, 0b010011>; -class DPSUB_U_W_ENC : MSA_3R_FMT<0b101, 0b10, 0b010011>; -class DPSUB_U_D_ENC : MSA_3R_FMT<0b101, 0b11, 0b010011>; - -class FADD_W_ENC : MSA_3RF_FMT<0b0000, 0b0, 0b011011>; -class FADD_D_ENC : MSA_3RF_FMT<0b0000, 0b1, 0b011011>; - -class FCAF_W_ENC : MSA_3RF_FMT<0b0000, 0b0, 0b011010>; -class FCAF_D_ENC : MSA_3RF_FMT<0b0000, 0b1, 0b011010>; - -class FCEQ_W_ENC : MSA_3RF_FMT<0b0010, 0b0, 0b011010>; -class FCEQ_D_ENC : MSA_3RF_FMT<0b0010, 0b1, 0b011010>; - -class FCLASS_W_ENC : MSA_2RF_FMT<0b110010000, 0b0, 0b011110>; -class FCLASS_D_ENC : MSA_2RF_FMT<0b110010000, 0b1, 0b011110>; - -class FCLE_W_ENC : MSA_3RF_FMT<0b0110, 0b0, 0b011010>; -class FCLE_D_ENC : MSA_3RF_FMT<0b0110, 0b1, 0b011010>; - -class FCLT_W_ENC : MSA_3RF_FMT<0b0100, 0b0, 0b011010>; -class FCLT_D_ENC : MSA_3RF_FMT<0b0100, 0b1, 0b011010>; - -class FCNE_W_ENC : MSA_3RF_FMT<0b0011, 0b0, 0b011100>; -class FCNE_D_ENC : MSA_3RF_FMT<0b0011, 0b1, 0b011100>; - -class FCOR_W_ENC : MSA_3RF_FMT<0b0001, 0b0, 0b011100>; -class FCOR_D_ENC : MSA_3RF_FMT<0b0001, 0b1, 0b011100>; - -class FCUEQ_W_ENC : MSA_3RF_FMT<0b0011, 0b0, 0b011010>; -class FCUEQ_D_ENC : MSA_3RF_FMT<0b0011, 0b1, 0b011010>; - -class FCULE_W_ENC : MSA_3RF_FMT<0b0111, 0b0, 0b011010>; -class FCULE_D_ENC : MSA_3RF_FMT<0b0111, 0b1, 0b011010>; - -class FCULT_W_ENC : MSA_3RF_FMT<0b0101, 0b0, 0b011010>; -class FCULT_D_ENC : MSA_3RF_FMT<0b0101, 0b1, 0b011010>; - -class FCUN_W_ENC : MSA_3RF_FMT<0b0001, 0b0, 0b011010>; -class FCUN_D_ENC : MSA_3RF_FMT<0b0001, 0b1, 0b011010>; - -class FCUNE_W_ENC : MSA_3RF_FMT<0b0010, 0b0, 0b011100>; -class FCUNE_D_ENC : MSA_3RF_FMT<0b0010, 0b1, 0b011100>; - -class FDIV_W_ENC : MSA_3RF_FMT<0b0011, 0b0, 0b011011>; -class FDIV_D_ENC : MSA_3RF_FMT<0b0011, 0b1, 0b011011>; - -class FEXDO_H_ENC : MSA_3RF_FMT<0b1000, 0b0, 0b011011>; -class FEXDO_W_ENC : MSA_3RF_FMT<0b1000, 0b1, 0b011011>; - -class FEXP2_W_ENC : MSA_3RF_FMT<0b0111, 0b0, 0b011011>; -class FEXP2_D_ENC : MSA_3RF_FMT<0b0111, 0b1, 0b011011>; - -class FEXUPL_W_ENC : MSA_2RF_FMT<0b110011000, 0b0, 0b011110>; -class FEXUPL_D_ENC : MSA_2RF_FMT<0b110011000, 0b1, 0b011110>; - -class FEXUPR_W_ENC : MSA_2RF_FMT<0b110011001, 0b0, 0b011110>; -class FEXUPR_D_ENC : MSA_2RF_FMT<0b110011001, 0b1, 0b011110>; - -class FFINT_S_W_ENC : MSA_2RF_FMT<0b110011110, 0b0, 0b011110>; -class FFINT_S_D_ENC : MSA_2RF_FMT<0b110011110, 0b1, 0b011110>; - -class FFINT_U_W_ENC : MSA_2RF_FMT<0b110011111, 0b0, 0b011110>; -class FFINT_U_D_ENC : MSA_2RF_FMT<0b110011111, 0b1, 0b011110>; - -class FFQL_W_ENC : MSA_2RF_FMT<0b110011010, 0b0, 0b011110>; -class FFQL_D_ENC : MSA_2RF_FMT<0b110011010, 0b1, 0b011110>; - -class FFQR_W_ENC : MSA_2RF_FMT<0b110011011, 0b0, 0b011110>; -class FFQR_D_ENC : MSA_2RF_FMT<0b110011011, 0b1, 0b011110>; - -class FILL_B_ENC : MSA_2R_FILL_FMT<0b11000000, 0b00, 0b011110>; -class FILL_H_ENC : MSA_2R_FILL_FMT<0b11000000, 0b01, 0b011110>; -class FILL_W_ENC : MSA_2R_FILL_FMT<0b11000000, 0b10, 0b011110>; -class FILL_D_ENC : MSA_2R_FILL_D_FMT<0b11000000, 0b11, 0b011110>; - -class FLOG2_W_ENC : MSA_2RF_FMT<0b110010111, 0b0, 0b011110>; -class FLOG2_D_ENC : MSA_2RF_FMT<0b110010111, 0b1, 0b011110>; - -class FMADD_W_ENC : MSA_3RF_FMT<0b0100, 0b0, 0b011011>; -class FMADD_D_ENC : MSA_3RF_FMT<0b0100, 0b1, 0b011011>; - -class FMAX_W_ENC : MSA_3RF_FMT<0b1110, 0b0, 0b011011>; -class FMAX_D_ENC : MSA_3RF_FMT<0b1110, 0b1, 0b011011>; - -class FMAX_A_W_ENC : MSA_3RF_FMT<0b1111, 0b0, 0b011011>; -class FMAX_A_D_ENC : MSA_3RF_FMT<0b1111, 0b1, 0b011011>; - -class FMIN_W_ENC : MSA_3RF_FMT<0b1100, 0b0, 0b011011>; -class FMIN_D_ENC : MSA_3RF_FMT<0b1100, 0b1, 0b011011>; - -class FMIN_A_W_ENC : MSA_3RF_FMT<0b1101, 0b0, 0b011011>; -class FMIN_A_D_ENC : MSA_3RF_FMT<0b1101, 0b1, 0b011011>; - -class FMSUB_W_ENC : MSA_3RF_FMT<0b0101, 0b0, 0b011011>; -class FMSUB_D_ENC : MSA_3RF_FMT<0b0101, 0b1, 0b011011>; - -class FMUL_W_ENC : MSA_3RF_FMT<0b0010, 0b0, 0b011011>; -class FMUL_D_ENC : MSA_3RF_FMT<0b0010, 0b1, 0b011011>; - -class FRINT_W_ENC : MSA_2RF_FMT<0b110010110, 0b0, 0b011110>; -class FRINT_D_ENC : MSA_2RF_FMT<0b110010110, 0b1, 0b011110>; - -class FRCP_W_ENC : MSA_2RF_FMT<0b110010101, 0b0, 0b011110>; -class FRCP_D_ENC : MSA_2RF_FMT<0b110010101, 0b1, 0b011110>; - -class FRSQRT_W_ENC : MSA_2RF_FMT<0b110010100, 0b0, 0b011110>; -class FRSQRT_D_ENC : MSA_2RF_FMT<0b110010100, 0b1, 0b011110>; - -class FSAF_W_ENC : MSA_3RF_FMT<0b1000, 0b0, 0b011010>; -class FSAF_D_ENC : MSA_3RF_FMT<0b1000, 0b1, 0b011010>; - -class FSEQ_W_ENC : MSA_3RF_FMT<0b1010, 0b0, 0b011010>; -class FSEQ_D_ENC : MSA_3RF_FMT<0b1010, 0b1, 0b011010>; - -class FSLE_W_ENC : MSA_3RF_FMT<0b1110, 0b0, 0b011010>; -class FSLE_D_ENC : MSA_3RF_FMT<0b1110, 0b1, 0b011010>; - -class FSLT_W_ENC : MSA_3RF_FMT<0b1100, 0b0, 0b011010>; -class FSLT_D_ENC : MSA_3RF_FMT<0b1100, 0b1, 0b011010>; - -class FSNE_W_ENC : MSA_3RF_FMT<0b1011, 0b0, 0b011100>; -class FSNE_D_ENC : MSA_3RF_FMT<0b1011, 0b1, 0b011100>; - -class FSOR_W_ENC : MSA_3RF_FMT<0b1001, 0b0, 0b011100>; -class FSOR_D_ENC : MSA_3RF_FMT<0b1001, 0b1, 0b011100>; - -class FSQRT_W_ENC : MSA_2RF_FMT<0b110010011, 0b0, 0b011110>; -class FSQRT_D_ENC : MSA_2RF_FMT<0b110010011, 0b1, 0b011110>; - -class FSUB_W_ENC : MSA_3RF_FMT<0b0001, 0b0, 0b011011>; -class FSUB_D_ENC : MSA_3RF_FMT<0b0001, 0b1, 0b011011>; - -class FSUEQ_W_ENC : MSA_3RF_FMT<0b1011, 0b0, 0b011010>; -class FSUEQ_D_ENC : MSA_3RF_FMT<0b1011, 0b1, 0b011010>; - -class FSULE_W_ENC : MSA_3RF_FMT<0b1111, 0b0, 0b011010>; -class FSULE_D_ENC : MSA_3RF_FMT<0b1111, 0b1, 0b011010>; - -class FSULT_W_ENC : MSA_3RF_FMT<0b1101, 0b0, 0b011010>; -class FSULT_D_ENC : MSA_3RF_FMT<0b1101, 0b1, 0b011010>; - -class FSUN_W_ENC : MSA_3RF_FMT<0b1001, 0b0, 0b011010>; -class FSUN_D_ENC : MSA_3RF_FMT<0b1001, 0b1, 0b011010>; - -class FSUNE_W_ENC : MSA_3RF_FMT<0b1010, 0b0, 0b011100>; -class FSUNE_D_ENC : MSA_3RF_FMT<0b1010, 0b1, 0b011100>; - -class FTINT_S_W_ENC : MSA_2RF_FMT<0b110011100, 0b0, 0b011110>; -class FTINT_S_D_ENC : MSA_2RF_FMT<0b110011100, 0b1, 0b011110>; - -class FTINT_U_W_ENC : MSA_2RF_FMT<0b110011101, 0b0, 0b011110>; -class FTINT_U_D_ENC : MSA_2RF_FMT<0b110011101, 0b1, 0b011110>; - -class FTQ_H_ENC : MSA_3RF_FMT<0b1010, 0b0, 0b011011>; -class FTQ_W_ENC : MSA_3RF_FMT<0b1010, 0b1, 0b011011>; - -class FTRUNC_S_W_ENC : MSA_2RF_FMT<0b110010001, 0b0, 0b011110>; -class FTRUNC_S_D_ENC : MSA_2RF_FMT<0b110010001, 0b1, 0b011110>; - -class FTRUNC_U_W_ENC : MSA_2RF_FMT<0b110010010, 0b0, 0b011110>; -class FTRUNC_U_D_ENC : MSA_2RF_FMT<0b110010010, 0b1, 0b011110>; - -class HADD_S_H_ENC : MSA_3R_FMT<0b100, 0b01, 0b010101>; -class HADD_S_W_ENC : MSA_3R_FMT<0b100, 0b10, 0b010101>; -class HADD_S_D_ENC : MSA_3R_FMT<0b100, 0b11, 0b010101>; - -class HADD_U_H_ENC : MSA_3R_FMT<0b101, 0b01, 0b010101>; -class HADD_U_W_ENC : MSA_3R_FMT<0b101, 0b10, 0b010101>; -class HADD_U_D_ENC : MSA_3R_FMT<0b101, 0b11, 0b010101>; - -class HSUB_S_H_ENC : MSA_3R_FMT<0b110, 0b01, 0b010101>; -class HSUB_S_W_ENC : MSA_3R_FMT<0b110, 0b10, 0b010101>; -class HSUB_S_D_ENC : MSA_3R_FMT<0b110, 0b11, 0b010101>; - -class HSUB_U_H_ENC : MSA_3R_FMT<0b111, 0b01, 0b010101>; -class HSUB_U_W_ENC : MSA_3R_FMT<0b111, 0b10, 0b010101>; -class HSUB_U_D_ENC : MSA_3R_FMT<0b111, 0b11, 0b010101>; - -class ILVEV_B_ENC : MSA_3R_FMT<0b110, 0b00, 0b010100>; -class ILVEV_H_ENC : MSA_3R_FMT<0b110, 0b01, 0b010100>; -class ILVEV_W_ENC : MSA_3R_FMT<0b110, 0b10, 0b010100>; -class ILVEV_D_ENC : MSA_3R_FMT<0b110, 0b11, 0b010100>; - -class ILVL_B_ENC : MSA_3R_FMT<0b100, 0b00, 0b010100>; -class ILVL_H_ENC : MSA_3R_FMT<0b100, 0b01, 0b010100>; -class ILVL_W_ENC : MSA_3R_FMT<0b100, 0b10, 0b010100>; -class ILVL_D_ENC : MSA_3R_FMT<0b100, 0b11, 0b010100>; - -class ILVOD_B_ENC : MSA_3R_FMT<0b111, 0b00, 0b010100>; -class ILVOD_H_ENC : MSA_3R_FMT<0b111, 0b01, 0b010100>; -class ILVOD_W_ENC : MSA_3R_FMT<0b111, 0b10, 0b010100>; -class ILVOD_D_ENC : MSA_3R_FMT<0b111, 0b11, 0b010100>; - -class ILVR_B_ENC : MSA_3R_FMT<0b101, 0b00, 0b010100>; -class ILVR_H_ENC : MSA_3R_FMT<0b101, 0b01, 0b010100>; -class ILVR_W_ENC : MSA_3R_FMT<0b101, 0b10, 0b010100>; -class ILVR_D_ENC : MSA_3R_FMT<0b101, 0b11, 0b010100>; - -class INSERT_B_ENC : MSA_ELM_INSERT_B_FMT<0b0100, 0b011001>; -class INSERT_H_ENC : MSA_ELM_INSERT_H_FMT<0b0100, 0b011001>; -class INSERT_W_ENC : MSA_ELM_INSERT_W_FMT<0b0100, 0b011001>; -class INSERT_D_ENC : MSA_ELM_INSERT_D_FMT<0b0100, 0b011001>; - -class INSVE_B_ENC : MSA_ELM_B_FMT<0b0101, 0b011001>; -class INSVE_H_ENC : MSA_ELM_H_FMT<0b0101, 0b011001>; -class INSVE_W_ENC : MSA_ELM_W_FMT<0b0101, 0b011001>; -class INSVE_D_ENC : MSA_ELM_D_FMT<0b0101, 0b011001>; - -class LD_B_ENC : MSA_MI10_FMT<0b00, 0b1000>; -class LD_H_ENC : MSA_MI10_FMT<0b01, 0b1000>; -class LD_W_ENC : MSA_MI10_FMT<0b10, 0b1000>; -class LD_D_ENC : MSA_MI10_FMT<0b11, 0b1000>; - -class LDI_B_ENC : MSA_I10_FMT<0b110, 0b00, 0b000111>; -class LDI_H_ENC : MSA_I10_FMT<0b110, 0b01, 0b000111>; -class LDI_W_ENC : MSA_I10_FMT<0b110, 0b10, 0b000111>; -class LDI_D_ENC : MSA_I10_FMT<0b110, 0b11, 0b000111>; - -class LSA_ENC : SPECIAL_LSA_FMT<0b000101>; -class DLSA_ENC : SPECIAL_DLSA_FMT<0b010101>; - -class MADD_Q_H_ENC : MSA_3RF_FMT<0b0101, 0b0, 0b011100>; -class MADD_Q_W_ENC : MSA_3RF_FMT<0b0101, 0b1, 0b011100>; - -class MADDR_Q_H_ENC : MSA_3RF_FMT<0b1101, 0b0, 0b011100>; -class MADDR_Q_W_ENC : MSA_3RF_FMT<0b1101, 0b1, 0b011100>; - -class MADDV_B_ENC : MSA_3R_FMT<0b001, 0b00, 0b010010>; -class MADDV_H_ENC : MSA_3R_FMT<0b001, 0b01, 0b010010>; -class MADDV_W_ENC : MSA_3R_FMT<0b001, 0b10, 0b010010>; -class MADDV_D_ENC : MSA_3R_FMT<0b001, 0b11, 0b010010>; - -class MAX_A_B_ENC : MSA_3R_FMT<0b110, 0b00, 0b001110>; -class MAX_A_H_ENC : MSA_3R_FMT<0b110, 0b01, 0b001110>; -class MAX_A_W_ENC : MSA_3R_FMT<0b110, 0b10, 0b001110>; -class MAX_A_D_ENC : MSA_3R_FMT<0b110, 0b11, 0b001110>; - -class MAX_S_B_ENC : MSA_3R_FMT<0b010, 0b00, 0b001110>; -class MAX_S_H_ENC : MSA_3R_FMT<0b010, 0b01, 0b001110>; -class MAX_S_W_ENC : MSA_3R_FMT<0b010, 0b10, 0b001110>; -class MAX_S_D_ENC : MSA_3R_FMT<0b010, 0b11, 0b001110>; - -class MAX_U_B_ENC : MSA_3R_FMT<0b011, 0b00, 0b001110>; -class MAX_U_H_ENC : MSA_3R_FMT<0b011, 0b01, 0b001110>; -class MAX_U_W_ENC : MSA_3R_FMT<0b011, 0b10, 0b001110>; -class MAX_U_D_ENC : MSA_3R_FMT<0b011, 0b11, 0b001110>; - -class MAXI_S_B_ENC : MSA_I5_FMT<0b010, 0b00, 0b000110>; -class MAXI_S_H_ENC : MSA_I5_FMT<0b010, 0b01, 0b000110>; -class MAXI_S_W_ENC : MSA_I5_FMT<0b010, 0b10, 0b000110>; -class MAXI_S_D_ENC : MSA_I5_FMT<0b010, 0b11, 0b000110>; - -class MAXI_U_B_ENC : MSA_I5_FMT<0b011, 0b00, 0b000110>; -class MAXI_U_H_ENC : MSA_I5_FMT<0b011, 0b01, 0b000110>; -class MAXI_U_W_ENC : MSA_I5_FMT<0b011, 0b10, 0b000110>; -class MAXI_U_D_ENC : MSA_I5_FMT<0b011, 0b11, 0b000110>; - -class MIN_A_B_ENC : MSA_3R_FMT<0b111, 0b00, 0b001110>; -class MIN_A_H_ENC : MSA_3R_FMT<0b111, 0b01, 0b001110>; -class MIN_A_W_ENC : MSA_3R_FMT<0b111, 0b10, 0b001110>; -class MIN_A_D_ENC : MSA_3R_FMT<0b111, 0b11, 0b001110>; - -class MIN_S_B_ENC : MSA_3R_FMT<0b100, 0b00, 0b001110>; -class MIN_S_H_ENC : MSA_3R_FMT<0b100, 0b01, 0b001110>; -class MIN_S_W_ENC : MSA_3R_FMT<0b100, 0b10, 0b001110>; -class MIN_S_D_ENC : MSA_3R_FMT<0b100, 0b11, 0b001110>; - -class MIN_U_B_ENC : MSA_3R_FMT<0b101, 0b00, 0b001110>; -class MIN_U_H_ENC : MSA_3R_FMT<0b101, 0b01, 0b001110>; -class MIN_U_W_ENC : MSA_3R_FMT<0b101, 0b10, 0b001110>; -class MIN_U_D_ENC : MSA_3R_FMT<0b101, 0b11, 0b001110>; - -class MINI_S_B_ENC : MSA_I5_FMT<0b100, 0b00, 0b000110>; -class MINI_S_H_ENC : MSA_I5_FMT<0b100, 0b01, 0b000110>; -class MINI_S_W_ENC : MSA_I5_FMT<0b100, 0b10, 0b000110>; -class MINI_S_D_ENC : MSA_I5_FMT<0b100, 0b11, 0b000110>; - -class MINI_U_B_ENC : MSA_I5_FMT<0b101, 0b00, 0b000110>; -class MINI_U_H_ENC : MSA_I5_FMT<0b101, 0b01, 0b000110>; -class MINI_U_W_ENC : MSA_I5_FMT<0b101, 0b10, 0b000110>; -class MINI_U_D_ENC : MSA_I5_FMT<0b101, 0b11, 0b000110>; - -class MOD_S_B_ENC : MSA_3R_FMT<0b110, 0b00, 0b010010>; -class MOD_S_H_ENC : MSA_3R_FMT<0b110, 0b01, 0b010010>; -class MOD_S_W_ENC : MSA_3R_FMT<0b110, 0b10, 0b010010>; -class MOD_S_D_ENC : MSA_3R_FMT<0b110, 0b11, 0b010010>; - -class MOD_U_B_ENC : MSA_3R_FMT<0b111, 0b00, 0b010010>; -class MOD_U_H_ENC : MSA_3R_FMT<0b111, 0b01, 0b010010>; -class MOD_U_W_ENC : MSA_3R_FMT<0b111, 0b10, 0b010010>; -class MOD_U_D_ENC : MSA_3R_FMT<0b111, 0b11, 0b010010>; - -class MOVE_V_ENC : MSA_ELM_FMT<0b0010111110, 0b011001>; - -class MSUB_Q_H_ENC : MSA_3RF_FMT<0b0110, 0b0, 0b011100>; -class MSUB_Q_W_ENC : MSA_3RF_FMT<0b0110, 0b1, 0b011100>; - -class MSUBR_Q_H_ENC : MSA_3RF_FMT<0b1110, 0b0, 0b011100>; -class MSUBR_Q_W_ENC : MSA_3RF_FMT<0b1110, 0b1, 0b011100>; - -class MSUBV_B_ENC : MSA_3R_FMT<0b010, 0b00, 0b010010>; -class MSUBV_H_ENC : MSA_3R_FMT<0b010, 0b01, 0b010010>; -class MSUBV_W_ENC : MSA_3R_FMT<0b010, 0b10, 0b010010>; -class MSUBV_D_ENC : MSA_3R_FMT<0b010, 0b11, 0b010010>; - -class MUL_Q_H_ENC : MSA_3RF_FMT<0b0100, 0b0, 0b011100>; -class MUL_Q_W_ENC : MSA_3RF_FMT<0b0100, 0b1, 0b011100>; - -class MULR_Q_H_ENC : MSA_3RF_FMT<0b1100, 0b0, 0b011100>; -class MULR_Q_W_ENC : MSA_3RF_FMT<0b1100, 0b1, 0b011100>; - -class MULV_B_ENC : MSA_3R_FMT<0b000, 0b00, 0b010010>; -class MULV_H_ENC : MSA_3R_FMT<0b000, 0b01, 0b010010>; -class MULV_W_ENC : MSA_3R_FMT<0b000, 0b10, 0b010010>; -class MULV_D_ENC : MSA_3R_FMT<0b000, 0b11, 0b010010>; - -class NLOC_B_ENC : MSA_2R_FMT<0b11000010, 0b00, 0b011110>; -class NLOC_H_ENC : MSA_2R_FMT<0b11000010, 0b01, 0b011110>; -class NLOC_W_ENC : MSA_2R_FMT<0b11000010, 0b10, 0b011110>; -class NLOC_D_ENC : MSA_2R_FMT<0b11000010, 0b11, 0b011110>; - -class NLZC_B_ENC : MSA_2R_FMT<0b11000011, 0b00, 0b011110>; -class NLZC_H_ENC : MSA_2R_FMT<0b11000011, 0b01, 0b011110>; -class NLZC_W_ENC : MSA_2R_FMT<0b11000011, 0b10, 0b011110>; -class NLZC_D_ENC : MSA_2R_FMT<0b11000011, 0b11, 0b011110>; - -class NOR_V_ENC : MSA_VEC_FMT<0b00010, 0b011110>; - -class NORI_B_ENC : MSA_I8_FMT<0b10, 0b000000>; - -class OR_V_ENC : MSA_VEC_FMT<0b00001, 0b011110>; - -class ORI_B_ENC : MSA_I8_FMT<0b01, 0b000000>; - -class PCKEV_B_ENC : MSA_3R_FMT<0b010, 0b00, 0b010100>; -class PCKEV_H_ENC : MSA_3R_FMT<0b010, 0b01, 0b010100>; -class PCKEV_W_ENC : MSA_3R_FMT<0b010, 0b10, 0b010100>; -class PCKEV_D_ENC : MSA_3R_FMT<0b010, 0b11, 0b010100>; - -class PCKOD_B_ENC : MSA_3R_FMT<0b011, 0b00, 0b010100>; -class PCKOD_H_ENC : MSA_3R_FMT<0b011, 0b01, 0b010100>; -class PCKOD_W_ENC : MSA_3R_FMT<0b011, 0b10, 0b010100>; -class PCKOD_D_ENC : MSA_3R_FMT<0b011, 0b11, 0b010100>; - -class PCNT_B_ENC : MSA_2R_FMT<0b11000001, 0b00, 0b011110>; -class PCNT_H_ENC : MSA_2R_FMT<0b11000001, 0b01, 0b011110>; -class PCNT_W_ENC : MSA_2R_FMT<0b11000001, 0b10, 0b011110>; -class PCNT_D_ENC : MSA_2R_FMT<0b11000001, 0b11, 0b011110>; - -class SAT_S_B_ENC : MSA_BIT_B_FMT<0b000, 0b001010>; -class SAT_S_H_ENC : MSA_BIT_H_FMT<0b000, 0b001010>; -class SAT_S_W_ENC : MSA_BIT_W_FMT<0b000, 0b001010>; -class SAT_S_D_ENC : MSA_BIT_D_FMT<0b000, 0b001010>; - -class SAT_U_B_ENC : MSA_BIT_B_FMT<0b001, 0b001010>; -class SAT_U_H_ENC : MSA_BIT_H_FMT<0b001, 0b001010>; -class SAT_U_W_ENC : MSA_BIT_W_FMT<0b001, 0b001010>; -class SAT_U_D_ENC : MSA_BIT_D_FMT<0b001, 0b001010>; - -class SHF_B_ENC : MSA_I8_FMT<0b00, 0b000010>; -class SHF_H_ENC : MSA_I8_FMT<0b01, 0b000010>; -class SHF_W_ENC : MSA_I8_FMT<0b10, 0b000010>; - -class SLD_B_ENC : MSA_3R_INDEX_FMT<0b000, 0b00, 0b010100>; -class SLD_H_ENC : MSA_3R_INDEX_FMT<0b000, 0b01, 0b010100>; -class SLD_W_ENC : MSA_3R_INDEX_FMT<0b000, 0b10, 0b010100>; -class SLD_D_ENC : MSA_3R_INDEX_FMT<0b000, 0b11, 0b010100>; - -class SLDI_B_ENC : MSA_ELM_B_FMT<0b0000, 0b011001>; -class SLDI_H_ENC : MSA_ELM_H_FMT<0b0000, 0b011001>; -class SLDI_W_ENC : MSA_ELM_W_FMT<0b0000, 0b011001>; -class SLDI_D_ENC : MSA_ELM_D_FMT<0b0000, 0b011001>; - -class SLL_B_ENC : MSA_3R_FMT<0b000, 0b00, 0b001101>; -class SLL_H_ENC : MSA_3R_FMT<0b000, 0b01, 0b001101>; -class SLL_W_ENC : MSA_3R_FMT<0b000, 0b10, 0b001101>; -class SLL_D_ENC : MSA_3R_FMT<0b000, 0b11, 0b001101>; - -class SLLI_B_ENC : MSA_BIT_B_FMT<0b000, 0b001001>; -class SLLI_H_ENC : MSA_BIT_H_FMT<0b000, 0b001001>; -class SLLI_W_ENC : MSA_BIT_W_FMT<0b000, 0b001001>; -class SLLI_D_ENC : MSA_BIT_D_FMT<0b000, 0b001001>; - -class SPLAT_B_ENC : MSA_3R_INDEX_FMT<0b001, 0b00, 0b010100>; -class SPLAT_H_ENC : MSA_3R_INDEX_FMT<0b001, 0b01, 0b010100>; -class SPLAT_W_ENC : MSA_3R_INDEX_FMT<0b001, 0b10, 0b010100>; -class SPLAT_D_ENC : MSA_3R_INDEX_FMT<0b001, 0b11, 0b010100>; - -class SPLATI_B_ENC : MSA_ELM_B_FMT<0b0001, 0b011001>; -class SPLATI_H_ENC : MSA_ELM_H_FMT<0b0001, 0b011001>; -class SPLATI_W_ENC : MSA_ELM_W_FMT<0b0001, 0b011001>; -class SPLATI_D_ENC : MSA_ELM_D_FMT<0b0001, 0b011001>; - -class SRA_B_ENC : MSA_3R_FMT<0b001, 0b00, 0b001101>; -class SRA_H_ENC : MSA_3R_FMT<0b001, 0b01, 0b001101>; -class SRA_W_ENC : MSA_3R_FMT<0b001, 0b10, 0b001101>; -class SRA_D_ENC : MSA_3R_FMT<0b001, 0b11, 0b001101>; - -class SRAI_B_ENC : MSA_BIT_B_FMT<0b001, 0b001001>; -class SRAI_H_ENC : MSA_BIT_H_FMT<0b001, 0b001001>; -class SRAI_W_ENC : MSA_BIT_W_FMT<0b001, 0b001001>; -class SRAI_D_ENC : MSA_BIT_D_FMT<0b001, 0b001001>; - -class SRAR_B_ENC : MSA_3R_FMT<0b001, 0b00, 0b010101>; -class SRAR_H_ENC : MSA_3R_FMT<0b001, 0b01, 0b010101>; -class SRAR_W_ENC : MSA_3R_FMT<0b001, 0b10, 0b010101>; -class SRAR_D_ENC : MSA_3R_FMT<0b001, 0b11, 0b010101>; - -class SRARI_B_ENC : MSA_BIT_B_FMT<0b010, 0b001010>; -class SRARI_H_ENC : MSA_BIT_H_FMT<0b010, 0b001010>; -class SRARI_W_ENC : MSA_BIT_W_FMT<0b010, 0b001010>; -class SRARI_D_ENC : MSA_BIT_D_FMT<0b010, 0b001010>; - -class SRL_B_ENC : MSA_3R_FMT<0b010, 0b00, 0b001101>; -class SRL_H_ENC : MSA_3R_FMT<0b010, 0b01, 0b001101>; -class SRL_W_ENC : MSA_3R_FMT<0b010, 0b10, 0b001101>; -class SRL_D_ENC : MSA_3R_FMT<0b010, 0b11, 0b001101>; - -class SRLI_B_ENC : MSA_BIT_B_FMT<0b010, 0b001001>; -class SRLI_H_ENC : MSA_BIT_H_FMT<0b010, 0b001001>; -class SRLI_W_ENC : MSA_BIT_W_FMT<0b010, 0b001001>; -class SRLI_D_ENC : MSA_BIT_D_FMT<0b010, 0b001001>; - -class SRLR_B_ENC : MSA_3R_FMT<0b010, 0b00, 0b010101>; -class SRLR_H_ENC : MSA_3R_FMT<0b010, 0b01, 0b010101>; -class SRLR_W_ENC : MSA_3R_FMT<0b010, 0b10, 0b010101>; -class SRLR_D_ENC : MSA_3R_FMT<0b010, 0b11, 0b010101>; - -class SRLRI_B_ENC : MSA_BIT_B_FMT<0b011, 0b001010>; -class SRLRI_H_ENC : MSA_BIT_H_FMT<0b011, 0b001010>; -class SRLRI_W_ENC : MSA_BIT_W_FMT<0b011, 0b001010>; -class SRLRI_D_ENC : MSA_BIT_D_FMT<0b011, 0b001010>; - -class ST_B_ENC : MSA_MI10_FMT<0b00, 0b1001>; -class ST_H_ENC : MSA_MI10_FMT<0b01, 0b1001>; -class ST_W_ENC : MSA_MI10_FMT<0b10, 0b1001>; -class ST_D_ENC : MSA_MI10_FMT<0b11, 0b1001>; - -class SUBS_S_B_ENC : MSA_3R_FMT<0b000, 0b00, 0b010001>; -class SUBS_S_H_ENC : MSA_3R_FMT<0b000, 0b01, 0b010001>; -class SUBS_S_W_ENC : MSA_3R_FMT<0b000, 0b10, 0b010001>; -class SUBS_S_D_ENC : MSA_3R_FMT<0b000, 0b11, 0b010001>; - -class SUBS_U_B_ENC : MSA_3R_FMT<0b001, 0b00, 0b010001>; -class SUBS_U_H_ENC : MSA_3R_FMT<0b001, 0b01, 0b010001>; -class SUBS_U_W_ENC : MSA_3R_FMT<0b001, 0b10, 0b010001>; -class SUBS_U_D_ENC : MSA_3R_FMT<0b001, 0b11, 0b010001>; - -class SUBSUS_U_B_ENC : MSA_3R_FMT<0b010, 0b00, 0b010001>; -class SUBSUS_U_H_ENC : MSA_3R_FMT<0b010, 0b01, 0b010001>; -class SUBSUS_U_W_ENC : MSA_3R_FMT<0b010, 0b10, 0b010001>; -class SUBSUS_U_D_ENC : MSA_3R_FMT<0b010, 0b11, 0b010001>; - -class SUBSUU_S_B_ENC : MSA_3R_FMT<0b011, 0b00, 0b010001>; -class SUBSUU_S_H_ENC : MSA_3R_FMT<0b011, 0b01, 0b010001>; -class SUBSUU_S_W_ENC : MSA_3R_FMT<0b011, 0b10, 0b010001>; -class SUBSUU_S_D_ENC : MSA_3R_FMT<0b011, 0b11, 0b010001>; - -class SUBV_B_ENC : MSA_3R_FMT<0b001, 0b00, 0b001110>; -class SUBV_H_ENC : MSA_3R_FMT<0b001, 0b01, 0b001110>; -class SUBV_W_ENC : MSA_3R_FMT<0b001, 0b10, 0b001110>; -class SUBV_D_ENC : MSA_3R_FMT<0b001, 0b11, 0b001110>; - -class SUBVI_B_ENC : MSA_I5_FMT<0b001, 0b00, 0b000110>; -class SUBVI_H_ENC : MSA_I5_FMT<0b001, 0b01, 0b000110>; -class SUBVI_W_ENC : MSA_I5_FMT<0b001, 0b10, 0b000110>; -class SUBVI_D_ENC : MSA_I5_FMT<0b001, 0b11, 0b000110>; - -class VSHF_B_ENC : MSA_3R_FMT<0b000, 0b00, 0b010101>; -class VSHF_H_ENC : MSA_3R_FMT<0b000, 0b01, 0b010101>; -class VSHF_W_ENC : MSA_3R_FMT<0b000, 0b10, 0b010101>; -class VSHF_D_ENC : MSA_3R_FMT<0b000, 0b11, 0b010101>; - -class XOR_V_ENC : MSA_VEC_FMT<0b00011, 0b011110>; - -class XORI_B_ENC : MSA_I8_FMT<0b11, 0b000000>; - -// Instruction desc. -class MSA_BIT_B_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - ComplexPattern Imm, RegisterOperand ROWD, - RegisterOperand ROWS = ROWD, - InstrItinClass itin = NoItinerary> { - dag OutOperandList = (outs ROWD:$wd); - dag InOperandList = (ins ROWS:$ws, vsplat_uimm3:$m); - string AsmString = !strconcat(instr_asm, "\t$wd, $ws, $m"); - list<dag> Pattern = [(set ROWD:$wd, (OpNode ROWS:$ws, Imm:$m))]; - InstrItinClass Itinerary = itin; -} - -class MSA_BIT_H_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - ComplexPattern Imm, RegisterOperand ROWD, - RegisterOperand ROWS = ROWD, - InstrItinClass itin = NoItinerary> { - dag OutOperandList = (outs ROWD:$wd); - dag InOperandList = (ins ROWS:$ws, vsplat_uimm4:$m); - string AsmString = !strconcat(instr_asm, "\t$wd, $ws, $m"); - list<dag> Pattern = [(set ROWD:$wd, (OpNode ROWS:$ws, Imm:$m))]; - InstrItinClass Itinerary = itin; -} - -class MSA_BIT_W_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - ComplexPattern Imm, RegisterOperand ROWD, - RegisterOperand ROWS = ROWD, - InstrItinClass itin = NoItinerary> { - dag OutOperandList = (outs ROWD:$wd); - dag InOperandList = (ins ROWS:$ws, vsplat_uimm5:$m); - string AsmString = !strconcat(instr_asm, "\t$wd, $ws, $m"); - list<dag> Pattern = [(set ROWD:$wd, (OpNode ROWS:$ws, Imm:$m))]; - InstrItinClass Itinerary = itin; -} - -class MSA_BIT_D_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - ComplexPattern Imm, RegisterOperand ROWD, - RegisterOperand ROWS = ROWD, - InstrItinClass itin = NoItinerary> { - dag OutOperandList = (outs ROWD:$wd); - dag InOperandList = (ins ROWS:$ws, vsplat_uimm6:$m); - string AsmString = !strconcat(instr_asm, "\t$wd, $ws, $m"); - list<dag> Pattern = [(set ROWD:$wd, (OpNode ROWS:$ws, Imm:$m))]; - InstrItinClass Itinerary = itin; -} - -class MSA_BIT_X_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - Operand ImmOp, ImmLeaf Imm, RegisterOperand ROWD, - RegisterOperand ROWS = ROWD, - InstrItinClass itin = NoItinerary> { - dag OutOperandList = (outs ROWD:$wd); - dag InOperandList = (ins ROWS:$ws, ImmOp:$m); - string AsmString = !strconcat(instr_asm, "\t$wd, $ws, $m"); - list<dag> Pattern = [(set ROWD:$wd, (OpNode ROWS:$ws, Imm:$m))]; - InstrItinClass Itinerary = itin; -} - -class MSA_BIT_BINSXI_DESC_BASE<string instr_asm, ValueType Ty, - SplatComplexPattern Mask, RegisterOperand ROWD, - RegisterOperand ROWS = ROWD, - InstrItinClass itin = NoItinerary> { - dag OutOperandList = (outs ROWD:$wd); - dag InOperandList = (ins ROWD:$wd_in, ROWS:$ws, Mask.OpClass:$m); - string AsmString = !strconcat(instr_asm, "\t$wd, $ws, $m"); - // Note that binsxi and vselect treat the condition operand the opposite - // way to each other. - // (vselect cond, if_set, if_clear) - // (BSEL_V cond, if_clear, if_set) - list<dag> Pattern = [(set ROWD:$wd, (vselect (Ty Mask:$m), (Ty ROWD:$ws), - ROWS:$wd_in))]; - InstrItinClass Itinerary = itin; - string Constraints = "$wd = $wd_in"; -} - -class MSA_BIT_BINSLI_DESC_BASE<string instr_asm, ValueType Ty, - SplatComplexPattern ImmOp, RegisterOperand ROWD, - RegisterOperand ROWS = ROWD, - InstrItinClass itin = NoItinerary> : - MSA_BIT_BINSXI_DESC_BASE<instr_asm, Ty, ImmOp, ROWD, ROWS, itin>; - -class MSA_BIT_BINSRI_DESC_BASE<string instr_asm, ValueType Ty, - SplatComplexPattern ImmOp, RegisterOperand ROWD, - RegisterOperand ROWS = ROWD, - InstrItinClass itin = NoItinerary> : - MSA_BIT_BINSXI_DESC_BASE<instr_asm, Ty, ImmOp, ROWD, ROWS, itin>; - -class MSA_BIT_SPLAT_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - SplatComplexPattern SplatImm, - RegisterOperand ROWD, RegisterOperand ROWS = ROWD, - InstrItinClass itin = NoItinerary> { - dag OutOperandList = (outs ROWD:$wd); - dag InOperandList = (ins ROWS:$ws, SplatImm.OpClass:$m); - string AsmString = !strconcat(instr_asm, "\t$wd, $ws, $m"); - list<dag> Pattern = [(set ROWD:$wd, (OpNode ROWS:$ws, SplatImm:$m))]; - InstrItinClass Itinerary = itin; -} - -class MSA_COPY_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - ValueType VecTy, Operand ImmOp, ImmLeaf Imm, - RegisterOperand ROD, RegisterOperand ROWS, - InstrItinClass itin = NoItinerary> { - dag OutOperandList = (outs ROD:$rd); - dag InOperandList = (ins ROWS:$ws, ImmOp:$n); - string AsmString = !strconcat(instr_asm, "\t$rd, $ws[$n]"); - list<dag> Pattern = [(set ROD:$rd, (OpNode (VecTy ROWS:$ws), Imm:$n))]; - InstrItinClass Itinerary = itin; -} - -class MSA_ELM_SLD_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - RegisterOperand ROWD, RegisterOperand ROWS, - Operand ImmOp, ImmLeaf Imm, - InstrItinClass itin = NoItinerary> { - dag OutOperandList = (outs ROWD:$wd); - dag InOperandList = (ins ROWD:$wd_in, ROWS:$ws, ImmOp:$n); - string AsmString = !strconcat(instr_asm, "\t$wd, $ws[$n]"); - list<dag> Pattern = [(set ROWD:$wd, (OpNode ROWD:$wd_in, ROWS:$ws, - Imm:$n))]; - string Constraints = "$wd = $wd_in"; - InstrItinClass Itinerary = itin; -} - -class MSA_COPY_PSEUDO_BASE<SDPatternOperator OpNode, ValueType VecTy, - Operand ImmOp, ImmLeaf Imm, RegisterClass RCD, - RegisterClass RCWS> : - MSAPseudo<(outs RCD:$wd), (ins RCWS:$ws, ImmOp:$n), - [(set RCD:$wd, (OpNode (VecTy RCWS:$ws), Imm:$n))]> { - bit usesCustomInserter = 1; - bit hasNoSchedulingInfo = 1; -} - -class MSA_I5_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - SplatComplexPattern SplatImm, RegisterOperand ROWD, - RegisterOperand ROWS = ROWD, - InstrItinClass itin = NoItinerary> { - dag OutOperandList = (outs ROWD:$wd); - dag InOperandList = (ins ROWS:$ws, SplatImm.OpClass:$imm); - string AsmString = !strconcat(instr_asm, "\t$wd, $ws, $imm"); - list<dag> Pattern = [(set ROWD:$wd, (OpNode ROWS:$ws, SplatImm:$imm))]; - InstrItinClass Itinerary = itin; -} - -class MSA_I8_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - SplatComplexPattern SplatImm, RegisterOperand ROWD, - RegisterOperand ROWS = ROWD, - InstrItinClass itin = NoItinerary> { - dag OutOperandList = (outs ROWD:$wd); - dag InOperandList = (ins ROWS:$ws, SplatImm.OpClass:$u8); - string AsmString = !strconcat(instr_asm, "\t$wd, $ws, $u8"); - list<dag> Pattern = [(set ROWD:$wd, (OpNode ROWS:$ws, SplatImm:$u8))]; - InstrItinClass Itinerary = itin; -} - -class MSA_I8_SHF_DESC_BASE<string instr_asm, RegisterOperand ROWD, - RegisterOperand ROWS = ROWD, - InstrItinClass itin = NoItinerary> { - dag OutOperandList = (outs ROWD:$wd); - dag InOperandList = (ins ROWS:$ws, uimm8:$u8); - string AsmString = !strconcat(instr_asm, "\t$wd, $ws, $u8"); - list<dag> Pattern = [(set ROWD:$wd, (MipsSHF immZExt8:$u8, ROWS:$ws))]; - InstrItinClass Itinerary = itin; -} - -class MSA_I10_LDI_DESC_BASE<string instr_asm, RegisterOperand ROWD, - InstrItinClass itin = NoItinerary> { - dag OutOperandList = (outs ROWD:$wd); - dag InOperandList = (ins vsplat_simm10:$s10); - string AsmString = !strconcat(instr_asm, "\t$wd, $s10"); - // LDI is matched using custom matching code in MipsSEISelDAGToDAG.cpp - list<dag> Pattern = []; - bit hasSideEffects = 0; - InstrItinClass Itinerary = itin; -} - -class MSA_2R_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - RegisterOperand ROWD, RegisterOperand ROWS = ROWD, - InstrItinClass itin = NoItinerary> { - dag OutOperandList = (outs ROWD:$wd); - dag InOperandList = (ins ROWS:$ws); - string AsmString = !strconcat(instr_asm, "\t$wd, $ws"); - list<dag> Pattern = [(set ROWD:$wd, (OpNode ROWS:$ws))]; - InstrItinClass Itinerary = itin; -} - -class MSA_2R_FILL_DESC_BASE<string instr_asm, ValueType VT, - SDPatternOperator OpNode, RegisterOperand ROWD, - RegisterOperand ROS = ROWD, - InstrItinClass itin = NoItinerary> { - dag OutOperandList = (outs ROWD:$wd); - dag InOperandList = (ins ROS:$rs); - string AsmString = !strconcat(instr_asm, "\t$wd, $rs"); - list<dag> Pattern = [(set ROWD:$wd, (VT (OpNode ROS:$rs)))]; - InstrItinClass Itinerary = itin; -} - -class MSA_2R_FILL_PSEUDO_BASE<ValueType VT, SDPatternOperator OpNode, - RegisterClass RCWD, RegisterClass RCWS = RCWD> : - MSAPseudo<(outs RCWD:$wd), (ins RCWS:$fs), - [(set RCWD:$wd, (OpNode RCWS:$fs))]> { - let usesCustomInserter = 1; -} - -class MSA_2RF_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - RegisterOperand ROWD, RegisterOperand ROWS = ROWD, - InstrItinClass itin = NoItinerary> { - dag OutOperandList = (outs ROWD:$wd); - dag InOperandList = (ins ROWS:$ws); - string AsmString = !strconcat(instr_asm, "\t$wd, $ws"); - list<dag> Pattern = [(set ROWD:$wd, (OpNode ROWS:$ws))]; - InstrItinClass Itinerary = itin; -} - -class MSA_3R_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - RegisterOperand ROWD, RegisterOperand ROWS = ROWD, - RegisterOperand ROWT = ROWD, - InstrItinClass itin = NoItinerary> { - dag OutOperandList = (outs ROWD:$wd); - dag InOperandList = (ins ROWS:$ws, ROWT:$wt); - string AsmString = !strconcat(instr_asm, "\t$wd, $ws, $wt"); - list<dag> Pattern = [(set ROWD:$wd, (OpNode ROWS:$ws, ROWT:$wt))]; - InstrItinClass Itinerary = itin; -} - -class MSA_3R_BINSX_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - RegisterOperand ROWD, RegisterOperand ROWS = ROWD, - RegisterOperand ROWT = ROWD, - InstrItinClass itin = NoItinerary> { - dag OutOperandList = (outs ROWD:$wd); - dag InOperandList = (ins ROWD:$wd_in, ROWS:$ws, ROWT:$wt); - string AsmString = !strconcat(instr_asm, "\t$wd, $ws, $wt"); - list<dag> Pattern = [(set ROWD:$wd, (OpNode ROWD:$wd_in, ROWS:$ws, - ROWT:$wt))]; - string Constraints = "$wd = $wd_in"; - InstrItinClass Itinerary = itin; -} - -class MSA_3R_SPLAT_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - RegisterOperand ROWD, RegisterOperand ROWS = ROWD, - InstrItinClass itin = NoItinerary> { - dag OutOperandList = (outs ROWD:$wd); - dag InOperandList = (ins ROWS:$ws, GPR32Opnd:$rt); - string AsmString = !strconcat(instr_asm, "\t$wd, $ws[$rt]"); - list<dag> Pattern = [(set ROWD:$wd, (OpNode ROWS:$ws, GPR32Opnd:$rt))]; - InstrItinClass Itinerary = itin; -} - -class MSA_3R_VSHF_DESC_BASE<string instr_asm, RegisterOperand ROWD, - RegisterOperand ROWS = ROWD, - RegisterOperand ROWT = ROWD, - InstrItinClass itin = NoItinerary> { - dag OutOperandList = (outs ROWD:$wd); - dag InOperandList = (ins ROWD:$wd_in, ROWS:$ws, ROWT:$wt); - string AsmString = !strconcat(instr_asm, "\t$wd, $ws, $wt"); - list<dag> Pattern = [(set ROWD:$wd, (MipsVSHF ROWD:$wd_in, ROWS:$ws, - ROWT:$wt))]; - string Constraints = "$wd = $wd_in"; - InstrItinClass Itinerary = itin; -} - -class MSA_3R_SLD_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - RegisterOperand ROWD, RegisterOperand ROWS = ROWD, - InstrItinClass itin = NoItinerary> { - dag OutOperandList = (outs ROWD:$wd); - dag InOperandList = (ins ROWD:$wd_in, ROWS:$ws, GPR32Opnd:$rt); - string AsmString = !strconcat(instr_asm, "\t$wd, $ws[$rt]"); - list<dag> Pattern = [(set ROWD:$wd, (OpNode ROWD:$wd_in, ROWS:$ws, - GPR32Opnd:$rt))]; - InstrItinClass Itinerary = itin; - string Constraints = "$wd = $wd_in"; -} - -class MSA_3R_4R_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - RegisterOperand ROWD, RegisterOperand ROWS = ROWD, - RegisterOperand ROWT = ROWD, - InstrItinClass itin = NoItinerary> { - dag OutOperandList = (outs ROWD:$wd); - dag InOperandList = (ins ROWD:$wd_in, ROWS:$ws, ROWT:$wt); - string AsmString = !strconcat(instr_asm, "\t$wd, $ws, $wt"); - list<dag> Pattern = [(set ROWD:$wd, (OpNode ROWD:$wd_in, ROWS:$ws, - ROWT:$wt))]; - InstrItinClass Itinerary = itin; - string Constraints = "$wd = $wd_in"; -} - -class MSA_3RF_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - RegisterOperand ROWD, RegisterOperand ROWS = ROWD, - RegisterOperand ROWT = ROWD, - InstrItinClass itin = NoItinerary> : - MSA_3R_DESC_BASE<instr_asm, OpNode, ROWD, ROWS, ROWT, itin>; - -class MSA_3RF_4RF_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - RegisterOperand ROWD, RegisterOperand ROWS = ROWD, - RegisterOperand ROWT = ROWD, - InstrItinClass itin = NoItinerary> : - MSA_3R_4R_DESC_BASE<instr_asm, OpNode, ROWD, ROWS, ROWT, itin>; - -class MSA_CBRANCH_DESC_BASE<string instr_asm, RegisterOperand ROWD> { - dag OutOperandList = (outs); - dag InOperandList = (ins ROWD:$wt, brtarget:$offset); - string AsmString = !strconcat(instr_asm, "\t$wt, $offset"); - list<dag> Pattern = []; - InstrItinClass Itinerary = NoItinerary; - bit isBranch = 1; - bit isTerminator = 1; - bit hasDelaySlot = 1; - list<Register> Defs = [AT]; -} - -class MSA_INSERT_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - Operand ImmOp, ImmLeaf Imm, RegisterOperand ROWD, - RegisterOperand ROS, - InstrItinClass itin = NoItinerary> { - dag OutOperandList = (outs ROWD:$wd); - dag InOperandList = (ins ROWD:$wd_in, ROS:$rs, ImmOp:$n); - string AsmString = !strconcat(instr_asm, "\t$wd[$n], $rs"); - list<dag> Pattern = [(set ROWD:$wd, (OpNode ROWD:$wd_in, ROS:$rs, Imm:$n))]; - InstrItinClass Itinerary = itin; - string Constraints = "$wd = $wd_in"; -} - -class MSA_INSERT_PSEUDO_BASE<SDPatternOperator OpNode, ValueType Ty, - Operand ImmOp, ImmLeaf Imm, RegisterOperand ROWD, - RegisterOperand ROFS> : - MSAPseudo<(outs ROWD:$wd), (ins ROWD:$wd_in, ImmOp:$n, ROFS:$fs), - [(set ROWD:$wd, (OpNode (Ty ROWD:$wd_in), ROFS:$fs, Imm:$n))]> { - bit usesCustomInserter = 1; - string Constraints = "$wd = $wd_in"; -} - -class MSA_INSERT_VIDX_PSEUDO_BASE<SDPatternOperator OpNode, ValueType Ty, - RegisterOperand ROWD, RegisterOperand ROFS, - RegisterOperand ROIdx> : - MSAPseudo<(outs ROWD:$wd), (ins ROWD:$wd_in, ROIdx:$n, ROFS:$fs), - [(set ROWD:$wd, (OpNode (Ty ROWD:$wd_in), ROFS:$fs, - ROIdx:$n))]> { - bit usesCustomInserter = 1; - bit hasNoSchedulingInfo = 1; - string Constraints = "$wd = $wd_in"; -} - -class MSA_INSVE_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - Operand ImmOp, ImmLeaf Imm, RegisterOperand ROWD, - RegisterOperand ROWS = ROWD, - InstrItinClass itin = NoItinerary> { - dag OutOperandList = (outs ROWD:$wd); - dag InOperandList = (ins ROWD:$wd_in, ImmOp:$n, ROWS:$ws, uimmz:$n2); - string AsmString = !strconcat(instr_asm, "\t$wd[$n], $ws[$n2]"); - list<dag> Pattern = [(set ROWD:$wd, (OpNode ROWD:$wd_in, - Imm:$n, - ROWS:$ws, - immz:$n2))]; - InstrItinClass Itinerary = itin; - string Constraints = "$wd = $wd_in"; -} - -class MSA_VEC_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - RegisterOperand ROWD, RegisterOperand ROWS = ROWD, - RegisterOperand ROWT = ROWD, - InstrItinClass itin = NoItinerary> { - dag OutOperandList = (outs ROWD:$wd); - dag InOperandList = (ins ROWS:$ws, ROWT:$wt); - string AsmString = !strconcat(instr_asm, "\t$wd, $ws, $wt"); - list<dag> Pattern = [(set ROWD:$wd, (OpNode ROWS:$ws, ROWT:$wt))]; - InstrItinClass Itinerary = itin; -} - -class MSA_ELM_SPLAT_DESC_BASE<string instr_asm, SplatComplexPattern SplatImm, - RegisterOperand ROWD, - RegisterOperand ROWS = ROWD, - InstrItinClass itin = NoItinerary> { - dag OutOperandList = (outs ROWD:$wd); - dag InOperandList = (ins ROWS:$ws, SplatImm.OpClass:$n); - string AsmString = !strconcat(instr_asm, "\t$wd, $ws[$n]"); - list<dag> Pattern = [(set ROWD:$wd, (MipsVSHF SplatImm:$n, ROWS:$ws, - ROWS:$ws))]; - InstrItinClass Itinerary = itin; -} - -class MSA_VEC_PSEUDO_BASE<SDPatternOperator OpNode, RegisterOperand ROWD, - RegisterOperand ROWS = ROWD, - RegisterOperand ROWT = ROWD> : - MSAPseudo<(outs ROWD:$wd), (ins ROWS:$ws, ROWT:$wt), - [(set ROWD:$wd, (OpNode ROWS:$ws, ROWT:$wt))]>; - -class ADD_A_B_DESC : MSA_3R_DESC_BASE<"add_a.b", int_mips_add_a_b, MSA128BOpnd>, - IsCommutable; -class ADD_A_H_DESC : MSA_3R_DESC_BASE<"add_a.h", int_mips_add_a_h, MSA128HOpnd>, - IsCommutable; -class ADD_A_W_DESC : MSA_3R_DESC_BASE<"add_a.w", int_mips_add_a_w, MSA128WOpnd>, - IsCommutable; -class ADD_A_D_DESC : MSA_3R_DESC_BASE<"add_a.d", int_mips_add_a_d, MSA128DOpnd>, - IsCommutable; - -class ADDS_A_B_DESC : MSA_3R_DESC_BASE<"adds_a.b", int_mips_adds_a_b, - MSA128BOpnd>, IsCommutable; -class ADDS_A_H_DESC : MSA_3R_DESC_BASE<"adds_a.h", int_mips_adds_a_h, - MSA128HOpnd>, IsCommutable; -class ADDS_A_W_DESC : MSA_3R_DESC_BASE<"adds_a.w", int_mips_adds_a_w, - MSA128WOpnd>, IsCommutable; -class ADDS_A_D_DESC : MSA_3R_DESC_BASE<"adds_a.d", int_mips_adds_a_d, - MSA128DOpnd>, IsCommutable; - -class ADDS_S_B_DESC : MSA_3R_DESC_BASE<"adds_s.b", int_mips_adds_s_b, - MSA128BOpnd>, IsCommutable; -class ADDS_S_H_DESC : MSA_3R_DESC_BASE<"adds_s.h", int_mips_adds_s_h, - MSA128HOpnd>, IsCommutable; -class ADDS_S_W_DESC : MSA_3R_DESC_BASE<"adds_s.w", int_mips_adds_s_w, - MSA128WOpnd>, IsCommutable; -class ADDS_S_D_DESC : MSA_3R_DESC_BASE<"adds_s.d", int_mips_adds_s_d, - MSA128DOpnd>, IsCommutable; - -class ADDS_U_B_DESC : MSA_3R_DESC_BASE<"adds_u.b", int_mips_adds_u_b, - MSA128BOpnd>, IsCommutable; -class ADDS_U_H_DESC : MSA_3R_DESC_BASE<"adds_u.h", int_mips_adds_u_h, - MSA128HOpnd>, IsCommutable; -class ADDS_U_W_DESC : MSA_3R_DESC_BASE<"adds_u.w", int_mips_adds_u_w, - MSA128WOpnd>, IsCommutable; -class ADDS_U_D_DESC : MSA_3R_DESC_BASE<"adds_u.d", int_mips_adds_u_d, - MSA128DOpnd>, IsCommutable; - -class ADDV_B_DESC : MSA_3R_DESC_BASE<"addv.b", add, MSA128BOpnd>, IsCommutable; -class ADDV_H_DESC : MSA_3R_DESC_BASE<"addv.h", add, MSA128HOpnd>, IsCommutable; -class ADDV_W_DESC : MSA_3R_DESC_BASE<"addv.w", add, MSA128WOpnd>, IsCommutable; -class ADDV_D_DESC : MSA_3R_DESC_BASE<"addv.d", add, MSA128DOpnd>, IsCommutable; - -class ADDVI_B_DESC : MSA_I5_DESC_BASE<"addvi.b", add, vsplati8_uimm5, - MSA128BOpnd>; -class ADDVI_H_DESC : MSA_I5_DESC_BASE<"addvi.h", add, vsplati16_uimm5, - MSA128HOpnd>; -class ADDVI_W_DESC : MSA_I5_DESC_BASE<"addvi.w", add, vsplati32_uimm5, - MSA128WOpnd>; -class ADDVI_D_DESC : MSA_I5_DESC_BASE<"addvi.d", add, vsplati64_uimm5, - MSA128DOpnd>; - -class AND_V_DESC : MSA_VEC_DESC_BASE<"and.v", and, MSA128BOpnd>; -class AND_V_H_PSEUDO_DESC : MSA_VEC_PSEUDO_BASE<and, MSA128HOpnd>; -class AND_V_W_PSEUDO_DESC : MSA_VEC_PSEUDO_BASE<and, MSA128WOpnd>; -class AND_V_D_PSEUDO_DESC : MSA_VEC_PSEUDO_BASE<and, MSA128DOpnd>; - -class ANDI_B_DESC : MSA_I8_DESC_BASE<"andi.b", and, vsplati8_uimm8, - MSA128BOpnd>; - -class ASUB_S_B_DESC : MSA_3R_DESC_BASE<"asub_s.b", int_mips_asub_s_b, - MSA128BOpnd>; -class ASUB_S_H_DESC : MSA_3R_DESC_BASE<"asub_s.h", int_mips_asub_s_h, - MSA128HOpnd>; -class ASUB_S_W_DESC : MSA_3R_DESC_BASE<"asub_s.w", int_mips_asub_s_w, - MSA128WOpnd>; -class ASUB_S_D_DESC : MSA_3R_DESC_BASE<"asub_s.d", int_mips_asub_s_d, - MSA128DOpnd>; - -class ASUB_U_B_DESC : MSA_3R_DESC_BASE<"asub_u.b", int_mips_asub_u_b, - MSA128BOpnd>; -class ASUB_U_H_DESC : MSA_3R_DESC_BASE<"asub_u.h", int_mips_asub_u_h, - MSA128HOpnd>; -class ASUB_U_W_DESC : MSA_3R_DESC_BASE<"asub_u.w", int_mips_asub_u_w, - MSA128WOpnd>; -class ASUB_U_D_DESC : MSA_3R_DESC_BASE<"asub_u.d", int_mips_asub_u_d, - MSA128DOpnd>; - -class AVE_S_B_DESC : MSA_3R_DESC_BASE<"ave_s.b", int_mips_ave_s_b, MSA128BOpnd>, - IsCommutable; -class AVE_S_H_DESC : MSA_3R_DESC_BASE<"ave_s.h", int_mips_ave_s_h, MSA128HOpnd>, - IsCommutable; -class AVE_S_W_DESC : MSA_3R_DESC_BASE<"ave_s.w", int_mips_ave_s_w, MSA128WOpnd>, - IsCommutable; -class AVE_S_D_DESC : MSA_3R_DESC_BASE<"ave_s.d", int_mips_ave_s_d, MSA128DOpnd>, - IsCommutable; - -class AVE_U_B_DESC : MSA_3R_DESC_BASE<"ave_u.b", int_mips_ave_u_b, MSA128BOpnd>, - IsCommutable; -class AVE_U_H_DESC : MSA_3R_DESC_BASE<"ave_u.h", int_mips_ave_u_h, MSA128HOpnd>, - IsCommutable; -class AVE_U_W_DESC : MSA_3R_DESC_BASE<"ave_u.w", int_mips_ave_u_w, MSA128WOpnd>, - IsCommutable; -class AVE_U_D_DESC : MSA_3R_DESC_BASE<"ave_u.d", int_mips_ave_u_d, MSA128DOpnd>, - IsCommutable; - -class AVER_S_B_DESC : MSA_3R_DESC_BASE<"aver_s.b", int_mips_aver_s_b, - MSA128BOpnd>, IsCommutable; -class AVER_S_H_DESC : MSA_3R_DESC_BASE<"aver_s.h", int_mips_aver_s_h, - MSA128HOpnd>, IsCommutable; -class AVER_S_W_DESC : MSA_3R_DESC_BASE<"aver_s.w", int_mips_aver_s_w, - MSA128WOpnd>, IsCommutable; -class AVER_S_D_DESC : MSA_3R_DESC_BASE<"aver_s.d", int_mips_aver_s_d, - MSA128DOpnd>, IsCommutable; - -class AVER_U_B_DESC : MSA_3R_DESC_BASE<"aver_u.b", int_mips_aver_u_b, - MSA128BOpnd>, IsCommutable; -class AVER_U_H_DESC : MSA_3R_DESC_BASE<"aver_u.h", int_mips_aver_u_h, - MSA128HOpnd>, IsCommutable; -class AVER_U_W_DESC : MSA_3R_DESC_BASE<"aver_u.w", int_mips_aver_u_w, - MSA128WOpnd>, IsCommutable; -class AVER_U_D_DESC : MSA_3R_DESC_BASE<"aver_u.d", int_mips_aver_u_d, - MSA128DOpnd>, IsCommutable; - -class BCLR_B_DESC : MSA_3R_DESC_BASE<"bclr.b", vbclr_b, MSA128BOpnd>; -class BCLR_H_DESC : MSA_3R_DESC_BASE<"bclr.h", vbclr_h, MSA128HOpnd>; -class BCLR_W_DESC : MSA_3R_DESC_BASE<"bclr.w", vbclr_w, MSA128WOpnd>; -class BCLR_D_DESC : MSA_3R_DESC_BASE<"bclr.d", vbclr_d, MSA128DOpnd>; - -class BCLRI_B_DESC : MSA_BIT_B_DESC_BASE<"bclri.b", and, vsplat_uimm_inv_pow2, - MSA128BOpnd>; -class BCLRI_H_DESC : MSA_BIT_H_DESC_BASE<"bclri.h", and, vsplat_uimm_inv_pow2, - MSA128HOpnd>; -class BCLRI_W_DESC : MSA_BIT_W_DESC_BASE<"bclri.w", and, vsplat_uimm_inv_pow2, - MSA128WOpnd>; -class BCLRI_D_DESC : MSA_BIT_D_DESC_BASE<"bclri.d", and, vsplat_uimm_inv_pow2, - MSA128DOpnd>; - -class BINSL_B_DESC : MSA_3R_BINSX_DESC_BASE<"binsl.b", int_mips_binsl_b, - MSA128BOpnd>; -class BINSL_H_DESC : MSA_3R_BINSX_DESC_BASE<"binsl.h", int_mips_binsl_h, - MSA128HOpnd>; -class BINSL_W_DESC : MSA_3R_BINSX_DESC_BASE<"binsl.w", int_mips_binsl_w, - MSA128WOpnd>; -class BINSL_D_DESC : MSA_3R_BINSX_DESC_BASE<"binsl.d", int_mips_binsl_d, - MSA128DOpnd>; - -class BINSLI_B_DESC : MSA_BIT_BINSLI_DESC_BASE<"binsli.b", v16i8, vsplat_maskl_bits_uimm3, MSA128BOpnd>; -class BINSLI_H_DESC : MSA_BIT_BINSLI_DESC_BASE<"binsli.h", v8i16, vsplat_maskl_bits_uimm4, MSA128HOpnd>; -class BINSLI_W_DESC : MSA_BIT_BINSLI_DESC_BASE<"binsli.w", v4i32, vsplat_maskl_bits_uimm5, MSA128WOpnd>; -class BINSLI_D_DESC : MSA_BIT_BINSLI_DESC_BASE<"binsli.d", v2i64, vsplat_maskl_bits_uimm6, MSA128DOpnd>; - -class BINSR_B_DESC : MSA_3R_BINSX_DESC_BASE<"binsr.b", int_mips_binsr_b, - MSA128BOpnd>; -class BINSR_H_DESC : MSA_3R_BINSX_DESC_BASE<"binsr.h", int_mips_binsr_h, - MSA128HOpnd>; -class BINSR_W_DESC : MSA_3R_BINSX_DESC_BASE<"binsr.w", int_mips_binsr_w, - MSA128WOpnd>; -class BINSR_D_DESC : MSA_3R_BINSX_DESC_BASE<"binsr.d", int_mips_binsr_d, - MSA128DOpnd>; - -class BINSRI_B_DESC - : MSA_BIT_BINSRI_DESC_BASE<"binsri.b", v16i8, vsplat_maskr_bits_uimm3, - MSA128BOpnd>; -class BINSRI_H_DESC - : MSA_BIT_BINSRI_DESC_BASE<"binsri.h", v8i16, vsplat_maskr_bits_uimm4, - MSA128HOpnd>; -class BINSRI_W_DESC - : MSA_BIT_BINSRI_DESC_BASE<"binsri.w", v4i32, vsplat_maskr_bits_uimm5, - MSA128WOpnd>; -class BINSRI_D_DESC - : MSA_BIT_BINSRI_DESC_BASE<"binsri.d", v2i64, vsplat_maskr_bits_uimm6, - MSA128DOpnd>; - -class BMNZ_V_DESC { - dag OutOperandList = (outs MSA128BOpnd:$wd); - dag InOperandList = (ins MSA128BOpnd:$wd_in, MSA128BOpnd:$ws, - MSA128BOpnd:$wt); - string AsmString = "bmnz.v\t$wd, $ws, $wt"; - list<dag> Pattern = [(set MSA128BOpnd:$wd, (vselect MSA128BOpnd:$wt, - MSA128BOpnd:$ws, - MSA128BOpnd:$wd_in))]; - InstrItinClass Itinerary = NoItinerary; - string Constraints = "$wd = $wd_in"; -} - -class BMNZI_B_DESC { - dag OutOperandList = (outs MSA128BOpnd:$wd); - dag InOperandList = (ins MSA128BOpnd:$wd_in, MSA128BOpnd:$ws, - vsplat_uimm8:$u8); - string AsmString = "bmnzi.b\t$wd, $ws, $u8"; - list<dag> Pattern = [(set MSA128BOpnd:$wd, (vselect vsplati8_uimm8:$u8, - MSA128BOpnd:$ws, - MSA128BOpnd:$wd_in))]; - InstrItinClass Itinerary = NoItinerary; - string Constraints = "$wd = $wd_in"; -} - -class BMZ_V_DESC { - dag OutOperandList = (outs MSA128BOpnd:$wd); - dag InOperandList = (ins MSA128BOpnd:$wd_in, MSA128BOpnd:$ws, - MSA128BOpnd:$wt); - string AsmString = "bmz.v\t$wd, $ws, $wt"; - list<dag> Pattern = [(set MSA128BOpnd:$wd, (vselect MSA128BOpnd:$wt, - MSA128BOpnd:$wd_in, - MSA128BOpnd:$ws))]; - InstrItinClass Itinerary = NoItinerary; - string Constraints = "$wd = $wd_in"; -} - -class BMZI_B_DESC { - dag OutOperandList = (outs MSA128BOpnd:$wd); - dag InOperandList = (ins MSA128BOpnd:$wd_in, MSA128BOpnd:$ws, - vsplat_uimm8:$u8); - string AsmString = "bmzi.b\t$wd, $ws, $u8"; - list<dag> Pattern = [(set MSA128BOpnd:$wd, (vselect vsplati8_uimm8:$u8, - MSA128BOpnd:$wd_in, - MSA128BOpnd:$ws))]; - InstrItinClass Itinerary = NoItinerary; - string Constraints = "$wd = $wd_in"; -} - -class BNEG_B_DESC : MSA_3R_DESC_BASE<"bneg.b", vbneg_b, MSA128BOpnd>; -class BNEG_H_DESC : MSA_3R_DESC_BASE<"bneg.h", vbneg_h, MSA128HOpnd>; -class BNEG_W_DESC : MSA_3R_DESC_BASE<"bneg.w", vbneg_w, MSA128WOpnd>; -class BNEG_D_DESC : MSA_3R_DESC_BASE<"bneg.d", vbneg_d, MSA128DOpnd>; - -class BNEGI_B_DESC : MSA_BIT_B_DESC_BASE<"bnegi.b", xor, vsplat_uimm_pow2, - MSA128BOpnd>; -class BNEGI_H_DESC : MSA_BIT_H_DESC_BASE<"bnegi.h", xor, vsplat_uimm_pow2, - MSA128HOpnd>; -class BNEGI_W_DESC : MSA_BIT_W_DESC_BASE<"bnegi.w", xor, vsplat_uimm_pow2, - MSA128WOpnd>; -class BNEGI_D_DESC : MSA_BIT_D_DESC_BASE<"bnegi.d", xor, vsplat_uimm_pow2, - MSA128DOpnd>; - -class BNZ_B_DESC : MSA_CBRANCH_DESC_BASE<"bnz.b", MSA128BOpnd>; -class BNZ_H_DESC : MSA_CBRANCH_DESC_BASE<"bnz.h", MSA128HOpnd>; -class BNZ_W_DESC : MSA_CBRANCH_DESC_BASE<"bnz.w", MSA128WOpnd>; -class BNZ_D_DESC : MSA_CBRANCH_DESC_BASE<"bnz.d", MSA128DOpnd>; - -class BNZ_V_DESC : MSA_CBRANCH_DESC_BASE<"bnz.v", MSA128BOpnd>; - -class BSEL_V_DESC { - dag OutOperandList = (outs MSA128BOpnd:$wd); - dag InOperandList = (ins MSA128BOpnd:$wd_in, MSA128BOpnd:$ws, - MSA128BOpnd:$wt); - string AsmString = "bsel.v\t$wd, $ws, $wt"; - // Note that vselect and BSEL_V treat the condition operand the opposite way - // from each other. - // (vselect cond, if_set, if_clear) - // (BSEL_V cond, if_clear, if_set) - list<dag> Pattern = [(set MSA128BOpnd:$wd, - (vselect MSA128BOpnd:$wd_in, MSA128BOpnd:$wt, - MSA128BOpnd:$ws))]; - InstrItinClass Itinerary = NoItinerary; - string Constraints = "$wd = $wd_in"; -} - -class BSELI_B_DESC { - dag OutOperandList = (outs MSA128BOpnd:$wd); - dag InOperandList = (ins MSA128BOpnd:$wd_in, MSA128BOpnd:$ws, - vsplat_uimm8:$u8); - string AsmString = "bseli.b\t$wd, $ws, $u8"; - // Note that vselect and BSEL_V treat the condition operand the opposite way - // from each other. - // (vselect cond, if_set, if_clear) - // (BSEL_V cond, if_clear, if_set) - list<dag> Pattern = [(set MSA128BOpnd:$wd, (vselect MSA128BOpnd:$wd_in, - vsplati8_uimm8:$u8, - MSA128BOpnd:$ws))]; - InstrItinClass Itinerary = NoItinerary; - string Constraints = "$wd = $wd_in"; -} - -class BSET_B_DESC : MSA_3R_DESC_BASE<"bset.b", vbset_b, MSA128BOpnd>; -class BSET_H_DESC : MSA_3R_DESC_BASE<"bset.h", vbset_h, MSA128HOpnd>; -class BSET_W_DESC : MSA_3R_DESC_BASE<"bset.w", vbset_w, MSA128WOpnd>; -class BSET_D_DESC : MSA_3R_DESC_BASE<"bset.d", vbset_d, MSA128DOpnd>; - -class BSETI_B_DESC : MSA_BIT_B_DESC_BASE<"bseti.b", or, vsplat_uimm_pow2, - MSA128BOpnd>; -class BSETI_H_DESC : MSA_BIT_H_DESC_BASE<"bseti.h", or, vsplat_uimm_pow2, - MSA128HOpnd>; -class BSETI_W_DESC : MSA_BIT_W_DESC_BASE<"bseti.w", or, vsplat_uimm_pow2, - MSA128WOpnd>; -class BSETI_D_DESC : MSA_BIT_D_DESC_BASE<"bseti.d", or, vsplat_uimm_pow2, - MSA128DOpnd>; - -class BZ_B_DESC : MSA_CBRANCH_DESC_BASE<"bz.b", MSA128BOpnd>; -class BZ_H_DESC : MSA_CBRANCH_DESC_BASE<"bz.h", MSA128HOpnd>; -class BZ_W_DESC : MSA_CBRANCH_DESC_BASE<"bz.w", MSA128WOpnd>; -class BZ_D_DESC : MSA_CBRANCH_DESC_BASE<"bz.d", MSA128DOpnd>; - -class BZ_V_DESC : MSA_CBRANCH_DESC_BASE<"bz.v", MSA128BOpnd>; - -class CEQ_B_DESC : MSA_3R_DESC_BASE<"ceq.b", vseteq_v16i8, MSA128BOpnd>, - IsCommutable; -class CEQ_H_DESC : MSA_3R_DESC_BASE<"ceq.h", vseteq_v8i16, MSA128HOpnd>, - IsCommutable; -class CEQ_W_DESC : MSA_3R_DESC_BASE<"ceq.w", vseteq_v4i32, MSA128WOpnd>, - IsCommutable; -class CEQ_D_DESC : MSA_3R_DESC_BASE<"ceq.d", vseteq_v2i64, MSA128DOpnd>, - IsCommutable; - -class CEQI_B_DESC : MSA_I5_DESC_BASE<"ceqi.b", vseteq_v16i8, vsplati8_simm5, - MSA128BOpnd>; -class CEQI_H_DESC : MSA_I5_DESC_BASE<"ceqi.h", vseteq_v8i16, vsplati16_simm5, - MSA128HOpnd>; -class CEQI_W_DESC : MSA_I5_DESC_BASE<"ceqi.w", vseteq_v4i32, vsplati32_simm5, - MSA128WOpnd>; -class CEQI_D_DESC : MSA_I5_DESC_BASE<"ceqi.d", vseteq_v2i64, vsplati64_simm5, - MSA128DOpnd>; - -class CFCMSA_DESC { - dag OutOperandList = (outs GPR32Opnd:$rd); - dag InOperandList = (ins MSA128CROpnd:$cs); - string AsmString = "cfcmsa\t$rd, $cs"; - InstrItinClass Itinerary = NoItinerary; - bit hasSideEffects = 1; - bit isMoveReg = 1; -} - -class CLE_S_B_DESC : MSA_3R_DESC_BASE<"cle_s.b", vsetle_v16i8, MSA128BOpnd>; -class CLE_S_H_DESC : MSA_3R_DESC_BASE<"cle_s.h", vsetle_v8i16, MSA128HOpnd>; -class CLE_S_W_DESC : MSA_3R_DESC_BASE<"cle_s.w", vsetle_v4i32, MSA128WOpnd>; -class CLE_S_D_DESC : MSA_3R_DESC_BASE<"cle_s.d", vsetle_v2i64, MSA128DOpnd>; - -class CLE_U_B_DESC : MSA_3R_DESC_BASE<"cle_u.b", vsetule_v16i8, MSA128BOpnd>; -class CLE_U_H_DESC : MSA_3R_DESC_BASE<"cle_u.h", vsetule_v8i16, MSA128HOpnd>; -class CLE_U_W_DESC : MSA_3R_DESC_BASE<"cle_u.w", vsetule_v4i32, MSA128WOpnd>; -class CLE_U_D_DESC : MSA_3R_DESC_BASE<"cle_u.d", vsetule_v2i64, MSA128DOpnd>; - -class CLEI_S_B_DESC : MSA_I5_DESC_BASE<"clei_s.b", vsetle_v16i8, - vsplati8_simm5, MSA128BOpnd>; -class CLEI_S_H_DESC : MSA_I5_DESC_BASE<"clei_s.h", vsetle_v8i16, - vsplati16_simm5, MSA128HOpnd>; -class CLEI_S_W_DESC : MSA_I5_DESC_BASE<"clei_s.w", vsetle_v4i32, - vsplati32_simm5, MSA128WOpnd>; -class CLEI_S_D_DESC : MSA_I5_DESC_BASE<"clei_s.d", vsetle_v2i64, - vsplati64_simm5, MSA128DOpnd>; - -class CLEI_U_B_DESC : MSA_I5_DESC_BASE<"clei_u.b", vsetule_v16i8, - vsplati8_uimm5, MSA128BOpnd>; -class CLEI_U_H_DESC : MSA_I5_DESC_BASE<"clei_u.h", vsetule_v8i16, - vsplati16_uimm5, MSA128HOpnd>; -class CLEI_U_W_DESC : MSA_I5_DESC_BASE<"clei_u.w", vsetule_v4i32, - vsplati32_uimm5, MSA128WOpnd>; -class CLEI_U_D_DESC : MSA_I5_DESC_BASE<"clei_u.d", vsetule_v2i64, - vsplati64_uimm5, MSA128DOpnd>; - -class CLT_S_B_DESC : MSA_3R_DESC_BASE<"clt_s.b", vsetlt_v16i8, MSA128BOpnd>; -class CLT_S_H_DESC : MSA_3R_DESC_BASE<"clt_s.h", vsetlt_v8i16, MSA128HOpnd>; -class CLT_S_W_DESC : MSA_3R_DESC_BASE<"clt_s.w", vsetlt_v4i32, MSA128WOpnd>; -class CLT_S_D_DESC : MSA_3R_DESC_BASE<"clt_s.d", vsetlt_v2i64, MSA128DOpnd>; - -class CLT_U_B_DESC : MSA_3R_DESC_BASE<"clt_u.b", vsetult_v16i8, MSA128BOpnd>; -class CLT_U_H_DESC : MSA_3R_DESC_BASE<"clt_u.h", vsetult_v8i16, MSA128HOpnd>; -class CLT_U_W_DESC : MSA_3R_DESC_BASE<"clt_u.w", vsetult_v4i32, MSA128WOpnd>; -class CLT_U_D_DESC : MSA_3R_DESC_BASE<"clt_u.d", vsetult_v2i64, MSA128DOpnd>; - -class CLTI_S_B_DESC : MSA_I5_DESC_BASE<"clti_s.b", vsetlt_v16i8, - vsplati8_simm5, MSA128BOpnd>; -class CLTI_S_H_DESC : MSA_I5_DESC_BASE<"clti_s.h", vsetlt_v8i16, - vsplati16_simm5, MSA128HOpnd>; -class CLTI_S_W_DESC : MSA_I5_DESC_BASE<"clti_s.w", vsetlt_v4i32, - vsplati32_simm5, MSA128WOpnd>; -class CLTI_S_D_DESC : MSA_I5_DESC_BASE<"clti_s.d", vsetlt_v2i64, - vsplati64_simm5, MSA128DOpnd>; - -class CLTI_U_B_DESC : MSA_I5_DESC_BASE<"clti_u.b", vsetult_v16i8, - vsplati8_uimm5, MSA128BOpnd>; -class CLTI_U_H_DESC : MSA_I5_DESC_BASE<"clti_u.h", vsetult_v8i16, - vsplati16_uimm5, MSA128HOpnd>; -class CLTI_U_W_DESC : MSA_I5_DESC_BASE<"clti_u.w", vsetult_v4i32, - vsplati32_uimm5, MSA128WOpnd>; -class CLTI_U_D_DESC : MSA_I5_DESC_BASE<"clti_u.d", vsetult_v2i64, - vsplati64_uimm5, MSA128DOpnd>; - -class COPY_S_B_DESC : MSA_COPY_DESC_BASE<"copy_s.b", vextract_sext_i8, v16i8, - uimm4_ptr, immZExt4Ptr, GPR32Opnd, - MSA128BOpnd>; -class COPY_S_H_DESC : MSA_COPY_DESC_BASE<"copy_s.h", vextract_sext_i16, v8i16, - uimm3_ptr, immZExt3Ptr, GPR32Opnd, - MSA128HOpnd>; -class COPY_S_W_DESC : MSA_COPY_DESC_BASE<"copy_s.w", vextract_sext_i32, v4i32, - uimm2_ptr, immZExt2Ptr, GPR32Opnd, - MSA128WOpnd>; -class COPY_S_D_DESC : MSA_COPY_DESC_BASE<"copy_s.d", vextract_sext_i64, v2i64, - uimm1_ptr, immZExt1Ptr, GPR64Opnd, - MSA128DOpnd>; - -class COPY_U_B_DESC : MSA_COPY_DESC_BASE<"copy_u.b", vextract_zext_i8, v16i8, - uimm4_ptr, immZExt4Ptr, GPR32Opnd, - MSA128BOpnd>; -class COPY_U_H_DESC : MSA_COPY_DESC_BASE<"copy_u.h", vextract_zext_i16, v8i16, - uimm3_ptr, immZExt3Ptr, GPR32Opnd, - MSA128HOpnd>; -class COPY_U_W_DESC : MSA_COPY_DESC_BASE<"copy_u.w", vextract_zext_i32, v4i32, - uimm2_ptr, immZExt2Ptr, GPR32Opnd, - MSA128WOpnd>; - -class COPY_FW_PSEUDO_DESC : MSA_COPY_PSEUDO_BASE<vector_extract, v4f32, - uimm2_ptr, immZExt2Ptr, FGR32, - MSA128W>; -class COPY_FD_PSEUDO_DESC : MSA_COPY_PSEUDO_BASE<vector_extract, v2f64, - uimm1_ptr, immZExt1Ptr, FGR64, - MSA128D>; - -class CTCMSA_DESC { - dag OutOperandList = (outs); - dag InOperandList = (ins MSA128CROpnd:$cd, GPR32Opnd:$rs); - string AsmString = "ctcmsa\t$cd, $rs"; - InstrItinClass Itinerary = NoItinerary; - bit hasSideEffects = 1; - bit isMoveReg = 1; -} - -class DIV_S_B_DESC : MSA_3R_DESC_BASE<"div_s.b", sdiv, MSA128BOpnd>; -class DIV_S_H_DESC : MSA_3R_DESC_BASE<"div_s.h", sdiv, MSA128HOpnd>; -class DIV_S_W_DESC : MSA_3R_DESC_BASE<"div_s.w", sdiv, MSA128WOpnd>; -class DIV_S_D_DESC : MSA_3R_DESC_BASE<"div_s.d", sdiv, MSA128DOpnd>; - -class DIV_U_B_DESC : MSA_3R_DESC_BASE<"div_u.b", udiv, MSA128BOpnd>; -class DIV_U_H_DESC : MSA_3R_DESC_BASE<"div_u.h", udiv, MSA128HOpnd>; -class DIV_U_W_DESC : MSA_3R_DESC_BASE<"div_u.w", udiv, MSA128WOpnd>; -class DIV_U_D_DESC : MSA_3R_DESC_BASE<"div_u.d", udiv, MSA128DOpnd>; - -class DOTP_S_H_DESC : MSA_3R_DESC_BASE<"dotp_s.h", int_mips_dotp_s_h, - MSA128HOpnd, MSA128BOpnd, MSA128BOpnd>, - IsCommutable; -class DOTP_S_W_DESC : MSA_3R_DESC_BASE<"dotp_s.w", int_mips_dotp_s_w, - MSA128WOpnd, MSA128HOpnd, MSA128HOpnd>, - IsCommutable; -class DOTP_S_D_DESC : MSA_3R_DESC_BASE<"dotp_s.d", int_mips_dotp_s_d, - MSA128DOpnd, MSA128WOpnd, MSA128WOpnd>, - IsCommutable; - -class DOTP_U_H_DESC : MSA_3R_DESC_BASE<"dotp_u.h", int_mips_dotp_u_h, - MSA128HOpnd, MSA128BOpnd, MSA128BOpnd>, - IsCommutable; -class DOTP_U_W_DESC : MSA_3R_DESC_BASE<"dotp_u.w", int_mips_dotp_u_w, - MSA128WOpnd, MSA128HOpnd, MSA128HOpnd>, - IsCommutable; -class DOTP_U_D_DESC : MSA_3R_DESC_BASE<"dotp_u.d", int_mips_dotp_u_d, - MSA128DOpnd, MSA128WOpnd, MSA128WOpnd>, - IsCommutable; - -class DPADD_S_H_DESC : MSA_3R_4R_DESC_BASE<"dpadd_s.h", int_mips_dpadd_s_h, - MSA128HOpnd, MSA128BOpnd, - MSA128BOpnd>, IsCommutable; -class DPADD_S_W_DESC : MSA_3R_4R_DESC_BASE<"dpadd_s.w", int_mips_dpadd_s_w, - MSA128WOpnd, MSA128HOpnd, - MSA128HOpnd>, IsCommutable; -class DPADD_S_D_DESC : MSA_3R_4R_DESC_BASE<"dpadd_s.d", int_mips_dpadd_s_d, - MSA128DOpnd, MSA128WOpnd, - MSA128WOpnd>, IsCommutable; - -class DPADD_U_H_DESC : MSA_3R_4R_DESC_BASE<"dpadd_u.h", int_mips_dpadd_u_h, - MSA128HOpnd, MSA128BOpnd, - MSA128BOpnd>, IsCommutable; -class DPADD_U_W_DESC : MSA_3R_4R_DESC_BASE<"dpadd_u.w", int_mips_dpadd_u_w, - MSA128WOpnd, MSA128HOpnd, - MSA128HOpnd>, IsCommutable; -class DPADD_U_D_DESC : MSA_3R_4R_DESC_BASE<"dpadd_u.d", int_mips_dpadd_u_d, - MSA128DOpnd, MSA128WOpnd, - MSA128WOpnd>, IsCommutable; - -class DPSUB_S_H_DESC : MSA_3R_4R_DESC_BASE<"dpsub_s.h", int_mips_dpsub_s_h, - MSA128HOpnd, MSA128BOpnd, - MSA128BOpnd>; -class DPSUB_S_W_DESC : MSA_3R_4R_DESC_BASE<"dpsub_s.w", int_mips_dpsub_s_w, - MSA128WOpnd, MSA128HOpnd, - MSA128HOpnd>; -class DPSUB_S_D_DESC : MSA_3R_4R_DESC_BASE<"dpsub_s.d", int_mips_dpsub_s_d, - MSA128DOpnd, MSA128WOpnd, - MSA128WOpnd>; - -class DPSUB_U_H_DESC : MSA_3R_4R_DESC_BASE<"dpsub_u.h", int_mips_dpsub_u_h, - MSA128HOpnd, MSA128BOpnd, - MSA128BOpnd>; -class DPSUB_U_W_DESC : MSA_3R_4R_DESC_BASE<"dpsub_u.w", int_mips_dpsub_u_w, - MSA128WOpnd, MSA128HOpnd, - MSA128HOpnd>; -class DPSUB_U_D_DESC : MSA_3R_4R_DESC_BASE<"dpsub_u.d", int_mips_dpsub_u_d, - MSA128DOpnd, MSA128WOpnd, - MSA128WOpnd>; - -class FADD_W_DESC : MSA_3RF_DESC_BASE<"fadd.w", fadd, MSA128WOpnd>, - IsCommutable; -class FADD_D_DESC : MSA_3RF_DESC_BASE<"fadd.d", fadd, MSA128DOpnd>, - IsCommutable; - -class FCAF_W_DESC : MSA_3RF_DESC_BASE<"fcaf.w", int_mips_fcaf_w, MSA128WOpnd>, - IsCommutable; -class FCAF_D_DESC : MSA_3RF_DESC_BASE<"fcaf.d", int_mips_fcaf_d, MSA128DOpnd>, - IsCommutable; - -class FCEQ_W_DESC : MSA_3RF_DESC_BASE<"fceq.w", vfsetoeq_v4f32, MSA128WOpnd>, - IsCommutable; -class FCEQ_D_DESC : MSA_3RF_DESC_BASE<"fceq.d", vfsetoeq_v2f64, MSA128DOpnd>, - IsCommutable; - -class FCLASS_W_DESC : MSA_2RF_DESC_BASE<"fclass.w", int_mips_fclass_w, - MSA128WOpnd>; -class FCLASS_D_DESC : MSA_2RF_DESC_BASE<"fclass.d", int_mips_fclass_d, - MSA128DOpnd>; - -class FCLE_W_DESC : MSA_3RF_DESC_BASE<"fcle.w", vfsetole_v4f32, MSA128WOpnd>; -class FCLE_D_DESC : MSA_3RF_DESC_BASE<"fcle.d", vfsetole_v2f64, MSA128DOpnd>; - -class FCLT_W_DESC : MSA_3RF_DESC_BASE<"fclt.w", vfsetolt_v4f32, MSA128WOpnd>; -class FCLT_D_DESC : MSA_3RF_DESC_BASE<"fclt.d", vfsetolt_v2f64, MSA128DOpnd>; - -class FCNE_W_DESC : MSA_3RF_DESC_BASE<"fcne.w", vfsetone_v4f32, MSA128WOpnd>, - IsCommutable; -class FCNE_D_DESC : MSA_3RF_DESC_BASE<"fcne.d", vfsetone_v2f64, MSA128DOpnd>, - IsCommutable; - -class FCOR_W_DESC : MSA_3RF_DESC_BASE<"fcor.w", vfsetord_v4f32, MSA128WOpnd>, - IsCommutable; -class FCOR_D_DESC : MSA_3RF_DESC_BASE<"fcor.d", vfsetord_v2f64, MSA128DOpnd>, - IsCommutable; - -class FCUEQ_W_DESC : MSA_3RF_DESC_BASE<"fcueq.w", vfsetueq_v4f32, MSA128WOpnd>, - IsCommutable; -class FCUEQ_D_DESC : MSA_3RF_DESC_BASE<"fcueq.d", vfsetueq_v2f64, MSA128DOpnd>, - IsCommutable; - -class FCULE_W_DESC : MSA_3RF_DESC_BASE<"fcule.w", vfsetule_v4f32, MSA128WOpnd>, - IsCommutable; -class FCULE_D_DESC : MSA_3RF_DESC_BASE<"fcule.d", vfsetule_v2f64, MSA128DOpnd>, - IsCommutable; - -class FCULT_W_DESC : MSA_3RF_DESC_BASE<"fcult.w", vfsetult_v4f32, MSA128WOpnd>, - IsCommutable; -class FCULT_D_DESC : MSA_3RF_DESC_BASE<"fcult.d", vfsetult_v2f64, MSA128DOpnd>, - IsCommutable; - -class FCUN_W_DESC : MSA_3RF_DESC_BASE<"fcun.w", vfsetun_v4f32, MSA128WOpnd>, - IsCommutable; -class FCUN_D_DESC : MSA_3RF_DESC_BASE<"fcun.d", vfsetun_v2f64, MSA128DOpnd>, - IsCommutable; - -class FCUNE_W_DESC : MSA_3RF_DESC_BASE<"fcune.w", vfsetune_v4f32, MSA128WOpnd>, - IsCommutable; -class FCUNE_D_DESC : MSA_3RF_DESC_BASE<"fcune.d", vfsetune_v2f64, MSA128DOpnd>, - IsCommutable; - -class FDIV_W_DESC : MSA_3RF_DESC_BASE<"fdiv.w", fdiv, MSA128WOpnd>; -class FDIV_D_DESC : MSA_3RF_DESC_BASE<"fdiv.d", fdiv, MSA128DOpnd>; - -class FEXDO_H_DESC : MSA_3RF_DESC_BASE<"fexdo.h", int_mips_fexdo_h, - MSA128HOpnd, MSA128WOpnd, MSA128WOpnd>; -class FEXDO_W_DESC : MSA_3RF_DESC_BASE<"fexdo.w", int_mips_fexdo_w, - MSA128WOpnd, MSA128DOpnd, MSA128DOpnd>; - -// The fexp2.df instruction multiplies the first operand by 2 to the power of -// the second operand. We therefore need a pseudo-insn in order to invent the -// 1.0 when we only need to match ISD::FEXP2. -class FEXP2_W_DESC : MSA_3RF_DESC_BASE<"fexp2.w", mul_fexp2, MSA128WOpnd>; -class FEXP2_D_DESC : MSA_3RF_DESC_BASE<"fexp2.d", mul_fexp2, MSA128DOpnd>; -let usesCustomInserter = 1, hasNoSchedulingInfo = 1 in { - class FEXP2_W_1_PSEUDO_DESC : - MSAPseudo<(outs MSA128W:$wd), (ins MSA128W:$ws), - [(set MSA128W:$wd, (fexp2 MSA128W:$ws))]>; - class FEXP2_D_1_PSEUDO_DESC : - MSAPseudo<(outs MSA128D:$wd), (ins MSA128D:$ws), - [(set MSA128D:$wd, (fexp2 MSA128D:$ws))]>; -} - -class FEXUPL_W_DESC : MSA_2RF_DESC_BASE<"fexupl.w", int_mips_fexupl_w, - MSA128WOpnd, MSA128HOpnd>; -class FEXUPL_D_DESC : MSA_2RF_DESC_BASE<"fexupl.d", int_mips_fexupl_d, - MSA128DOpnd, MSA128WOpnd>; - -class FEXUPR_W_DESC : MSA_2RF_DESC_BASE<"fexupr.w", int_mips_fexupr_w, - MSA128WOpnd, MSA128HOpnd>; -class FEXUPR_D_DESC : MSA_2RF_DESC_BASE<"fexupr.d", int_mips_fexupr_d, - MSA128DOpnd, MSA128WOpnd>; - -class FFINT_S_W_DESC : MSA_2RF_DESC_BASE<"ffint_s.w", sint_to_fp, MSA128WOpnd>; -class FFINT_S_D_DESC : MSA_2RF_DESC_BASE<"ffint_s.d", sint_to_fp, MSA128DOpnd>; - -class FFINT_U_W_DESC : MSA_2RF_DESC_BASE<"ffint_u.w", uint_to_fp, MSA128WOpnd>; -class FFINT_U_D_DESC : MSA_2RF_DESC_BASE<"ffint_u.d", uint_to_fp, MSA128DOpnd>; - -class FFQL_W_DESC : MSA_2RF_DESC_BASE<"ffql.w", int_mips_ffql_w, - MSA128WOpnd, MSA128HOpnd>; -class FFQL_D_DESC : MSA_2RF_DESC_BASE<"ffql.d", int_mips_ffql_d, - MSA128DOpnd, MSA128WOpnd>; - -class FFQR_W_DESC : MSA_2RF_DESC_BASE<"ffqr.w", int_mips_ffqr_w, - MSA128WOpnd, MSA128HOpnd>; -class FFQR_D_DESC : MSA_2RF_DESC_BASE<"ffqr.d", int_mips_ffqr_d, - MSA128DOpnd, MSA128WOpnd>; - -class FILL_B_DESC : MSA_2R_FILL_DESC_BASE<"fill.b", v16i8, vsplati8, - MSA128BOpnd, GPR32Opnd>; -class FILL_H_DESC : MSA_2R_FILL_DESC_BASE<"fill.h", v8i16, vsplati16, - MSA128HOpnd, GPR32Opnd>; -class FILL_W_DESC : MSA_2R_FILL_DESC_BASE<"fill.w", v4i32, vsplati32, - MSA128WOpnd, GPR32Opnd>; -class FILL_D_DESC : MSA_2R_FILL_DESC_BASE<"fill.d", v2i64, vsplati64, - MSA128DOpnd, GPR64Opnd>; - -class FILL_FW_PSEUDO_DESC : MSA_2R_FILL_PSEUDO_BASE<v4f32, vsplatf32, MSA128W, - FGR32>; -class FILL_FD_PSEUDO_DESC : MSA_2R_FILL_PSEUDO_BASE<v2f64, vsplatf64, MSA128D, - FGR64>; - -class FLOG2_W_DESC : MSA_2RF_DESC_BASE<"flog2.w", flog2, MSA128WOpnd>; -class FLOG2_D_DESC : MSA_2RF_DESC_BASE<"flog2.d", flog2, MSA128DOpnd>; - -class FMADD_W_DESC : MSA_3RF_4RF_DESC_BASE<"fmadd.w", fma, MSA128WOpnd>; -class FMADD_D_DESC : MSA_3RF_4RF_DESC_BASE<"fmadd.d", fma, MSA128DOpnd>; - -class FMAX_W_DESC : MSA_3RF_DESC_BASE<"fmax.w", int_mips_fmax_w, MSA128WOpnd>; -class FMAX_D_DESC : MSA_3RF_DESC_BASE<"fmax.d", int_mips_fmax_d, MSA128DOpnd>; - -class FMAX_A_W_DESC : MSA_3RF_DESC_BASE<"fmax_a.w", int_mips_fmax_a_w, - MSA128WOpnd>; -class FMAX_A_D_DESC : MSA_3RF_DESC_BASE<"fmax_a.d", int_mips_fmax_a_d, - MSA128DOpnd>; - -class FMIN_W_DESC : MSA_3RF_DESC_BASE<"fmin.w", int_mips_fmin_w, MSA128WOpnd>; -class FMIN_D_DESC : MSA_3RF_DESC_BASE<"fmin.d", int_mips_fmin_d, MSA128DOpnd>; - -class FMIN_A_W_DESC : MSA_3RF_DESC_BASE<"fmin_a.w", int_mips_fmin_a_w, - MSA128WOpnd>; -class FMIN_A_D_DESC : MSA_3RF_DESC_BASE<"fmin_a.d", int_mips_fmin_a_d, - MSA128DOpnd>; - -class FMSUB_W_DESC : MSA_3RF_4RF_DESC_BASE<"fmsub.w", MipsFMS, MSA128WOpnd>; -class FMSUB_D_DESC : MSA_3RF_4RF_DESC_BASE<"fmsub.d", MipsFMS, MSA128DOpnd>; - -class FMUL_W_DESC : MSA_3RF_DESC_BASE<"fmul.w", fmul, MSA128WOpnd>; -class FMUL_D_DESC : MSA_3RF_DESC_BASE<"fmul.d", fmul, MSA128DOpnd>; - -class FRINT_W_DESC : MSA_2RF_DESC_BASE<"frint.w", frint, MSA128WOpnd>; -class FRINT_D_DESC : MSA_2RF_DESC_BASE<"frint.d", frint, MSA128DOpnd>; - -class FRCP_W_DESC : MSA_2RF_DESC_BASE<"frcp.w", int_mips_frcp_w, MSA128WOpnd>; -class FRCP_D_DESC : MSA_2RF_DESC_BASE<"frcp.d", int_mips_frcp_d, MSA128DOpnd>; - -class FRSQRT_W_DESC : MSA_2RF_DESC_BASE<"frsqrt.w", int_mips_frsqrt_w, - MSA128WOpnd>; -class FRSQRT_D_DESC : MSA_2RF_DESC_BASE<"frsqrt.d", int_mips_frsqrt_d, - MSA128DOpnd>; - -class FSAF_W_DESC : MSA_3RF_DESC_BASE<"fsaf.w", int_mips_fsaf_w, MSA128WOpnd>; -class FSAF_D_DESC : MSA_3RF_DESC_BASE<"fsaf.d", int_mips_fsaf_d, MSA128DOpnd>; - -class FSEQ_W_DESC : MSA_3RF_DESC_BASE<"fseq.w", int_mips_fseq_w, MSA128WOpnd>; -class FSEQ_D_DESC : MSA_3RF_DESC_BASE<"fseq.d", int_mips_fseq_d, MSA128DOpnd>; - -class FSLE_W_DESC : MSA_3RF_DESC_BASE<"fsle.w", int_mips_fsle_w, MSA128WOpnd>; -class FSLE_D_DESC : MSA_3RF_DESC_BASE<"fsle.d", int_mips_fsle_d, MSA128DOpnd>; - -class FSLT_W_DESC : MSA_3RF_DESC_BASE<"fslt.w", int_mips_fslt_w, MSA128WOpnd>; -class FSLT_D_DESC : MSA_3RF_DESC_BASE<"fslt.d", int_mips_fslt_d, MSA128DOpnd>; - -class FSNE_W_DESC : MSA_3RF_DESC_BASE<"fsne.w", int_mips_fsne_w, MSA128WOpnd>; -class FSNE_D_DESC : MSA_3RF_DESC_BASE<"fsne.d", int_mips_fsne_d, MSA128DOpnd>; - -class FSOR_W_DESC : MSA_3RF_DESC_BASE<"fsor.w", int_mips_fsor_w, MSA128WOpnd>; -class FSOR_D_DESC : MSA_3RF_DESC_BASE<"fsor.d", int_mips_fsor_d, MSA128DOpnd>; - -class FSQRT_W_DESC : MSA_2RF_DESC_BASE<"fsqrt.w", fsqrt, MSA128WOpnd>; -class FSQRT_D_DESC : MSA_2RF_DESC_BASE<"fsqrt.d", fsqrt, MSA128DOpnd>; - -class FSUB_W_DESC : MSA_3RF_DESC_BASE<"fsub.w", fsub, MSA128WOpnd>; -class FSUB_D_DESC : MSA_3RF_DESC_BASE<"fsub.d", fsub, MSA128DOpnd>; - -class FSUEQ_W_DESC : MSA_3RF_DESC_BASE<"fsueq.w", int_mips_fsueq_w, - MSA128WOpnd>; -class FSUEQ_D_DESC : MSA_3RF_DESC_BASE<"fsueq.d", int_mips_fsueq_d, - MSA128DOpnd>; - -class FSULE_W_DESC : MSA_3RF_DESC_BASE<"fsule.w", int_mips_fsule_w, - MSA128WOpnd>; -class FSULE_D_DESC : MSA_3RF_DESC_BASE<"fsule.d", int_mips_fsule_d, - MSA128DOpnd>; - -class FSULT_W_DESC : MSA_3RF_DESC_BASE<"fsult.w", int_mips_fsult_w, - MSA128WOpnd>; -class FSULT_D_DESC : MSA_3RF_DESC_BASE<"fsult.d", int_mips_fsult_d, - MSA128DOpnd>; - -class FSUN_W_DESC : MSA_3RF_DESC_BASE<"fsun.w", int_mips_fsun_w, - MSA128WOpnd>; -class FSUN_D_DESC : MSA_3RF_DESC_BASE<"fsun.d", int_mips_fsun_d, - MSA128DOpnd>; - -class FSUNE_W_DESC : MSA_3RF_DESC_BASE<"fsune.w", int_mips_fsune_w, - MSA128WOpnd>; -class FSUNE_D_DESC : MSA_3RF_DESC_BASE<"fsune.d", int_mips_fsune_d, - MSA128DOpnd>; - -class FTINT_S_W_DESC : MSA_2RF_DESC_BASE<"ftint_s.w", int_mips_ftint_s_w, - MSA128WOpnd>; -class FTINT_S_D_DESC : MSA_2RF_DESC_BASE<"ftint_s.d", int_mips_ftint_s_d, - MSA128DOpnd>; - -class FTINT_U_W_DESC : MSA_2RF_DESC_BASE<"ftint_u.w", int_mips_ftint_u_w, - MSA128WOpnd>; -class FTINT_U_D_DESC : MSA_2RF_DESC_BASE<"ftint_u.d", int_mips_ftint_u_d, - MSA128DOpnd>; - -class FTQ_H_DESC : MSA_3RF_DESC_BASE<"ftq.h", int_mips_ftq_h, - MSA128HOpnd, MSA128WOpnd, MSA128WOpnd>; -class FTQ_W_DESC : MSA_3RF_DESC_BASE<"ftq.w", int_mips_ftq_w, - MSA128WOpnd, MSA128DOpnd, MSA128DOpnd>; - -class FTRUNC_S_W_DESC : MSA_2RF_DESC_BASE<"ftrunc_s.w", fp_to_sint, - MSA128WOpnd>; -class FTRUNC_S_D_DESC : MSA_2RF_DESC_BASE<"ftrunc_s.d", fp_to_sint, - MSA128DOpnd>; - -class FTRUNC_U_W_DESC : MSA_2RF_DESC_BASE<"ftrunc_u.w", fp_to_uint, - MSA128WOpnd>; -class FTRUNC_U_D_DESC : MSA_2RF_DESC_BASE<"ftrunc_u.d", fp_to_uint, - MSA128DOpnd>; - -class HADD_S_H_DESC : MSA_3R_DESC_BASE<"hadd_s.h", int_mips_hadd_s_h, - MSA128HOpnd, MSA128BOpnd, MSA128BOpnd>; -class HADD_S_W_DESC : MSA_3R_DESC_BASE<"hadd_s.w", int_mips_hadd_s_w, - MSA128WOpnd, MSA128HOpnd, MSA128HOpnd>; -class HADD_S_D_DESC : MSA_3R_DESC_BASE<"hadd_s.d", int_mips_hadd_s_d, - MSA128DOpnd, MSA128WOpnd, MSA128WOpnd>; - -class HADD_U_H_DESC : MSA_3R_DESC_BASE<"hadd_u.h", int_mips_hadd_u_h, - MSA128HOpnd, MSA128BOpnd, MSA128BOpnd>; -class HADD_U_W_DESC : MSA_3R_DESC_BASE<"hadd_u.w", int_mips_hadd_u_w, - MSA128WOpnd, MSA128HOpnd, MSA128HOpnd>; -class HADD_U_D_DESC : MSA_3R_DESC_BASE<"hadd_u.d", int_mips_hadd_u_d, - MSA128DOpnd, MSA128WOpnd, MSA128WOpnd>; - -class HSUB_S_H_DESC : MSA_3R_DESC_BASE<"hsub_s.h", int_mips_hsub_s_h, - MSA128HOpnd, MSA128BOpnd, MSA128BOpnd>; -class HSUB_S_W_DESC : MSA_3R_DESC_BASE<"hsub_s.w", int_mips_hsub_s_w, - MSA128WOpnd, MSA128HOpnd, MSA128HOpnd>; -class HSUB_S_D_DESC : MSA_3R_DESC_BASE<"hsub_s.d", int_mips_hsub_s_d, - MSA128DOpnd, MSA128WOpnd, MSA128WOpnd>; - -class HSUB_U_H_DESC : MSA_3R_DESC_BASE<"hsub_u.h", int_mips_hsub_u_h, - MSA128HOpnd, MSA128BOpnd, MSA128BOpnd>; -class HSUB_U_W_DESC : MSA_3R_DESC_BASE<"hsub_u.w", int_mips_hsub_u_w, - MSA128WOpnd, MSA128HOpnd, MSA128HOpnd>; -class HSUB_U_D_DESC : MSA_3R_DESC_BASE<"hsub_u.d", int_mips_hsub_u_d, - MSA128DOpnd, MSA128WOpnd, MSA128WOpnd>; - -class ILVEV_B_DESC : MSA_3R_DESC_BASE<"ilvev.b", MipsILVEV, MSA128BOpnd>; -class ILVEV_H_DESC : MSA_3R_DESC_BASE<"ilvev.h", MipsILVEV, MSA128HOpnd>; -class ILVEV_W_DESC : MSA_3R_DESC_BASE<"ilvev.w", MipsILVEV, MSA128WOpnd>; -class ILVEV_D_DESC : MSA_3R_DESC_BASE<"ilvev.d", MipsILVEV, MSA128DOpnd>; - -class ILVL_B_DESC : MSA_3R_DESC_BASE<"ilvl.b", MipsILVL, MSA128BOpnd>; -class ILVL_H_DESC : MSA_3R_DESC_BASE<"ilvl.h", MipsILVL, MSA128HOpnd>; -class ILVL_W_DESC : MSA_3R_DESC_BASE<"ilvl.w", MipsILVL, MSA128WOpnd>; -class ILVL_D_DESC : MSA_3R_DESC_BASE<"ilvl.d", MipsILVL, MSA128DOpnd>; - -class ILVOD_B_DESC : MSA_3R_DESC_BASE<"ilvod.b", MipsILVOD, MSA128BOpnd>; -class ILVOD_H_DESC : MSA_3R_DESC_BASE<"ilvod.h", MipsILVOD, MSA128HOpnd>; -class ILVOD_W_DESC : MSA_3R_DESC_BASE<"ilvod.w", MipsILVOD, MSA128WOpnd>; -class ILVOD_D_DESC : MSA_3R_DESC_BASE<"ilvod.d", MipsILVOD, MSA128DOpnd>; - -class ILVR_B_DESC : MSA_3R_DESC_BASE<"ilvr.b", MipsILVR, MSA128BOpnd>; -class ILVR_H_DESC : MSA_3R_DESC_BASE<"ilvr.h", MipsILVR, MSA128HOpnd>; -class ILVR_W_DESC : MSA_3R_DESC_BASE<"ilvr.w", MipsILVR, MSA128WOpnd>; -class ILVR_D_DESC : MSA_3R_DESC_BASE<"ilvr.d", MipsILVR, MSA128DOpnd>; - -class INSERT_B_DESC : MSA_INSERT_DESC_BASE<"insert.b", vinsert_v16i8, uimm4, - immZExt4Ptr, MSA128BOpnd, GPR32Opnd>; -class INSERT_H_DESC : MSA_INSERT_DESC_BASE<"insert.h", vinsert_v8i16, uimm3, - immZExt3Ptr, MSA128HOpnd, GPR32Opnd>; -class INSERT_W_DESC : MSA_INSERT_DESC_BASE<"insert.w", vinsert_v4i32, uimm2, - immZExt2Ptr, MSA128WOpnd, GPR32Opnd>; -class INSERT_D_DESC : MSA_INSERT_DESC_BASE<"insert.d", vinsert_v2i64, uimm1, - immZExt1Ptr, MSA128DOpnd, GPR64Opnd>; - -class INSERT_B_VIDX_PSEUDO_DESC : - MSA_INSERT_VIDX_PSEUDO_BASE<vector_insert, v16i8, MSA128BOpnd, GPR32Opnd, GPR32Opnd>; -class INSERT_H_VIDX_PSEUDO_DESC : - MSA_INSERT_VIDX_PSEUDO_BASE<vector_insert, v8i16, MSA128HOpnd, GPR32Opnd, GPR32Opnd>; -class INSERT_W_VIDX_PSEUDO_DESC : - MSA_INSERT_VIDX_PSEUDO_BASE<vector_insert, v4i32, MSA128WOpnd, GPR32Opnd, GPR32Opnd>; -class INSERT_D_VIDX_PSEUDO_DESC : - MSA_INSERT_VIDX_PSEUDO_BASE<vector_insert, v2i64, MSA128DOpnd, GPR64Opnd, GPR32Opnd>; - -class INSERT_FW_PSEUDO_DESC : MSA_INSERT_PSEUDO_BASE<vector_insert, v4f32, - uimm2, immZExt2Ptr, - MSA128WOpnd, FGR32Opnd>; -class INSERT_FD_PSEUDO_DESC : MSA_INSERT_PSEUDO_BASE<vector_insert, v2f64, - uimm1, immZExt1Ptr, - MSA128DOpnd, FGR64Opnd>; - -class INSERT_FW_VIDX_PSEUDO_DESC : - MSA_INSERT_VIDX_PSEUDO_BASE<vector_insert, v4f32, MSA128WOpnd, FGR32Opnd, GPR32Opnd>; -class INSERT_FD_VIDX_PSEUDO_DESC : - MSA_INSERT_VIDX_PSEUDO_BASE<vector_insert, v2f64, MSA128DOpnd, FGR64Opnd, GPR32Opnd>; - -class INSERT_B_VIDX64_PSEUDO_DESC : - MSA_INSERT_VIDX_PSEUDO_BASE<vector_insert, v16i8, MSA128BOpnd, GPR32Opnd, GPR64Opnd>; -class INSERT_H_VIDX64_PSEUDO_DESC : - MSA_INSERT_VIDX_PSEUDO_BASE<vector_insert, v8i16, MSA128HOpnd, GPR32Opnd, GPR64Opnd>; -class INSERT_W_VIDX64_PSEUDO_DESC : - MSA_INSERT_VIDX_PSEUDO_BASE<vector_insert, v4i32, MSA128WOpnd, GPR32Opnd, GPR64Opnd>; -class INSERT_D_VIDX64_PSEUDO_DESC : - MSA_INSERT_VIDX_PSEUDO_BASE<vector_insert, v2i64, MSA128DOpnd, GPR64Opnd, GPR64Opnd>; - -class INSERT_FW_VIDX64_PSEUDO_DESC : - MSA_INSERT_VIDX_PSEUDO_BASE<vector_insert, v4f32, MSA128WOpnd, FGR32Opnd, GPR64Opnd>; -class INSERT_FD_VIDX64_PSEUDO_DESC : - MSA_INSERT_VIDX_PSEUDO_BASE<vector_insert, v2f64, MSA128DOpnd, FGR64Opnd, GPR64Opnd>; - -class INSVE_B_DESC : MSA_INSVE_DESC_BASE<"insve.b", insve_v16i8, uimm4, immZExt4, - MSA128BOpnd>; -class INSVE_H_DESC : MSA_INSVE_DESC_BASE<"insve.h", insve_v8i16, uimm3, immZExt3, - MSA128HOpnd>; -class INSVE_W_DESC : MSA_INSVE_DESC_BASE<"insve.w", insve_v4i32, uimm2, immZExt2, - MSA128WOpnd>; -class INSVE_D_DESC : MSA_INSVE_DESC_BASE<"insve.d", insve_v2i64, uimm1, immZExt1, - MSA128DOpnd>; - -class LD_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - ValueType TyNode, RegisterOperand ROWD, - Operand MemOpnd, ComplexPattern Addr = addrimm10, - InstrItinClass itin = NoItinerary> { - dag OutOperandList = (outs ROWD:$wd); - dag InOperandList = (ins MemOpnd:$addr); - string AsmString = !strconcat(instr_asm, "\t$wd, $addr"); - list<dag> Pattern = [(set ROWD:$wd, (TyNode (OpNode Addr:$addr)))]; - InstrItinClass Itinerary = itin; - string DecoderMethod = "DecodeMSA128Mem"; -} - -class LD_B_DESC : LD_DESC_BASE<"ld.b", load, v16i8, MSA128BOpnd, mem_simm10>; -class LD_H_DESC : LD_DESC_BASE<"ld.h", load, v8i16, MSA128HOpnd, - mem_simm10_lsl1, addrimm10lsl1>; -class LD_W_DESC : LD_DESC_BASE<"ld.w", load, v4i32, MSA128WOpnd, - mem_simm10_lsl2, addrimm10lsl2>; -class LD_D_DESC : LD_DESC_BASE<"ld.d", load, v2i64, MSA128DOpnd, - mem_simm10_lsl3, addrimm10lsl3>; - -class LDI_B_DESC : MSA_I10_LDI_DESC_BASE<"ldi.b", MSA128BOpnd>; -class LDI_H_DESC : MSA_I10_LDI_DESC_BASE<"ldi.h", MSA128HOpnd>; -class LDI_W_DESC : MSA_I10_LDI_DESC_BASE<"ldi.w", MSA128WOpnd>; -class LDI_D_DESC : MSA_I10_LDI_DESC_BASE<"ldi.d", MSA128DOpnd>; - -class LSA_DESC_BASE<string instr_asm, RegisterOperand RORD, - InstrItinClass itin = NoItinerary> { - dag OutOperandList = (outs RORD:$rd); - dag InOperandList = (ins RORD:$rs, RORD:$rt, uimm2_plus1:$sa); - string AsmString = !strconcat(instr_asm, "\t$rd, $rs, $rt, $sa"); - list<dag> Pattern = [(set RORD:$rd, (add RORD:$rt, - (shl RORD:$rs, - immZExt2Lsa:$sa)))]; - InstrItinClass Itinerary = itin; -} - -class LSA_DESC : LSA_DESC_BASE<"lsa", GPR32Opnd, II_LSA>; -class DLSA_DESC : LSA_DESC_BASE<"dlsa", GPR64Opnd, II_DLSA>; - -class MADD_Q_H_DESC : MSA_3RF_4RF_DESC_BASE<"madd_q.h", int_mips_madd_q_h, - MSA128HOpnd>; -class MADD_Q_W_DESC : MSA_3RF_4RF_DESC_BASE<"madd_q.w", int_mips_madd_q_w, - MSA128WOpnd>; - -class MADDR_Q_H_DESC : MSA_3RF_4RF_DESC_BASE<"maddr_q.h", int_mips_maddr_q_h, - MSA128HOpnd>; -class MADDR_Q_W_DESC : MSA_3RF_4RF_DESC_BASE<"maddr_q.w", int_mips_maddr_q_w, - MSA128WOpnd>; - -class MADDV_B_DESC : MSA_3R_4R_DESC_BASE<"maddv.b", muladd, MSA128BOpnd>; -class MADDV_H_DESC : MSA_3R_4R_DESC_BASE<"maddv.h", muladd, MSA128HOpnd>; -class MADDV_W_DESC : MSA_3R_4R_DESC_BASE<"maddv.w", muladd, MSA128WOpnd>; -class MADDV_D_DESC : MSA_3R_4R_DESC_BASE<"maddv.d", muladd, MSA128DOpnd>; - -class MAX_A_B_DESC : MSA_3R_DESC_BASE<"max_a.b", int_mips_max_a_b, MSA128BOpnd>; -class MAX_A_H_DESC : MSA_3R_DESC_BASE<"max_a.h", int_mips_max_a_h, MSA128HOpnd>; -class MAX_A_W_DESC : MSA_3R_DESC_BASE<"max_a.w", int_mips_max_a_w, MSA128WOpnd>; -class MAX_A_D_DESC : MSA_3R_DESC_BASE<"max_a.d", int_mips_max_a_d, MSA128DOpnd>; - -class MAX_S_B_DESC : MSA_3R_DESC_BASE<"max_s.b", smax, MSA128BOpnd>; -class MAX_S_H_DESC : MSA_3R_DESC_BASE<"max_s.h", smax, MSA128HOpnd>; -class MAX_S_W_DESC : MSA_3R_DESC_BASE<"max_s.w", smax, MSA128WOpnd>; -class MAX_S_D_DESC : MSA_3R_DESC_BASE<"max_s.d", smax, MSA128DOpnd>; - -class MAX_U_B_DESC : MSA_3R_DESC_BASE<"max_u.b", umax, MSA128BOpnd>; -class MAX_U_H_DESC : MSA_3R_DESC_BASE<"max_u.h", umax, MSA128HOpnd>; -class MAX_U_W_DESC : MSA_3R_DESC_BASE<"max_u.w", umax, MSA128WOpnd>; -class MAX_U_D_DESC : MSA_3R_DESC_BASE<"max_u.d", umax, MSA128DOpnd>; - -class MAXI_S_B_DESC : MSA_I5_DESC_BASE<"maxi_s.b", smax, vsplati8_simm5, - MSA128BOpnd>; -class MAXI_S_H_DESC : MSA_I5_DESC_BASE<"maxi_s.h", smax, vsplati16_simm5, - MSA128HOpnd>; -class MAXI_S_W_DESC : MSA_I5_DESC_BASE<"maxi_s.w", smax, vsplati32_simm5, - MSA128WOpnd>; -class MAXI_S_D_DESC : MSA_I5_DESC_BASE<"maxi_s.d", smax, vsplati64_simm5, - MSA128DOpnd>; - -class MAXI_U_B_DESC : MSA_I5_DESC_BASE<"maxi_u.b", umax, vsplati8_uimm5, - MSA128BOpnd>; -class MAXI_U_H_DESC : MSA_I5_DESC_BASE<"maxi_u.h", umax, vsplati16_uimm5, - MSA128HOpnd>; -class MAXI_U_W_DESC : MSA_I5_DESC_BASE<"maxi_u.w", umax, vsplati32_uimm5, - MSA128WOpnd>; -class MAXI_U_D_DESC : MSA_I5_DESC_BASE<"maxi_u.d", umax, vsplati64_uimm5, - MSA128DOpnd>; - -class MIN_A_B_DESC : MSA_3R_DESC_BASE<"min_a.b", int_mips_min_a_b, MSA128BOpnd>; -class MIN_A_H_DESC : MSA_3R_DESC_BASE<"min_a.h", int_mips_min_a_h, MSA128HOpnd>; -class MIN_A_W_DESC : MSA_3R_DESC_BASE<"min_a.w", int_mips_min_a_w, MSA128WOpnd>; -class MIN_A_D_DESC : MSA_3R_DESC_BASE<"min_a.d", int_mips_min_a_d, MSA128DOpnd>; - -class MIN_S_B_DESC : MSA_3R_DESC_BASE<"min_s.b", smin, MSA128BOpnd>; -class MIN_S_H_DESC : MSA_3R_DESC_BASE<"min_s.h", smin, MSA128HOpnd>; -class MIN_S_W_DESC : MSA_3R_DESC_BASE<"min_s.w", smin, MSA128WOpnd>; -class MIN_S_D_DESC : MSA_3R_DESC_BASE<"min_s.d", smin, MSA128DOpnd>; - -class MIN_U_B_DESC : MSA_3R_DESC_BASE<"min_u.b", umin, MSA128BOpnd>; -class MIN_U_H_DESC : MSA_3R_DESC_BASE<"min_u.h", umin, MSA128HOpnd>; -class MIN_U_W_DESC : MSA_3R_DESC_BASE<"min_u.w", umin, MSA128WOpnd>; -class MIN_U_D_DESC : MSA_3R_DESC_BASE<"min_u.d", umin, MSA128DOpnd>; - -class MINI_S_B_DESC : MSA_I5_DESC_BASE<"mini_s.b", smin, vsplati8_simm5, - MSA128BOpnd>; -class MINI_S_H_DESC : MSA_I5_DESC_BASE<"mini_s.h", smin, vsplati16_simm5, - MSA128HOpnd>; -class MINI_S_W_DESC : MSA_I5_DESC_BASE<"mini_s.w", smin, vsplati32_simm5, - MSA128WOpnd>; -class MINI_S_D_DESC : MSA_I5_DESC_BASE<"mini_s.d", smin, vsplati64_simm5, - MSA128DOpnd>; - -class MINI_U_B_DESC : MSA_I5_DESC_BASE<"mini_u.b", umin, vsplati8_uimm5, - MSA128BOpnd>; -class MINI_U_H_DESC : MSA_I5_DESC_BASE<"mini_u.h", umin, vsplati16_uimm5, - MSA128HOpnd>; -class MINI_U_W_DESC : MSA_I5_DESC_BASE<"mini_u.w", umin, vsplati32_uimm5, - MSA128WOpnd>; -class MINI_U_D_DESC : MSA_I5_DESC_BASE<"mini_u.d", umin, vsplati64_uimm5, - MSA128DOpnd>; - -class MOD_S_B_DESC : MSA_3R_DESC_BASE<"mod_s.b", srem, MSA128BOpnd>; -class MOD_S_H_DESC : MSA_3R_DESC_BASE<"mod_s.h", srem, MSA128HOpnd>; -class MOD_S_W_DESC : MSA_3R_DESC_BASE<"mod_s.w", srem, MSA128WOpnd>; -class MOD_S_D_DESC : MSA_3R_DESC_BASE<"mod_s.d", srem, MSA128DOpnd>; - -class MOD_U_B_DESC : MSA_3R_DESC_BASE<"mod_u.b", urem, MSA128BOpnd>; -class MOD_U_H_DESC : MSA_3R_DESC_BASE<"mod_u.h", urem, MSA128HOpnd>; -class MOD_U_W_DESC : MSA_3R_DESC_BASE<"mod_u.w", urem, MSA128WOpnd>; -class MOD_U_D_DESC : MSA_3R_DESC_BASE<"mod_u.d", urem, MSA128DOpnd>; - -class MOVE_V_DESC { - dag OutOperandList = (outs MSA128BOpnd:$wd); - dag InOperandList = (ins MSA128BOpnd:$ws); - string AsmString = "move.v\t$wd, $ws"; - list<dag> Pattern = []; - InstrItinClass Itinerary = NoItinerary; - bit isMoveReg = 1; -} - -class MSUB_Q_H_DESC : MSA_3RF_4RF_DESC_BASE<"msub_q.h", int_mips_msub_q_h, - MSA128HOpnd>; -class MSUB_Q_W_DESC : MSA_3RF_4RF_DESC_BASE<"msub_q.w", int_mips_msub_q_w, - MSA128WOpnd>; - -class MSUBR_Q_H_DESC : MSA_3RF_4RF_DESC_BASE<"msubr_q.h", int_mips_msubr_q_h, - MSA128HOpnd>; -class MSUBR_Q_W_DESC : MSA_3RF_4RF_DESC_BASE<"msubr_q.w", int_mips_msubr_q_w, - MSA128WOpnd>; - -class MSUBV_B_DESC : MSA_3R_4R_DESC_BASE<"msubv.b", mulsub, MSA128BOpnd>; -class MSUBV_H_DESC : MSA_3R_4R_DESC_BASE<"msubv.h", mulsub, MSA128HOpnd>; -class MSUBV_W_DESC : MSA_3R_4R_DESC_BASE<"msubv.w", mulsub, MSA128WOpnd>; -class MSUBV_D_DESC : MSA_3R_4R_DESC_BASE<"msubv.d", mulsub, MSA128DOpnd>; - -class MUL_Q_H_DESC : MSA_3RF_DESC_BASE<"mul_q.h", int_mips_mul_q_h, - MSA128HOpnd>; -class MUL_Q_W_DESC : MSA_3RF_DESC_BASE<"mul_q.w", int_mips_mul_q_w, - MSA128WOpnd>; - -class MULR_Q_H_DESC : MSA_3RF_DESC_BASE<"mulr_q.h", int_mips_mulr_q_h, - MSA128HOpnd>; -class MULR_Q_W_DESC : MSA_3RF_DESC_BASE<"mulr_q.w", int_mips_mulr_q_w, - MSA128WOpnd>; - -class MULV_B_DESC : MSA_3R_DESC_BASE<"mulv.b", mul, MSA128BOpnd>; -class MULV_H_DESC : MSA_3R_DESC_BASE<"mulv.h", mul, MSA128HOpnd>; -class MULV_W_DESC : MSA_3R_DESC_BASE<"mulv.w", mul, MSA128WOpnd>; -class MULV_D_DESC : MSA_3R_DESC_BASE<"mulv.d", mul, MSA128DOpnd>; - -class NLOC_B_DESC : MSA_2R_DESC_BASE<"nloc.b", int_mips_nloc_b, MSA128BOpnd>; -class NLOC_H_DESC : MSA_2R_DESC_BASE<"nloc.h", int_mips_nloc_h, MSA128HOpnd>; -class NLOC_W_DESC : MSA_2R_DESC_BASE<"nloc.w", int_mips_nloc_w, MSA128WOpnd>; -class NLOC_D_DESC : MSA_2R_DESC_BASE<"nloc.d", int_mips_nloc_d, MSA128DOpnd>; - -class NLZC_B_DESC : MSA_2R_DESC_BASE<"nlzc.b", ctlz, MSA128BOpnd>; -class NLZC_H_DESC : MSA_2R_DESC_BASE<"nlzc.h", ctlz, MSA128HOpnd>; -class NLZC_W_DESC : MSA_2R_DESC_BASE<"nlzc.w", ctlz, MSA128WOpnd>; -class NLZC_D_DESC : MSA_2R_DESC_BASE<"nlzc.d", ctlz, MSA128DOpnd>; - -class NOR_V_DESC : MSA_VEC_DESC_BASE<"nor.v", MipsVNOR, MSA128BOpnd>; -class NOR_V_H_PSEUDO_DESC : MSA_VEC_PSEUDO_BASE<MipsVNOR, MSA128HOpnd>; -class NOR_V_W_PSEUDO_DESC : MSA_VEC_PSEUDO_BASE<MipsVNOR, MSA128WOpnd>; -class NOR_V_D_PSEUDO_DESC : MSA_VEC_PSEUDO_BASE<MipsVNOR, MSA128DOpnd>; - -class NORI_B_DESC : MSA_I8_DESC_BASE<"nori.b", MipsVNOR, vsplati8_uimm8, - MSA128BOpnd>; - -class OR_V_DESC : MSA_VEC_DESC_BASE<"or.v", or, MSA128BOpnd>; -class OR_V_H_PSEUDO_DESC : MSA_VEC_PSEUDO_BASE<or, MSA128HOpnd>; -class OR_V_W_PSEUDO_DESC : MSA_VEC_PSEUDO_BASE<or, MSA128WOpnd>; -class OR_V_D_PSEUDO_DESC : MSA_VEC_PSEUDO_BASE<or, MSA128DOpnd>; - -class ORI_B_DESC : MSA_I8_DESC_BASE<"ori.b", or, vsplati8_uimm8, MSA128BOpnd>; - -class PCKEV_B_DESC : MSA_3R_DESC_BASE<"pckev.b", MipsPCKEV, MSA128BOpnd>; -class PCKEV_H_DESC : MSA_3R_DESC_BASE<"pckev.h", MipsPCKEV, MSA128HOpnd>; -class PCKEV_W_DESC : MSA_3R_DESC_BASE<"pckev.w", MipsPCKEV, MSA128WOpnd>; -class PCKEV_D_DESC : MSA_3R_DESC_BASE<"pckev.d", MipsPCKEV, MSA128DOpnd>; - -class PCKOD_B_DESC : MSA_3R_DESC_BASE<"pckod.b", MipsPCKOD, MSA128BOpnd>; -class PCKOD_H_DESC : MSA_3R_DESC_BASE<"pckod.h", MipsPCKOD, MSA128HOpnd>; -class PCKOD_W_DESC : MSA_3R_DESC_BASE<"pckod.w", MipsPCKOD, MSA128WOpnd>; -class PCKOD_D_DESC : MSA_3R_DESC_BASE<"pckod.d", MipsPCKOD, MSA128DOpnd>; - -class PCNT_B_DESC : MSA_2R_DESC_BASE<"pcnt.b", ctpop, MSA128BOpnd>; -class PCNT_H_DESC : MSA_2R_DESC_BASE<"pcnt.h", ctpop, MSA128HOpnd>; -class PCNT_W_DESC : MSA_2R_DESC_BASE<"pcnt.w", ctpop, MSA128WOpnd>; -class PCNT_D_DESC : MSA_2R_DESC_BASE<"pcnt.d", ctpop, MSA128DOpnd>; - -class SAT_S_B_DESC : MSA_BIT_X_DESC_BASE<"sat_s.b", int_mips_sat_s_b, uimm3, - immZExt3, MSA128BOpnd>; -class SAT_S_H_DESC : MSA_BIT_X_DESC_BASE<"sat_s.h", int_mips_sat_s_h, uimm4, - immZExt4, MSA128HOpnd>; -class SAT_S_W_DESC : MSA_BIT_X_DESC_BASE<"sat_s.w", int_mips_sat_s_w, uimm5, - immZExt5, MSA128WOpnd>; -class SAT_S_D_DESC : MSA_BIT_X_DESC_BASE<"sat_s.d", int_mips_sat_s_d, uimm6, - immZExt6, MSA128DOpnd>; - -class SAT_U_B_DESC : MSA_BIT_X_DESC_BASE<"sat_u.b", int_mips_sat_u_b, uimm3, - immZExt3, MSA128BOpnd>; -class SAT_U_H_DESC : MSA_BIT_X_DESC_BASE<"sat_u.h", int_mips_sat_u_h, uimm4, - immZExt4, MSA128HOpnd>; -class SAT_U_W_DESC : MSA_BIT_X_DESC_BASE<"sat_u.w", int_mips_sat_u_w, uimm5, - immZExt5, MSA128WOpnd>; -class SAT_U_D_DESC : MSA_BIT_X_DESC_BASE<"sat_u.d", int_mips_sat_u_d, uimm6, - immZExt6, MSA128DOpnd>; - -class SHF_B_DESC : MSA_I8_SHF_DESC_BASE<"shf.b", MSA128BOpnd>; -class SHF_H_DESC : MSA_I8_SHF_DESC_BASE<"shf.h", MSA128HOpnd>; -class SHF_W_DESC : MSA_I8_SHF_DESC_BASE<"shf.w", MSA128WOpnd>; - -class SLD_B_DESC : MSA_3R_SLD_DESC_BASE<"sld.b", int_mips_sld_b, MSA128BOpnd>; -class SLD_H_DESC : MSA_3R_SLD_DESC_BASE<"sld.h", int_mips_sld_h, MSA128HOpnd>; -class SLD_W_DESC : MSA_3R_SLD_DESC_BASE<"sld.w", int_mips_sld_w, MSA128WOpnd>; -class SLD_D_DESC : MSA_3R_SLD_DESC_BASE<"sld.d", int_mips_sld_d, MSA128DOpnd>; - -class SLDI_B_DESC : MSA_ELM_SLD_DESC_BASE<"sldi.b", int_mips_sldi_b, - MSA128BOpnd, MSA128BOpnd, uimm4, - immZExt4>; -class SLDI_H_DESC : MSA_ELM_SLD_DESC_BASE<"sldi.h", int_mips_sldi_h, - MSA128HOpnd, MSA128HOpnd, uimm3, - immZExt3>; -class SLDI_W_DESC : MSA_ELM_SLD_DESC_BASE<"sldi.w", int_mips_sldi_w, - MSA128WOpnd, MSA128WOpnd, uimm2, - immZExt2>; -class SLDI_D_DESC : MSA_ELM_SLD_DESC_BASE<"sldi.d", int_mips_sldi_d, - MSA128DOpnd, MSA128DOpnd, uimm1, - immZExt1>; - -class SLL_B_DESC : MSA_3R_DESC_BASE<"sll.b", shl, MSA128BOpnd>; -class SLL_H_DESC : MSA_3R_DESC_BASE<"sll.h", shl, MSA128HOpnd>; -class SLL_W_DESC : MSA_3R_DESC_BASE<"sll.w", shl, MSA128WOpnd>; -class SLL_D_DESC : MSA_3R_DESC_BASE<"sll.d", shl, MSA128DOpnd>; - -class SLLI_B_DESC : MSA_BIT_SPLAT_DESC_BASE<"slli.b", shl, vsplati8_uimm3, - MSA128BOpnd>; -class SLLI_H_DESC : MSA_BIT_SPLAT_DESC_BASE<"slli.h", shl, vsplati16_uimm4, - MSA128HOpnd>; -class SLLI_W_DESC : MSA_BIT_SPLAT_DESC_BASE<"slli.w", shl, vsplati32_uimm5, - MSA128WOpnd>; -class SLLI_D_DESC : MSA_BIT_SPLAT_DESC_BASE<"slli.d", shl, vsplati64_uimm6, - MSA128DOpnd>; - -class SPLAT_B_DESC : MSA_3R_SPLAT_DESC_BASE<"splat.b", vsplati8_elt, - MSA128BOpnd>; -class SPLAT_H_DESC : MSA_3R_SPLAT_DESC_BASE<"splat.h", vsplati16_elt, - MSA128HOpnd>; -class SPLAT_W_DESC : MSA_3R_SPLAT_DESC_BASE<"splat.w", vsplati32_elt, - MSA128WOpnd>; -class SPLAT_D_DESC : MSA_3R_SPLAT_DESC_BASE<"splat.d", vsplati64_elt, - MSA128DOpnd>; - -class SPLATI_B_DESC : MSA_ELM_SPLAT_DESC_BASE<"splati.b", vsplati8_uimm4, - MSA128BOpnd>; -class SPLATI_H_DESC : MSA_ELM_SPLAT_DESC_BASE<"splati.h", vsplati16_uimm3, - MSA128HOpnd>; -class SPLATI_W_DESC : MSA_ELM_SPLAT_DESC_BASE<"splati.w", vsplati32_uimm2, - MSA128WOpnd>; -class SPLATI_D_DESC : MSA_ELM_SPLAT_DESC_BASE<"splati.d", vsplati64_uimm1, - MSA128DOpnd>; - -class SRA_B_DESC : MSA_3R_DESC_BASE<"sra.b", sra, MSA128BOpnd>; -class SRA_H_DESC : MSA_3R_DESC_BASE<"sra.h", sra, MSA128HOpnd>; -class SRA_W_DESC : MSA_3R_DESC_BASE<"sra.w", sra, MSA128WOpnd>; -class SRA_D_DESC : MSA_3R_DESC_BASE<"sra.d", sra, MSA128DOpnd>; - -class SRAI_B_DESC : MSA_BIT_SPLAT_DESC_BASE<"srai.b", sra, vsplati8_uimm3, - MSA128BOpnd>; -class SRAI_H_DESC : MSA_BIT_SPLAT_DESC_BASE<"srai.h", sra, vsplati16_uimm4, - MSA128HOpnd>; -class SRAI_W_DESC : MSA_BIT_SPLAT_DESC_BASE<"srai.w", sra, vsplati32_uimm5, - MSA128WOpnd>; -class SRAI_D_DESC : MSA_BIT_SPLAT_DESC_BASE<"srai.d", sra, vsplati64_uimm6, - MSA128DOpnd>; - -class SRAR_B_DESC : MSA_3R_DESC_BASE<"srar.b", int_mips_srar_b, MSA128BOpnd>; -class SRAR_H_DESC : MSA_3R_DESC_BASE<"srar.h", int_mips_srar_h, MSA128HOpnd>; -class SRAR_W_DESC : MSA_3R_DESC_BASE<"srar.w", int_mips_srar_w, MSA128WOpnd>; -class SRAR_D_DESC : MSA_3R_DESC_BASE<"srar.d", int_mips_srar_d, MSA128DOpnd>; - -class SRARI_B_DESC : MSA_BIT_X_DESC_BASE<"srari.b", int_mips_srari_b, uimm3, - immZExt3, MSA128BOpnd>; -class SRARI_H_DESC : MSA_BIT_X_DESC_BASE<"srari.h", int_mips_srari_h, uimm4, - immZExt4, MSA128HOpnd>; -class SRARI_W_DESC : MSA_BIT_X_DESC_BASE<"srari.w", int_mips_srari_w, uimm5, - immZExt5, MSA128WOpnd>; -class SRARI_D_DESC : MSA_BIT_X_DESC_BASE<"srari.d", int_mips_srari_d, uimm6, - immZExt6, MSA128DOpnd>; - -class SRL_B_DESC : MSA_3R_DESC_BASE<"srl.b", srl, MSA128BOpnd>; -class SRL_H_DESC : MSA_3R_DESC_BASE<"srl.h", srl, MSA128HOpnd>; -class SRL_W_DESC : MSA_3R_DESC_BASE<"srl.w", srl, MSA128WOpnd>; -class SRL_D_DESC : MSA_3R_DESC_BASE<"srl.d", srl, MSA128DOpnd>; - -class SRLI_B_DESC : MSA_BIT_SPLAT_DESC_BASE<"srli.b", srl, vsplati8_uimm3, - MSA128BOpnd>; -class SRLI_H_DESC : MSA_BIT_SPLAT_DESC_BASE<"srli.h", srl, vsplati16_uimm4, - MSA128HOpnd>; -class SRLI_W_DESC : MSA_BIT_SPLAT_DESC_BASE<"srli.w", srl, vsplati32_uimm5, - MSA128WOpnd>; -class SRLI_D_DESC : MSA_BIT_SPLAT_DESC_BASE<"srli.d", srl, vsplati64_uimm6, - MSA128DOpnd>; - -class SRLR_B_DESC : MSA_3R_DESC_BASE<"srlr.b", int_mips_srlr_b, MSA128BOpnd>; -class SRLR_H_DESC : MSA_3R_DESC_BASE<"srlr.h", int_mips_srlr_h, MSA128HOpnd>; -class SRLR_W_DESC : MSA_3R_DESC_BASE<"srlr.w", int_mips_srlr_w, MSA128WOpnd>; -class SRLR_D_DESC : MSA_3R_DESC_BASE<"srlr.d", int_mips_srlr_d, MSA128DOpnd>; - -class SRLRI_B_DESC : MSA_BIT_X_DESC_BASE<"srlri.b", int_mips_srlri_b, uimm3, - immZExt3, MSA128BOpnd>; -class SRLRI_H_DESC : MSA_BIT_X_DESC_BASE<"srlri.h", int_mips_srlri_h, uimm4, - immZExt4, MSA128HOpnd>; -class SRLRI_W_DESC : MSA_BIT_X_DESC_BASE<"srlri.w", int_mips_srlri_w, uimm5, - immZExt5, MSA128WOpnd>; -class SRLRI_D_DESC : MSA_BIT_X_DESC_BASE<"srlri.d", int_mips_srlri_d, uimm6, - immZExt6, MSA128DOpnd>; - -class ST_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - ValueType TyNode, RegisterOperand ROWD, - Operand MemOpnd, ComplexPattern Addr = addrimm10, - InstrItinClass itin = NoItinerary> { - dag OutOperandList = (outs); - dag InOperandList = (ins ROWD:$wd, MemOpnd:$addr); - string AsmString = !strconcat(instr_asm, "\t$wd, $addr"); - list<dag> Pattern = [(OpNode (TyNode ROWD:$wd), Addr:$addr)]; - InstrItinClass Itinerary = itin; - string DecoderMethod = "DecodeMSA128Mem"; -} - -class ST_B_DESC : ST_DESC_BASE<"st.b", store, v16i8, MSA128BOpnd, mem_simm10>; -class ST_H_DESC : ST_DESC_BASE<"st.h", store, v8i16, MSA128HOpnd, - mem_simm10_lsl1, addrimm10lsl1>; -class ST_W_DESC : ST_DESC_BASE<"st.w", store, v4i32, MSA128WOpnd, - mem_simm10_lsl2, addrimm10lsl2>; -class ST_D_DESC : ST_DESC_BASE<"st.d", store, v2i64, MSA128DOpnd, - mem_simm10_lsl3, addrimm10lsl3>; - -class SUBS_S_B_DESC : MSA_3R_DESC_BASE<"subs_s.b", int_mips_subs_s_b, - MSA128BOpnd>; -class SUBS_S_H_DESC : MSA_3R_DESC_BASE<"subs_s.h", int_mips_subs_s_h, - MSA128HOpnd>; -class SUBS_S_W_DESC : MSA_3R_DESC_BASE<"subs_s.w", int_mips_subs_s_w, - MSA128WOpnd>; -class SUBS_S_D_DESC : MSA_3R_DESC_BASE<"subs_s.d", int_mips_subs_s_d, - MSA128DOpnd>; - -class SUBS_U_B_DESC : MSA_3R_DESC_BASE<"subs_u.b", int_mips_subs_u_b, - MSA128BOpnd>; -class SUBS_U_H_DESC : MSA_3R_DESC_BASE<"subs_u.h", int_mips_subs_u_h, - MSA128HOpnd>; -class SUBS_U_W_DESC : MSA_3R_DESC_BASE<"subs_u.w", int_mips_subs_u_w, - MSA128WOpnd>; -class SUBS_U_D_DESC : MSA_3R_DESC_BASE<"subs_u.d", int_mips_subs_u_d, - MSA128DOpnd>; - -class SUBSUS_U_B_DESC : MSA_3R_DESC_BASE<"subsus_u.b", int_mips_subsus_u_b, - MSA128BOpnd>; -class SUBSUS_U_H_DESC : MSA_3R_DESC_BASE<"subsus_u.h", int_mips_subsus_u_h, - MSA128HOpnd>; -class SUBSUS_U_W_DESC : MSA_3R_DESC_BASE<"subsus_u.w", int_mips_subsus_u_w, - MSA128WOpnd>; -class SUBSUS_U_D_DESC : MSA_3R_DESC_BASE<"subsus_u.d", int_mips_subsus_u_d, - MSA128DOpnd>; - -class SUBSUU_S_B_DESC : MSA_3R_DESC_BASE<"subsuu_s.b", int_mips_subsuu_s_b, - MSA128BOpnd>; -class SUBSUU_S_H_DESC : MSA_3R_DESC_BASE<"subsuu_s.h", int_mips_subsuu_s_h, - MSA128HOpnd>; -class SUBSUU_S_W_DESC : MSA_3R_DESC_BASE<"subsuu_s.w", int_mips_subsuu_s_w, - MSA128WOpnd>; -class SUBSUU_S_D_DESC : MSA_3R_DESC_BASE<"subsuu_s.d", int_mips_subsuu_s_d, - MSA128DOpnd>; - -class SUBV_B_DESC : MSA_3R_DESC_BASE<"subv.b", sub, MSA128BOpnd>; -class SUBV_H_DESC : MSA_3R_DESC_BASE<"subv.h", sub, MSA128HOpnd>; -class SUBV_W_DESC : MSA_3R_DESC_BASE<"subv.w", sub, MSA128WOpnd>; -class SUBV_D_DESC : MSA_3R_DESC_BASE<"subv.d", sub, MSA128DOpnd>; - -class SUBVI_B_DESC : MSA_I5_DESC_BASE<"subvi.b", sub, vsplati8_uimm5, - MSA128BOpnd>; -class SUBVI_H_DESC : MSA_I5_DESC_BASE<"subvi.h", sub, vsplati16_uimm5, - MSA128HOpnd>; -class SUBVI_W_DESC : MSA_I5_DESC_BASE<"subvi.w", sub, vsplati32_uimm5, - MSA128WOpnd>; -class SUBVI_D_DESC : MSA_I5_DESC_BASE<"subvi.d", sub, vsplati64_uimm5, - MSA128DOpnd>; - -class VSHF_B_DESC : MSA_3R_VSHF_DESC_BASE<"vshf.b", MSA128BOpnd>; -class VSHF_H_DESC : MSA_3R_VSHF_DESC_BASE<"vshf.h", MSA128HOpnd>; -class VSHF_W_DESC : MSA_3R_VSHF_DESC_BASE<"vshf.w", MSA128WOpnd>; -class VSHF_D_DESC : MSA_3R_VSHF_DESC_BASE<"vshf.d", MSA128DOpnd>; - -class XOR_V_DESC : MSA_VEC_DESC_BASE<"xor.v", xor, MSA128BOpnd>; -class XOR_V_H_PSEUDO_DESC : MSA_VEC_PSEUDO_BASE<xor, MSA128HOpnd>; -class XOR_V_W_PSEUDO_DESC : MSA_VEC_PSEUDO_BASE<xor, MSA128WOpnd>; -class XOR_V_D_PSEUDO_DESC : MSA_VEC_PSEUDO_BASE<xor, MSA128DOpnd>; - -class XORI_B_DESC : MSA_I8_DESC_BASE<"xori.b", xor, vsplati8_uimm8, - MSA128BOpnd>; - -// Instruction defs. -def ADD_A_B : ADD_A_B_ENC, ADD_A_B_DESC; -def ADD_A_H : ADD_A_H_ENC, ADD_A_H_DESC; -def ADD_A_W : ADD_A_W_ENC, ADD_A_W_DESC; -def ADD_A_D : ADD_A_D_ENC, ADD_A_D_DESC; - -def ADDS_A_B : ADDS_A_B_ENC, ADDS_A_B_DESC; -def ADDS_A_H : ADDS_A_H_ENC, ADDS_A_H_DESC; -def ADDS_A_W : ADDS_A_W_ENC, ADDS_A_W_DESC; -def ADDS_A_D : ADDS_A_D_ENC, ADDS_A_D_DESC; - -def ADDS_S_B : ADDS_S_B_ENC, ADDS_S_B_DESC; -def ADDS_S_H : ADDS_S_H_ENC, ADDS_S_H_DESC; -def ADDS_S_W : ADDS_S_W_ENC, ADDS_S_W_DESC; -def ADDS_S_D : ADDS_S_D_ENC, ADDS_S_D_DESC; - -def ADDS_U_B : ADDS_U_B_ENC, ADDS_U_B_DESC; -def ADDS_U_H : ADDS_U_H_ENC, ADDS_U_H_DESC; -def ADDS_U_W : ADDS_U_W_ENC, ADDS_U_W_DESC; -def ADDS_U_D : ADDS_U_D_ENC, ADDS_U_D_DESC; - -def ADDV_B : ADDV_B_ENC, ADDV_B_DESC; -def ADDV_H : ADDV_H_ENC, ADDV_H_DESC; -def ADDV_W : ADDV_W_ENC, ADDV_W_DESC; -def ADDV_D : ADDV_D_ENC, ADDV_D_DESC; - -def ADDVI_B : ADDVI_B_ENC, ADDVI_B_DESC; -def ADDVI_H : ADDVI_H_ENC, ADDVI_H_DESC; -def ADDVI_W : ADDVI_W_ENC, ADDVI_W_DESC; -def ADDVI_D : ADDVI_D_ENC, ADDVI_D_DESC; - -def AND_V : AND_V_ENC, AND_V_DESC; -def AND_V_H_PSEUDO : AND_V_H_PSEUDO_DESC, - PseudoInstExpansion<(AND_V MSA128BOpnd:$wd, - MSA128BOpnd:$ws, - MSA128BOpnd:$wt)>; -def AND_V_W_PSEUDO : AND_V_W_PSEUDO_DESC, - PseudoInstExpansion<(AND_V MSA128BOpnd:$wd, - MSA128BOpnd:$ws, - MSA128BOpnd:$wt)>; -def AND_V_D_PSEUDO : AND_V_D_PSEUDO_DESC, - PseudoInstExpansion<(AND_V MSA128BOpnd:$wd, - MSA128BOpnd:$ws, - MSA128BOpnd:$wt)>; - -def ANDI_B : ANDI_B_ENC, ANDI_B_DESC; - -def ASUB_S_B : ASUB_S_B_ENC, ASUB_S_B_DESC; -def ASUB_S_H : ASUB_S_H_ENC, ASUB_S_H_DESC; -def ASUB_S_W : ASUB_S_W_ENC, ASUB_S_W_DESC; -def ASUB_S_D : ASUB_S_D_ENC, ASUB_S_D_DESC; - -def ASUB_U_B : ASUB_U_B_ENC, ASUB_U_B_DESC; -def ASUB_U_H : ASUB_U_H_ENC, ASUB_U_H_DESC; -def ASUB_U_W : ASUB_U_W_ENC, ASUB_U_W_DESC; -def ASUB_U_D : ASUB_U_D_ENC, ASUB_U_D_DESC; - -def AVE_S_B : AVE_S_B_ENC, AVE_S_B_DESC; -def AVE_S_H : AVE_S_H_ENC, AVE_S_H_DESC; -def AVE_S_W : AVE_S_W_ENC, AVE_S_W_DESC; -def AVE_S_D : AVE_S_D_ENC, AVE_S_D_DESC; - -def AVE_U_B : AVE_U_B_ENC, AVE_U_B_DESC; -def AVE_U_H : AVE_U_H_ENC, AVE_U_H_DESC; -def AVE_U_W : AVE_U_W_ENC, AVE_U_W_DESC; -def AVE_U_D : AVE_U_D_ENC, AVE_U_D_DESC; - -def AVER_S_B : AVER_S_B_ENC, AVER_S_B_DESC; -def AVER_S_H : AVER_S_H_ENC, AVER_S_H_DESC; -def AVER_S_W : AVER_S_W_ENC, AVER_S_W_DESC; -def AVER_S_D : AVER_S_D_ENC, AVER_S_D_DESC; - -def AVER_U_B : AVER_U_B_ENC, AVER_U_B_DESC; -def AVER_U_H : AVER_U_H_ENC, AVER_U_H_DESC; -def AVER_U_W : AVER_U_W_ENC, AVER_U_W_DESC; -def AVER_U_D : AVER_U_D_ENC, AVER_U_D_DESC; - -def BCLR_B : BCLR_B_ENC, BCLR_B_DESC; -def BCLR_H : BCLR_H_ENC, BCLR_H_DESC; -def BCLR_W : BCLR_W_ENC, BCLR_W_DESC; -def BCLR_D : BCLR_D_ENC, BCLR_D_DESC; - -def BCLRI_B : BCLRI_B_ENC, BCLRI_B_DESC; -def BCLRI_H : BCLRI_H_ENC, BCLRI_H_DESC; -def BCLRI_W : BCLRI_W_ENC, BCLRI_W_DESC; -def BCLRI_D : BCLRI_D_ENC, BCLRI_D_DESC; - -def BINSL_B : BINSL_B_ENC, BINSL_B_DESC; -def BINSL_H : BINSL_H_ENC, BINSL_H_DESC; -def BINSL_W : BINSL_W_ENC, BINSL_W_DESC; -def BINSL_D : BINSL_D_ENC, BINSL_D_DESC; - -def BINSLI_B : BINSLI_B_ENC, BINSLI_B_DESC; -def BINSLI_H : BINSLI_H_ENC, BINSLI_H_DESC; -def BINSLI_W : BINSLI_W_ENC, BINSLI_W_DESC; -def BINSLI_D : BINSLI_D_ENC, BINSLI_D_DESC; - -def BINSR_B : BINSR_B_ENC, BINSR_B_DESC; -def BINSR_H : BINSR_H_ENC, BINSR_H_DESC; -def BINSR_W : BINSR_W_ENC, BINSR_W_DESC; -def BINSR_D : BINSR_D_ENC, BINSR_D_DESC; - -def BINSRI_B : BINSRI_B_ENC, BINSRI_B_DESC; -def BINSRI_H : BINSRI_H_ENC, BINSRI_H_DESC; -def BINSRI_W : BINSRI_W_ENC, BINSRI_W_DESC; -def BINSRI_D : BINSRI_D_ENC, BINSRI_D_DESC; - -def BMNZ_V : BMNZ_V_ENC, BMNZ_V_DESC; - -def BMNZI_B : BMNZI_B_ENC, BMNZI_B_DESC; - -def BMZ_V : BMZ_V_ENC, BMZ_V_DESC; - -def BMZI_B : BMZI_B_ENC, BMZI_B_DESC; - -def BNEG_B : BNEG_B_ENC, BNEG_B_DESC; -def BNEG_H : BNEG_H_ENC, BNEG_H_DESC; -def BNEG_W : BNEG_W_ENC, BNEG_W_DESC; -def BNEG_D : BNEG_D_ENC, BNEG_D_DESC; - -def BNEGI_B : BNEGI_B_ENC, BNEGI_B_DESC; -def BNEGI_H : BNEGI_H_ENC, BNEGI_H_DESC; -def BNEGI_W : BNEGI_W_ENC, BNEGI_W_DESC; -def BNEGI_D : BNEGI_D_ENC, BNEGI_D_DESC; - -def BNZ_B : BNZ_B_ENC, BNZ_B_DESC; -def BNZ_H : BNZ_H_ENC, BNZ_H_DESC; -def BNZ_W : BNZ_W_ENC, BNZ_W_DESC; -def BNZ_D : BNZ_D_ENC, BNZ_D_DESC; - -def BNZ_V : BNZ_V_ENC, BNZ_V_DESC; - -def BSEL_V : BSEL_V_ENC, BSEL_V_DESC; - -class MSA_BSEL_PSEUDO_BASE<RegisterOperand RO, ValueType Ty> : - MSAPseudo<(outs RO:$wd), (ins RO:$wd_in, RO:$ws, RO:$wt), - [(set RO:$wd, (Ty (vselect RO:$wd_in, RO:$wt, RO:$ws)))]>, - // Note that vselect and BSEL_V treat the condition operand the opposite way - // from each other. - // (vselect cond, if_set, if_clear) - // (BSEL_V cond, if_clear, if_set) - PseudoInstExpansion<(BSEL_V MSA128BOpnd:$wd, MSA128BOpnd:$wd_in, - MSA128BOpnd:$ws, MSA128BOpnd:$wt)> { - let Constraints = "$wd_in = $wd"; -} - -def BSEL_H_PSEUDO : MSA_BSEL_PSEUDO_BASE<MSA128HOpnd, v8i16>; -def BSEL_W_PSEUDO : MSA_BSEL_PSEUDO_BASE<MSA128WOpnd, v4i32>; -def BSEL_D_PSEUDO : MSA_BSEL_PSEUDO_BASE<MSA128DOpnd, v2i64>; -def BSEL_FW_PSEUDO : MSA_BSEL_PSEUDO_BASE<MSA128WOpnd, v4f32>; -def BSEL_FD_PSEUDO : MSA_BSEL_PSEUDO_BASE<MSA128DOpnd, v2f64>; - -def BSELI_B : BSELI_B_ENC, BSELI_B_DESC; - -def BSET_B : BSET_B_ENC, BSET_B_DESC; -def BSET_H : BSET_H_ENC, BSET_H_DESC; -def BSET_W : BSET_W_ENC, BSET_W_DESC; -def BSET_D : BSET_D_ENC, BSET_D_DESC; - -def BSETI_B : BSETI_B_ENC, BSETI_B_DESC; -def BSETI_H : BSETI_H_ENC, BSETI_H_DESC; -def BSETI_W : BSETI_W_ENC, BSETI_W_DESC; -def BSETI_D : BSETI_D_ENC, BSETI_D_DESC; - -def BZ_B : BZ_B_ENC, BZ_B_DESC; -def BZ_H : BZ_H_ENC, BZ_H_DESC; -def BZ_W : BZ_W_ENC, BZ_W_DESC; -def BZ_D : BZ_D_ENC, BZ_D_DESC; - -def BZ_V : BZ_V_ENC, BZ_V_DESC; - -def CEQ_B : CEQ_B_ENC, CEQ_B_DESC; -def CEQ_H : CEQ_H_ENC, CEQ_H_DESC; -def CEQ_W : CEQ_W_ENC, CEQ_W_DESC; -def CEQ_D : CEQ_D_ENC, CEQ_D_DESC; - -def CEQI_B : CEQI_B_ENC, CEQI_B_DESC; -def CEQI_H : CEQI_H_ENC, CEQI_H_DESC; -def CEQI_W : CEQI_W_ENC, CEQI_W_DESC; -def CEQI_D : CEQI_D_ENC, CEQI_D_DESC; - -def CFCMSA : CFCMSA_ENC, CFCMSA_DESC; - -def CLE_S_B : CLE_S_B_ENC, CLE_S_B_DESC; -def CLE_S_H : CLE_S_H_ENC, CLE_S_H_DESC; -def CLE_S_W : CLE_S_W_ENC, CLE_S_W_DESC; -def CLE_S_D : CLE_S_D_ENC, CLE_S_D_DESC; - -def CLE_U_B : CLE_U_B_ENC, CLE_U_B_DESC; -def CLE_U_H : CLE_U_H_ENC, CLE_U_H_DESC; -def CLE_U_W : CLE_U_W_ENC, CLE_U_W_DESC; -def CLE_U_D : CLE_U_D_ENC, CLE_U_D_DESC; - -def CLEI_S_B : CLEI_S_B_ENC, CLEI_S_B_DESC; -def CLEI_S_H : CLEI_S_H_ENC, CLEI_S_H_DESC; -def CLEI_S_W : CLEI_S_W_ENC, CLEI_S_W_DESC; -def CLEI_S_D : CLEI_S_D_ENC, CLEI_S_D_DESC; - -def CLEI_U_B : CLEI_U_B_ENC, CLEI_U_B_DESC; -def CLEI_U_H : CLEI_U_H_ENC, CLEI_U_H_DESC; -def CLEI_U_W : CLEI_U_W_ENC, CLEI_U_W_DESC; -def CLEI_U_D : CLEI_U_D_ENC, CLEI_U_D_DESC; - -def CLT_S_B : CLT_S_B_ENC, CLT_S_B_DESC; -def CLT_S_H : CLT_S_H_ENC, CLT_S_H_DESC; -def CLT_S_W : CLT_S_W_ENC, CLT_S_W_DESC; -def CLT_S_D : CLT_S_D_ENC, CLT_S_D_DESC; - -def CLT_U_B : CLT_U_B_ENC, CLT_U_B_DESC; -def CLT_U_H : CLT_U_H_ENC, CLT_U_H_DESC; -def CLT_U_W : CLT_U_W_ENC, CLT_U_W_DESC; -def CLT_U_D : CLT_U_D_ENC, CLT_U_D_DESC; - -def CLTI_S_B : CLTI_S_B_ENC, CLTI_S_B_DESC; -def CLTI_S_H : CLTI_S_H_ENC, CLTI_S_H_DESC; -def CLTI_S_W : CLTI_S_W_ENC, CLTI_S_W_DESC; -def CLTI_S_D : CLTI_S_D_ENC, CLTI_S_D_DESC; - -def CLTI_U_B : CLTI_U_B_ENC, CLTI_U_B_DESC; -def CLTI_U_H : CLTI_U_H_ENC, CLTI_U_H_DESC; -def CLTI_U_W : CLTI_U_W_ENC, CLTI_U_W_DESC; -def CLTI_U_D : CLTI_U_D_ENC, CLTI_U_D_DESC; - -def COPY_S_B : COPY_S_B_ENC, COPY_S_B_DESC; -def COPY_S_H : COPY_S_H_ENC, COPY_S_H_DESC; -def COPY_S_W : COPY_S_W_ENC, COPY_S_W_DESC; -def COPY_S_D : COPY_S_D_ENC, COPY_S_D_DESC, ASE_MSA64; - -def COPY_U_B : COPY_U_B_ENC, COPY_U_B_DESC; -def COPY_U_H : COPY_U_H_ENC, COPY_U_H_DESC; -def COPY_U_W : COPY_U_W_ENC, COPY_U_W_DESC, ASE_MSA64; - -def COPY_FW_PSEUDO : COPY_FW_PSEUDO_DESC; -def COPY_FD_PSEUDO : COPY_FD_PSEUDO_DESC; - -def CTCMSA : CTCMSA_ENC, CTCMSA_DESC; - -def DIV_S_B : DIV_S_B_ENC, DIV_S_B_DESC; -def DIV_S_H : DIV_S_H_ENC, DIV_S_H_DESC; -def DIV_S_W : DIV_S_W_ENC, DIV_S_W_DESC; -def DIV_S_D : DIV_S_D_ENC, DIV_S_D_DESC; - -def DIV_U_B : DIV_U_B_ENC, DIV_U_B_DESC; -def DIV_U_H : DIV_U_H_ENC, DIV_U_H_DESC; -def DIV_U_W : DIV_U_W_ENC, DIV_U_W_DESC; -def DIV_U_D : DIV_U_D_ENC, DIV_U_D_DESC; - -def DOTP_S_H : DOTP_S_H_ENC, DOTP_S_H_DESC; -def DOTP_S_W : DOTP_S_W_ENC, DOTP_S_W_DESC; -def DOTP_S_D : DOTP_S_D_ENC, DOTP_S_D_DESC; - -def DOTP_U_H : DOTP_U_H_ENC, DOTP_U_H_DESC; -def DOTP_U_W : DOTP_U_W_ENC, DOTP_U_W_DESC; -def DOTP_U_D : DOTP_U_D_ENC, DOTP_U_D_DESC; - -def DPADD_S_H : DPADD_S_H_ENC, DPADD_S_H_DESC; -def DPADD_S_W : DPADD_S_W_ENC, DPADD_S_W_DESC; -def DPADD_S_D : DPADD_S_D_ENC, DPADD_S_D_DESC; - -def DPADD_U_H : DPADD_U_H_ENC, DPADD_U_H_DESC; -def DPADD_U_W : DPADD_U_W_ENC, DPADD_U_W_DESC; -def DPADD_U_D : DPADD_U_D_ENC, DPADD_U_D_DESC; - -def DPSUB_S_H : DPSUB_S_H_ENC, DPSUB_S_H_DESC; -def DPSUB_S_W : DPSUB_S_W_ENC, DPSUB_S_W_DESC; -def DPSUB_S_D : DPSUB_S_D_ENC, DPSUB_S_D_DESC; - -def DPSUB_U_H : DPSUB_U_H_ENC, DPSUB_U_H_DESC; -def DPSUB_U_W : DPSUB_U_W_ENC, DPSUB_U_W_DESC; -def DPSUB_U_D : DPSUB_U_D_ENC, DPSUB_U_D_DESC; - -def FADD_W : FADD_W_ENC, FADD_W_DESC; -def FADD_D : FADD_D_ENC, FADD_D_DESC; - -def FCAF_W : FCAF_W_ENC, FCAF_W_DESC; -def FCAF_D : FCAF_D_ENC, FCAF_D_DESC; - -def FCEQ_W : FCEQ_W_ENC, FCEQ_W_DESC; -def FCEQ_D : FCEQ_D_ENC, FCEQ_D_DESC; - -def FCLE_W : FCLE_W_ENC, FCLE_W_DESC; -def FCLE_D : FCLE_D_ENC, FCLE_D_DESC; - -def FCLT_W : FCLT_W_ENC, FCLT_W_DESC; -def FCLT_D : FCLT_D_ENC, FCLT_D_DESC; - -def FCLASS_W : FCLASS_W_ENC, FCLASS_W_DESC; -def FCLASS_D : FCLASS_D_ENC, FCLASS_D_DESC; - -def FCNE_W : FCNE_W_ENC, FCNE_W_DESC; -def FCNE_D : FCNE_D_ENC, FCNE_D_DESC; - -def FCOR_W : FCOR_W_ENC, FCOR_W_DESC; -def FCOR_D : FCOR_D_ENC, FCOR_D_DESC; - -def FCUEQ_W : FCUEQ_W_ENC, FCUEQ_W_DESC; -def FCUEQ_D : FCUEQ_D_ENC, FCUEQ_D_DESC; - -def FCULE_W : FCULE_W_ENC, FCULE_W_DESC; -def FCULE_D : FCULE_D_ENC, FCULE_D_DESC; - -def FCULT_W : FCULT_W_ENC, FCULT_W_DESC; -def FCULT_D : FCULT_D_ENC, FCULT_D_DESC; - -def FCUN_W : FCUN_W_ENC, FCUN_W_DESC; -def FCUN_D : FCUN_D_ENC, FCUN_D_DESC; - -def FCUNE_W : FCUNE_W_ENC, FCUNE_W_DESC; -def FCUNE_D : FCUNE_D_ENC, FCUNE_D_DESC; - -def FDIV_W : FDIV_W_ENC, FDIV_W_DESC; -def FDIV_D : FDIV_D_ENC, FDIV_D_DESC; - -def FEXDO_H : FEXDO_H_ENC, FEXDO_H_DESC; -def FEXDO_W : FEXDO_W_ENC, FEXDO_W_DESC; - -def FEXP2_W : FEXP2_W_ENC, FEXP2_W_DESC; -def FEXP2_D : FEXP2_D_ENC, FEXP2_D_DESC; -def FEXP2_W_1_PSEUDO : FEXP2_W_1_PSEUDO_DESC; -def FEXP2_D_1_PSEUDO : FEXP2_D_1_PSEUDO_DESC; - -def FEXUPL_W : FEXUPL_W_ENC, FEXUPL_W_DESC; -def FEXUPL_D : FEXUPL_D_ENC, FEXUPL_D_DESC; - -def FEXUPR_W : FEXUPR_W_ENC, FEXUPR_W_DESC; -def FEXUPR_D : FEXUPR_D_ENC, FEXUPR_D_DESC; - -def FFINT_S_W : FFINT_S_W_ENC, FFINT_S_W_DESC; -def FFINT_S_D : FFINT_S_D_ENC, FFINT_S_D_DESC; - -def FFINT_U_W : FFINT_U_W_ENC, FFINT_U_W_DESC; -def FFINT_U_D : FFINT_U_D_ENC, FFINT_U_D_DESC; - -def FFQL_W : FFQL_W_ENC, FFQL_W_DESC; -def FFQL_D : FFQL_D_ENC, FFQL_D_DESC; - -def FFQR_W : FFQR_W_ENC, FFQR_W_DESC; -def FFQR_D : FFQR_D_ENC, FFQR_D_DESC; - -def FILL_B : FILL_B_ENC, FILL_B_DESC; -def FILL_H : FILL_H_ENC, FILL_H_DESC; -def FILL_W : FILL_W_ENC, FILL_W_DESC; -def FILL_D : FILL_D_ENC, FILL_D_DESC, ASE_MSA64; -def FILL_FW_PSEUDO : FILL_FW_PSEUDO_DESC; -def FILL_FD_PSEUDO : FILL_FD_PSEUDO_DESC; - -def FLOG2_W : FLOG2_W_ENC, FLOG2_W_DESC; -def FLOG2_D : FLOG2_D_ENC, FLOG2_D_DESC; - -def FMADD_W : FMADD_W_ENC, FMADD_W_DESC; -def FMADD_D : FMADD_D_ENC, FMADD_D_DESC; - -def FMAX_W : FMAX_W_ENC, FMAX_W_DESC; -def FMAX_D : FMAX_D_ENC, FMAX_D_DESC; - -def FMAX_A_W : FMAX_A_W_ENC, FMAX_A_W_DESC; -def FMAX_A_D : FMAX_A_D_ENC, FMAX_A_D_DESC; - -def FMIN_W : FMIN_W_ENC, FMIN_W_DESC; -def FMIN_D : FMIN_D_ENC, FMIN_D_DESC; - -def FMIN_A_W : FMIN_A_W_ENC, FMIN_A_W_DESC; -def FMIN_A_D : FMIN_A_D_ENC, FMIN_A_D_DESC; - -def FMSUB_W : FMSUB_W_ENC, FMSUB_W_DESC; -def FMSUB_D : FMSUB_D_ENC, FMSUB_D_DESC; - -def FMUL_W : FMUL_W_ENC, FMUL_W_DESC; -def FMUL_D : FMUL_D_ENC, FMUL_D_DESC; - -def FRINT_W : FRINT_W_ENC, FRINT_W_DESC; -def FRINT_D : FRINT_D_ENC, FRINT_D_DESC; - -def FRCP_W : FRCP_W_ENC, FRCP_W_DESC; -def FRCP_D : FRCP_D_ENC, FRCP_D_DESC; - -def FRSQRT_W : FRSQRT_W_ENC, FRSQRT_W_DESC; -def FRSQRT_D : FRSQRT_D_ENC, FRSQRT_D_DESC; - -def FSAF_W : FSAF_W_ENC, FSAF_W_DESC; -def FSAF_D : FSAF_D_ENC, FSAF_D_DESC; - -def FSEQ_W : FSEQ_W_ENC, FSEQ_W_DESC; -def FSEQ_D : FSEQ_D_ENC, FSEQ_D_DESC; - -def FSLE_W : FSLE_W_ENC, FSLE_W_DESC; -def FSLE_D : FSLE_D_ENC, FSLE_D_DESC; - -def FSLT_W : FSLT_W_ENC, FSLT_W_DESC; -def FSLT_D : FSLT_D_ENC, FSLT_D_DESC; - -def FSNE_W : FSNE_W_ENC, FSNE_W_DESC; -def FSNE_D : FSNE_D_ENC, FSNE_D_DESC; - -def FSOR_W : FSOR_W_ENC, FSOR_W_DESC; -def FSOR_D : FSOR_D_ENC, FSOR_D_DESC; - -def FSQRT_W : FSQRT_W_ENC, FSQRT_W_DESC; -def FSQRT_D : FSQRT_D_ENC, FSQRT_D_DESC; - -def FSUB_W : FSUB_W_ENC, FSUB_W_DESC; -def FSUB_D : FSUB_D_ENC, FSUB_D_DESC; - -def FSUEQ_W : FSUEQ_W_ENC, FSUEQ_W_DESC; -def FSUEQ_D : FSUEQ_D_ENC, FSUEQ_D_DESC; - -def FSULE_W : FSULE_W_ENC, FSULE_W_DESC; -def FSULE_D : FSULE_D_ENC, FSULE_D_DESC; - -def FSULT_W : FSULT_W_ENC, FSULT_W_DESC; -def FSULT_D : FSULT_D_ENC, FSULT_D_DESC; - -def FSUN_W : FSUN_W_ENC, FSUN_W_DESC; -def FSUN_D : FSUN_D_ENC, FSUN_D_DESC; - -def FSUNE_W : FSUNE_W_ENC, FSUNE_W_DESC; -def FSUNE_D : FSUNE_D_ENC, FSUNE_D_DESC; - -def FTINT_S_W : FTINT_S_W_ENC, FTINT_S_W_DESC; -def FTINT_S_D : FTINT_S_D_ENC, FTINT_S_D_DESC; - -def FTINT_U_W : FTINT_U_W_ENC, FTINT_U_W_DESC; -def FTINT_U_D : FTINT_U_D_ENC, FTINT_U_D_DESC; - -def FTQ_H : FTQ_H_ENC, FTQ_H_DESC; -def FTQ_W : FTQ_W_ENC, FTQ_W_DESC; - -def FTRUNC_S_W : FTRUNC_S_W_ENC, FTRUNC_S_W_DESC; -def FTRUNC_S_D : FTRUNC_S_D_ENC, FTRUNC_S_D_DESC; - -def FTRUNC_U_W : FTRUNC_U_W_ENC, FTRUNC_U_W_DESC; -def FTRUNC_U_D : FTRUNC_U_D_ENC, FTRUNC_U_D_DESC; - -def : MipsPat<(fsub MSA128WOpnd:$wd, (fmul MSA128WOpnd:$ws, MSA128WOpnd:$wt)), - (FMSUB_W MSA128WOpnd:$wd, MSA128WOpnd:$ws, MSA128WOpnd:$wt)>, - ISA_MIPS1, ASE_MSA, FPOP_FUSION_FAST; -def : MipsPat<(fsub MSA128DOpnd:$wd, (fmul MSA128DOpnd:$ws, MSA128DOpnd:$wt)), - (FMSUB_D MSA128DOpnd:$wd, MSA128DOpnd:$ws, MSA128DOpnd:$wt)>, - ISA_MIPS1, ASE_MSA, FPOP_FUSION_FAST; - -def : MipsPat<(fadd MSA128WOpnd:$wd, (fmul MSA128WOpnd:$ws, MSA128WOpnd:$wt)), - (FMADD_W MSA128WOpnd:$wd, MSA128WOpnd:$ws, MSA128WOpnd:$wt)>, - ISA_MIPS1, ASE_MSA, FPOP_FUSION_FAST; -def : MipsPat<(fadd MSA128DOpnd:$wd, (fmul MSA128DOpnd:$ws, MSA128DOpnd:$wt)), - (FMADD_D MSA128DOpnd:$wd, MSA128DOpnd:$ws, MSA128DOpnd:$wt)>, - ISA_MIPS1, ASE_MSA, FPOP_FUSION_FAST; - -def HADD_S_H : HADD_S_H_ENC, HADD_S_H_DESC; -def HADD_S_W : HADD_S_W_ENC, HADD_S_W_DESC; -def HADD_S_D : HADD_S_D_ENC, HADD_S_D_DESC; - -def HADD_U_H : HADD_U_H_ENC, HADD_U_H_DESC; -def HADD_U_W : HADD_U_W_ENC, HADD_U_W_DESC; -def HADD_U_D : HADD_U_D_ENC, HADD_U_D_DESC; - -def HSUB_S_H : HSUB_S_H_ENC, HSUB_S_H_DESC; -def HSUB_S_W : HSUB_S_W_ENC, HSUB_S_W_DESC; -def HSUB_S_D : HSUB_S_D_ENC, HSUB_S_D_DESC; - -def HSUB_U_H : HSUB_U_H_ENC, HSUB_U_H_DESC; -def HSUB_U_W : HSUB_U_W_ENC, HSUB_U_W_DESC; -def HSUB_U_D : HSUB_U_D_ENC, HSUB_U_D_DESC; - -def ILVEV_B : ILVEV_B_ENC, ILVEV_B_DESC; -def ILVEV_H : ILVEV_H_ENC, ILVEV_H_DESC; -def ILVEV_W : ILVEV_W_ENC, ILVEV_W_DESC; -def ILVEV_D : ILVEV_D_ENC, ILVEV_D_DESC; - -def ILVL_B : ILVL_B_ENC, ILVL_B_DESC; -def ILVL_H : ILVL_H_ENC, ILVL_H_DESC; -def ILVL_W : ILVL_W_ENC, ILVL_W_DESC; -def ILVL_D : ILVL_D_ENC, ILVL_D_DESC; - -def ILVOD_B : ILVOD_B_ENC, ILVOD_B_DESC; -def ILVOD_H : ILVOD_H_ENC, ILVOD_H_DESC; -def ILVOD_W : ILVOD_W_ENC, ILVOD_W_DESC; -def ILVOD_D : ILVOD_D_ENC, ILVOD_D_DESC; - -def ILVR_B : ILVR_B_ENC, ILVR_B_DESC; -def ILVR_H : ILVR_H_ENC, ILVR_H_DESC; -def ILVR_W : ILVR_W_ENC, ILVR_W_DESC; -def ILVR_D : ILVR_D_ENC, ILVR_D_DESC; - -def INSERT_B : INSERT_B_ENC, INSERT_B_DESC; -def INSERT_H : INSERT_H_ENC, INSERT_H_DESC; -def INSERT_W : INSERT_W_ENC, INSERT_W_DESC; -def INSERT_D : INSERT_D_ENC, INSERT_D_DESC, ASE_MSA64; - -// INSERT_FW_PSEUDO defined after INSVE_W -// INSERT_FD_PSEUDO defined after INSVE_D - -// There is a fourth operand that is not present in the encoding. Use a -// custom decoder to get a chance to add it. -let DecoderMethod = "DecodeINSVE_DF" in { - def INSVE_B : INSVE_B_ENC, INSVE_B_DESC; - def INSVE_H : INSVE_H_ENC, INSVE_H_DESC; - def INSVE_W : INSVE_W_ENC, INSVE_W_DESC; - def INSVE_D : INSVE_D_ENC, INSVE_D_DESC; -} - -def INSERT_FW_PSEUDO : INSERT_FW_PSEUDO_DESC; -def INSERT_FD_PSEUDO : INSERT_FD_PSEUDO_DESC; - -def INSERT_B_VIDX_PSEUDO : INSERT_B_VIDX_PSEUDO_DESC; -def INSERT_H_VIDX_PSEUDO : INSERT_H_VIDX_PSEUDO_DESC; -def INSERT_W_VIDX_PSEUDO : INSERT_W_VIDX_PSEUDO_DESC; -def INSERT_D_VIDX_PSEUDO : INSERT_D_VIDX_PSEUDO_DESC; -def INSERT_FW_VIDX_PSEUDO : INSERT_FW_VIDX_PSEUDO_DESC; -def INSERT_FD_VIDX_PSEUDO : INSERT_FD_VIDX_PSEUDO_DESC; - -def INSERT_B_VIDX64_PSEUDO : INSERT_B_VIDX64_PSEUDO_DESC; -def INSERT_H_VIDX64_PSEUDO : INSERT_H_VIDX64_PSEUDO_DESC; -def INSERT_W_VIDX64_PSEUDO : INSERT_W_VIDX64_PSEUDO_DESC; -def INSERT_D_VIDX64_PSEUDO : INSERT_D_VIDX64_PSEUDO_DESC; -def INSERT_FW_VIDX64_PSEUDO : INSERT_FW_VIDX64_PSEUDO_DESC; -def INSERT_FD_VIDX64_PSEUDO : INSERT_FD_VIDX64_PSEUDO_DESC; - -def LD_B: LD_B_ENC, LD_B_DESC; -def LD_H: LD_H_ENC, LD_H_DESC; -def LD_W: LD_W_ENC, LD_W_DESC; -def LD_D: LD_D_ENC, LD_D_DESC; - -def LDI_B : LDI_B_ENC, LDI_B_DESC; -def LDI_H : LDI_H_ENC, LDI_H_DESC; -def LDI_W : LDI_W_ENC, LDI_W_DESC; -def LDI_D : LDI_D_ENC, LDI_D_DESC; - -def LSA : LSA_ENC, LSA_DESC; -def DLSA : DLSA_ENC, DLSA_DESC, ASE_MSA64; - -def MADD_Q_H : MADD_Q_H_ENC, MADD_Q_H_DESC; -def MADD_Q_W : MADD_Q_W_ENC, MADD_Q_W_DESC; - -def MADDR_Q_H : MADDR_Q_H_ENC, MADDR_Q_H_DESC; -def MADDR_Q_W : MADDR_Q_W_ENC, MADDR_Q_W_DESC; - -def MADDV_B : MADDV_B_ENC, MADDV_B_DESC; -def MADDV_H : MADDV_H_ENC, MADDV_H_DESC; -def MADDV_W : MADDV_W_ENC, MADDV_W_DESC; -def MADDV_D : MADDV_D_ENC, MADDV_D_DESC; - -def MAX_A_B : MAX_A_B_ENC, MAX_A_B_DESC; -def MAX_A_H : MAX_A_H_ENC, MAX_A_H_DESC; -def MAX_A_W : MAX_A_W_ENC, MAX_A_W_DESC; -def MAX_A_D : MAX_A_D_ENC, MAX_A_D_DESC; - -def MAX_S_B : MAX_S_B_ENC, MAX_S_B_DESC; -def MAX_S_H : MAX_S_H_ENC, MAX_S_H_DESC; -def MAX_S_W : MAX_S_W_ENC, MAX_S_W_DESC; -def MAX_S_D : MAX_S_D_ENC, MAX_S_D_DESC; - -def MAX_U_B : MAX_U_B_ENC, MAX_U_B_DESC; -def MAX_U_H : MAX_U_H_ENC, MAX_U_H_DESC; -def MAX_U_W : MAX_U_W_ENC, MAX_U_W_DESC; -def MAX_U_D : MAX_U_D_ENC, MAX_U_D_DESC; - -def MAXI_S_B : MAXI_S_B_ENC, MAXI_S_B_DESC; -def MAXI_S_H : MAXI_S_H_ENC, MAXI_S_H_DESC; -def MAXI_S_W : MAXI_S_W_ENC, MAXI_S_W_DESC; -def MAXI_S_D : MAXI_S_D_ENC, MAXI_S_D_DESC; - -def MAXI_U_B : MAXI_U_B_ENC, MAXI_U_B_DESC; -def MAXI_U_H : MAXI_U_H_ENC, MAXI_U_H_DESC; -def MAXI_U_W : MAXI_U_W_ENC, MAXI_U_W_DESC; -def MAXI_U_D : MAXI_U_D_ENC, MAXI_U_D_DESC; - -def MIN_A_B : MIN_A_B_ENC, MIN_A_B_DESC; -def MIN_A_H : MIN_A_H_ENC, MIN_A_H_DESC; -def MIN_A_W : MIN_A_W_ENC, MIN_A_W_DESC; -def MIN_A_D : MIN_A_D_ENC, MIN_A_D_DESC; - -def MIN_S_B : MIN_S_B_ENC, MIN_S_B_DESC; -def MIN_S_H : MIN_S_H_ENC, MIN_S_H_DESC; -def MIN_S_W : MIN_S_W_ENC, MIN_S_W_DESC; -def MIN_S_D : MIN_S_D_ENC, MIN_S_D_DESC; - -def MIN_U_B : MIN_U_B_ENC, MIN_U_B_DESC; -def MIN_U_H : MIN_U_H_ENC, MIN_U_H_DESC; -def MIN_U_W : MIN_U_W_ENC, MIN_U_W_DESC; -def MIN_U_D : MIN_U_D_ENC, MIN_U_D_DESC; - -def MINI_S_B : MINI_S_B_ENC, MINI_S_B_DESC; -def MINI_S_H : MINI_S_H_ENC, MINI_S_H_DESC; -def MINI_S_W : MINI_S_W_ENC, MINI_S_W_DESC; -def MINI_S_D : MINI_S_D_ENC, MINI_S_D_DESC; - -def MINI_U_B : MINI_U_B_ENC, MINI_U_B_DESC; -def MINI_U_H : MINI_U_H_ENC, MINI_U_H_DESC; -def MINI_U_W : MINI_U_W_ENC, MINI_U_W_DESC; -def MINI_U_D : MINI_U_D_ENC, MINI_U_D_DESC; - -def MOD_S_B : MOD_S_B_ENC, MOD_S_B_DESC; -def MOD_S_H : MOD_S_H_ENC, MOD_S_H_DESC; -def MOD_S_W : MOD_S_W_ENC, MOD_S_W_DESC; -def MOD_S_D : MOD_S_D_ENC, MOD_S_D_DESC; - -def MOD_U_B : MOD_U_B_ENC, MOD_U_B_DESC; -def MOD_U_H : MOD_U_H_ENC, MOD_U_H_DESC; -def MOD_U_W : MOD_U_W_ENC, MOD_U_W_DESC; -def MOD_U_D : MOD_U_D_ENC, MOD_U_D_DESC; - -def MOVE_V : MOVE_V_ENC, MOVE_V_DESC; - -def MSUB_Q_H : MSUB_Q_H_ENC, MSUB_Q_H_DESC; -def MSUB_Q_W : MSUB_Q_W_ENC, MSUB_Q_W_DESC; - -def MSUBR_Q_H : MSUBR_Q_H_ENC, MSUBR_Q_H_DESC; -def MSUBR_Q_W : MSUBR_Q_W_ENC, MSUBR_Q_W_DESC; - -def MSUBV_B : MSUBV_B_ENC, MSUBV_B_DESC; -def MSUBV_H : MSUBV_H_ENC, MSUBV_H_DESC; -def MSUBV_W : MSUBV_W_ENC, MSUBV_W_DESC; -def MSUBV_D : MSUBV_D_ENC, MSUBV_D_DESC; - -def MUL_Q_H : MUL_Q_H_ENC, MUL_Q_H_DESC; -def MUL_Q_W : MUL_Q_W_ENC, MUL_Q_W_DESC; - -def MULR_Q_H : MULR_Q_H_ENC, MULR_Q_H_DESC; -def MULR_Q_W : MULR_Q_W_ENC, MULR_Q_W_DESC; - -def MULV_B : MULV_B_ENC, MULV_B_DESC; -def MULV_H : MULV_H_ENC, MULV_H_DESC; -def MULV_W : MULV_W_ENC, MULV_W_DESC; -def MULV_D : MULV_D_ENC, MULV_D_DESC; - -def NLOC_B : NLOC_B_ENC, NLOC_B_DESC; -def NLOC_H : NLOC_H_ENC, NLOC_H_DESC; -def NLOC_W : NLOC_W_ENC, NLOC_W_DESC; -def NLOC_D : NLOC_D_ENC, NLOC_D_DESC; - -def NLZC_B : NLZC_B_ENC, NLZC_B_DESC; -def NLZC_H : NLZC_H_ENC, NLZC_H_DESC; -def NLZC_W : NLZC_W_ENC, NLZC_W_DESC; -def NLZC_D : NLZC_D_ENC, NLZC_D_DESC; - -def NOR_V : NOR_V_ENC, NOR_V_DESC; -def NOR_V_H_PSEUDO : NOR_V_H_PSEUDO_DESC, - PseudoInstExpansion<(NOR_V MSA128BOpnd:$wd, - MSA128BOpnd:$ws, - MSA128BOpnd:$wt)>; -def NOR_V_W_PSEUDO : NOR_V_W_PSEUDO_DESC, - PseudoInstExpansion<(NOR_V MSA128BOpnd:$wd, - MSA128BOpnd:$ws, - MSA128BOpnd:$wt)>; -def NOR_V_D_PSEUDO : NOR_V_D_PSEUDO_DESC, - PseudoInstExpansion<(NOR_V MSA128BOpnd:$wd, - MSA128BOpnd:$ws, - MSA128BOpnd:$wt)>; - -def NORI_B : NORI_B_ENC, NORI_B_DESC; - -def OR_V : OR_V_ENC, OR_V_DESC; -def OR_V_H_PSEUDO : OR_V_H_PSEUDO_DESC, - PseudoInstExpansion<(OR_V MSA128BOpnd:$wd, - MSA128BOpnd:$ws, - MSA128BOpnd:$wt)>; -def OR_V_W_PSEUDO : OR_V_W_PSEUDO_DESC, - PseudoInstExpansion<(OR_V MSA128BOpnd:$wd, - MSA128BOpnd:$ws, - MSA128BOpnd:$wt)>; -def OR_V_D_PSEUDO : OR_V_D_PSEUDO_DESC, - PseudoInstExpansion<(OR_V MSA128BOpnd:$wd, - MSA128BOpnd:$ws, - MSA128BOpnd:$wt)>; - -def ORI_B : ORI_B_ENC, ORI_B_DESC; - -def PCKEV_B : PCKEV_B_ENC, PCKEV_B_DESC; -def PCKEV_H : PCKEV_H_ENC, PCKEV_H_DESC; -def PCKEV_W : PCKEV_W_ENC, PCKEV_W_DESC; -def PCKEV_D : PCKEV_D_ENC, PCKEV_D_DESC; - -def PCKOD_B : PCKOD_B_ENC, PCKOD_B_DESC; -def PCKOD_H : PCKOD_H_ENC, PCKOD_H_DESC; -def PCKOD_W : PCKOD_W_ENC, PCKOD_W_DESC; -def PCKOD_D : PCKOD_D_ENC, PCKOD_D_DESC; - -def PCNT_B : PCNT_B_ENC, PCNT_B_DESC; -def PCNT_H : PCNT_H_ENC, PCNT_H_DESC; -def PCNT_W : PCNT_W_ENC, PCNT_W_DESC; -def PCNT_D : PCNT_D_ENC, PCNT_D_DESC; - -def SAT_S_B : SAT_S_B_ENC, SAT_S_B_DESC; -def SAT_S_H : SAT_S_H_ENC, SAT_S_H_DESC; -def SAT_S_W : SAT_S_W_ENC, SAT_S_W_DESC; -def SAT_S_D : SAT_S_D_ENC, SAT_S_D_DESC; - -def SAT_U_B : SAT_U_B_ENC, SAT_U_B_DESC; -def SAT_U_H : SAT_U_H_ENC, SAT_U_H_DESC; -def SAT_U_W : SAT_U_W_ENC, SAT_U_W_DESC; -def SAT_U_D : SAT_U_D_ENC, SAT_U_D_DESC; - -def SHF_B : SHF_B_ENC, SHF_B_DESC; -def SHF_H : SHF_H_ENC, SHF_H_DESC; -def SHF_W : SHF_W_ENC, SHF_W_DESC; - -def SLD_B : SLD_B_ENC, SLD_B_DESC; -def SLD_H : SLD_H_ENC, SLD_H_DESC; -def SLD_W : SLD_W_ENC, SLD_W_DESC; -def SLD_D : SLD_D_ENC, SLD_D_DESC; - -def SLDI_B : SLDI_B_ENC, SLDI_B_DESC; -def SLDI_H : SLDI_H_ENC, SLDI_H_DESC; -def SLDI_W : SLDI_W_ENC, SLDI_W_DESC; -def SLDI_D : SLDI_D_ENC, SLDI_D_DESC; - -def SLL_B : SLL_B_ENC, SLL_B_DESC; -def SLL_H : SLL_H_ENC, SLL_H_DESC; -def SLL_W : SLL_W_ENC, SLL_W_DESC; -def SLL_D : SLL_D_ENC, SLL_D_DESC; - -def SLLI_B : SLLI_B_ENC, SLLI_B_DESC; -def SLLI_H : SLLI_H_ENC, SLLI_H_DESC; -def SLLI_W : SLLI_W_ENC, SLLI_W_DESC; -def SLLI_D : SLLI_D_ENC, SLLI_D_DESC; - -def SPLAT_B : SPLAT_B_ENC, SPLAT_B_DESC; -def SPLAT_H : SPLAT_H_ENC, SPLAT_H_DESC; -def SPLAT_W : SPLAT_W_ENC, SPLAT_W_DESC; -def SPLAT_D : SPLAT_D_ENC, SPLAT_D_DESC; - -def SPLATI_B : SPLATI_B_ENC, SPLATI_B_DESC; -def SPLATI_H : SPLATI_H_ENC, SPLATI_H_DESC; -def SPLATI_W : SPLATI_W_ENC, SPLATI_W_DESC; -def SPLATI_D : SPLATI_D_ENC, SPLATI_D_DESC; - -def SRA_B : SRA_B_ENC, SRA_B_DESC; -def SRA_H : SRA_H_ENC, SRA_H_DESC; -def SRA_W : SRA_W_ENC, SRA_W_DESC; -def SRA_D : SRA_D_ENC, SRA_D_DESC; - -def SRAI_B : SRAI_B_ENC, SRAI_B_DESC; -def SRAI_H : SRAI_H_ENC, SRAI_H_DESC; -def SRAI_W : SRAI_W_ENC, SRAI_W_DESC; -def SRAI_D : SRAI_D_ENC, SRAI_D_DESC; - -def SRAR_B : SRAR_B_ENC, SRAR_B_DESC; -def SRAR_H : SRAR_H_ENC, SRAR_H_DESC; -def SRAR_W : SRAR_W_ENC, SRAR_W_DESC; -def SRAR_D : SRAR_D_ENC, SRAR_D_DESC; - -def SRARI_B : SRARI_B_ENC, SRARI_B_DESC; -def SRARI_H : SRARI_H_ENC, SRARI_H_DESC; -def SRARI_W : SRARI_W_ENC, SRARI_W_DESC; -def SRARI_D : SRARI_D_ENC, SRARI_D_DESC; - -def SRL_B : SRL_B_ENC, SRL_B_DESC; -def SRL_H : SRL_H_ENC, SRL_H_DESC; -def SRL_W : SRL_W_ENC, SRL_W_DESC; -def SRL_D : SRL_D_ENC, SRL_D_DESC; - -def SRLI_B : SRLI_B_ENC, SRLI_B_DESC; -def SRLI_H : SRLI_H_ENC, SRLI_H_DESC; -def SRLI_W : SRLI_W_ENC, SRLI_W_DESC; -def SRLI_D : SRLI_D_ENC, SRLI_D_DESC; - -def SRLR_B : SRLR_B_ENC, SRLR_B_DESC; -def SRLR_H : SRLR_H_ENC, SRLR_H_DESC; -def SRLR_W : SRLR_W_ENC, SRLR_W_DESC; -def SRLR_D : SRLR_D_ENC, SRLR_D_DESC; - -def SRLRI_B : SRLRI_B_ENC, SRLRI_B_DESC; -def SRLRI_H : SRLRI_H_ENC, SRLRI_H_DESC; -def SRLRI_W : SRLRI_W_ENC, SRLRI_W_DESC; -def SRLRI_D : SRLRI_D_ENC, SRLRI_D_DESC; - -def ST_B: ST_B_ENC, ST_B_DESC; -def ST_H: ST_H_ENC, ST_H_DESC; -def ST_W: ST_W_ENC, ST_W_DESC; -def ST_D: ST_D_ENC, ST_D_DESC; - -def SUBS_S_B : SUBS_S_B_ENC, SUBS_S_B_DESC; -def SUBS_S_H : SUBS_S_H_ENC, SUBS_S_H_DESC; -def SUBS_S_W : SUBS_S_W_ENC, SUBS_S_W_DESC; -def SUBS_S_D : SUBS_S_D_ENC, SUBS_S_D_DESC; - -def SUBS_U_B : SUBS_U_B_ENC, SUBS_U_B_DESC; -def SUBS_U_H : SUBS_U_H_ENC, SUBS_U_H_DESC; -def SUBS_U_W : SUBS_U_W_ENC, SUBS_U_W_DESC; -def SUBS_U_D : SUBS_U_D_ENC, SUBS_U_D_DESC; - -def SUBSUS_U_B : SUBSUS_U_B_ENC, SUBSUS_U_B_DESC; -def SUBSUS_U_H : SUBSUS_U_H_ENC, SUBSUS_U_H_DESC; -def SUBSUS_U_W : SUBSUS_U_W_ENC, SUBSUS_U_W_DESC; -def SUBSUS_U_D : SUBSUS_U_D_ENC, SUBSUS_U_D_DESC; - -def SUBSUU_S_B : SUBSUU_S_B_ENC, SUBSUU_S_B_DESC; -def SUBSUU_S_H : SUBSUU_S_H_ENC, SUBSUU_S_H_DESC; -def SUBSUU_S_W : SUBSUU_S_W_ENC, SUBSUU_S_W_DESC; -def SUBSUU_S_D : SUBSUU_S_D_ENC, SUBSUU_S_D_DESC; - -def SUBV_B : SUBV_B_ENC, SUBV_B_DESC; -def SUBV_H : SUBV_H_ENC, SUBV_H_DESC; -def SUBV_W : SUBV_W_ENC, SUBV_W_DESC; -def SUBV_D : SUBV_D_ENC, SUBV_D_DESC; - -def SUBVI_B : SUBVI_B_ENC, SUBVI_B_DESC; -def SUBVI_H : SUBVI_H_ENC, SUBVI_H_DESC; -def SUBVI_W : SUBVI_W_ENC, SUBVI_W_DESC; -def SUBVI_D : SUBVI_D_ENC, SUBVI_D_DESC; - -def VSHF_B : VSHF_B_ENC, VSHF_B_DESC; -def VSHF_H : VSHF_H_ENC, VSHF_H_DESC; -def VSHF_W : VSHF_W_ENC, VSHF_W_DESC; -def VSHF_D : VSHF_D_ENC, VSHF_D_DESC; - -def XOR_V : XOR_V_ENC, XOR_V_DESC; -def XOR_V_H_PSEUDO : XOR_V_H_PSEUDO_DESC, - PseudoInstExpansion<(XOR_V MSA128BOpnd:$wd, - MSA128BOpnd:$ws, - MSA128BOpnd:$wt)>; -def XOR_V_W_PSEUDO : XOR_V_W_PSEUDO_DESC, - PseudoInstExpansion<(XOR_V MSA128BOpnd:$wd, - MSA128BOpnd:$ws, - MSA128BOpnd:$wt)>; -def XOR_V_D_PSEUDO : XOR_V_D_PSEUDO_DESC, - PseudoInstExpansion<(XOR_V MSA128BOpnd:$wd, - MSA128BOpnd:$ws, - MSA128BOpnd:$wt)>; - -def XORI_B : XORI_B_ENC, XORI_B_DESC; - -// Patterns. -class MSAPat<dag pattern, dag result, list<Predicate> pred = [HasMSA]> : - Pat<pattern, result>, Requires<pred>; - -def : MSAPat<(extractelt (v4i32 MSA128W:$ws), immZExt4:$idx), - (COPY_S_W MSA128W:$ws, immZExt4:$idx)>; - -def : MSAPat<(v8f16 (load addrimm10lsl1:$addr)), (LD_H addrimm10lsl1:$addr)>; -def : MSAPat<(v4f32 (load addrimm10lsl2:$addr)), (LD_W addrimm10lsl2:$addr)>; -def : MSAPat<(v2f64 (load addrimm10lsl3:$addr)), (LD_D addrimm10lsl3:$addr)>; - -def ST_FH : MSAPat<(store (v8f16 MSA128H:$ws), addrimm10lsl1:$addr), - (ST_H MSA128H:$ws, addrimm10lsl1:$addr)>; -def ST_FW : MSAPat<(store (v4f32 MSA128W:$ws), addrimm10lsl2:$addr), - (ST_W MSA128W:$ws, addrimm10lsl2:$addr)>; -def ST_FD : MSAPat<(store (v2f64 MSA128D:$ws), addrimm10lsl3:$addr), - (ST_D MSA128D:$ws, addrimm10lsl3:$addr)>; - -class MSA_FABS_PSEUDO_DESC_BASE<RegisterOperand ROWD, - RegisterOperand ROWS = ROWD, - InstrItinClass itin = NoItinerary> : - MSAPseudo<(outs ROWD:$wd), - (ins ROWS:$ws), - [(set ROWD:$wd, (fabs ROWS:$ws))]> { - InstrItinClass Itinerary = itin; -} -def FABS_W : MSA_FABS_PSEUDO_DESC_BASE<MSA128WOpnd>, - PseudoInstExpansion<(FMAX_A_W MSA128WOpnd:$wd, MSA128WOpnd:$ws, - MSA128WOpnd:$ws)>; -def FABS_D : MSA_FABS_PSEUDO_DESC_BASE<MSA128DOpnd>, - PseudoInstExpansion<(FMAX_A_D MSA128DOpnd:$wd, MSA128DOpnd:$ws, - MSA128DOpnd:$ws)>; - -class MSABitconvertPat<ValueType DstVT, ValueType SrcVT, - RegisterClass DstRC, list<Predicate> preds = [HasMSA]> : - MSAPat<(DstVT (bitconvert SrcVT:$src)), - (COPY_TO_REGCLASS SrcVT:$src, DstRC), preds>; - -// These are endian-independent because the element size doesnt change -def : MSABitconvertPat<v8i16, v8f16, MSA128H>; -def : MSABitconvertPat<v4i32, v4f32, MSA128W>; -def : MSABitconvertPat<v2i64, v2f64, MSA128D>; -def : MSABitconvertPat<v8f16, v8i16, MSA128H>; -def : MSABitconvertPat<v4f32, v4i32, MSA128W>; -def : MSABitconvertPat<v2f64, v2i64, MSA128D>; - -// Little endian bitcasts are always no-ops -def : MSABitconvertPat<v16i8, v8i16, MSA128B, [HasMSA, IsLE]>; -def : MSABitconvertPat<v16i8, v4i32, MSA128B, [HasMSA, IsLE]>; -def : MSABitconvertPat<v16i8, v2i64, MSA128B, [HasMSA, IsLE]>; -def : MSABitconvertPat<v16i8, v8f16, MSA128B, [HasMSA, IsLE]>; -def : MSABitconvertPat<v16i8, v4f32, MSA128B, [HasMSA, IsLE]>; -def : MSABitconvertPat<v16i8, v2f64, MSA128B, [HasMSA, IsLE]>; - -def : MSABitconvertPat<v8i16, v16i8, MSA128H, [HasMSA, IsLE]>; -def : MSABitconvertPat<v8i16, v4i32, MSA128H, [HasMSA, IsLE]>; -def : MSABitconvertPat<v8i16, v2i64, MSA128H, [HasMSA, IsLE]>; -def : MSABitconvertPat<v8i16, v4f32, MSA128H, [HasMSA, IsLE]>; -def : MSABitconvertPat<v8i16, v2f64, MSA128H, [HasMSA, IsLE]>; - -def : MSABitconvertPat<v4i32, v16i8, MSA128W, [HasMSA, IsLE]>; -def : MSABitconvertPat<v4i32, v8i16, MSA128W, [HasMSA, IsLE]>; -def : MSABitconvertPat<v4i32, v2i64, MSA128W, [HasMSA, IsLE]>; -def : MSABitconvertPat<v4i32, v8f16, MSA128W, [HasMSA, IsLE]>; -def : MSABitconvertPat<v4i32, v2f64, MSA128W, [HasMSA, IsLE]>; - -def : MSABitconvertPat<v2i64, v16i8, MSA128D, [HasMSA, IsLE]>; -def : MSABitconvertPat<v2i64, v8i16, MSA128D, [HasMSA, IsLE]>; -def : MSABitconvertPat<v2i64, v4i32, MSA128D, [HasMSA, IsLE]>; -def : MSABitconvertPat<v2i64, v8f16, MSA128D, [HasMSA, IsLE]>; -def : MSABitconvertPat<v2i64, v4f32, MSA128D, [HasMSA, IsLE]>; - -def : MSABitconvertPat<v4f32, v16i8, MSA128W, [HasMSA, IsLE]>; -def : MSABitconvertPat<v4f32, v8i16, MSA128W, [HasMSA, IsLE]>; -def : MSABitconvertPat<v4f32, v2i64, MSA128W, [HasMSA, IsLE]>; -def : MSABitconvertPat<v4f32, v8f16, MSA128W, [HasMSA, IsLE]>; -def : MSABitconvertPat<v4f32, v2f64, MSA128W, [HasMSA, IsLE]>; - -def : MSABitconvertPat<v2f64, v16i8, MSA128D, [HasMSA, IsLE]>; -def : MSABitconvertPat<v2f64, v8i16, MSA128D, [HasMSA, IsLE]>; -def : MSABitconvertPat<v2f64, v4i32, MSA128D, [HasMSA, IsLE]>; -def : MSABitconvertPat<v2f64, v8f16, MSA128D, [HasMSA, IsLE]>; -def : MSABitconvertPat<v2f64, v4f32, MSA128D, [HasMSA, IsLE]>; - -// Big endian bitcasts expand to shuffle instructions. -// This is because bitcast is defined to be a store/load sequence and the -// vector store/load instructions are mixed-endian with respect to the vector -// as a whole (little endian with respect to element order, but big endian -// elements). - -class MSABitconvertReverseQuartersPat<ValueType DstVT, ValueType SrcVT, - RegisterClass DstRC, MSAInst Insn, - RegisterClass ViaRC> : - MSAPat<(DstVT (bitconvert SrcVT:$src)), - (COPY_TO_REGCLASS (Insn (COPY_TO_REGCLASS SrcVT:$src, ViaRC), 27), - DstRC), - [HasMSA, IsBE]>; - -class MSABitconvertReverseHalvesPat<ValueType DstVT, ValueType SrcVT, - RegisterClass DstRC, MSAInst Insn, - RegisterClass ViaRC> : - MSAPat<(DstVT (bitconvert SrcVT:$src)), - (COPY_TO_REGCLASS (Insn (COPY_TO_REGCLASS SrcVT:$src, ViaRC), 177), - DstRC), - [HasMSA, IsBE]>; - -class MSABitconvertReverseBInHPat<ValueType DstVT, ValueType SrcVT, - RegisterClass DstRC> : - MSABitconvertReverseHalvesPat<DstVT, SrcVT, DstRC, SHF_B, MSA128B>; - -class MSABitconvertReverseBInWPat<ValueType DstVT, ValueType SrcVT, - RegisterClass DstRC> : - MSABitconvertReverseQuartersPat<DstVT, SrcVT, DstRC, SHF_B, MSA128B>; - -class MSABitconvertReverseBInDPat<ValueType DstVT, ValueType SrcVT, - RegisterClass DstRC> : - MSAPat<(DstVT (bitconvert SrcVT:$src)), - (COPY_TO_REGCLASS - (SHF_W - (COPY_TO_REGCLASS - (SHF_B (COPY_TO_REGCLASS SrcVT:$src, MSA128B), 27), - MSA128W), 177), - DstRC), - [HasMSA, IsBE]>; - -class MSABitconvertReverseHInWPat<ValueType DstVT, ValueType SrcVT, - RegisterClass DstRC> : - MSABitconvertReverseHalvesPat<DstVT, SrcVT, DstRC, SHF_H, MSA128H>; - -class MSABitconvertReverseHInDPat<ValueType DstVT, ValueType SrcVT, - RegisterClass DstRC> : - MSABitconvertReverseQuartersPat<DstVT, SrcVT, DstRC, SHF_H, MSA128H>; - -class MSABitconvertReverseWInDPat<ValueType DstVT, ValueType SrcVT, - RegisterClass DstRC> : - MSABitconvertReverseHalvesPat<DstVT, SrcVT, DstRC, SHF_W, MSA128W>; - -def : MSABitconvertReverseBInHPat<v8i16, v16i8, MSA128H>; -def : MSABitconvertReverseBInHPat<v8f16, v16i8, MSA128H>; -def : MSABitconvertReverseBInWPat<v4i32, v16i8, MSA128W>; -def : MSABitconvertReverseBInWPat<v4f32, v16i8, MSA128W>; -def : MSABitconvertReverseBInDPat<v2i64, v16i8, MSA128D>; -def : MSABitconvertReverseBInDPat<v2f64, v16i8, MSA128D>; - -def : MSABitconvertReverseBInHPat<v16i8, v8i16, MSA128B>; -def : MSABitconvertReverseHInWPat<v4i32, v8i16, MSA128W>; -def : MSABitconvertReverseHInWPat<v4f32, v8i16, MSA128W>; -def : MSABitconvertReverseHInDPat<v2i64, v8i16, MSA128D>; -def : MSABitconvertReverseHInDPat<v2f64, v8i16, MSA128D>; - -def : MSABitconvertReverseBInHPat<v16i8, v8f16, MSA128B>; -def : MSABitconvertReverseHInWPat<v4i32, v8f16, MSA128W>; -def : MSABitconvertReverseHInWPat<v4f32, v8f16, MSA128W>; -def : MSABitconvertReverseHInDPat<v2i64, v8f16, MSA128D>; -def : MSABitconvertReverseHInDPat<v2f64, v8f16, MSA128D>; - -def : MSABitconvertReverseBInWPat<v16i8, v4i32, MSA128B>; -def : MSABitconvertReverseHInWPat<v8i16, v4i32, MSA128H>; -def : MSABitconvertReverseHInWPat<v8f16, v4i32, MSA128H>; -def : MSABitconvertReverseWInDPat<v2i64, v4i32, MSA128D>; -def : MSABitconvertReverseWInDPat<v2f64, v4i32, MSA128D>; - -def : MSABitconvertReverseBInWPat<v16i8, v4f32, MSA128B>; -def : MSABitconvertReverseHInWPat<v8i16, v4f32, MSA128H>; -def : MSABitconvertReverseHInWPat<v8f16, v4f32, MSA128H>; -def : MSABitconvertReverseWInDPat<v2i64, v4f32, MSA128D>; -def : MSABitconvertReverseWInDPat<v2f64, v4f32, MSA128D>; - -def : MSABitconvertReverseBInDPat<v16i8, v2i64, MSA128B>; -def : MSABitconvertReverseHInDPat<v8i16, v2i64, MSA128H>; -def : MSABitconvertReverseHInDPat<v8f16, v2i64, MSA128H>; -def : MSABitconvertReverseWInDPat<v4i32, v2i64, MSA128W>; -def : MSABitconvertReverseWInDPat<v4f32, v2i64, MSA128W>; - -def : MSABitconvertReverseBInDPat<v16i8, v2f64, MSA128B>; -def : MSABitconvertReverseHInDPat<v8i16, v2f64, MSA128H>; -def : MSABitconvertReverseHInDPat<v8f16, v2f64, MSA128H>; -def : MSABitconvertReverseWInDPat<v4i32, v2f64, MSA128W>; -def : MSABitconvertReverseWInDPat<v4f32, v2f64, MSA128W>; - -// Pseudos used to implement BNZ.df, and BZ.df - -class MSA_CBRANCH_PSEUDO_DESC_BASE<SDPatternOperator OpNode, ValueType TyNode, - RegisterClass RCWS, - InstrItinClass itin = NoItinerary> : - MipsPseudo<(outs GPR32:$dst), - (ins RCWS:$ws), - [(set GPR32:$dst, (OpNode (TyNode RCWS:$ws)))]> { - bit usesCustomInserter = 1; - bit hasNoSchedulingInfo = 1; -} - -def SNZ_B_PSEUDO : MSA_CBRANCH_PSEUDO_DESC_BASE<MipsVAllNonZero, v16i8, - MSA128B, NoItinerary>; -def SNZ_H_PSEUDO : MSA_CBRANCH_PSEUDO_DESC_BASE<MipsVAllNonZero, v8i16, - MSA128H, NoItinerary>; -def SNZ_W_PSEUDO : MSA_CBRANCH_PSEUDO_DESC_BASE<MipsVAllNonZero, v4i32, - MSA128W, NoItinerary>; -def SNZ_D_PSEUDO : MSA_CBRANCH_PSEUDO_DESC_BASE<MipsVAllNonZero, v2i64, - MSA128D, NoItinerary>; -def SNZ_V_PSEUDO : MSA_CBRANCH_PSEUDO_DESC_BASE<MipsVAnyNonZero, v16i8, - MSA128B, NoItinerary>; - -def SZ_B_PSEUDO : MSA_CBRANCH_PSEUDO_DESC_BASE<MipsVAllZero, v16i8, - MSA128B, NoItinerary>; -def SZ_H_PSEUDO : MSA_CBRANCH_PSEUDO_DESC_BASE<MipsVAllZero, v8i16, - MSA128H, NoItinerary>; -def SZ_W_PSEUDO : MSA_CBRANCH_PSEUDO_DESC_BASE<MipsVAllZero, v4i32, - MSA128W, NoItinerary>; -def SZ_D_PSEUDO : MSA_CBRANCH_PSEUDO_DESC_BASE<MipsVAllZero, v2i64, - MSA128D, NoItinerary>; -def SZ_V_PSEUDO : MSA_CBRANCH_PSEUDO_DESC_BASE<MipsVAnyZero, v16i8, - MSA128B, NoItinerary>; - -// Pseudoes used to implement transparent fp16 support. - -let ASEPredicate = [HasMSA] in { - let usesCustomInserter = 1 in { - def ST_F16 : - MipsPseudo<(outs), (ins MSA128F16:$ws, mem_simm10:$addr), - [(store (f16 MSA128F16:$ws), (addrimm10:$addr))]>; - def LD_F16 : - MipsPseudo<(outs MSA128F16:$ws), (ins mem_simm10:$addr), - [(set MSA128F16:$ws, (f16 (load addrimm10:$addr)))]>; - } - - let usesCustomInserter = 1, hasNoSchedulingInfo = 1 in { - def MSA_FP_EXTEND_W_PSEUDO : - MipsPseudo<(outs FGR32Opnd:$fd), (ins MSA128F16:$ws), - [(set FGR32Opnd:$fd, (f32 (fpextend MSA128F16:$ws)))]>; - def MSA_FP_ROUND_W_PSEUDO : - MipsPseudo<(outs MSA128F16:$wd), (ins FGR32Opnd:$fs), - [(set MSA128F16:$wd, (f16 (fpround FGR32Opnd:$fs)))]>; - def MSA_FP_EXTEND_D_PSEUDO : - MipsPseudo<(outs FGR64Opnd:$fd), (ins MSA128F16:$ws), - [(set FGR64Opnd:$fd, (f64 (fpextend MSA128F16:$ws)))]>; - def MSA_FP_ROUND_D_PSEUDO : - MipsPseudo<(outs MSA128F16:$wd), (ins FGR64Opnd:$fs), - [(set MSA128F16:$wd, (f16 (fpround FGR64Opnd:$fs)))]>; - } - - def : MipsPat<(MipsTruncIntFP MSA128F16:$ws), - (TRUNC_W_D64 (MSA_FP_EXTEND_D_PSEUDO MSA128F16:$ws))>, - ISA_MIPS1, ASE_MSA; - - def : MipsPat<(MipsFPCmp MSA128F16:$ws, MSA128F16:$wt, imm:$cond), - (FCMP_S32 (MSA_FP_EXTEND_W_PSEUDO MSA128F16:$ws), - (MSA_FP_EXTEND_W_PSEUDO MSA128F16:$wt), imm:$cond)>, - ISA_MIPS1_NOT_32R6_64R6, ASE_MSA; -} - -def vsplati64_imm_eq_63 : PatLeaf<(bitconvert (v4i32 (build_vector))), [{ - APInt Imm; - SDNode *BV = N->getOperand(0).getNode(); - EVT EltTy = N->getValueType(0).getVectorElementType(); - - return selectVSplat(BV, Imm, EltTy.getSizeInBits()) && - Imm.getBitWidth() == EltTy.getSizeInBits() && Imm == 63; -}]>; - -def immi32Cst7 : ImmLeaf<i32, [{return isUInt<32>(Imm) && Imm == 7;}]>; -def immi32Cst15 : ImmLeaf<i32, [{return isUInt<32>(Imm) && Imm == 15;}]>; -def immi32Cst31 : ImmLeaf<i32, [{return isUInt<32>(Imm) && Imm == 31;}]>; - -def vsplati8imm7 : PatFrag<(ops node:$wt), - (and node:$wt, (vsplati8 immi32Cst7))>; -def vsplati16imm15 : PatFrag<(ops node:$wt), - (and node:$wt, (vsplati16 immi32Cst15))>; -def vsplati32imm31 : PatFrag<(ops node:$wt), - (and node:$wt, (vsplati32 immi32Cst31))>; -def vsplati64imm63 : PatFrag<(ops node:$wt), - (and node:$wt, vsplati64_imm_eq_63)>; - -class MSAShiftPat<SDNode Node, ValueType VT, MSAInst Insn, dag Vec> : - MSAPat<(VT (Node VT:$ws, (VT (and VT:$wt, Vec)))), - (VT (Insn VT:$ws, VT:$wt))>; - -class MSABitPat<SDNode Node, ValueType VT, MSAInst Insn, PatFrag Frag> : - MSAPat<(VT (Node VT:$ws, (shl vsplat_imm_eq_1, (Frag VT:$wt)))), - (VT (Insn VT:$ws, VT:$wt))>; - -multiclass MSAShiftPats<SDNode Node, string Insn> { - def : MSAShiftPat<Node, v16i8, !cast<MSAInst>(Insn#_B), - (vsplati8 immi32Cst7)>; - def : MSAShiftPat<Node, v8i16, !cast<MSAInst>(Insn#_H), - (vsplati16 immi32Cst15)>; - def : MSAShiftPat<Node, v4i32, !cast<MSAInst>(Insn#_W), - (vsplati32 immi32Cst31)>; - def : MSAPat<(v2i64 (Node v2i64:$ws, (v2i64 (and v2i64:$wt, - vsplati64_imm_eq_63)))), - (v2i64 (!cast<MSAInst>(Insn#_D) v2i64:$ws, v2i64:$wt))>; -} - -multiclass MSABitPats<SDNode Node, string Insn> { - def : MSABitPat<Node, v16i8, !cast<MSAInst>(Insn#_B), vsplati8imm7>; - def : MSABitPat<Node, v8i16, !cast<MSAInst>(Insn#_H), vsplati16imm15>; - def : MSABitPat<Node, v4i32, !cast<MSAInst>(Insn#_W), vsplati32imm31>; - def : MSAPat<(Node v2i64:$ws, (shl (v2i64 vsplati64_imm_eq_1), - (vsplati64imm63 v2i64:$wt))), - (v2i64 (!cast<MSAInst>(Insn#_D) v2i64:$ws, v2i64:$wt))>; -} - -defm : MSAShiftPats<shl, "SLL">; -defm : MSAShiftPats<srl, "SRL">; -defm : MSAShiftPats<sra, "SRA">; -defm : MSABitPats<xor, "BNEG">; -defm : MSABitPats<or, "BSET">; - -def : MSAPat<(and v16i8:$ws, (xor (shl vsplat_imm_eq_1, - (vsplati8imm7 v16i8:$wt)), - immAllOnesV)), - (v16i8 (BCLR_B v16i8:$ws, v16i8:$wt))>; -def : MSAPat<(and v8i16:$ws, (xor (shl vsplat_imm_eq_1, - (vsplati16imm15 v8i16:$wt)), - immAllOnesV)), - (v8i16 (BCLR_H v8i16:$ws, v8i16:$wt))>; -def : MSAPat<(and v4i32:$ws, (xor (shl vsplat_imm_eq_1, - (vsplati32imm31 v4i32:$wt)), - immAllOnesV)), - (v4i32 (BCLR_W v4i32:$ws, v4i32:$wt))>; -def : MSAPat<(and v2i64:$ws, (xor (shl (v2i64 vsplati64_imm_eq_1), - (vsplati64imm63 v2i64:$wt)), - (bitconvert (v4i32 immAllOnesV)))), - (v2i64 (BCLR_D v2i64:$ws, v2i64:$wt))>; - -// Vector extraction with fixed index. -// -// Extracting 32-bit values on MSA32 should always use COPY_S_W rather than -// COPY_U_W, even for the zero-extended case. This is because our forward -// compatibility strategy is to consider registers to be infinitely -// sign-extended so that a MIPS64 can execute MIPS32 code without getting -// different register values. -def : MSAPat<(vextract_zext_i32 (v4i32 MSA128W:$ws), immZExt2Ptr:$idx), - (COPY_S_W MSA128W:$ws, immZExt2:$idx)>, ASE_MSA_NOT_MSA64; -def : MSAPat<(vextract_zext_i32 (v4f32 MSA128W:$ws), immZExt2Ptr:$idx), - (COPY_S_W MSA128W:$ws, immZExt2:$idx)>, ASE_MSA_NOT_MSA64; - -// Extracting 64-bit values on MSA64 should always use COPY_S_D rather than -// COPY_U_D, even for the zero-extended case. This is because our forward -// compatibility strategy is to consider registers to be infinitely -// sign-extended so that a hypothetical MIPS128 would be able to execute MIPS64 -// code without getting different register values. -def : MSAPat<(vextract_zext_i64 (v2i64 MSA128D:$ws), immZExt1Ptr:$idx), - (COPY_S_D MSA128D:$ws, immZExt1:$idx)>, ASE_MSA64; -def : MSAPat<(vextract_zext_i64 (v2f64 MSA128D:$ws), immZExt1Ptr:$idx), - (COPY_S_D MSA128D:$ws, immZExt1:$idx)>, ASE_MSA64; - -// Vector extraction with variable index -def : MSAPat<(i32 (vextract_sext_i8 v16i8:$ws, i32:$idx)), - (SRA (COPY_TO_REGCLASS (i32 (EXTRACT_SUBREG (SPLAT_B v16i8:$ws, - i32:$idx), - sub_lo)), - GPR32), (i32 24))>; -def : MSAPat<(i32 (vextract_sext_i16 v8i16:$ws, i32:$idx)), - (SRA (COPY_TO_REGCLASS (i32 (EXTRACT_SUBREG (SPLAT_H v8i16:$ws, - i32:$idx), - sub_lo)), - GPR32), (i32 16))>; -def : MSAPat<(i32 (vextract_sext_i32 v4i32:$ws, i32:$idx)), - (COPY_TO_REGCLASS (i32 (EXTRACT_SUBREG (SPLAT_W v4i32:$ws, - i32:$idx), - sub_lo)), - GPR32)>; -def : MSAPat<(i64 (vextract_sext_i64 v2i64:$ws, i32:$idx)), - (COPY_TO_REGCLASS (i64 (EXTRACT_SUBREG (SPLAT_D v2i64:$ws, - i32:$idx), - sub_64)), - GPR64), [HasMSA, IsGP64bit]>; - -def : MSAPat<(i32 (vextract_zext_i8 v16i8:$ws, i32:$idx)), - (SRL (COPY_TO_REGCLASS (i32 (EXTRACT_SUBREG (SPLAT_B v16i8:$ws, - i32:$idx), - sub_lo)), - GPR32), (i32 24))>; -def : MSAPat<(i32 (vextract_zext_i16 v8i16:$ws, i32:$idx)), - (SRL (COPY_TO_REGCLASS (i32 (EXTRACT_SUBREG (SPLAT_H v8i16:$ws, - i32:$idx), - sub_lo)), - GPR32), (i32 16))>; -def : MSAPat<(i32 (vextract_zext_i32 v4i32:$ws, i32:$idx)), - (COPY_TO_REGCLASS (i32 (EXTRACT_SUBREG (SPLAT_W v4i32:$ws, - i32:$idx), - sub_lo)), - GPR32)>; -def : MSAPat<(i64 (vextract_zext_i64 v2i64:$ws, i32:$idx)), - (COPY_TO_REGCLASS (i64 (EXTRACT_SUBREG (SPLAT_D v2i64:$ws, - i32:$idx), - sub_64)), - GPR64), [HasMSA, IsGP64bit]>; - -def : MSAPat<(f32 (vector_extract v4f32:$ws, i32:$idx)), - (f32 (EXTRACT_SUBREG (SPLAT_W v4f32:$ws, - i32:$idx), - sub_lo))>; -def : MSAPat<(f64 (vector_extract v2f64:$ws, i32:$idx)), - (f64 (EXTRACT_SUBREG (SPLAT_D v2f64:$ws, - i32:$idx), - sub_64))>; - -// Vector extraction with variable index (N64 ABI) -def : MSAPat< - (i32 (vextract_sext_i8 v16i8:$ws, i64:$idx)), - (SRA (COPY_TO_REGCLASS - (i32 (EXTRACT_SUBREG - (SPLAT_B v16i8:$ws, - (COPY_TO_REGCLASS - (i32 (EXTRACT_SUBREG i64:$idx, sub_32)), GPR32)), - sub_lo)), - GPR32), - (i32 24))>; -def : MSAPat< - (i32 (vextract_sext_i16 v8i16:$ws, i64:$idx)), - (SRA (COPY_TO_REGCLASS - (i32 (EXTRACT_SUBREG - (SPLAT_H v8i16:$ws, - (COPY_TO_REGCLASS - (i32 (EXTRACT_SUBREG i64:$idx, sub_32)), GPR32)), - sub_lo)), - GPR32), - (i32 16))>; -def : MSAPat< - (i32 (vextract_sext_i32 v4i32:$ws, i64:$idx)), - (COPY_TO_REGCLASS - (i32 (EXTRACT_SUBREG - (SPLAT_W v4i32:$ws, - (COPY_TO_REGCLASS - (i32 (EXTRACT_SUBREG i64:$idx, sub_32)), GPR32)), - sub_lo)), - GPR32)>; -def : MSAPat< - (i64 (vextract_sext_i64 v2i64:$ws, i64:$idx)), - (COPY_TO_REGCLASS - (i64 (EXTRACT_SUBREG - (SPLAT_D v2i64:$ws, - (COPY_TO_REGCLASS (i32 (EXTRACT_SUBREG i64:$idx, sub_32)), GPR32)), - sub_64)), - GPR64), [HasMSA, IsGP64bit]>; - -def : MSAPat< - (i32 (vextract_zext_i8 v16i8:$ws, i64:$idx)), - (SRL (COPY_TO_REGCLASS - (i32 (EXTRACT_SUBREG - (SPLAT_B v16i8:$ws, - (COPY_TO_REGCLASS - (i32 (EXTRACT_SUBREG i64:$idx, sub_32)), GPR32)), - sub_lo)), - GPR32), - (i32 24))>; -def : MSAPat< - (i32 (vextract_zext_i16 v8i16:$ws, i64:$idx)), - (SRL (COPY_TO_REGCLASS - (i32 (EXTRACT_SUBREG - (SPLAT_H v8i16:$ws, - (COPY_TO_REGCLASS - (i32 (EXTRACT_SUBREG i64:$idx, sub_32)), GPR32)), - sub_lo)), - GPR32), - (i32 16))>; -def : MSAPat< - (i32 (vextract_zext_i32 v4i32:$ws, i64:$idx)), - (COPY_TO_REGCLASS - (i32 (EXTRACT_SUBREG - (SPLAT_W v4i32:$ws, - (COPY_TO_REGCLASS (i32 (EXTRACT_SUBREG i64:$idx, sub_32)), GPR32)), - sub_lo)), - GPR32)>; -def : MSAPat< - (i64 (vextract_zext_i64 v2i64:$ws, i64:$idx)), - (COPY_TO_REGCLASS - (i64 (EXTRACT_SUBREG - (SPLAT_D v2i64:$ws, - (COPY_TO_REGCLASS (i32 (EXTRACT_SUBREG i64:$idx, sub_32)), GPR32)), - sub_64)), - GPR64), - [HasMSA, IsGP64bit]>; - -def : MSAPat< - (f32 (vector_extract v4f32:$ws, i64:$idx)), - (f32 (EXTRACT_SUBREG - (SPLAT_W v4f32:$ws, - (COPY_TO_REGCLASS (i32 (EXTRACT_SUBREG i64:$idx, sub_32)), GPR32)), - sub_lo))>; -def : MSAPat< - (f64 (vector_extract v2f64:$ws, i64:$idx)), - (f64 (EXTRACT_SUBREG - (SPLAT_D v2f64:$ws, - (COPY_TO_REGCLASS (i32 (EXTRACT_SUBREG i64:$idx, sub_32)), GPR32)), - sub_64))>; - -def : MSAPat<(vfseteq_v4f32 MSA128WOpnd:$a, MSA128WOpnd:$b), - (FCEQ_W MSA128WOpnd:$a, MSA128WOpnd:$b)>; -def : MSAPat<(vfseteq_v2f64 MSA128DOpnd:$a, MSA128DOpnd:$b), - (FCEQ_D MSA128DOpnd:$a, MSA128DOpnd:$b)>; -def : MSAPat<(vfsetle_v4f32 MSA128WOpnd:$a, MSA128WOpnd:$b), - (FCLE_W MSA128WOpnd:$a, MSA128WOpnd:$b)>; -def : MSAPat<(vfsetle_v2f64 MSA128DOpnd:$a, MSA128DOpnd:$b), - (FCLE_D MSA128DOpnd:$a, MSA128DOpnd:$b)>; -def : MSAPat<(vfsetlt_v4f32 MSA128WOpnd:$a, MSA128WOpnd:$b), - (FCLT_W MSA128WOpnd:$a, MSA128WOpnd:$b)>; -def : MSAPat<(vfsetlt_v2f64 MSA128DOpnd:$a, MSA128DOpnd:$b), - (FCLT_D MSA128DOpnd:$a, MSA128DOpnd:$b)>; -def : MSAPat<(vfsetne_v4f32 MSA128WOpnd:$a, MSA128WOpnd:$b), - (FCNE_W MSA128WOpnd:$a, MSA128WOpnd:$b)>; -def : MSAPat<(vfsetne_v2f64 MSA128DOpnd:$a, MSA128DOpnd:$b), - (FCNE_D MSA128DOpnd:$a, MSA128DOpnd:$b)>; diff --git a/contrib/llvm/lib/Target/Mips/MipsMTInstrFormats.td b/contrib/llvm/lib/Target/Mips/MipsMTInstrFormats.td deleted file mode 100644 index 22c290b1c114..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsMTInstrFormats.td +++ /dev/null @@ -1,97 +0,0 @@ -//===-- MipsMTInstrFormats.td - Mips Instruction Formats ---*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// Describe the MIPS MT instructions format -// -// opcode - operation code. -// rt - destination register -// -//===----------------------------------------------------------------------===// - -class MipsMTInst : MipsInst<(outs), (ins), "", [], NoItinerary, FrmOther> { - let DecoderNamespace = "Mips"; - let EncodingPredicates = [HasStdEnc]; -} - -class OPCODE1<bits<1> Val> { - bits<1> Value = Val; -} - -def OPCODE_SC_D : OPCODE1<0b0>; -def OPCODE_SC_E : OPCODE1<0b1>; - -class FIELD5<bits<5> Val> { - bits<5> Value = Val; -} - -def FIELD5_1_DMT_EMT : FIELD5<0b00001>; -def FIELD5_2_DMT_EMT : FIELD5<0b01111>; -def FIELD5_1_2_DVPE_EVPE : FIELD5<0b00000>; -def FIELD5_MFTR : FIELD5<0b01000>; -def FIELD5_MTTR : FIELD5<0b01100>; - -class COP0_MFMC0_MT<FIELD5 Op1, FIELD5 Op2, OPCODE1 sc> : MipsMTInst { - bits<32> Inst; - - bits<5> rt; - let Inst{31-26} = 0b010000; // COP0 - let Inst{25-21} = 0b01011; // MFMC0 - let Inst{20-16} = rt; - let Inst{15-11} = Op1.Value; - let Inst{10-6} = Op2.Value; - let Inst{5} = sc.Value; - let Inst{4-3} = 0b00; - let Inst{2-0} = 0b001; -} - -class COP0_MFTTR_MT<FIELD5 Op> : MipsMTInst { - bits<32> Inst; - - bits<5> rt; - bits<5> rd; - bits<1> u; - bits<1> h; - bits<3> sel; - let Inst{31-26} = 0b010000; // COP0 - let Inst{25-21} = Op.Value; // MFMC0 - let Inst{20-16} = rt; - let Inst{15-11} = rd; - let Inst{10-6} = 0b00000; // rx - currently unsupported. - let Inst{5} = u; - let Inst{4} = h; - let Inst{3} = 0b0; - let Inst{2-0} = sel; -} - -class SPECIAL3_MT_FORK : MipsMTInst { - bits<32> Inst; - - bits<5> rs; - bits<5> rt; - bits<5> rd; - let Inst{31-26} = 0b011111; // SPECIAL3 - let Inst{25-21} = rs; - let Inst{20-16} = rt; - let Inst{15-11} = rd; - let Inst{10-6} = 0b00000; - let Inst{5-0} = 0b001000; // FORK -} - -class SPECIAL3_MT_YIELD : MipsMTInst { - bits<32> Inst; - - bits<5> rs; - bits<5> rd; - let Inst{31-26} = 0b011111; // SPECIAL3 - let Inst{25-21} = rs; - let Inst{20-16} = 0b00000; - let Inst{15-11} = rd; - let Inst{10-6} = 0b00000; - let Inst{5-0} = 0b001001; // FORK -} diff --git a/contrib/llvm/lib/Target/Mips/MipsMTInstrInfo.td b/contrib/llvm/lib/Target/Mips/MipsMTInstrInfo.td deleted file mode 100644 index 3edeb57b1876..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsMTInstrInfo.td +++ /dev/null @@ -1,207 +0,0 @@ -//===-- MipsMTInstrInfo.td - Mips MT Instruction Infos -----*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file describes the MIPS MT ASE as defined by MD00378 1.12. -// -// TODO: Add support for the microMIPS encodings for the MT ASE and add the -// instruction mappings. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// MIPS MT Instruction Encodings -//===----------------------------------------------------------------------===// - -class DMT_ENC : COP0_MFMC0_MT<FIELD5_1_DMT_EMT, FIELD5_2_DMT_EMT, - OPCODE_SC_D>; - -class EMT_ENC : COP0_MFMC0_MT<FIELD5_1_DMT_EMT, FIELD5_2_DMT_EMT, - OPCODE_SC_E>; - -class DVPE_ENC : COP0_MFMC0_MT<FIELD5_1_2_DVPE_EVPE, FIELD5_1_2_DVPE_EVPE, - OPCODE_SC_D>; - -class EVPE_ENC : COP0_MFMC0_MT<FIELD5_1_2_DVPE_EVPE, FIELD5_1_2_DVPE_EVPE, - OPCODE_SC_E>; - -class FORK_ENC : SPECIAL3_MT_FORK; - -class YIELD_ENC : SPECIAL3_MT_YIELD; - -class MFTR_ENC : COP0_MFTTR_MT<FIELD5_MFTR>; - -class MTTR_ENC : COP0_MFTTR_MT<FIELD5_MTTR>; - -//===----------------------------------------------------------------------===// -// MIPS MT Instruction Descriptions -//===----------------------------------------------------------------------===// - -class MT_1R_DESC_BASE<string instr_asm, InstrItinClass Itin = NoItinerary> { - dag OutOperandList = (outs GPR32Opnd:$rt); - dag InOperandList = (ins); - string AsmString = !strconcat(instr_asm, "\t$rt"); - list<dag> Pattern = []; - InstrItinClass Itinerary = Itin; -} - -class MFTR_DESC { - dag OutOperandList = (outs GPR32Opnd:$rd); - dag InOperandList = (ins GPR32Opnd:$rt, uimm1:$u, uimm3:$sel, uimm1:$h); - string AsmString = "mftr\t$rd, $rt, $u, $sel, $h"; - list<dag> Pattern = []; - InstrItinClass Itinerary = II_MFTR; -} - -class MTTR_DESC { - dag OutOperandList = (outs GPR32Opnd:$rd); - dag InOperandList = (ins GPR32Opnd:$rt, uimm1:$u, uimm3:$sel, uimm1:$h); - string AsmString = "mttr\t$rt, $rd, $u, $sel, $h"; - list<dag> Pattern = []; - InstrItinClass Itinerary = II_MTTR; -} - -class FORK_DESC { - dag OutOperandList = (outs GPR32Opnd:$rs, GPR32Opnd:$rd); - dag InOperandList = (ins GPR32Opnd:$rt); - string AsmString = "fork\t$rd, $rs, $rt"; - list<dag> Pattern = []; - InstrItinClass Itinerary = II_FORK; -} - -class YIELD_DESC { - dag OutOperandList = (outs GPR32Opnd:$rd); - dag InOperandList = (ins GPR32Opnd:$rs); - string AsmString = "yield\t$rd, $rs"; - list<dag> Pattern = []; - InstrItinClass Itinerary = II_YIELD; -} - -class DMT_DESC : MT_1R_DESC_BASE<"dmt", II_DMT>; - -class EMT_DESC : MT_1R_DESC_BASE<"emt", II_EMT>; - -class DVPE_DESC : MT_1R_DESC_BASE<"dvpe", II_DVPE>; - -class EVPE_DESC : MT_1R_DESC_BASE<"evpe", II_EVPE>; - -//===----------------------------------------------------------------------===// -// MIPS MT Instruction Definitions -//===----------------------------------------------------------------------===// -let hasSideEffects = 1, isNotDuplicable = 1, - AdditionalPredicates = [NotInMicroMips] in { - def DMT : DMT_ENC, DMT_DESC, ASE_MT; - - def EMT : EMT_ENC, EMT_DESC, ASE_MT; - - def DVPE : DVPE_ENC, DVPE_DESC, ASE_MT; - - def EVPE : EVPE_ENC, EVPE_DESC, ASE_MT; - - def FORK : FORK_ENC, FORK_DESC, ASE_MT; - - def YIELD : YIELD_ENC, YIELD_DESC, ASE_MT; - - def MFTR : MFTR_ENC, MFTR_DESC, ASE_MT; - - def MTTR : MTTR_ENC, MTTR_DESC, ASE_MT; -} - -//===----------------------------------------------------------------------===// -// MIPS MT Pseudo Instructions - used to support mtfr & mttr aliases. -//===----------------------------------------------------------------------===// -def MFTC0 : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), (ins COP0Opnd:$rt, - uimm3:$sel), - "mftc0 $rd, $rt, $sel">, ASE_MT; - -def MFTGPR : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), (ins GPR32Opnd:$rt, - uimm3:$sel), - "mftgpr $rd, $rt">, ASE_MT; - -def MFTLO : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), (ins ACC64DSPOpnd:$ac), - "mftlo $rt, $ac">, ASE_MT; - -def MFTHI : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), (ins ACC64DSPOpnd:$ac), - "mfthi $rt, $ac">, ASE_MT; - -def MFTACX : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), (ins ACC64DSPOpnd:$ac), - "mftacx $rt, $ac">, ASE_MT; - -def MFTDSP : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), (ins), - "mftdsp $rt">, ASE_MT; - -def MFTC1 : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), (ins FGR32Opnd:$ft), - "mftc1 $rt, $ft">, ASE_MT; - -def MFTHC1 : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), (ins FGR32Opnd:$ft), - "mfthc1 $rt, $ft">, ASE_MT; - -def CFTC1 : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), (ins FGRCCOpnd:$ft), - "cftc1 $rt, $ft">, ASE_MT; - - -def MTTC0 : MipsAsmPseudoInst<(outs COP0Opnd:$rd), (ins GPR32Opnd:$rt, - uimm3:$sel), - "mttc0 $rt, $rd, $sel">, ASE_MT; - -def MTTGPR : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), (ins GPR32Opnd:$rd), - "mttgpr $rd, $rt">, ASE_MT; - -def MTTLO : MipsAsmPseudoInst<(outs ACC64DSPOpnd:$ac), (ins GPR32Opnd:$rt), - "mttlo $rt, $ac">, ASE_MT; - -def MTTHI : MipsAsmPseudoInst<(outs ACC64DSPOpnd:$ac), (ins GPR32Opnd:$rt), - "mtthi $rt, $ac">, ASE_MT; - -def MTTACX : MipsAsmPseudoInst<(outs ACC64DSPOpnd:$ac), (ins GPR32Opnd:$rt), - "mttacx $rt, $ac">, ASE_MT; - -def MTTDSP : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rt), - "mttdsp $rt">, ASE_MT; - -def MTTC1 : MipsAsmPseudoInst<(outs FGR32Opnd:$ft), (ins GPR32Opnd:$rt), - "mttc1 $rt, $ft">, ASE_MT; - -def MTTHC1 : MipsAsmPseudoInst<(outs FGR32Opnd:$ft), (ins GPR32Opnd:$rt), - "mtthc1 $rt, $ft">, ASE_MT; - -def CTTC1 : MipsAsmPseudoInst<(outs FGRCCOpnd:$ft), (ins GPR32Opnd:$rt), - "cttc1 $rt, $ft">, ASE_MT; - -//===----------------------------------------------------------------------===// -// MIPS MT Instruction Definitions -//===----------------------------------------------------------------------===// - -let AdditionalPredicates = [NotInMicroMips] in { - def : MipsInstAlias<"dmt", (DMT ZERO), 1>, ASE_MT; - - def : MipsInstAlias<"emt", (EMT ZERO), 1>, ASE_MT; - - def : MipsInstAlias<"dvpe", (DVPE ZERO), 1>, ASE_MT; - - def : MipsInstAlias<"evpe", (EVPE ZERO), 1>, ASE_MT; - - def : MipsInstAlias<"yield $rs", (YIELD ZERO, GPR32Opnd:$rs), 1>, ASE_MT; - - def : MipsInstAlias<"mftc0 $rd, $rt", (MFTC0 GPR32Opnd:$rd, COP0Opnd:$rt, 0), - 1>, ASE_MT; - - def : MipsInstAlias<"mftlo $rt", (MFTLO GPR32Opnd:$rt, AC0), 1>, ASE_MT; - - def : MipsInstAlias<"mfthi $rt", (MFTHI GPR32Opnd:$rt, AC0), 1>, ASE_MT; - - def : MipsInstAlias<"mftacx $rt", (MFTACX GPR32Opnd:$rt, AC0), 1>, ASE_MT; - - def : MipsInstAlias<"mttc0 $rd, $rt", (MTTC0 COP0Opnd:$rt, GPR32Opnd:$rd, 0), - 1>, ASE_MT; - - def : MipsInstAlias<"mttlo $rt", (MTTLO AC0, GPR32Opnd:$rt), 1>, ASE_MT; - - def : MipsInstAlias<"mtthi $rt", (MTTHI AC0, GPR32Opnd:$rt), 1>, ASE_MT; - - def : MipsInstAlias<"mttacx $rt", (MTTACX AC0, GPR32Opnd:$rt), 1>, ASE_MT; -} diff --git a/contrib/llvm/lib/Target/Mips/MipsMachineFunction.cpp b/contrib/llvm/lib/Target/Mips/MipsMachineFunction.cpp deleted file mode 100644 index 85b20fc58231..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsMachineFunction.cpp +++ /dev/null @@ -1,201 +0,0 @@ -//===-- MipsMachineFunctionInfo.cpp - Private data used for Mips ----------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "MipsMachineFunction.h" -#include "MCTargetDesc/MipsABIInfo.h" -#include "MipsSubtarget.h" -#include "MipsTargetMachine.h" -#include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/PseudoSourceValue.h" -#include "llvm/CodeGen/TargetRegisterInfo.h" -#include "llvm/Support/CommandLine.h" - -using namespace llvm; - -static cl::opt<bool> -FixGlobalBaseReg("mips-fix-global-base-reg", cl::Hidden, cl::init(true), - cl::desc("Always use $gp as the global base register.")); - -MipsFunctionInfo::~MipsFunctionInfo() = default; - -bool MipsFunctionInfo::globalBaseRegSet() const { - return GlobalBaseReg; -} - -static const TargetRegisterClass &getGlobalBaseRegClass(MachineFunction &MF) { - auto &STI = static_cast<const MipsSubtarget &>(MF.getSubtarget()); - auto &TM = static_cast<const MipsTargetMachine &>(MF.getTarget()); - - if (STI.inMips16Mode()) - return Mips::CPU16RegsRegClass; - - if (STI.inMicroMipsMode()) - return Mips::GPRMM16RegClass; - - if (TM.getABI().IsN64()) - return Mips::GPR64RegClass; - - return Mips::GPR32RegClass; -} - -Register MipsFunctionInfo::getGlobalBaseReg() { - if (!GlobalBaseReg) - GlobalBaseReg = - MF.getRegInfo().createVirtualRegister(&getGlobalBaseRegClass(MF)); - return GlobalBaseReg; -} - -Register MipsFunctionInfo::getGlobalBaseRegForGlobalISel() { - if (!GlobalBaseReg) { - getGlobalBaseReg(); - initGlobalBaseReg(); - } - return GlobalBaseReg; -} - -void MipsFunctionInfo::initGlobalBaseReg() { - if (!GlobalBaseReg) - return; - - MachineBasicBlock &MBB = MF.front(); - MachineBasicBlock::iterator I = MBB.begin(); - MachineRegisterInfo &RegInfo = MF.getRegInfo(); - const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); - DebugLoc DL; - unsigned V0, V1; - const TargetRegisterClass *RC; - const MipsABIInfo &ABI = - static_cast<const MipsTargetMachine &>(MF.getTarget()).getABI(); - RC = (ABI.IsN64()) ? &Mips::GPR64RegClass : &Mips::GPR32RegClass; - - V0 = RegInfo.createVirtualRegister(RC); - V1 = RegInfo.createVirtualRegister(RC); - - if (ABI.IsN64()) { - MF.getRegInfo().addLiveIn(Mips::T9_64); - MBB.addLiveIn(Mips::T9_64); - - // lui $v0, %hi(%neg(%gp_rel(fname))) - // daddu $v1, $v0, $t9 - // daddiu $globalbasereg, $v1, %lo(%neg(%gp_rel(fname))) - const GlobalValue *FName = &MF.getFunction(); - BuildMI(MBB, I, DL, TII.get(Mips::LUi64), V0) - .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_HI); - BuildMI(MBB, I, DL, TII.get(Mips::DADDu), V1).addReg(V0) - .addReg(Mips::T9_64); - BuildMI(MBB, I, DL, TII.get(Mips::DADDiu), GlobalBaseReg).addReg(V1) - .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_LO); - return; - } - - if (!MF.getTarget().isPositionIndependent()) { - // Set global register to __gnu_local_gp. - // - // lui $v0, %hi(__gnu_local_gp) - // addiu $globalbasereg, $v0, %lo(__gnu_local_gp) - BuildMI(MBB, I, DL, TII.get(Mips::LUi), V0) - .addExternalSymbol("__gnu_local_gp", MipsII::MO_ABS_HI); - BuildMI(MBB, I, DL, TII.get(Mips::ADDiu), GlobalBaseReg).addReg(V0) - .addExternalSymbol("__gnu_local_gp", MipsII::MO_ABS_LO); - return; - } - - MF.getRegInfo().addLiveIn(Mips::T9); - MBB.addLiveIn(Mips::T9); - - if (ABI.IsN32()) { - // lui $v0, %hi(%neg(%gp_rel(fname))) - // addu $v1, $v0, $t9 - // addiu $globalbasereg, $v1, %lo(%neg(%gp_rel(fname))) - const GlobalValue *FName = &MF.getFunction(); - BuildMI(MBB, I, DL, TII.get(Mips::LUi), V0) - .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_HI); - BuildMI(MBB, I, DL, TII.get(Mips::ADDu), V1).addReg(V0).addReg(Mips::T9); - BuildMI(MBB, I, DL, TII.get(Mips::ADDiu), GlobalBaseReg).addReg(V1) - .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_LO); - return; - } - - assert(ABI.IsO32()); - - // For O32 ABI, the following instruction sequence is emitted to initialize - // the global base register: - // - // 0. lui $2, %hi(_gp_disp) - // 1. addiu $2, $2, %lo(_gp_disp) - // 2. addu $globalbasereg, $2, $t9 - // - // We emit only the last instruction here. - // - // GNU linker requires that the first two instructions appear at the beginning - // of a function and no instructions be inserted before or between them. - // The two instructions are emitted during lowering to MC layer in order to - // avoid any reordering. - // - // Register $2 (Mips::V0) is added to the list of live-in registers to ensure - // the value instruction 1 (addiu) defines is valid when instruction 2 (addu) - // reads it. - MF.getRegInfo().addLiveIn(Mips::V0); - MBB.addLiveIn(Mips::V0); - BuildMI(MBB, I, DL, TII.get(Mips::ADDu), GlobalBaseReg) - .addReg(Mips::V0).addReg(Mips::T9); -} - -void MipsFunctionInfo::createEhDataRegsFI() { - const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo(); - for (int I = 0; I < 4; ++I) { - const TargetRegisterClass &RC = - static_cast<const MipsTargetMachine &>(MF.getTarget()).getABI().IsN64() - ? Mips::GPR64RegClass - : Mips::GPR32RegClass; - - EhDataRegFI[I] = MF.getFrameInfo().CreateStackObject(TRI.getSpillSize(RC), - TRI.getSpillAlignment(RC), false); - } -} - -void MipsFunctionInfo::createISRRegFI() { - // ISRs require spill slots for Status & ErrorPC Coprocessor 0 registers. - // The current implementation only supports Mips32r2+ not Mips64rX. Status - // is always 32 bits, ErrorPC is 32 or 64 bits dependent on architecture, - // however Mips32r2+ is the supported architecture. - const TargetRegisterClass &RC = Mips::GPR32RegClass; - const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo(); - - for (int I = 0; I < 2; ++I) - ISRDataRegFI[I] = MF.getFrameInfo().CreateStackObject( - TRI.getSpillSize(RC), TRI.getSpillAlignment(RC), false); -} - -bool MipsFunctionInfo::isEhDataRegFI(int FI) const { - return CallsEhReturn && (FI == EhDataRegFI[0] || FI == EhDataRegFI[1] - || FI == EhDataRegFI[2] || FI == EhDataRegFI[3]); -} - -bool MipsFunctionInfo::isISRRegFI(int FI) const { - return IsISR && (FI == ISRDataRegFI[0] || FI == ISRDataRegFI[1]); -} -MachinePointerInfo MipsFunctionInfo::callPtrInfo(const char *ES) { - return MachinePointerInfo(MF.getPSVManager().getExternalSymbolCallEntry(ES)); -} - -MachinePointerInfo MipsFunctionInfo::callPtrInfo(const GlobalValue *GV) { - return MachinePointerInfo(MF.getPSVManager().getGlobalValueCallEntry(GV)); -} - -int MipsFunctionInfo::getMoveF64ViaSpillFI(const TargetRegisterClass *RC) { - const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo(); - if (MoveF64ViaSpillFI == -1) { - MoveF64ViaSpillFI = MF.getFrameInfo().CreateStackObject( - TRI.getSpillSize(*RC), TRI.getSpillAlignment(*RC), false); - } - return MoveF64ViaSpillFI; -} - -void MipsFunctionInfo::anchor() {} diff --git a/contrib/llvm/lib/Target/Mips/MipsMachineFunction.h b/contrib/llvm/lib/Target/Mips/MipsMachineFunction.h deleted file mode 100644 index aaa1e0e18441..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsMachineFunction.h +++ /dev/null @@ -1,130 +0,0 @@ -//===- MipsMachineFunctionInfo.h - Private data used for Mips ---*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file declares the Mips specific subclass of MachineFunctionInfo. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_MIPS_MIPSMACHINEFUNCTION_H -#define LLVM_LIB_TARGET_MIPS_MIPSMACHINEFUNCTION_H - -#include "Mips16HardFloatInfo.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineMemOperand.h" -#include <map> - -namespace llvm { - -/// MipsFunctionInfo - This class is derived from MachineFunction private -/// Mips target-specific information for each MachineFunction. -class MipsFunctionInfo : public MachineFunctionInfo { -public: - MipsFunctionInfo(MachineFunction &MF) : MF(MF) {} - - ~MipsFunctionInfo() override; - - unsigned getSRetReturnReg() const { return SRetReturnReg; } - void setSRetReturnReg(unsigned Reg) { SRetReturnReg = Reg; } - - bool globalBaseRegSet() const; - Register getGlobalBaseReg(); - Register getGlobalBaseRegForGlobalISel(); - - // Insert instructions to initialize the global base register in the - // first MBB of the function. - void initGlobalBaseReg(); - - int getVarArgsFrameIndex() const { return VarArgsFrameIndex; } - void setVarArgsFrameIndex(int Index) { VarArgsFrameIndex = Index; } - - bool hasByvalArg() const { return HasByvalArg; } - void setFormalArgInfo(unsigned Size, bool HasByval) { - IncomingArgSize = Size; - HasByvalArg = HasByval; - } - - unsigned getIncomingArgSize() const { return IncomingArgSize; } - - bool callsEhReturn() const { return CallsEhReturn; } - void setCallsEhReturn() { CallsEhReturn = true; } - - void createEhDataRegsFI(); - int getEhDataRegFI(unsigned Reg) const { return EhDataRegFI[Reg]; } - bool isEhDataRegFI(int FI) const; - - /// Create a MachinePointerInfo that has an ExternalSymbolPseudoSourceValue - /// object representing a GOT entry for an external function. - MachinePointerInfo callPtrInfo(const char *ES); - - // Functions with the "interrupt" attribute require special prologues, - // epilogues and additional spill slots. - bool isISR() const { return IsISR; } - void setISR() { IsISR = true; } - void createISRRegFI(); - int getISRRegFI(unsigned Reg) const { return ISRDataRegFI[Reg]; } - bool isISRRegFI(int FI) const; - - /// Create a MachinePointerInfo that has a GlobalValuePseudoSourceValue object - /// representing a GOT entry for a global function. - MachinePointerInfo callPtrInfo(const GlobalValue *GV); - - void setSaveS2() { SaveS2 = true; } - bool hasSaveS2() const { return SaveS2; } - - int getMoveF64ViaSpillFI(const TargetRegisterClass *RC); - - std::map<const char *, const Mips16HardFloatInfo::FuncSignature *> - StubsNeeded; - -private: - virtual void anchor(); - - MachineFunction& MF; - - /// SRetReturnReg - Some subtargets require that sret lowering includes - /// returning the value of the returned struct in a register. This field - /// holds the virtual register into which the sret argument is passed. - unsigned SRetReturnReg = 0; - - /// GlobalBaseReg - keeps track of the virtual register initialized for - /// use as the global base register. This is used for PIC in some PIC - /// relocation models. - unsigned GlobalBaseReg = 0; - - /// VarArgsFrameIndex - FrameIndex for start of varargs area. - int VarArgsFrameIndex = 0; - - /// True if function has a byval argument. - bool HasByvalArg; - - /// Size of incoming argument area. - unsigned IncomingArgSize; - - /// CallsEhReturn - Whether the function calls llvm.eh.return. - bool CallsEhReturn = false; - - /// Frame objects for spilling eh data registers. - int EhDataRegFI[4]; - - /// ISR - Whether the function is an Interrupt Service Routine. - bool IsISR = false; - - /// Frame objects for spilling C0_STATUS, C0_EPC - int ISRDataRegFI[2]; - - // saveS2 - bool SaveS2 = false; - - /// FrameIndex for expanding BuildPairF64 nodes to spill and reload when the - /// O32 FPXX ABI is enabled. -1 is used to denote invalid index. - int MoveF64ViaSpillFI = -1; -}; - -} // end namespace llvm - -#endif // LLVM_LIB_TARGET_MIPS_MIPSMACHINEFUNCTION_H diff --git a/contrib/llvm/lib/Target/Mips/MipsModuleISelDAGToDAG.cpp b/contrib/llvm/lib/Target/Mips/MipsModuleISelDAGToDAG.cpp deleted file mode 100644 index a2b55e8bddcd..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsModuleISelDAGToDAG.cpp +++ /dev/null @@ -1,56 +0,0 @@ -//===----------------------------------------------------------------------===// -// Instruction Selector Subtarget Control -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// This file defines a pass used to change the subtarget for the -// Mips Instruction selector. -// -//===----------------------------------------------------------------------===// - -#include "Mips.h" -#include "MipsTargetMachine.h" -#include "llvm/CodeGen/TargetPassConfig.h" -#include "llvm/CodeGen/StackProtector.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/raw_ostream.h" - -using namespace llvm; - -#define DEBUG_TYPE "mips-isel" - -namespace { - class MipsModuleDAGToDAGISel : public MachineFunctionPass { - public: - static char ID; - - MipsModuleDAGToDAGISel() : MachineFunctionPass(ID) {} - - // Pass Name - StringRef getPassName() const override { - return "MIPS DAG->DAG Pattern Instruction Selection"; - } - - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.addRequired<TargetPassConfig>(); - AU.addPreserved<StackProtector>(); - MachineFunctionPass::getAnalysisUsage(AU); - } - - bool runOnMachineFunction(MachineFunction &MF) override; - }; - - char MipsModuleDAGToDAGISel::ID = 0; -} - -bool MipsModuleDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) { - LLVM_DEBUG(errs() << "In MipsModuleDAGToDAGISel::runMachineFunction\n"); - auto &TPC = getAnalysis<TargetPassConfig>(); - auto &TM = TPC.getTM<MipsTargetMachine>(); - TM.resetSubtarget(&MF); - return false; -} - -llvm::FunctionPass *llvm::createMipsModuleISelDagPass() { - return new MipsModuleDAGToDAGISel(); -} diff --git a/contrib/llvm/lib/Target/Mips/MipsOptimizePICCall.cpp b/contrib/llvm/lib/Target/Mips/MipsOptimizePICCall.cpp deleted file mode 100644 index 5ef07a2d283e..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsOptimizePICCall.cpp +++ /dev/null @@ -1,322 +0,0 @@ -//===- MipsOptimizePICCall.cpp - Optimize PIC Calls -----------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This pass eliminates unnecessary instructions that set up $gp and replace -// instructions that load target function addresses with copy instructions. -// -//===----------------------------------------------------------------------===// - -#include "MCTargetDesc/MipsBaseInfo.h" -#include "Mips.h" -#include "MipsRegisterInfo.h" -#include "MipsSubtarget.h" -#include "llvm/ADT/PointerUnion.h" -#include "llvm/ADT/ScopedHashTable.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/MachineDominators.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/MachineOperand.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/TargetInstrInfo.h" -#include "llvm/CodeGen/TargetOpcodes.h" -#include "llvm/CodeGen/TargetRegisterInfo.h" -#include "llvm/CodeGen/TargetSubtargetInfo.h" -#include "llvm/Support/Allocator.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MachineValueType.h" -#include "llvm/Support/RecyclingAllocator.h" -#include <cassert> -#include <utility> -#include <vector> - -using namespace llvm; - -#define DEBUG_TYPE "optimize-mips-pic-call" - -static cl::opt<bool> LoadTargetFromGOT("mips-load-target-from-got", - cl::init(true), - cl::desc("Load target address from GOT"), - cl::Hidden); - -static cl::opt<bool> EraseGPOpnd("mips-erase-gp-opnd", - cl::init(true), cl::desc("Erase GP Operand"), - cl::Hidden); - -namespace { - -using ValueType = PointerUnion<const Value *, const PseudoSourceValue *>; -using CntRegP = std::pair<unsigned, unsigned>; -using AllocatorTy = RecyclingAllocator<BumpPtrAllocator, - ScopedHashTableVal<ValueType, CntRegP>>; -using ScopedHTType = ScopedHashTable<ValueType, CntRegP, - DenseMapInfo<ValueType>, AllocatorTy>; - -class MBBInfo { -public: - MBBInfo(MachineDomTreeNode *N); - - const MachineDomTreeNode *getNode() const; - bool isVisited() const; - void preVisit(ScopedHTType &ScopedHT); - void postVisit(); - -private: - MachineDomTreeNode *Node; - ScopedHTType::ScopeTy *HTScope; -}; - -class OptimizePICCall : public MachineFunctionPass { -public: - OptimizePICCall() : MachineFunctionPass(ID) {} - - StringRef getPassName() const override { return "Mips OptimizePICCall"; } - - bool runOnMachineFunction(MachineFunction &F) override; - - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.addRequired<MachineDominatorTree>(); - MachineFunctionPass::getAnalysisUsage(AU); - } - -private: - /// Visit MBB. - bool visitNode(MBBInfo &MBBI); - - /// Test if MI jumps to a function via a register. - /// - /// Also, return the virtual register containing the target function's address - /// and the underlying object in Reg and Val respectively, if the function's - /// address can be resolved lazily. - bool isCallViaRegister(MachineInstr &MI, unsigned &Reg, - ValueType &Val) const; - - /// Return the number of instructions that dominate the current - /// instruction and load the function address from object Entry. - unsigned getCount(ValueType Entry); - - /// Return the destination virtual register of the last instruction - /// that loads from object Entry. - unsigned getReg(ValueType Entry); - - /// Update ScopedHT. - void incCntAndSetReg(ValueType Entry, unsigned Reg); - - ScopedHTType ScopedHT; - - static char ID; -}; - -} // end of anonymous namespace - -char OptimizePICCall::ID = 0; - -/// Return the first MachineOperand of MI if it is a used virtual register. -static MachineOperand *getCallTargetRegOpnd(MachineInstr &MI) { - if (MI.getNumOperands() == 0) - return nullptr; - - MachineOperand &MO = MI.getOperand(0); - - if (!MO.isReg() || !MO.isUse() || - !TargetRegisterInfo::isVirtualRegister(MO.getReg())) - return nullptr; - - return &MO; -} - -/// Return type of register Reg. -static MVT::SimpleValueType getRegTy(unsigned Reg, MachineFunction &MF) { - const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo(); - const TargetRegisterClass *RC = MF.getRegInfo().getRegClass(Reg); - assert(TRI.legalclasstypes_end(*RC) - TRI.legalclasstypes_begin(*RC) == 1); - return *TRI.legalclasstypes_begin(*RC); -} - -/// Do the following transformation: -/// -/// jalr $vreg -/// => -/// copy $t9, $vreg -/// jalr $t9 -static void setCallTargetReg(MachineBasicBlock *MBB, - MachineBasicBlock::iterator I) { - MachineFunction &MF = *MBB->getParent(); - const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); - unsigned SrcReg = I->getOperand(0).getReg(); - unsigned DstReg = getRegTy(SrcReg, MF) == MVT::i32 ? Mips::T9 : Mips::T9_64; - BuildMI(*MBB, I, I->getDebugLoc(), TII.get(TargetOpcode::COPY), DstReg) - .addReg(SrcReg); - I->getOperand(0).setReg(DstReg); -} - -/// Search MI's operands for register GP and erase it. -static void eraseGPOpnd(MachineInstr &MI) { - if (!EraseGPOpnd) - return; - - MachineFunction &MF = *MI.getParent()->getParent(); - MVT::SimpleValueType Ty = getRegTy(MI.getOperand(0).getReg(), MF); - unsigned Reg = Ty == MVT::i32 ? Mips::GP : Mips::GP_64; - - for (unsigned I = 0; I < MI.getNumOperands(); ++I) { - MachineOperand &MO = MI.getOperand(I); - if (MO.isReg() && MO.getReg() == Reg) { - MI.RemoveOperand(I); - return; - } - } - - llvm_unreachable(nullptr); -} - -MBBInfo::MBBInfo(MachineDomTreeNode *N) : Node(N), HTScope(nullptr) {} - -const MachineDomTreeNode *MBBInfo::getNode() const { return Node; } - -bool MBBInfo::isVisited() const { return HTScope; } - -void MBBInfo::preVisit(ScopedHTType &ScopedHT) { - HTScope = new ScopedHTType::ScopeTy(ScopedHT); -} - -void MBBInfo::postVisit() { - delete HTScope; -} - -// OptimizePICCall methods. -bool OptimizePICCall::runOnMachineFunction(MachineFunction &F) { - if (static_cast<const MipsSubtarget &>(F.getSubtarget()).inMips16Mode()) - return false; - - // Do a pre-order traversal of the dominator tree. - MachineDominatorTree *MDT = &getAnalysis<MachineDominatorTree>(); - bool Changed = false; - - SmallVector<MBBInfo, 8> WorkList(1, MBBInfo(MDT->getRootNode())); - - while (!WorkList.empty()) { - MBBInfo &MBBI = WorkList.back(); - - // If this MBB has already been visited, destroy the scope for the MBB and - // pop it from the work list. - if (MBBI.isVisited()) { - MBBI.postVisit(); - WorkList.pop_back(); - continue; - } - - // Visit the MBB and add its children to the work list. - MBBI.preVisit(ScopedHT); - Changed |= visitNode(MBBI); - const MachineDomTreeNode *Node = MBBI.getNode(); - const std::vector<MachineDomTreeNode *> &Children = Node->getChildren(); - WorkList.append(Children.begin(), Children.end()); - } - - return Changed; -} - -bool OptimizePICCall::visitNode(MBBInfo &MBBI) { - bool Changed = false; - MachineBasicBlock *MBB = MBBI.getNode()->getBlock(); - - for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); I != E; - ++I) { - unsigned Reg; - ValueType Entry; - - // Skip instructions that are not call instructions via registers. - if (!isCallViaRegister(*I, Reg, Entry)) - continue; - - Changed = true; - unsigned N = getCount(Entry); - - if (N != 0) { - // If a function has been called more than twice, we do not have to emit a - // load instruction to get the function address from the GOT, but can - // instead reuse the address that has been loaded before. - if (N >= 2 && !LoadTargetFromGOT) - getCallTargetRegOpnd(*I)->setReg(getReg(Entry)); - - // Erase the $gp operand if this isn't the first time a function has - // been called. $gp needs to be set up only if the function call can go - // through a lazy binding stub. - eraseGPOpnd(*I); - } - - if (Entry) - incCntAndSetReg(Entry, Reg); - - setCallTargetReg(MBB, I); - } - - return Changed; -} - -bool OptimizePICCall::isCallViaRegister(MachineInstr &MI, unsigned &Reg, - ValueType &Val) const { - if (!MI.isCall()) - return false; - - MachineOperand *MO = getCallTargetRegOpnd(MI); - - // Return if MI is not a function call via a register. - if (!MO) - return false; - - // Get the instruction that loads the function address from the GOT. - Reg = MO->getReg(); - Val = nullptr; - MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo(); - MachineInstr *DefMI = MRI.getVRegDef(Reg); - - assert(DefMI); - - // See if DefMI is an instruction that loads from a GOT entry that holds the - // address of a lazy binding stub. - if (!DefMI->mayLoad() || DefMI->getNumOperands() < 3) - return true; - - unsigned Flags = DefMI->getOperand(2).getTargetFlags(); - - if (Flags != MipsII::MO_GOT_CALL && Flags != MipsII::MO_CALL_LO16) - return true; - - // Return the underlying object for the GOT entry in Val. - assert(DefMI->hasOneMemOperand()); - Val = (*DefMI->memoperands_begin())->getValue(); - if (!Val) - Val = (*DefMI->memoperands_begin())->getPseudoValue(); - return true; -} - -unsigned OptimizePICCall::getCount(ValueType Entry) { - return ScopedHT.lookup(Entry).first; -} - -unsigned OptimizePICCall::getReg(ValueType Entry) { - unsigned Reg = ScopedHT.lookup(Entry).second; - assert(Reg); - return Reg; -} - -void OptimizePICCall::incCntAndSetReg(ValueType Entry, unsigned Reg) { - CntRegP P = ScopedHT.lookup(Entry); - ScopedHT.insert(Entry, std::make_pair(P.first + 1, Reg)); -} - -/// Return an OptimizeCall object. -FunctionPass *llvm::createMipsOptimizePICCallPass() { - return new OptimizePICCall(); -} diff --git a/contrib/llvm/lib/Target/Mips/MipsOptionRecord.h b/contrib/llvm/lib/Target/Mips/MipsOptionRecord.h deleted file mode 100644 index 7897095ef894..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsOptionRecord.h +++ /dev/null @@ -1,82 +0,0 @@ -//===- MipsOptionRecord.h - Abstraction for storing information -*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// MipsOptionRecord - Abstraction for storing arbitrary information in -// ELF files. Arbitrary information (e.g. register usage) can be stored in Mips -// specific ELF sections like .Mips.options. Specific records should subclass -// MipsOptionRecord and provide an implementation to EmitMipsOptionRecord which -// basically just dumps the information into an ELF section. More information -// about .Mips.option can be found in the SysV ABI and the 64-bit ELF Object -// specification. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_MIPS_MIPSOPTIONRECORD_H -#define LLVM_LIB_TARGET_MIPS_MIPSOPTIONRECORD_H - -#include "MCTargetDesc/MipsMCTargetDesc.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCRegisterInfo.h" -#include <cstdint> - -namespace llvm { - -class MipsELFStreamer; - -class MipsOptionRecord { -public: - virtual ~MipsOptionRecord() = default; - - virtual void EmitMipsOptionRecord() = 0; -}; - -class MipsRegInfoRecord : public MipsOptionRecord { -public: - MipsRegInfoRecord(MipsELFStreamer *S, MCContext &Context) - : Streamer(S), Context(Context) { - ri_gprmask = 0; - ri_cprmask[0] = ri_cprmask[1] = ri_cprmask[2] = ri_cprmask[3] = 0; - ri_gp_value = 0; - - const MCRegisterInfo *TRI = Context.getRegisterInfo(); - GPR32RegClass = &(TRI->getRegClass(Mips::GPR32RegClassID)); - GPR64RegClass = &(TRI->getRegClass(Mips::GPR64RegClassID)); - FGR32RegClass = &(TRI->getRegClass(Mips::FGR32RegClassID)); - FGR64RegClass = &(TRI->getRegClass(Mips::FGR64RegClassID)); - AFGR64RegClass = &(TRI->getRegClass(Mips::AFGR64RegClassID)); - MSA128BRegClass = &(TRI->getRegClass(Mips::MSA128BRegClassID)); - COP0RegClass = &(TRI->getRegClass(Mips::COP0RegClassID)); - COP2RegClass = &(TRI->getRegClass(Mips::COP2RegClassID)); - COP3RegClass = &(TRI->getRegClass(Mips::COP3RegClassID)); - } - - ~MipsRegInfoRecord() override = default; - - void EmitMipsOptionRecord() override; - void SetPhysRegUsed(unsigned Reg, const MCRegisterInfo *MCRegInfo); - -private: - MipsELFStreamer *Streamer; - MCContext &Context; - const MCRegisterClass *GPR32RegClass; - const MCRegisterClass *GPR64RegClass; - const MCRegisterClass *FGR32RegClass; - const MCRegisterClass *FGR64RegClass; - const MCRegisterClass *AFGR64RegClass; - const MCRegisterClass *MSA128BRegClass; - const MCRegisterClass *COP0RegClass; - const MCRegisterClass *COP2RegClass; - const MCRegisterClass *COP3RegClass; - uint32_t ri_gprmask; - uint32_t ri_cprmask[4]; - int64_t ri_gp_value; -}; - -} // end namespace llvm - -#endif // LLVM_LIB_TARGET_MIPS_MIPSOPTIONRECORD_H diff --git a/contrib/llvm/lib/Target/Mips/MipsOs16.cpp b/contrib/llvm/lib/Target/Mips/MipsOs16.cpp deleted file mode 100644 index ac4e55f8a1f5..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsOs16.cpp +++ /dev/null @@ -1,159 +0,0 @@ -//===---- MipsOs16.cpp for Mips Option -Os16 --------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines an optimization phase for the MIPS target. -// -//===----------------------------------------------------------------------===// - -#include "Mips.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/Module.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/raw_ostream.h" - -using namespace llvm; - -#define DEBUG_TYPE "mips-os16" - -static cl::opt<std::string> Mips32FunctionMask( - "mips32-function-mask", - cl::init(""), - cl::desc("Force function to be mips32"), - cl::Hidden); - -namespace { - class MipsOs16 : public ModulePass { - public: - static char ID; - - MipsOs16() : ModulePass(ID) {} - - StringRef getPassName() const override { return "MIPS Os16 Optimization"; } - - bool runOnModule(Module &M) override; - }; - - char MipsOs16::ID = 0; -} - -// Figure out if we need float point based on the function signature. -// We need to move variables in and/or out of floating point -// registers because of the ABI -// -static bool needsFPFromSig(Function &F) { - Type* RetType = F.getReturnType(); - switch (RetType->getTypeID()) { - case Type::FloatTyID: - case Type::DoubleTyID: - return true; - default: - ; - } - if (F.arg_size() >=1) { - Argument &Arg = *F.arg_begin(); - switch (Arg.getType()->getTypeID()) { - case Type::FloatTyID: - case Type::DoubleTyID: - return true; - default: - ; - } - } - return false; -} - -// Figure out if the function will need floating point operations -// -static bool needsFP(Function &F) { - if (needsFPFromSig(F)) - return true; - for (Function::const_iterator BB = F.begin(), E = F.end(); BB != E; ++BB) - for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); - I != E; ++I) { - const Instruction &Inst = *I; - switch (Inst.getOpcode()) { - case Instruction::FAdd: - case Instruction::FSub: - case Instruction::FMul: - case Instruction::FDiv: - case Instruction::FRem: - case Instruction::FPToUI: - case Instruction::FPToSI: - case Instruction::UIToFP: - case Instruction::SIToFP: - case Instruction::FPTrunc: - case Instruction::FPExt: - case Instruction::FCmp: - return true; - default: - ; - } - if (const CallInst *CI = dyn_cast<CallInst>(I)) { - LLVM_DEBUG(dbgs() << "Working on call" - << "\n"); - Function &F_ = *CI->getCalledFunction(); - if (needsFPFromSig(F_)) - return true; - } - } - return false; -} - - -bool MipsOs16::runOnModule(Module &M) { - bool usingMask = Mips32FunctionMask.length() > 0; - bool doneUsingMask = false; // this will make it stop repeating - - LLVM_DEBUG(dbgs() << "Run on Module MipsOs16 \n" - << Mips32FunctionMask << "\n"); - if (usingMask) - LLVM_DEBUG(dbgs() << "using mask \n" << Mips32FunctionMask << "\n"); - - unsigned int functionIndex = 0; - bool modified = false; - - for (auto &F : M) { - if (F.isDeclaration()) - continue; - - LLVM_DEBUG(dbgs() << "Working on " << F.getName() << "\n"); - if (usingMask) { - if (!doneUsingMask) { - if (functionIndex == Mips32FunctionMask.length()) - functionIndex = 0; - switch (Mips32FunctionMask[functionIndex]) { - case '1': - LLVM_DEBUG(dbgs() << "mask forced mips32: " << F.getName() << "\n"); - F.addFnAttr("nomips16"); - break; - case '.': - doneUsingMask = true; - break; - default: - break; - } - functionIndex++; - } - } - else { - if (needsFP(F)) { - LLVM_DEBUG(dbgs() << "os16 forced mips32: " << F.getName() << "\n"); - F.addFnAttr("nomips16"); - } - else { - LLVM_DEBUG(dbgs() << "os16 forced mips16: " << F.getName() << "\n"); - F.addFnAttr("mips16"); - } - } - } - - return modified; -} - -ModulePass *llvm::createMipsOs16Pass() { return new MipsOs16(); } diff --git a/contrib/llvm/lib/Target/Mips/MipsPreLegalizerCombiner.cpp b/contrib/llvm/lib/Target/Mips/MipsPreLegalizerCombiner.cpp deleted file mode 100644 index 85076590d407..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsPreLegalizerCombiner.cpp +++ /dev/null @@ -1,102 +0,0 @@ -//=== lib/CodeGen/GlobalISel/MipsPreLegalizerCombiner.cpp --------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This pass does combining of machine instructions at the generic MI level, -// before the legalizer. -// -//===----------------------------------------------------------------------===// - -#include "MipsTargetMachine.h" -#include "llvm/CodeGen/GlobalISel/Combiner.h" -#include "llvm/CodeGen/GlobalISel/CombinerHelper.h" -#include "llvm/CodeGen/GlobalISel/CombinerInfo.h" -#include "llvm/CodeGen/GlobalISel/MIPatternMatch.h" -#include "llvm/CodeGen/TargetPassConfig.h" - -#define DEBUG_TYPE "mips-prelegalizer-combiner" - -using namespace llvm; - -namespace { -class MipsPreLegalizerCombinerInfo : public CombinerInfo { -public: - MipsPreLegalizerCombinerInfo() - : CombinerInfo(/*AllowIllegalOps*/ true, /*ShouldLegalizeIllegal*/ false, - /*LegalizerInfo*/ nullptr) {} - virtual bool combine(GISelChangeObserver &Observer, MachineInstr &MI, - MachineIRBuilder &B) const override; -}; - -bool MipsPreLegalizerCombinerInfo::combine(GISelChangeObserver &Observer, - MachineInstr &MI, - MachineIRBuilder &B) const { - CombinerHelper Helper(Observer, B); - - switch (MI.getOpcode()) { - default: - return false; - case TargetOpcode::G_LOAD: - case TargetOpcode::G_SEXTLOAD: - case TargetOpcode::G_ZEXTLOAD: - return Helper.tryCombineExtendingLoads(MI); - } - return false; -} - -// Pass boilerplate -// ================ - -class MipsPreLegalizerCombiner : public MachineFunctionPass { -public: - static char ID; - - MipsPreLegalizerCombiner(); - - StringRef getPassName() const override { return "MipsPreLegalizerCombiner"; } - - bool runOnMachineFunction(MachineFunction &MF) override; - - void getAnalysisUsage(AnalysisUsage &AU) const override; -}; -} // end anonymous namespace - -void MipsPreLegalizerCombiner::getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequired<TargetPassConfig>(); - AU.setPreservesCFG(); - getSelectionDAGFallbackAnalysisUsage(AU); - MachineFunctionPass::getAnalysisUsage(AU); -} - -MipsPreLegalizerCombiner::MipsPreLegalizerCombiner() : MachineFunctionPass(ID) { - initializeMipsPreLegalizerCombinerPass(*PassRegistry::getPassRegistry()); -} - -bool MipsPreLegalizerCombiner::runOnMachineFunction(MachineFunction &MF) { - if (MF.getProperties().hasProperty( - MachineFunctionProperties::Property::FailedISel)) - return false; - auto *TPC = &getAnalysis<TargetPassConfig>(); - MipsPreLegalizerCombinerInfo PCInfo; - Combiner C(PCInfo, TPC); - return C.combineMachineInstrs(MF, nullptr); -} - -char MipsPreLegalizerCombiner::ID = 0; -INITIALIZE_PASS_BEGIN(MipsPreLegalizerCombiner, DEBUG_TYPE, - "Combine Mips machine instrs before legalization", false, - false) -INITIALIZE_PASS_DEPENDENCY(TargetPassConfig) -INITIALIZE_PASS_END(MipsPreLegalizerCombiner, DEBUG_TYPE, - "Combine Mips machine instrs before legalization", false, - false) - -namespace llvm { -FunctionPass *createMipsPreLegalizeCombiner() { - return new MipsPreLegalizerCombiner(); -} -} // end namespace llvm diff --git a/contrib/llvm/lib/Target/Mips/MipsRegisterBankInfo.cpp b/contrib/llvm/lib/Target/Mips/MipsRegisterBankInfo.cpp deleted file mode 100644 index d8bcf16afd50..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsRegisterBankInfo.cpp +++ /dev/null @@ -1,677 +0,0 @@ -//===- MipsRegisterBankInfo.cpp ---------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// \file -/// This file implements the targeting of the RegisterBankInfo class for Mips. -/// \todo This should be generated by TableGen. -//===----------------------------------------------------------------------===// - -#include "MipsRegisterBankInfo.h" -#include "MipsInstrInfo.h" -#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h" -#include "llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h" -#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" - -#define GET_TARGET_REGBANK_IMPL - -#include "MipsGenRegisterBank.inc" - -namespace llvm { -namespace Mips { -enum PartialMappingIdx { - PMI_GPR, - PMI_SPR, - PMI_DPR, - PMI_Min = PMI_GPR, -}; - -RegisterBankInfo::PartialMapping PartMappings[]{ - {0, 32, GPRBRegBank}, - {0, 32, FPRBRegBank}, - {0, 64, FPRBRegBank} -}; - -enum ValueMappingIdx { - InvalidIdx = 0, - GPRIdx = 1, - SPRIdx = 4, - DPRIdx = 7 -}; - -RegisterBankInfo::ValueMapping ValueMappings[] = { - // invalid - {nullptr, 0}, - // up to 3 operands in GPRs - {&PartMappings[PMI_GPR - PMI_Min], 1}, - {&PartMappings[PMI_GPR - PMI_Min], 1}, - {&PartMappings[PMI_GPR - PMI_Min], 1}, - // up to 3 ops operands FPRs - single precission - {&PartMappings[PMI_SPR - PMI_Min], 1}, - {&PartMappings[PMI_SPR - PMI_Min], 1}, - {&PartMappings[PMI_SPR - PMI_Min], 1}, - // up to 3 ops operands FPRs - double precission - {&PartMappings[PMI_DPR - PMI_Min], 1}, - {&PartMappings[PMI_DPR - PMI_Min], 1}, - {&PartMappings[PMI_DPR - PMI_Min], 1} -}; - -} // end namespace Mips -} // end namespace llvm - -using namespace llvm; - -MipsRegisterBankInfo::MipsRegisterBankInfo(const TargetRegisterInfo &TRI) - : MipsGenRegisterBankInfo() {} - -const RegisterBank &MipsRegisterBankInfo::getRegBankFromRegClass( - const TargetRegisterClass &RC) const { - using namespace Mips; - - switch (RC.getID()) { - case Mips::GPR32RegClassID: - case Mips::CPU16Regs_and_GPRMM16ZeroRegClassID: - case Mips::GPRMM16MovePPairFirstRegClassID: - case Mips::CPU16Regs_and_GPRMM16MovePPairSecondRegClassID: - case Mips::GPRMM16MoveP_and_CPU16Regs_and_GPRMM16ZeroRegClassID: - case Mips::GPRMM16MovePPairFirst_and_GPRMM16MovePPairSecondRegClassID: - case Mips::SP32RegClassID: - case Mips::GP32RegClassID: - return getRegBank(Mips::GPRBRegBankID); - case Mips::FGRCCRegClassID: - case Mips::FGR32RegClassID: - case Mips::FGR64RegClassID: - case Mips::AFGR64RegClassID: - return getRegBank(Mips::FPRBRegBankID); - default: - llvm_unreachable("Register class not supported"); - } -} - -// Instructions where all register operands are floating point. -static bool isFloatingPointOpcode(unsigned Opc) { - switch (Opc) { - case TargetOpcode::G_FCONSTANT: - case TargetOpcode::G_FADD: - case TargetOpcode::G_FSUB: - case TargetOpcode::G_FMUL: - case TargetOpcode::G_FDIV: - case TargetOpcode::G_FABS: - case TargetOpcode::G_FSQRT: - case TargetOpcode::G_FCEIL: - case TargetOpcode::G_FFLOOR: - case TargetOpcode::G_FPEXT: - case TargetOpcode::G_FPTRUNC: - return true; - default: - return false; - } -} - -// Instructions where use operands are floating point registers. -// Def operands are general purpose. -static bool isFloatingPointOpcodeUse(unsigned Opc) { - switch (Opc) { - case TargetOpcode::G_FPTOSI: - case TargetOpcode::G_FPTOUI: - case TargetOpcode::G_FCMP: - case Mips::MFC1: - case Mips::ExtractElementF64: - case Mips::ExtractElementF64_64: - return true; - default: - return isFloatingPointOpcode(Opc); - } -} - -// Instructions where def operands are floating point registers. -// Use operands are general purpose. -static bool isFloatingPointOpcodeDef(unsigned Opc) { - switch (Opc) { - case TargetOpcode::G_SITOFP: - case TargetOpcode::G_UITOFP: - case Mips::MTC1: - case Mips::BuildPairF64: - case Mips::BuildPairF64_64: - return true; - default: - return isFloatingPointOpcode(Opc); - } -} - -static bool isAmbiguous(unsigned Opc) { - switch (Opc) { - case TargetOpcode::G_LOAD: - case TargetOpcode::G_STORE: - case TargetOpcode::G_PHI: - case TargetOpcode::G_SELECT: - return true; - default: - return false; - } -} - -void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addDefUses( - Register Reg, const MachineRegisterInfo &MRI) { - assert(!MRI.getType(Reg).isPointer() && - "Pointers are gprb, they should not be considered as ambiguous.\n"); - for (MachineInstr &UseMI : MRI.use_instructions(Reg)) { - MachineInstr *NonCopyInstr = skipCopiesOutgoing(&UseMI); - // Copy with many uses. - if (NonCopyInstr->getOpcode() == TargetOpcode::COPY && - !TargetRegisterInfo::isPhysicalRegister( - NonCopyInstr->getOperand(0).getReg())) - addDefUses(NonCopyInstr->getOperand(0).getReg(), MRI); - else - DefUses.push_back(skipCopiesOutgoing(&UseMI)); - } -} - -void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addUseDef( - Register Reg, const MachineRegisterInfo &MRI) { - assert(!MRI.getType(Reg).isPointer() && - "Pointers are gprb, they should not be considered as ambiguous.\n"); - MachineInstr *DefMI = MRI.getVRegDef(Reg); - UseDefs.push_back(skipCopiesIncoming(DefMI)); -} - -MachineInstr * -MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesOutgoing( - MachineInstr *MI) const { - const MachineFunction &MF = *MI->getParent()->getParent(); - const MachineRegisterInfo &MRI = MF.getRegInfo(); - MachineInstr *Ret = MI; - while (Ret->getOpcode() == TargetOpcode::COPY && - !TargetRegisterInfo::isPhysicalRegister(Ret->getOperand(0).getReg()) && - MRI.hasOneUse(Ret->getOperand(0).getReg())) { - Ret = &(*MRI.use_instr_begin(Ret->getOperand(0).getReg())); - } - return Ret; -} - -MachineInstr * -MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesIncoming( - MachineInstr *MI) const { - const MachineFunction &MF = *MI->getParent()->getParent(); - const MachineRegisterInfo &MRI = MF.getRegInfo(); - MachineInstr *Ret = MI; - while (Ret->getOpcode() == TargetOpcode::COPY && - !TargetRegisterInfo::isPhysicalRegister(Ret->getOperand(1).getReg())) - Ret = MRI.getVRegDef(Ret->getOperand(1).getReg()); - return Ret; -} - -MipsRegisterBankInfo::AmbiguousRegDefUseContainer::AmbiguousRegDefUseContainer( - const MachineInstr *MI) { - assert(isAmbiguous(MI->getOpcode()) && - "Not implemented for non Ambiguous opcode.\n"); - - const MachineRegisterInfo &MRI = MI->getMF()->getRegInfo(); - - if (MI->getOpcode() == TargetOpcode::G_LOAD) - addDefUses(MI->getOperand(0).getReg(), MRI); - - if (MI->getOpcode() == TargetOpcode::G_STORE) - addUseDef(MI->getOperand(0).getReg(), MRI); - - if (MI->getOpcode() == TargetOpcode::G_PHI) { - addDefUses(MI->getOperand(0).getReg(), MRI); - - for (unsigned i = 1; i < MI->getNumOperands(); i += 2) - addUseDef(MI->getOperand(i).getReg(), MRI); - } - - if (MI->getOpcode() == TargetOpcode::G_SELECT) { - addDefUses(MI->getOperand(0).getReg(), MRI); - - addUseDef(MI->getOperand(2).getReg(), MRI); - addUseDef(MI->getOperand(3).getReg(), MRI); - } -} - -bool MipsRegisterBankInfo::TypeInfoForMF::visit( - const MachineInstr *MI, const MachineInstr *WaitingForTypeOfMI) { - assert(isAmbiguous(MI->getOpcode()) && "Visiting non-Ambiguous opcode.\n"); - if (wasVisited(MI)) - return true; // InstType has already been determined for MI. - - startVisit(MI); - AmbiguousRegDefUseContainer DefUseContainer(MI); - - // Visit instructions where MI's DEF operands are USED. - if (visitAdjacentInstrs(MI, DefUseContainer.getDefUses(), true)) - return true; - - // Visit instructions that DEFINE MI's USE operands. - if (visitAdjacentInstrs(MI, DefUseContainer.getUseDefs(), false)) - return true; - - // All MI's adjacent instructions, are ambiguous. - if (!WaitingForTypeOfMI) { - // This is chain of ambiguous instructions. - setTypes(MI, InstType::Ambiguous); - return true; - } - // Excluding WaitingForTypeOfMI, MI is either connected to chains of ambiguous - // instructions or has no other adjacent instructions. Anyway InstType could - // not be determined. There could be unexplored path from some of - // WaitingForTypeOfMI's adjacent instructions to an instruction with only one - // mapping available. - // We are done with this branch, add MI to WaitingForTypeOfMI's WaitingQueue, - // this way when WaitingForTypeOfMI figures out its InstType same InstType - // will be assigned to all instructions in this branch. - addToWaitingQueue(WaitingForTypeOfMI, MI); - return false; -} - -bool MipsRegisterBankInfo::TypeInfoForMF::visitAdjacentInstrs( - const MachineInstr *MI, SmallVectorImpl<MachineInstr *> &AdjacentInstrs, - bool isDefUse) { - while (!AdjacentInstrs.empty()) { - MachineInstr *AdjMI = AdjacentInstrs.pop_back_val(); - - if (isDefUse ? isFloatingPointOpcodeUse(AdjMI->getOpcode()) - : isFloatingPointOpcodeDef(AdjMI->getOpcode())) { - setTypes(MI, InstType::FloatingPoint); - return true; - } - - // Determine InstType from register bank of phys register that is - // 'isDefUse ? def : use' of this copy. - if (AdjMI->getOpcode() == TargetOpcode::COPY) { - setTypesAccordingToPhysicalRegister(MI, AdjMI, isDefUse ? 0 : 1); - return true; - } - - // Defaults to integer instruction. Includes G_MERGE_VALUES and - // G_UNMERGE_VALUES. - if (!isAmbiguous(AdjMI->getOpcode())) { - setTypes(MI, InstType::Integer); - return true; - } - - // When AdjMI was visited first, MI has to continue to explore remaining - // adjacent instructions and determine InstType without visiting AdjMI. - if (!wasVisited(AdjMI) || - getRecordedTypeForInstr(AdjMI) != InstType::NotDetermined) { - if (visit(AdjMI, MI)) { - // InstType is successfully determined and is same as for AdjMI. - setTypes(MI, getRecordedTypeForInstr(AdjMI)); - return true; - } - } - } - return false; -} - -void MipsRegisterBankInfo::TypeInfoForMF::setTypes(const MachineInstr *MI, - InstType InstTy) { - changeRecordedTypeForInstr(MI, InstTy); - for (const MachineInstr *WaitingInstr : getWaitingQueueFor(MI)) { - setTypes(WaitingInstr, InstTy); - } -} - -void MipsRegisterBankInfo::TypeInfoForMF::setTypesAccordingToPhysicalRegister( - const MachineInstr *MI, const MachineInstr *CopyInst, unsigned Op) { - assert((TargetRegisterInfo::isPhysicalRegister( - CopyInst->getOperand(Op).getReg())) && - "Copies of non physical registers should not be considered here.\n"); - - const MachineFunction &MF = *CopyInst->getMF(); - const MachineRegisterInfo &MRI = MF.getRegInfo(); - const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo(); - const RegisterBankInfo &RBI = - *CopyInst->getMF()->getSubtarget().getRegBankInfo(); - const RegisterBank *Bank = - RBI.getRegBank(CopyInst->getOperand(Op).getReg(), MRI, TRI); - - if (Bank == &Mips::FPRBRegBank) - setTypes(MI, InstType::FloatingPoint); - else if (Bank == &Mips::GPRBRegBank) - setTypes(MI, InstType::Integer); - else - llvm_unreachable("Unsupported register bank.\n"); -} - -MipsRegisterBankInfo::InstType -MipsRegisterBankInfo::TypeInfoForMF::determineInstType(const MachineInstr *MI) { - visit(MI, nullptr); - return getRecordedTypeForInstr(MI); -} - -void MipsRegisterBankInfo::TypeInfoForMF::cleanupIfNewFunction( - llvm::StringRef FunctionName) { - if (MFName != FunctionName) { - MFName = FunctionName; - WaitingQueues.clear(); - Types.clear(); - } -} - -const RegisterBankInfo::InstructionMapping & -MipsRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { - - static TypeInfoForMF TI; - - // Reset TI internal data when MF changes. - TI.cleanupIfNewFunction(MI.getMF()->getName()); - - unsigned Opc = MI.getOpcode(); - const MachineFunction &MF = *MI.getParent()->getParent(); - const MachineRegisterInfo &MRI = MF.getRegInfo(); - - if (MI.getOpcode() != TargetOpcode::G_PHI) { - const RegisterBankInfo::InstructionMapping &Mapping = - getInstrMappingImpl(MI); - if (Mapping.isValid()) - return Mapping; - } - - using namespace TargetOpcode; - - unsigned NumOperands = MI.getNumOperands(); - const ValueMapping *OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx]; - unsigned MappingID = DefaultMappingID; - const unsigned CustomMappingID = 1; - - switch (Opc) { - case G_TRUNC: - case G_ADD: - case G_SUB: - case G_MUL: - case G_UMULH: - case G_ZEXTLOAD: - case G_SEXTLOAD: - case G_GEP: - case G_AND: - case G_OR: - case G_XOR: - case G_SHL: - case G_ASHR: - case G_LSHR: - case G_SDIV: - case G_UDIV: - case G_SREM: - case G_UREM: - OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx]; - break; - case G_LOAD: { - unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); - InstType InstTy = InstType::Integer; - if (!MRI.getType(MI.getOperand(0).getReg()).isPointer()) { - InstTy = TI.determineInstType(&MI); - } - - if (InstTy == InstType::FloatingPoint || - (Size == 64 && InstTy == InstType::Ambiguous)) { // fprb - OperandsMapping = - getOperandsMapping({Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx] - : &Mips::ValueMappings[Mips::DPRIdx], - &Mips::ValueMappings[Mips::GPRIdx]}); - break; - } else { // gprb - OperandsMapping = - getOperandsMapping({Size <= 32 ? &Mips::ValueMappings[Mips::GPRIdx] - : &Mips::ValueMappings[Mips::DPRIdx], - &Mips::ValueMappings[Mips::GPRIdx]}); - if (Size == 64) - MappingID = CustomMappingID; - } - - break; - } - case G_STORE: { - unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); - InstType InstTy = InstType::Integer; - if (!MRI.getType(MI.getOperand(0).getReg()).isPointer()) { - InstTy = TI.determineInstType(&MI); - } - - if (InstTy == InstType::FloatingPoint || - (Size == 64 && InstTy == InstType::Ambiguous)) { // fprb - OperandsMapping = - getOperandsMapping({Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx] - : &Mips::ValueMappings[Mips::DPRIdx], - &Mips::ValueMappings[Mips::GPRIdx]}); - break; - } else { // gprb - OperandsMapping = - getOperandsMapping({Size <= 32 ? &Mips::ValueMappings[Mips::GPRIdx] - : &Mips::ValueMappings[Mips::DPRIdx], - &Mips::ValueMappings[Mips::GPRIdx]}); - if (Size == 64) - MappingID = CustomMappingID; - } - break; - } - case G_PHI: { - unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); - InstType InstTy = InstType::Integer; - if (!MRI.getType(MI.getOperand(0).getReg()).isPointer()) { - InstTy = TI.determineInstType(&MI); - } - - // PHI is copylike and should have one regbank in mapping for def register. - if (InstTy == InstType::Integer && Size == 64) { // fprb - OperandsMapping = - getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx]}); - return getInstructionMapping(CustomMappingID, /*Cost=*/1, OperandsMapping, - /*NumOperands=*/1); - } - // Use default handling for PHI, i.e. set reg bank of def operand to match - // register banks of use operands. - const RegisterBankInfo::InstructionMapping &Mapping = - getInstrMappingImpl(MI); - return Mapping; - } - case G_SELECT: { - unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); - InstType InstTy = InstType::Integer; - if (!MRI.getType(MI.getOperand(0).getReg()).isPointer()) { - InstTy = TI.determineInstType(&MI); - } - - if (InstTy == InstType::FloatingPoint || - (Size == 64 && InstTy == InstType::Ambiguous)) { // fprb - const RegisterBankInfo::ValueMapping *Bank = - Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx] - : &Mips::ValueMappings[Mips::DPRIdx]; - OperandsMapping = getOperandsMapping( - {Bank, &Mips::ValueMappings[Mips::GPRIdx], Bank, Bank}); - break; - } else { // gprb - const RegisterBankInfo::ValueMapping *Bank = - Size <= 32 ? &Mips::ValueMappings[Mips::GPRIdx] - : &Mips::ValueMappings[Mips::DPRIdx]; - OperandsMapping = getOperandsMapping( - {Bank, &Mips::ValueMappings[Mips::GPRIdx], Bank, Bank}); - if (Size == 64) - MappingID = CustomMappingID; - } - break; - } - case G_UNMERGE_VALUES: { - OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], - &Mips::ValueMappings[Mips::GPRIdx], - &Mips::ValueMappings[Mips::DPRIdx]}); - MappingID = CustomMappingID; - break; - } - case G_MERGE_VALUES: { - OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx], - &Mips::ValueMappings[Mips::GPRIdx], - &Mips::ValueMappings[Mips::GPRIdx]}); - MappingID = CustomMappingID; - break; - } - case G_FADD: - case G_FSUB: - case G_FMUL: - case G_FDIV: - case G_FABS: - case G_FSQRT:{ - unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); - assert((Size == 32 || Size == 64) && "Unsupported floating point size"); - OperandsMapping = Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx] - : &Mips::ValueMappings[Mips::DPRIdx]; - break; - } - case G_FCONSTANT: { - unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); - assert((Size == 32 || Size == 64) && "Unsupported floating point size"); - const RegisterBankInfo::ValueMapping *FPRValueMapping = - Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx] - : &Mips::ValueMappings[Mips::DPRIdx]; - OperandsMapping = getOperandsMapping({FPRValueMapping, nullptr}); - break; - } - case G_FCMP: { - unsigned Size = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits(); - assert((Size == 32 || Size == 64) && "Unsupported floating point size"); - const RegisterBankInfo::ValueMapping *FPRValueMapping = - Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx] - : &Mips::ValueMappings[Mips::DPRIdx]; - OperandsMapping = - getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr, - FPRValueMapping, FPRValueMapping}); - break; - } - case G_FPEXT: - OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx], - &Mips::ValueMappings[Mips::SPRIdx]}); - break; - case G_FPTRUNC: - OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::SPRIdx], - &Mips::ValueMappings[Mips::DPRIdx]}); - break; - case G_FPTOSI: { - unsigned SizeFP = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits(); - assert((MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() == 32) && - "Unsupported integer size"); - assert((SizeFP == 32 || SizeFP == 64) && "Unsupported floating point size"); - OperandsMapping = getOperandsMapping({ - &Mips::ValueMappings[Mips::GPRIdx], - SizeFP == 32 ? &Mips::ValueMappings[Mips::SPRIdx] - : &Mips::ValueMappings[Mips::DPRIdx], - }); - break; - } - case G_SITOFP: { - unsigned SizeInt = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits(); - unsigned SizeFP = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); - (void)SizeInt; - assert((SizeInt == 32) && "Unsupported integer size"); - assert((SizeFP == 32 || SizeFP == 64) && "Unsupported floating point size"); - OperandsMapping = - getOperandsMapping({SizeFP == 32 ? &Mips::ValueMappings[Mips::SPRIdx] - : &Mips::ValueMappings[Mips::DPRIdx], - &Mips::ValueMappings[Mips::GPRIdx]}); - break; - } - case G_CONSTANT: - case G_FRAME_INDEX: - case G_GLOBAL_VALUE: - case G_BRCOND: - OperandsMapping = - getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr}); - break; - case G_ICMP: - OperandsMapping = - getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr, - &Mips::ValueMappings[Mips::GPRIdx], - &Mips::ValueMappings[Mips::GPRIdx]}); - break; - default: - return getInvalidInstructionMapping(); - } - - return getInstructionMapping(MappingID, /*Cost=*/1, OperandsMapping, - NumOperands); -} - -using InstListTy = GISelWorkList<4>; -namespace { -class InstManager : public GISelChangeObserver { - InstListTy &InstList; - -public: - InstManager(InstListTy &Insts) : InstList(Insts) {} - - void createdInstr(MachineInstr &MI) override { InstList.insert(&MI); } - void erasingInstr(MachineInstr &MI) override {} - void changingInstr(MachineInstr &MI) override {} - void changedInstr(MachineInstr &MI) override {} -}; -} // end anonymous namespace - -/// Here we have to narrowScalar s64 operands to s32, combine away -/// G_MERGE/G_UNMERGE and erase instructions that became dead in the process. -/// We manually assign 32 bit gprb to register operands of all new instructions -/// that got created in the process since they will not end up in RegBankSelect -/// loop. Careful not to delete instruction after MI i.e. MI.getIterator()++. -void MipsRegisterBankInfo::applyMappingImpl( - const OperandsMapper &OpdMapper) const { - MachineInstr &MI = OpdMapper.getMI(); - InstListTy NewInstrs; - MachineIRBuilder B(MI); - MachineFunction *MF = MI.getMF(); - MachineRegisterInfo &MRI = OpdMapper.getMRI(); - - InstManager NewInstrObserver(NewInstrs); - GISelObserverWrapper WrapperObserver(&NewInstrObserver); - LegalizerHelper Helper(*MF, WrapperObserver, B); - LegalizationArtifactCombiner ArtCombiner( - B, MF->getRegInfo(), *MF->getSubtarget().getLegalizerInfo()); - - switch (MI.getOpcode()) { - case TargetOpcode::G_LOAD: - case TargetOpcode::G_STORE: - case TargetOpcode::G_PHI: - case TargetOpcode::G_SELECT: { - Helper.narrowScalar(MI, 0, LLT::scalar(32)); - // Handle new instructions. - while (!NewInstrs.empty()) { - MachineInstr *NewMI = NewInstrs.pop_back_val(); - // This is new G_UNMERGE that was created during narrowScalar and will - // not be considered for regbank selection. RegBankSelect for mips - // visits/makes corresponding G_MERGE first. Combine them here. - if (NewMI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES) { - SmallVector<MachineInstr *, 2> DeadInstrs; - ArtCombiner.tryCombineMerges(*NewMI, DeadInstrs); - for (MachineInstr *DeadMI : DeadInstrs) - DeadMI->eraseFromParent(); - } - // This G_MERGE will be combined away when its corresponding G_UNMERGE - // gets regBankSelected. - else if (NewMI->getOpcode() == TargetOpcode::G_MERGE_VALUES) - continue; - else - // Manually set register banks for all register operands to 32 bit gprb. - for (auto Op : NewMI->operands()) { - if (Op.isReg()) { - assert(MRI.getType(Op.getReg()).getSizeInBits() == 32 && - "Only 32 bit gprb is handled here.\n"); - MRI.setRegBank(Op.getReg(), getRegBank(Mips::GPRBRegBankID)); - } - } - } - return; - } - case TargetOpcode::G_UNMERGE_VALUES: { - SmallVector<MachineInstr *, 2> DeadInstrs; - ArtCombiner.tryCombineMerges(MI, DeadInstrs); - for (MachineInstr *DeadMI : DeadInstrs) - DeadMI->eraseFromParent(); - return; - } - default: - break; - } - - return applyDefaultMapping(OpdMapper); -} diff --git a/contrib/llvm/lib/Target/Mips/MipsRegisterBankInfo.h b/contrib/llvm/lib/Target/Mips/MipsRegisterBankInfo.h deleted file mode 100644 index 176813c031ed..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsRegisterBankInfo.h +++ /dev/null @@ -1,167 +0,0 @@ -//===- MipsRegisterBankInfo.h -----------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// \file -/// This file declares the targeting of the RegisterBankInfo class for Mips. -/// \todo This should be generated by TableGen. -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_MIPS_MIPSREGISTERBANKINFO_H -#define LLVM_LIB_TARGET_MIPS_MIPSREGISTERBANKINFO_H - -#include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h" - -#define GET_REGBANK_DECLARATIONS -#include "MipsGenRegisterBank.inc" - -namespace llvm { - -class TargetRegisterInfo; - -class MipsGenRegisterBankInfo : public RegisterBankInfo { -#define GET_TARGET_REGBANK_CLASS -#include "MipsGenRegisterBank.inc" -}; - -/// This class provides the information for the target register banks. -class MipsRegisterBankInfo final : public MipsGenRegisterBankInfo { -public: - MipsRegisterBankInfo(const TargetRegisterInfo &TRI); - - const RegisterBank & - getRegBankFromRegClass(const TargetRegisterClass &RC) const override; - - const InstructionMapping & - getInstrMapping(const MachineInstr &MI) const override; - - void applyMappingImpl(const OperandsMapper &OpdMapper) const override; - -private: - /// Some instructions are used with both floating point and integer operands. - /// We assign InstType to such instructions as it helps us to avoid cross bank - /// copies. InstType deppends on context. - enum InstType { - /// Temporary type, when visit(..., nullptr) finishes will convert to one of - /// the remaining types: Integer, FloatingPoint or Ambiguous. - NotDetermined, - /// Connected with instruction that interprets 'bags of bits' as integers. - /// Select gprb to avoid cross bank copies. - Integer, - /// Connected with instruction that interprets 'bags of bits' as floating - /// point numbers. Select fprb to avoid cross bank copies. - FloatingPoint, - /// Represents moving 'bags of bits' around. Select same bank for entire - /// chain to avoid cross bank copies. Currently we select fprb for s64 and - /// gprb for s32 Ambiguous operands. - Ambiguous - }; - - /// Some generic instructions have operands that can be mapped to either fprb - /// or gprb e.g. for G_LOAD we consider only operand 0 as ambiguous, operand 1 - /// is always gprb since it is a pointer. - /// This class provides containers for MI's ambiguous: - /// DefUses : MachineInstrs that use one of MI's ambiguous def operands. - /// UseDefs : MachineInstrs that define MI's ambiguous use operands. - class AmbiguousRegDefUseContainer { - SmallVector<MachineInstr *, 2> DefUses; - SmallVector<MachineInstr *, 2> UseDefs; - - void addDefUses(Register Reg, const MachineRegisterInfo &MRI); - void addUseDef(Register Reg, const MachineRegisterInfo &MRI); - - /// Skip copy instructions until we get to a non-copy instruction or to a - /// copy with phys register as def. Used during search for DefUses. - /// MI : %5 = COPY %4 - /// %6 = COPY %5 - /// $v0 = COPY %6 <- we want this one. - MachineInstr *skipCopiesOutgoing(MachineInstr *MI) const; - - /// Skip copy instructions until we get to a non-copy instruction or to a - /// copy with phys register as use. Used during search for UseDefs. - /// %1 = COPY $a1 <- we want this one. - /// %2 = COPY %1 - /// MI = %3 = COPY %2 - MachineInstr *skipCopiesIncoming(MachineInstr *MI) const; - - public: - AmbiguousRegDefUseContainer(const MachineInstr *MI); - SmallVectorImpl<MachineInstr *> &getDefUses() { return DefUses; } - SmallVectorImpl<MachineInstr *> &getUseDefs() { return UseDefs; } - }; - - class TypeInfoForMF { - /// MachineFunction name is used to recognise when MF changes. - std::string MFName = ""; - /// <key, value> : value is vector of all MachineInstrs that are waiting for - /// key to figure out type of some of its ambiguous operands. - DenseMap<const MachineInstr *, SmallVector<const MachineInstr *, 2>> - WaitingQueues; - /// Recorded InstTypes for visited instructions. - DenseMap<const MachineInstr *, InstType> Types; - - /// Recursively visit MI's adjacent instructions and find MI's InstType. - bool visit(const MachineInstr *MI, const MachineInstr *WaitingForTypeOfMI); - - /// Visit MI's adjacent UseDefs or DefUses. - bool visitAdjacentInstrs(const MachineInstr *MI, - SmallVectorImpl<MachineInstr *> &AdjacentInstrs, - bool isDefUse); - - /// Set type for MI, and recursively for all instructions that are - /// waiting for MI's type. - void setTypes(const MachineInstr *MI, InstType ITy); - - /// InstType for MI is determined, set it to InstType that corresponds to - /// physical regisiter that is operand number Op in CopyInst. - void setTypesAccordingToPhysicalRegister(const MachineInstr *MI, - const MachineInstr *CopyInst, - unsigned Op); - - /// Set default values for MI in order to start visit. - void startVisit(const MachineInstr *MI) { - Types.try_emplace(MI, InstType::NotDetermined); - WaitingQueues.try_emplace(MI); - } - - /// Returns true if instruction was already visited. Type might not be - /// determined at this point but will be when visit(..., nullptr) finishes. - bool wasVisited(const MachineInstr *MI) const { return Types.count(MI); }; - - /// Returns recorded type for instruction. - const InstType &getRecordedTypeForInstr(const MachineInstr *MI) const { - assert(wasVisited(MI) && "Instruction was not visited!"); - return Types.find(MI)->getSecond(); - }; - - /// Change recorded type for instruction. - void changeRecordedTypeForInstr(const MachineInstr *MI, InstType InstTy) { - assert(wasVisited(MI) && "Instruction was not visited!"); - Types.find(MI)->getSecond() = InstTy; - }; - - /// Returns WaitingQueue for instruction. - const SmallVectorImpl<const MachineInstr *> & - getWaitingQueueFor(const MachineInstr *MI) const { - assert(WaitingQueues.count(MI) && "Instruction was not visited!"); - return WaitingQueues.find(MI)->getSecond(); - }; - - /// Add WaitingForMI to MI's WaitingQueue. - void addToWaitingQueue(const MachineInstr *MI, - const MachineInstr *WaitingForMI) { - assert(WaitingQueues.count(MI) && "Instruction was not visited!"); - WaitingQueues.find(MI)->getSecond().push_back(WaitingForMI); - }; - - public: - InstType determineInstType(const MachineInstr *MI); - - void cleanupIfNewFunction(llvm::StringRef FunctionName); - }; -}; -} // end namespace llvm -#endif diff --git a/contrib/llvm/lib/Target/Mips/MipsRegisterBanks.td b/contrib/llvm/lib/Target/Mips/MipsRegisterBanks.td deleted file mode 100644 index 14a0181f8f11..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsRegisterBanks.td +++ /dev/null @@ -1,14 +0,0 @@ -//===- MipsRegisterBank.td ---------------------------------*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// -//===----------------------------------------------------------------------===// - -def GPRBRegBank : RegisterBank<"GPRB", [GPR32]>; - -def FPRBRegBank : RegisterBank<"FPRB", [FGR64, AFGR64]>; diff --git a/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.cpp b/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.cpp deleted file mode 100644 index 7b02d126eb28..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.cpp +++ /dev/null @@ -1,326 +0,0 @@ -//===- MipsRegisterInfo.cpp - MIPS Register Information -------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains the MIPS implementation of the TargetRegisterInfo class. -// -//===----------------------------------------------------------------------===// - -#include "MipsRegisterInfo.h" -#include "MCTargetDesc/MipsABIInfo.h" -#include "Mips.h" -#include "MipsMachineFunction.h" -#include "MipsSubtarget.h" -#include "MipsTargetMachine.h" -#include "llvm/ADT/BitVector.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/TargetFrameLowering.h" -#include "llvm/CodeGen/TargetRegisterInfo.h" -#include "llvm/CodeGen/TargetSubtargetInfo.h" -#include "llvm/IR/Function.h" -#include "llvm/MC/MCRegisterInfo.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" -#include <cstdint> - -using namespace llvm; - -#define DEBUG_TYPE "mips-reg-info" - -#define GET_REGINFO_TARGET_DESC -#include "MipsGenRegisterInfo.inc" - -MipsRegisterInfo::MipsRegisterInfo() : MipsGenRegisterInfo(Mips::RA) {} - -unsigned MipsRegisterInfo::getPICCallReg() { return Mips::T9; } - -const TargetRegisterClass * -MipsRegisterInfo::getPointerRegClass(const MachineFunction &MF, - unsigned Kind) const { - MipsABIInfo ABI = MF.getSubtarget<MipsSubtarget>().getABI(); - MipsPtrClass PtrClassKind = static_cast<MipsPtrClass>(Kind); - - switch (PtrClassKind) { - case MipsPtrClass::Default: - return ABI.ArePtrs64bit() ? &Mips::GPR64RegClass : &Mips::GPR32RegClass; - case MipsPtrClass::GPR16MM: - return &Mips::GPRMM16RegClass; - case MipsPtrClass::StackPointer: - return ABI.ArePtrs64bit() ? &Mips::SP64RegClass : &Mips::SP32RegClass; - case MipsPtrClass::GlobalPointer: - return ABI.ArePtrs64bit() ? &Mips::GP64RegClass : &Mips::GP32RegClass; - } - - llvm_unreachable("Unknown pointer kind"); -} - -unsigned -MipsRegisterInfo::getRegPressureLimit(const TargetRegisterClass *RC, - MachineFunction &MF) const { - switch (RC->getID()) { - default: - return 0; - case Mips::GPR32RegClassID: - case Mips::GPR64RegClassID: - case Mips::DSPRRegClassID: { - const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering(); - return 28 - TFI->hasFP(MF); - } - case Mips::FGR32RegClassID: - return 32; - case Mips::AFGR64RegClassID: - return 16; - case Mips::FGR64RegClassID: - return 32; - } -} - -//===----------------------------------------------------------------------===// -// Callee Saved Registers methods -//===----------------------------------------------------------------------===// - -/// Mips Callee Saved Registers -const MCPhysReg * -MipsRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { - const MipsSubtarget &Subtarget = MF->getSubtarget<MipsSubtarget>(); - const Function &F = MF->getFunction(); - if (F.hasFnAttribute("interrupt")) { - if (Subtarget.hasMips64()) - return Subtarget.hasMips64r6() ? CSR_Interrupt_64R6_SaveList - : CSR_Interrupt_64_SaveList; - else - return Subtarget.hasMips32r6() ? CSR_Interrupt_32R6_SaveList - : CSR_Interrupt_32_SaveList; - } - - if (Subtarget.isSingleFloat()) - return CSR_SingleFloatOnly_SaveList; - - if (Subtarget.isABI_N64()) - return CSR_N64_SaveList; - - if (Subtarget.isABI_N32()) - return CSR_N32_SaveList; - - if (Subtarget.isFP64bit()) - return CSR_O32_FP64_SaveList; - - if (Subtarget.isFPXX()) - return CSR_O32_FPXX_SaveList; - - return CSR_O32_SaveList; -} - -const uint32_t * -MipsRegisterInfo::getCallPreservedMask(const MachineFunction &MF, - CallingConv::ID) const { - const MipsSubtarget &Subtarget = MF.getSubtarget<MipsSubtarget>(); - if (Subtarget.isSingleFloat()) - return CSR_SingleFloatOnly_RegMask; - - if (Subtarget.isABI_N64()) - return CSR_N64_RegMask; - - if (Subtarget.isABI_N32()) - return CSR_N32_RegMask; - - if (Subtarget.isFP64bit()) - return CSR_O32_FP64_RegMask; - - if (Subtarget.isFPXX()) - return CSR_O32_FPXX_RegMask; - - return CSR_O32_RegMask; -} - -const uint32_t *MipsRegisterInfo::getMips16RetHelperMask() { - return CSR_Mips16RetHelper_RegMask; -} - -BitVector MipsRegisterInfo:: -getReservedRegs(const MachineFunction &MF) const { - static const MCPhysReg ReservedGPR32[] = { - Mips::ZERO, Mips::K0, Mips::K1, Mips::SP - }; - - static const MCPhysReg ReservedGPR64[] = { - Mips::ZERO_64, Mips::K0_64, Mips::K1_64, Mips::SP_64 - }; - - BitVector Reserved(getNumRegs()); - const MipsSubtarget &Subtarget = MF.getSubtarget<MipsSubtarget>(); - - for (unsigned I = 0; I < array_lengthof(ReservedGPR32); ++I) - Reserved.set(ReservedGPR32[I]); - - // Reserve registers for the NaCl sandbox. - if (Subtarget.isTargetNaCl()) { - Reserved.set(Mips::T6); // Reserved for control flow mask. - Reserved.set(Mips::T7); // Reserved for memory access mask. - Reserved.set(Mips::T8); // Reserved for thread pointer. - } - - for (unsigned I = 0; I < array_lengthof(ReservedGPR64); ++I) - Reserved.set(ReservedGPR64[I]); - - // For mno-abicalls, GP is a program invariant! - if (!Subtarget.isABICalls()) { - Reserved.set(Mips::GP); - Reserved.set(Mips::GP_64); - } - - if (Subtarget.isFP64bit()) { - // Reserve all registers in AFGR64. - for (MCPhysReg Reg : Mips::AFGR64RegClass) - Reserved.set(Reg); - } else { - // Reserve all registers in FGR64. - for (MCPhysReg Reg : Mips::FGR64RegClass) - Reserved.set(Reg); - } - // Reserve FP if this function should have a dedicated frame pointer register. - if (Subtarget.getFrameLowering()->hasFP(MF)) { - if (Subtarget.inMips16Mode()) - Reserved.set(Mips::S0); - else { - Reserved.set(Mips::FP); - Reserved.set(Mips::FP_64); - - // Reserve the base register if we need to both realign the stack and - // allocate variable-sized objects at runtime. This should test the - // same conditions as MipsFrameLowering::hasBP(). - if (needsStackRealignment(MF) && - MF.getFrameInfo().hasVarSizedObjects()) { - Reserved.set(Mips::S7); - Reserved.set(Mips::S7_64); - } - } - } - - // Reserve hardware registers. - Reserved.set(Mips::HWR29); - - // Reserve DSP control register. - Reserved.set(Mips::DSPPos); - Reserved.set(Mips::DSPSCount); - Reserved.set(Mips::DSPCarry); - Reserved.set(Mips::DSPEFI); - Reserved.set(Mips::DSPOutFlag); - - // Reserve MSA control registers. - for (MCPhysReg Reg : Mips::MSACtrlRegClass) - Reserved.set(Reg); - - // Reserve RA if in mips16 mode. - if (Subtarget.inMips16Mode()) { - const MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); - Reserved.set(Mips::RA); - Reserved.set(Mips::RA_64); - Reserved.set(Mips::T0); - Reserved.set(Mips::T1); - if (MF.getFunction().hasFnAttribute("saveS2") || MipsFI->hasSaveS2()) - Reserved.set(Mips::S2); - } - - // Reserve GP if small section is used. - if (Subtarget.useSmallSection()) { - Reserved.set(Mips::GP); - Reserved.set(Mips::GP_64); - } - - return Reserved; -} - -bool -MipsRegisterInfo::requiresRegisterScavenging(const MachineFunction &MF) const { - return true; -} - -bool -MipsRegisterInfo::trackLivenessAfterRegAlloc(const MachineFunction &MF) const { - return true; -} - -// FrameIndex represent objects inside a abstract stack. -// We must replace FrameIndex with an stack/frame pointer -// direct reference. -void MipsRegisterInfo:: -eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, - unsigned FIOperandNum, RegScavenger *RS) const { - MachineInstr &MI = *II; - MachineFunction &MF = *MI.getParent()->getParent(); - - LLVM_DEBUG(errs() << "\nFunction : " << MF.getName() << "\n"; - errs() << "<--------->\n" - << MI); - - int FrameIndex = MI.getOperand(FIOperandNum).getIndex(); - uint64_t stackSize = MF.getFrameInfo().getStackSize(); - int64_t spOffset = MF.getFrameInfo().getObjectOffset(FrameIndex); - - LLVM_DEBUG(errs() << "FrameIndex : " << FrameIndex << "\n" - << "spOffset : " << spOffset << "\n" - << "stackSize : " << stackSize << "\n" - << "alignment : " - << MF.getFrameInfo().getObjectAlignment(FrameIndex) - << "\n"); - - eliminateFI(MI, FIOperandNum, FrameIndex, stackSize, spOffset); -} - -Register MipsRegisterInfo:: -getFrameRegister(const MachineFunction &MF) const { - const MipsSubtarget &Subtarget = MF.getSubtarget<MipsSubtarget>(); - const TargetFrameLowering *TFI = Subtarget.getFrameLowering(); - bool IsN64 = - static_cast<const MipsTargetMachine &>(MF.getTarget()).getABI().IsN64(); - - if (Subtarget.inMips16Mode()) - return TFI->hasFP(MF) ? Mips::S0 : Mips::SP; - else - return TFI->hasFP(MF) ? (IsN64 ? Mips::FP_64 : Mips::FP) : - (IsN64 ? Mips::SP_64 : Mips::SP); -} - -bool MipsRegisterInfo::canRealignStack(const MachineFunction &MF) const { - // Avoid realigning functions that explicitly do not want to be realigned. - // Normally, we should report an error when a function should be dynamically - // realigned but also has the attribute no-realign-stack. Unfortunately, - // with this attribute, MachineFrameInfo clamps each new object's alignment - // to that of the stack's alignment as specified by the ABI. As a result, - // the information of whether we have objects with larger alignment - // requirement than the stack's alignment is already lost at this point. - if (!TargetRegisterInfo::canRealignStack(MF)) - return false; - - const MipsSubtarget &Subtarget = MF.getSubtarget<MipsSubtarget>(); - unsigned FP = Subtarget.isGP32bit() ? Mips::FP : Mips::FP_64; - unsigned BP = Subtarget.isGP32bit() ? Mips::S7 : Mips::S7_64; - - // Support dynamic stack realignment for all targets except Mips16. - if (Subtarget.inMips16Mode()) - return false; - - // We can't perform dynamic stack realignment if we can't reserve the - // frame pointer register. - if (!MF.getRegInfo().canReserveReg(FP)) - return false; - - // We can realign the stack if we know the maximum call frame size and we - // don't have variable sized objects. - if (Subtarget.getFrameLowering()->hasReservedCallFrame(MF)) - return true; - - // We have to reserve the base pointer register in the presence of variable - // sized objects. - return MF.getRegInfo().canReserveReg(BP); -} diff --git a/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.h b/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.h deleted file mode 100644 index 4ed32b09718b..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.h +++ /dev/null @@ -1,85 +0,0 @@ -//===- MipsRegisterInfo.h - Mips Register Information Impl ------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains the Mips implementation of the TargetRegisterInfo class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_MIPS_MIPSREGISTERINFO_H -#define LLVM_LIB_TARGET_MIPS_MIPSREGISTERINFO_H - -#include "Mips.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include <cstdint> - -#define GET_REGINFO_HEADER -#include "MipsGenRegisterInfo.inc" - -namespace llvm { - -class TargetRegisterClass; - -class MipsRegisterInfo : public MipsGenRegisterInfo { -public: - enum class MipsPtrClass { - /// The default register class for integer values. - Default = 0, - /// The subset of registers permitted in certain microMIPS instructions - /// such as lw16. - GPR16MM = 1, - /// The stack pointer only. - StackPointer = 2, - /// The global pointer only. - GlobalPointer = 3, - }; - - MipsRegisterInfo(); - - /// Get PIC indirect call register - static unsigned getPICCallReg(); - - /// Code Generation virtual methods... - const TargetRegisterClass *getPointerRegClass(const MachineFunction &MF, - unsigned Kind) const override; - - unsigned getRegPressureLimit(const TargetRegisterClass *RC, - MachineFunction &MF) const override; - const MCPhysReg *getCalleeSavedRegs(const MachineFunction *MF) const override; - const uint32_t *getCallPreservedMask(const MachineFunction &MF, - CallingConv::ID) const override; - static const uint32_t *getMips16RetHelperMask(); - - BitVector getReservedRegs(const MachineFunction &MF) const override; - - bool requiresRegisterScavenging(const MachineFunction &MF) const override; - - bool trackLivenessAfterRegAlloc(const MachineFunction &MF) const override; - - /// Stack Frame Processing Methods - void eliminateFrameIndex(MachineBasicBlock::iterator II, - int SPAdj, unsigned FIOperandNum, - RegScavenger *RS = nullptr) const override; - - // Stack realignment queries. - bool canRealignStack(const MachineFunction &MF) const override; - - /// Debug information queries. - Register getFrameRegister(const MachineFunction &MF) const override; - - /// Return GPR register class. - virtual const TargetRegisterClass *intRegClass(unsigned Size) const = 0; - -private: - virtual void eliminateFI(MachineBasicBlock::iterator II, unsigned OpNo, - int FrameIndex, uint64_t StackSize, - int64_t SPOffset) const = 0; -}; - -} // end namespace llvm - -#endif // LLVM_LIB_TARGET_MIPS_MIPSREGISTERINFO_H diff --git a/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.td b/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.td deleted file mode 100644 index 8a6279da46b7..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.td +++ /dev/null @@ -1,758 +0,0 @@ -//===-- MipsRegisterInfo.td - Mips Register defs -----------*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// Declarations that describe the MIPS register file -//===----------------------------------------------------------------------===// -let Namespace = "Mips" in { -def sub_32 : SubRegIndex<32>; -def sub_64 : SubRegIndex<64>; -def sub_lo : SubRegIndex<32>; -def sub_hi : SubRegIndex<32, 32>; -def sub_dsp16_19 : SubRegIndex<4, 16>; -def sub_dsp20 : SubRegIndex<1, 20>; -def sub_dsp21 : SubRegIndex<1, 21>; -def sub_dsp22 : SubRegIndex<1, 22>; -def sub_dsp23 : SubRegIndex<1, 23>; -} - -class Unallocatable { - bit isAllocatable = 0; -} - -// We have banks of 32 registers each. -class MipsReg<bits<16> Enc, string n> : Register<n> { - let HWEncoding = Enc; - let Namespace = "Mips"; -} - -class MipsRegWithSubRegs<bits<16> Enc, string n, list<Register> subregs> - : RegisterWithSubRegs<n, subregs> { - let HWEncoding = Enc; - let Namespace = "Mips"; -} - -// Mips CPU Registers. -class MipsGPRReg<bits<16> Enc, string n> : MipsReg<Enc, n>; - -// Mips 64-bit CPU Registers -class Mips64GPRReg<bits<16> Enc, string n, list<Register> subregs> - : MipsRegWithSubRegs<Enc, n, subregs> { - let SubRegIndices = [sub_32]; -} - -// Mips 32-bit FPU Registers -class FPR<bits<16> Enc, string n> : MipsReg<Enc, n>; - -// Mips 64-bit (aliased) FPU Registers -class AFPR<bits<16> Enc, string n, list<Register> subregs> - : MipsRegWithSubRegs<Enc, n, subregs> { - let SubRegIndices = [sub_lo, sub_hi]; - let CoveredBySubRegs = 1; -} - -class AFPR64<bits<16> Enc, string n, list<Register> subregs> - : MipsRegWithSubRegs<Enc, n, subregs> { - let SubRegIndices = [sub_lo, sub_hi]; - let CoveredBySubRegs = 1; -} - -// Mips 128-bit (aliased) MSA Registers -class AFPR128<bits<16> Enc, string n, list<Register> subregs> - : MipsRegWithSubRegs<Enc, n, subregs> { - let SubRegIndices = [sub_64]; -} - -// Accumulator Registers -class ACCReg<bits<16> Enc, string n, list<Register> subregs> - : MipsRegWithSubRegs<Enc, n, subregs> { - let SubRegIndices = [sub_lo, sub_hi]; - let CoveredBySubRegs = 1; -} - -// Mips Hardware Registers -class HWR<bits<16> Enc, string n> : MipsReg<Enc, n>; - -//===----------------------------------------------------------------------===// -// Registers -//===----------------------------------------------------------------------===// - -let Namespace = "Mips" in { - // General Purpose Registers - def ZERO : MipsGPRReg< 0, "zero">, DwarfRegNum<[0]>; - def AT : MipsGPRReg< 1, "1">, DwarfRegNum<[1]>; - def V0 : MipsGPRReg< 2, "2">, DwarfRegNum<[2]>; - def V1 : MipsGPRReg< 3, "3">, DwarfRegNum<[3]>; - def A0 : MipsGPRReg< 4, "4">, DwarfRegNum<[4]>; - def A1 : MipsGPRReg< 5, "5">, DwarfRegNum<[5]>; - def A2 : MipsGPRReg< 6, "6">, DwarfRegNum<[6]>; - def A3 : MipsGPRReg< 7, "7">, DwarfRegNum<[7]>; - def T0 : MipsGPRReg< 8, "8">, DwarfRegNum<[8]>; - def T1 : MipsGPRReg< 9, "9">, DwarfRegNum<[9]>; - def T2 : MipsGPRReg< 10, "10">, DwarfRegNum<[10]>; - def T3 : MipsGPRReg< 11, "11">, DwarfRegNum<[11]>; - def T4 : MipsGPRReg< 12, "12">, DwarfRegNum<[12]>; - def T5 : MipsGPRReg< 13, "13">, DwarfRegNum<[13]>; - def T6 : MipsGPRReg< 14, "14">, DwarfRegNum<[14]>; - def T7 : MipsGPRReg< 15, "15">, DwarfRegNum<[15]>; - def S0 : MipsGPRReg< 16, "16">, DwarfRegNum<[16]>; - def S1 : MipsGPRReg< 17, "17">, DwarfRegNum<[17]>; - def S2 : MipsGPRReg< 18, "18">, DwarfRegNum<[18]>; - def S3 : MipsGPRReg< 19, "19">, DwarfRegNum<[19]>; - def S4 : MipsGPRReg< 20, "20">, DwarfRegNum<[20]>; - def S5 : MipsGPRReg< 21, "21">, DwarfRegNum<[21]>; - def S6 : MipsGPRReg< 22, "22">, DwarfRegNum<[22]>; - def S7 : MipsGPRReg< 23, "23">, DwarfRegNum<[23]>; - def T8 : MipsGPRReg< 24, "24">, DwarfRegNum<[24]>; - def T9 : MipsGPRReg< 25, "25">, DwarfRegNum<[25]>; - def K0 : MipsGPRReg< 26, "26">, DwarfRegNum<[26]>; - def K1 : MipsGPRReg< 27, "27">, DwarfRegNum<[27]>; - def GP : MipsGPRReg< 28, "gp">, DwarfRegNum<[28]>; - def SP : MipsGPRReg< 29, "sp">, DwarfRegNum<[29]>; - def FP : MipsGPRReg< 30, "fp">, DwarfRegNum<[30]>; - def RA : MipsGPRReg< 31, "ra">, DwarfRegNum<[31]>; - - // General Purpose 64-bit Registers - def ZERO_64 : Mips64GPRReg< 0, "zero", [ZERO]>, DwarfRegNum<[0]>; - def AT_64 : Mips64GPRReg< 1, "1", [AT]>, DwarfRegNum<[1]>; - def V0_64 : Mips64GPRReg< 2, "2", [V0]>, DwarfRegNum<[2]>; - def V1_64 : Mips64GPRReg< 3, "3", [V1]>, DwarfRegNum<[3]>; - def A0_64 : Mips64GPRReg< 4, "4", [A0]>, DwarfRegNum<[4]>; - def A1_64 : Mips64GPRReg< 5, "5", [A1]>, DwarfRegNum<[5]>; - def A2_64 : Mips64GPRReg< 6, "6", [A2]>, DwarfRegNum<[6]>; - def A3_64 : Mips64GPRReg< 7, "7", [A3]>, DwarfRegNum<[7]>; - def T0_64 : Mips64GPRReg< 8, "8", [T0]>, DwarfRegNum<[8]>; - def T1_64 : Mips64GPRReg< 9, "9", [T1]>, DwarfRegNum<[9]>; - def T2_64 : Mips64GPRReg< 10, "10", [T2]>, DwarfRegNum<[10]>; - def T3_64 : Mips64GPRReg< 11, "11", [T3]>, DwarfRegNum<[11]>; - def T4_64 : Mips64GPRReg< 12, "12", [T4]>, DwarfRegNum<[12]>; - def T5_64 : Mips64GPRReg< 13, "13", [T5]>, DwarfRegNum<[13]>; - def T6_64 : Mips64GPRReg< 14, "14", [T6]>, DwarfRegNum<[14]>; - def T7_64 : Mips64GPRReg< 15, "15", [T7]>, DwarfRegNum<[15]>; - def S0_64 : Mips64GPRReg< 16, "16", [S0]>, DwarfRegNum<[16]>; - def S1_64 : Mips64GPRReg< 17, "17", [S1]>, DwarfRegNum<[17]>; - def S2_64 : Mips64GPRReg< 18, "18", [S2]>, DwarfRegNum<[18]>; - def S3_64 : Mips64GPRReg< 19, "19", [S3]>, DwarfRegNum<[19]>; - def S4_64 : Mips64GPRReg< 20, "20", [S4]>, DwarfRegNum<[20]>; - def S5_64 : Mips64GPRReg< 21, "21", [S5]>, DwarfRegNum<[21]>; - def S6_64 : Mips64GPRReg< 22, "22", [S6]>, DwarfRegNum<[22]>; - def S7_64 : Mips64GPRReg< 23, "23", [S7]>, DwarfRegNum<[23]>; - def T8_64 : Mips64GPRReg< 24, "24", [T8]>, DwarfRegNum<[24]>; - def T9_64 : Mips64GPRReg< 25, "25", [T9]>, DwarfRegNum<[25]>; - def K0_64 : Mips64GPRReg< 26, "26", [K0]>, DwarfRegNum<[26]>; - def K1_64 : Mips64GPRReg< 27, "27", [K1]>, DwarfRegNum<[27]>; - def GP_64 : Mips64GPRReg< 28, "gp", [GP]>, DwarfRegNum<[28]>; - def SP_64 : Mips64GPRReg< 29, "sp", [SP]>, DwarfRegNum<[29]>; - def FP_64 : Mips64GPRReg< 30, "fp", [FP]>, DwarfRegNum<[30]>; - def RA_64 : Mips64GPRReg< 31, "ra", [RA]>, DwarfRegNum<[31]>; - - /// Mips Single point precision FPU Registers - foreach I = 0-31 in - def F#I : FPR<I, "f"#I>, DwarfRegNum<[!add(I, 32)]>; - - // Higher half of 64-bit FP registers. - foreach I = 0-31 in - def F_HI#I : FPR<I, "f"#I>, DwarfRegNum<[!add(I, 32)]>; - - /// Mips Double point precision FPU Registers (aliased - /// with the single precision to hold 64 bit values) - foreach I = 0-15 in - def D#I : AFPR<!shl(I, 1), "f"#!shl(I, 1), - [!cast<FPR>("F"#!shl(I, 1)), - !cast<FPR>("F"#!add(!shl(I, 1), 1))]>; - - /// Mips Double point precision FPU Registers in MFP64 mode. - foreach I = 0-31 in - def D#I#_64 : AFPR64<I, "f"#I, [!cast<FPR>("F"#I), !cast<FPR>("F_HI"#I)]>, - DwarfRegNum<[!add(I, 32)]>; - - /// Mips MSA registers - /// MSA and FPU cannot both be present unless the FPU has 64-bit registers - foreach I = 0-31 in - def W#I : AFPR128<I, "w"#I, [!cast<AFPR64>("D"#I#"_64")]>, - DwarfRegNum<[!add(I, 32)]>; - - // Hi/Lo registers - def HI0 : MipsReg<0, "ac0">, DwarfRegNum<[64]>; - def HI1 : MipsReg<1, "ac1">, DwarfRegNum<[176]>; - def HI2 : MipsReg<2, "ac2">, DwarfRegNum<[178]>; - def HI3 : MipsReg<3, "ac3">, DwarfRegNum<[180]>; - def LO0 : MipsReg<0, "ac0">, DwarfRegNum<[65]>; - def LO1 : MipsReg<1, "ac1">, DwarfRegNum<[177]>; - def LO2 : MipsReg<2, "ac2">, DwarfRegNum<[179]>; - def LO3 : MipsReg<3, "ac3">, DwarfRegNum<[181]>; - - let SubRegIndices = [sub_32] in { - def HI0_64 : RegisterWithSubRegs<"hi", [HI0]>; - def LO0_64 : RegisterWithSubRegs<"lo", [LO0]>; - } - - // FP control registers. - foreach I = 0-31 in - def FCR#I : MipsReg<#I, ""#I>; - - // FP condition code registers. - foreach I = 0-7 in - def FCC#I : MipsReg<#I, "fcc"#I>; - - // COP0 registers. - foreach I = 0-31 in - def COP0#I : MipsReg<#I, ""#I>; - - // COP2 registers. - foreach I = 0-31 in - def COP2#I : MipsReg<#I, ""#I>; - - // COP3 registers. - foreach I = 0-31 in - def COP3#I : MipsReg<#I, ""#I>; - - // PC register - def PC : Register<"pc">; - - // Hardware registers - def HWR0 : MipsReg<0, "hwr_cpunum">; - def HWR1 : MipsReg<1, "hwr_synci_step">; - def HWR2 : MipsReg<2, "hwr_cc">; - def HWR3 : MipsReg<3, "hwr_ccres">; - - foreach I = 4-31 in - def HWR#I : MipsReg<#I, ""#I>; - - // Accum registers - foreach I = 0-3 in - def AC#I : ACCReg<#I, "ac"#I, - [!cast<Register>("LO"#I), !cast<Register>("HI"#I)]>; - - def AC0_64 : ACCReg<0, "ac0", [LO0_64, HI0_64]>; - - // DSP-ASE control register fields. - def DSPPos : Register<"">; - def DSPSCount : Register<"">; - def DSPCarry : Register<"">; - def DSPEFI : Register<"">; - def DSPOutFlag16_19 : Register<"">; - def DSPOutFlag20 : Register<"">; - def DSPOutFlag21 : Register<"">; - def DSPOutFlag22 : Register<"">; - def DSPOutFlag23 : Register<"">; - def DSPCCond : Register<"">; - - let SubRegIndices = [sub_dsp16_19, sub_dsp20, sub_dsp21, sub_dsp22, - sub_dsp23] in - def DSPOutFlag : RegisterWithSubRegs<"", [DSPOutFlag16_19, DSPOutFlag20, - DSPOutFlag21, DSPOutFlag22, - DSPOutFlag23]>; - - // MSA-ASE control registers. - def MSAIR : MipsReg<0, "0">; - def MSACSR : MipsReg<1, "1">; - def MSAAccess : MipsReg<2, "2">; - def MSASave : MipsReg<3, "3">; - def MSAModify : MipsReg<4, "4">; - def MSARequest : MipsReg<5, "5">; - def MSAMap : MipsReg<6, "6">; - def MSAUnmap : MipsReg<7, "7">; - // MSA-ASE fake control registers. - // These registers do not exist, but instructions like `cfcmsa` - // and `ctcmsa` allows to specify them. - foreach I = 8-31 in - def MSA#I : MipsReg<#I, ""#I>; - - // Octeon multiplier and product registers - def MPL0 : MipsReg<0, "mpl0">; - def MPL1 : MipsReg<1, "mpl1">; - def MPL2 : MipsReg<2, "mpl2">; - def P0 : MipsReg<0, "p0">; - def P1 : MipsReg<1, "p1">; - def P2 : MipsReg<2, "p2">; - -} - -//===----------------------------------------------------------------------===// -// Register Classes -//===----------------------------------------------------------------------===// - -class GPR32Class<list<ValueType> regTypes> : - RegisterClass<"Mips", regTypes, 32, (add - // Reserved - ZERO, AT, - // Return Values and Arguments - V0, V1, A0, A1, A2, A3, - // Not preserved across procedure calls - T0, T1, T2, T3, T4, T5, T6, T7, - // Callee save - S0, S1, S2, S3, S4, S5, S6, S7, - // Not preserved across procedure calls - T8, T9, - // Reserved - K0, K1, GP, SP, FP, RA)>; - -def GPR32 : GPR32Class<[i32]>; - -def GPR32ZERO : RegisterClass<"Mips", [i32], 32, (add - // Reserved - ZERO)>; - -def GPR32NONZERO : RegisterClass<"Mips", [i32], 32, (add - // Reserved - AT, - // Return Values and Arguments - V0, V1, A0, A1, A2, A3, - // Not preserved across procedure calls - T0, T1, T2, T3, T4, T5, T6, T7, - // Callee save - S0, S1, S2, S3, S4, S5, S6, S7, - // Not preserved across procedure calls - T8, T9, - // Reserved - K0, K1, GP, SP, FP, RA)>; - -def DSPR : GPR32Class<[v4i8, v2i16]>; - -def GPRMM16 : RegisterClass<"Mips", [i32], 32, (add - // Callee save - S0, S1, - // Return Values and Arguments - V0, V1, A0, A1, A2, A3)>; - -def GPRMM16Zero : RegisterClass<"Mips", [i32], 32, (add - // Reserved - ZERO, - // Callee save - S1, - // Return Values and Arguments - V0, V1, A0, A1, A2, A3)>; - -def GPRMM16MoveP : RegisterClass<"Mips", [i32], 32, (add - // Reserved - ZERO, - // Callee save - S1, - // Return Values and Arguments - V0, V1, - // Callee save - S0, S2, S3, S4)>; - -def GPRMM16MovePPairFirst : RegisterClass<"Mips", [i32], 32, (add - // Arguments - A0, A1, A2)>; - -def GPRMM16MovePPairSecond : RegisterClass<"Mips", [i32], 32, (add - // Arguments - A1, A2, A3, - // Callee save - S5, S6)>; - -def GPR64 : RegisterClass<"Mips", [i64], 64, (add - // Reserved - ZERO_64, AT_64, - // Return Values and Arguments - V0_64, V1_64, A0_64, A1_64, A2_64, A3_64, - // Not preserved across procedure calls - T0_64, T1_64, T2_64, T3_64, T4_64, T5_64, T6_64, T7_64, - // Callee save - S0_64, S1_64, S2_64, S3_64, S4_64, S5_64, S6_64, S7_64, - // Not preserved across procedure calls - T8_64, T9_64, - // Reserved - K0_64, K1_64, GP_64, SP_64, FP_64, RA_64)>; - -def CPU16Regs : RegisterClass<"Mips", [i32], 32, (add - // Return Values and Arguments - V0, V1, A0, A1, A2, A3, - // Callee save - S0, S1)>; - -def CPU16RegsPlusSP : RegisterClass<"Mips", [i32], 32, (add - // Return Values and Arguments - V0, V1, A0, A1, A2, A3, - // Callee save - S0, S1, - SP)>; - -def CPURAReg : RegisterClass<"Mips", [i32], 32, (add RA)>, Unallocatable; - -def CPUSPReg : RegisterClass<"Mips", [i32], 32, (add SP)>, Unallocatable; - -// 64bit fp: -// * FGR64 - 32 64-bit registers -// * AFGR64 - 16 32-bit even registers (32-bit FP Mode) -// -// 32bit fp: -// * FGR32 - 16 32-bit even registers -// * FGR32 - 32 32-bit registers (single float only mode) -def FGR32 : RegisterClass<"Mips", [f32], 32, (sequence "F%u", 0, 31)> { - // Do not allocate odd registers when given -mattr=+nooddspreg. - let AltOrders = [(decimate FGR32, 2)]; - let AltOrderSelect = [{ - const auto & S = MF.getSubtarget<MipsSubtarget>(); - return S.isABI_O32() && !S.useOddSPReg(); - }]; -} - -def AFGR64 : RegisterClass<"Mips", [f64], 64, (add - // Return Values and Arguments - D0, D1, - // Not preserved across procedure calls - D2, D3, D4, D5, - // Return Values and Arguments - D6, D7, - // Not preserved across procedure calls - D8, D9, - // Callee save - D10, D11, D12, D13, D14, D15)>; - -def FGR64 : RegisterClass<"Mips", [f64], 64, (sequence "D%u_64", 0, 31)> { - // Do not allocate odd registers when given -mattr=+nooddspreg. - let AltOrders = [(decimate FGR64, 2)]; - let AltOrderSelect = [{ - const auto & S = MF.getSubtarget<MipsSubtarget>(); - return S.isABI_O32() && !S.useOddSPReg(); - }]; -} - -// FP control registers. -def CCR : RegisterClass<"Mips", [i32], 32, (sequence "FCR%u", 0, 31)>, - Unallocatable; - -// FP condition code registers. -def FCC : RegisterClass<"Mips", [i32], 32, (sequence "FCC%u", 0, 7)>, - Unallocatable; - -// MIPS32r6/MIPS64r6 store FPU condition codes in normal FGR registers. -// This class allows us to represent this in codegen patterns. -def FGRCC : RegisterClass<"Mips", [i32], 32, (sequence "F%u", 0, 31)>; - -def MSA128F16 : RegisterClass<"Mips", [f16], 128, (sequence "W%u", 0, 31)>; - -def MSA128B: RegisterClass<"Mips", [v16i8], 128, - (sequence "W%u", 0, 31)>; -def MSA128H: RegisterClass<"Mips", [v8i16, v8f16], 128, - (sequence "W%u", 0, 31)>; -def MSA128W: RegisterClass<"Mips", [v4i32, v4f32], 128, - (sequence "W%u", 0, 31)>; -def MSA128D: RegisterClass<"Mips", [v2i64, v2f64], 128, - (sequence "W%u", 0, 31)>; -def MSA128WEvens: RegisterClass<"Mips", [v4i32, v4f32], 128, - (decimate (sequence "W%u", 0, 31), 2)>; - -def MSACtrl: RegisterClass<"Mips", [i32], 32, (add - MSAIR, MSACSR, MSAAccess, MSASave, MSAModify, MSARequest, MSAMap, MSAUnmap, - (sequence "MSA%u", 8, 31))>, Unallocatable; - -// Hi/Lo Registers -def LO32 : RegisterClass<"Mips", [i32], 32, (add LO0)>; -def HI32 : RegisterClass<"Mips", [i32], 32, (add HI0)>; -def LO32DSP : RegisterClass<"Mips", [i32], 32, (sequence "LO%u", 0, 3)>; -def HI32DSP : RegisterClass<"Mips", [i32], 32, (sequence "HI%u", 0, 3)>; -def LO64 : RegisterClass<"Mips", [i64], 64, (add LO0_64)>; -def HI64 : RegisterClass<"Mips", [i64], 64, (add HI0_64)>; - -// Hardware registers -def HWRegs : RegisterClass<"Mips", [i32], 32, (sequence "HWR%u", 0, 31)>, - Unallocatable; - -// Accumulator Registers -def ACC64 : RegisterClass<"Mips", [untyped], 64, (add AC0)> { - let Size = 64; -} - -def ACC128 : RegisterClass<"Mips", [untyped], 128, (add AC0_64)> { - let Size = 128; -} - -def ACC64DSP : RegisterClass<"Mips", [untyped], 64, (sequence "AC%u", 0, 3)> { - let Size = 64; -} - -def DSPCC : RegisterClass<"Mips", [v4i8, v2i16], 32, (add DSPCCond)>; - -// Coprocessor 0 registers. -def COP0 : RegisterClass<"Mips", [i32], 32, (sequence "COP0%u", 0, 31)>, - Unallocatable; - -// Coprocessor 2 registers. -def COP2 : RegisterClass<"Mips", [i32], 32, (sequence "COP2%u", 0, 31)>, - Unallocatable; - -// Coprocessor 3 registers. -def COP3 : RegisterClass<"Mips", [i32], 32, (sequence "COP3%u", 0, 31)>, - Unallocatable; - -// Stack pointer and global pointer classes for instructions that are limited -// to a single register such as lwgp/lwsp in microMIPS. -def SP32 : RegisterClass<"Mips", [i32], 32, (add SP)>, Unallocatable; -def SP64 : RegisterClass<"Mips", [i64], 64, (add SP_64)>, Unallocatable; -def GP32 : RegisterClass<"Mips", [i32], 32, (add GP)>, Unallocatable; -def GP64 : RegisterClass<"Mips", [i64], 64, (add GP_64)>, Unallocatable; - -// Octeon multiplier and product registers -def OCTEON_MPL : RegisterClass<"Mips", [i64], 64, (add MPL0, MPL1, MPL2)>, - Unallocatable; -def OCTEON_P : RegisterClass<"Mips", [i64], 64, (add P0, P1, P2)>, - Unallocatable; - -// Register Operands. - -class MipsAsmRegOperand : AsmOperandClass { - let ParserMethod = "parseAnyRegister"; -} - -def GPR64AsmOperand : MipsAsmRegOperand { - let Name = "GPR64AsmReg"; - let PredicateMethod = "isGPRAsmReg"; -} - -def GPR32ZeroAsmOperand : MipsAsmRegOperand { - let Name = "GPR32ZeroAsmReg"; - let PredicateMethod = "isGPRZeroAsmReg"; -} - -def GPR32NonZeroAsmOperand : MipsAsmRegOperand { - let Name = "GPR32NonZeroAsmReg"; - let PredicateMethod = "isGPRNonZeroAsmReg"; -} - -def GPR32AsmOperand : MipsAsmRegOperand { - let Name = "GPR32AsmReg"; - let PredicateMethod = "isGPRAsmReg"; -} - -def GPRMM16AsmOperand : MipsAsmRegOperand { - let Name = "GPRMM16AsmReg"; - let PredicateMethod = "isMM16AsmReg"; -} - -def GPRMM16AsmOperandZero : MipsAsmRegOperand { - let Name = "GPRMM16AsmRegZero"; - let PredicateMethod = "isMM16AsmRegZero"; -} - -def GPRMM16AsmOperandMoveP : MipsAsmRegOperand { - let Name = "GPRMM16AsmRegMoveP"; - let PredicateMethod = "isMM16AsmRegMoveP"; -} - -def GPRMM16AsmOperandMovePPairFirst : MipsAsmRegOperand { - let Name = "GPRMM16AsmRegMovePPairFirst"; - let PredicateMethod = "isMM16AsmRegMovePPairFirst"; -} - -def GPRMM16AsmOperandMovePPairSecond : MipsAsmRegOperand { - let Name = "GPRMM16AsmRegMovePPairSecond"; - let PredicateMethod = "isMM16AsmRegMovePPairSecond"; -} - -def ACC64DSPAsmOperand : MipsAsmRegOperand { - let Name = "ACC64DSPAsmReg"; - let PredicateMethod = "isACCAsmReg"; -} - -def HI32DSPAsmOperand : MipsAsmRegOperand { - let Name = "HI32DSPAsmReg"; - let PredicateMethod = "isACCAsmReg"; -} - -def LO32DSPAsmOperand : MipsAsmRegOperand { - let Name = "LO32DSPAsmReg"; - let PredicateMethod = "isACCAsmReg"; -} - -def CCRAsmOperand : MipsAsmRegOperand { - let Name = "CCRAsmReg"; -} - -def AFGR64AsmOperand : MipsAsmRegOperand { - let Name = "AFGR64AsmReg"; - let PredicateMethod = "isFGRAsmReg"; -} - -def StrictlyAFGR64AsmOperand : MipsAsmRegOperand { - let Name = "StrictlyAFGR64AsmReg"; - let PredicateMethod = "isStrictlyFGRAsmReg"; -} - -def FGR64AsmOperand : MipsAsmRegOperand { - let Name = "FGR64AsmReg"; - let PredicateMethod = "isFGRAsmReg"; -} - -def StrictlyFGR64AsmOperand : MipsAsmRegOperand { - let Name = "StrictlyFGR64AsmReg"; - let PredicateMethod = "isStrictlyFGRAsmReg"; -} - -def FGR32AsmOperand : MipsAsmRegOperand { - let Name = "FGR32AsmReg"; - let PredicateMethod = "isFGRAsmReg"; -} - -def StrictlyFGR32AsmOperand : MipsAsmRegOperand { - let Name = "StrictlyFGR32AsmReg"; - let PredicateMethod = "isStrictlyFGRAsmReg"; -} - -def FCCRegsAsmOperand : MipsAsmRegOperand { - let Name = "FCCAsmReg"; -} - -def MSA128AsmOperand : MipsAsmRegOperand { - let Name = "MSA128AsmReg"; -} - -def MSACtrlAsmOperand : MipsAsmRegOperand { - let Name = "MSACtrlAsmReg"; -} - -def GPR32ZeroOpnd : RegisterOperand<GPR32ZERO> { - let ParserMatchClass = GPR32ZeroAsmOperand; -} - -def GPR32NonZeroOpnd : RegisterOperand<GPR32NONZERO> { - let ParserMatchClass = GPR32NonZeroAsmOperand; -} - -def GPR32Opnd : RegisterOperand<GPR32> { - let ParserMatchClass = GPR32AsmOperand; -} - -def GPRMM16Opnd : RegisterOperand<GPRMM16> { - let ParserMatchClass = GPRMM16AsmOperand; -} - -def GPRMM16OpndZero : RegisterOperand<GPRMM16Zero> { - let ParserMatchClass = GPRMM16AsmOperandZero; -} - -def GPRMM16OpndMoveP : RegisterOperand<GPRMM16MoveP> { - let ParserMatchClass = GPRMM16AsmOperandMoveP; - let EncoderMethod = "getMovePRegSingleOpValue"; -} - -def GPRMM16OpndMovePPairFirst : RegisterOperand<GPRMM16MovePPairFirst> { - let ParserMatchClass = GPRMM16AsmOperandMovePPairFirst; -} - -def GPRMM16OpndMovePPairSecond : RegisterOperand<GPRMM16MovePPairSecond> { - let ParserMatchClass = GPRMM16AsmOperandMovePPairSecond; -} - -def GPR64Opnd : RegisterOperand<GPR64> { - let ParserMatchClass = GPR64AsmOperand; -} - -def DSPROpnd : RegisterOperand<DSPR> { - let ParserMatchClass = GPR32AsmOperand; -} - -def CCROpnd : RegisterOperand<CCR> { - let ParserMatchClass = CCRAsmOperand; -} - -def HWRegsAsmOperand : MipsAsmRegOperand { - let Name = "HWRegsAsmReg"; -} - -def COP0AsmOperand : MipsAsmRegOperand { - let Name = "COP0AsmReg"; -} - -def COP2AsmOperand : MipsAsmRegOperand { - let Name = "COP2AsmReg"; -} - -def COP3AsmOperand : MipsAsmRegOperand { - let Name = "COP3AsmReg"; -} - -def HWRegsOpnd : RegisterOperand<HWRegs> { - let ParserMatchClass = HWRegsAsmOperand; -} - -def AFGR64Opnd : RegisterOperand<AFGR64> { - let ParserMatchClass = AFGR64AsmOperand; -} - -def StrictlyAFGR64Opnd : RegisterOperand<AFGR64> { - let ParserMatchClass = StrictlyAFGR64AsmOperand; -} - -def FGR64Opnd : RegisterOperand<FGR64> { - let ParserMatchClass = FGR64AsmOperand; -} - -def StrictlyFGR64Opnd : RegisterOperand<FGR64> { - let ParserMatchClass = StrictlyFGR64AsmOperand; -} - -def FGR32Opnd : RegisterOperand<FGR32> { - let ParserMatchClass = FGR32AsmOperand; -} - -def StrictlyFGR32Opnd : RegisterOperand<FGR32> { - let ParserMatchClass = StrictlyFGR32AsmOperand; -} - -def FGRCCOpnd : RegisterOperand<FGRCC> { - // The assembler doesn't use register classes so we can re-use - // FGR32AsmOperand. - let ParserMatchClass = FGR32AsmOperand; -} - -def FCCRegsOpnd : RegisterOperand<FCC> { - let ParserMatchClass = FCCRegsAsmOperand; -} - -def LO32DSPOpnd : RegisterOperand<LO32DSP> { - let ParserMatchClass = LO32DSPAsmOperand; -} - -def HI32DSPOpnd : RegisterOperand<HI32DSP> { - let ParserMatchClass = HI32DSPAsmOperand; -} - -def ACC64DSPOpnd : RegisterOperand<ACC64DSP> { - let ParserMatchClass = ACC64DSPAsmOperand; -} - -def COP0Opnd : RegisterOperand<COP0> { - let ParserMatchClass = COP0AsmOperand; -} - -def COP2Opnd : RegisterOperand<COP2> { - let ParserMatchClass = COP2AsmOperand; -} - -def COP3Opnd : RegisterOperand<COP3> { - let ParserMatchClass = COP3AsmOperand; -} - -def MSA128F16Opnd : RegisterOperand<MSA128F16> { - let ParserMatchClass = MSA128AsmOperand; -} - -def MSA128BOpnd : RegisterOperand<MSA128B> { - let ParserMatchClass = MSA128AsmOperand; -} - -def MSA128HOpnd : RegisterOperand<MSA128H> { - let ParserMatchClass = MSA128AsmOperand; -} - -def MSA128WOpnd : RegisterOperand<MSA128W> { - let ParserMatchClass = MSA128AsmOperand; -} - -def MSA128DOpnd : RegisterOperand<MSA128D> { - let ParserMatchClass = MSA128AsmOperand; -} - -def MSA128CROpnd : RegisterOperand<MSACtrl> { - let ParserMatchClass = MSACtrlAsmOperand; -} diff --git a/contrib/llvm/lib/Target/Mips/MipsSEFrameLowering.cpp b/contrib/llvm/lib/Target/Mips/MipsSEFrameLowering.cpp deleted file mode 100644 index 4c6cc1ef771c..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsSEFrameLowering.cpp +++ /dev/null @@ -1,920 +0,0 @@ -//===- MipsSEFrameLowering.cpp - Mips32/64 Frame Information --------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains the Mips32/64 implementation of TargetFrameLowering class. -// -//===----------------------------------------------------------------------===// - -#include "MipsSEFrameLowering.h" -#include "MCTargetDesc/MipsABIInfo.h" -#include "MipsMachineFunction.h" -#include "MipsRegisterInfo.h" -#include "MipsSEInstrInfo.h" -#include "MipsSubtarget.h" -#include "llvm/ADT/BitVector.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/StringSwitch.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/MachineModuleInfo.h" -#include "llvm/CodeGen/MachineOperand.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/RegisterScavenging.h" -#include "llvm/CodeGen/TargetInstrInfo.h" -#include "llvm/CodeGen/TargetRegisterInfo.h" -#include "llvm/CodeGen/TargetSubtargetInfo.h" -#include "llvm/IR/DebugLoc.h" -#include "llvm/IR/Function.h" -#include "llvm/MC/MCDwarf.h" -#include "llvm/MC/MCRegisterInfo.h" -#include "llvm/MC/MachineLocation.h" -#include "llvm/Support/CodeGen.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MathExtras.h" -#include <cassert> -#include <cstdint> -#include <utility> -#include <vector> - -using namespace llvm; - -static std::pair<unsigned, unsigned> getMFHiLoOpc(unsigned Src) { - if (Mips::ACC64RegClass.contains(Src)) - return std::make_pair((unsigned)Mips::PseudoMFHI, - (unsigned)Mips::PseudoMFLO); - - if (Mips::ACC64DSPRegClass.contains(Src)) - return std::make_pair((unsigned)Mips::MFHI_DSP, (unsigned)Mips::MFLO_DSP); - - if (Mips::ACC128RegClass.contains(Src)) - return std::make_pair((unsigned)Mips::PseudoMFHI64, - (unsigned)Mips::PseudoMFLO64); - - return std::make_pair(0, 0); -} - -namespace { - -/// Helper class to expand pseudos. -class ExpandPseudo { -public: - ExpandPseudo(MachineFunction &MF); - bool expand(); - -private: - using Iter = MachineBasicBlock::iterator; - - bool expandInstr(MachineBasicBlock &MBB, Iter I); - void expandLoadCCond(MachineBasicBlock &MBB, Iter I); - void expandStoreCCond(MachineBasicBlock &MBB, Iter I); - void expandLoadACC(MachineBasicBlock &MBB, Iter I, unsigned RegSize); - void expandStoreACC(MachineBasicBlock &MBB, Iter I, unsigned MFHiOpc, - unsigned MFLoOpc, unsigned RegSize); - bool expandCopy(MachineBasicBlock &MBB, Iter I); - bool expandCopyACC(MachineBasicBlock &MBB, Iter I, unsigned MFHiOpc, - unsigned MFLoOpc); - bool expandBuildPairF64(MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, bool FP64) const; - bool expandExtractElementF64(MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, bool FP64) const; - - MachineFunction &MF; - MachineRegisterInfo &MRI; - const MipsSubtarget &Subtarget; - const MipsSEInstrInfo &TII; - const MipsRegisterInfo &RegInfo; -}; - -} // end anonymous namespace - -ExpandPseudo::ExpandPseudo(MachineFunction &MF_) - : MF(MF_), MRI(MF.getRegInfo()), - Subtarget(static_cast<const MipsSubtarget &>(MF.getSubtarget())), - TII(*static_cast<const MipsSEInstrInfo *>(Subtarget.getInstrInfo())), - RegInfo(*Subtarget.getRegisterInfo()) {} - -bool ExpandPseudo::expand() { - bool Expanded = false; - - for (auto &MBB : MF) { - for (Iter I = MBB.begin(), End = MBB.end(); I != End;) - Expanded |= expandInstr(MBB, I++); - } - - return Expanded; -} - -bool ExpandPseudo::expandInstr(MachineBasicBlock &MBB, Iter I) { - switch(I->getOpcode()) { - case Mips::LOAD_CCOND_DSP: - expandLoadCCond(MBB, I); - break; - case Mips::STORE_CCOND_DSP: - expandStoreCCond(MBB, I); - break; - case Mips::LOAD_ACC64: - case Mips::LOAD_ACC64DSP: - expandLoadACC(MBB, I, 4); - break; - case Mips::LOAD_ACC128: - expandLoadACC(MBB, I, 8); - break; - case Mips::STORE_ACC64: - expandStoreACC(MBB, I, Mips::PseudoMFHI, Mips::PseudoMFLO, 4); - break; - case Mips::STORE_ACC64DSP: - expandStoreACC(MBB, I, Mips::MFHI_DSP, Mips::MFLO_DSP, 4); - break; - case Mips::STORE_ACC128: - expandStoreACC(MBB, I, Mips::PseudoMFHI64, Mips::PseudoMFLO64, 8); - break; - case Mips::BuildPairF64: - if (expandBuildPairF64(MBB, I, false)) - MBB.erase(I); - return false; - case Mips::BuildPairF64_64: - if (expandBuildPairF64(MBB, I, true)) - MBB.erase(I); - return false; - case Mips::ExtractElementF64: - if (expandExtractElementF64(MBB, I, false)) - MBB.erase(I); - return false; - case Mips::ExtractElementF64_64: - if (expandExtractElementF64(MBB, I, true)) - MBB.erase(I); - return false; - case TargetOpcode::COPY: - if (!expandCopy(MBB, I)) - return false; - break; - default: - return false; - } - - MBB.erase(I); - return true; -} - -void ExpandPseudo::expandLoadCCond(MachineBasicBlock &MBB, Iter I) { - // load $vr, FI - // copy ccond, $vr - - assert(I->getOperand(0).isReg() && I->getOperand(1).isFI()); - - const TargetRegisterClass *RC = RegInfo.intRegClass(4); - unsigned VR = MRI.createVirtualRegister(RC); - unsigned Dst = I->getOperand(0).getReg(), FI = I->getOperand(1).getIndex(); - - TII.loadRegFromStack(MBB, I, VR, FI, RC, &RegInfo, 0); - BuildMI(MBB, I, I->getDebugLoc(), TII.get(TargetOpcode::COPY), Dst) - .addReg(VR, RegState::Kill); -} - -void ExpandPseudo::expandStoreCCond(MachineBasicBlock &MBB, Iter I) { - // copy $vr, ccond - // store $vr, FI - - assert(I->getOperand(0).isReg() && I->getOperand(1).isFI()); - - const TargetRegisterClass *RC = RegInfo.intRegClass(4); - unsigned VR = MRI.createVirtualRegister(RC); - unsigned Src = I->getOperand(0).getReg(), FI = I->getOperand(1).getIndex(); - - BuildMI(MBB, I, I->getDebugLoc(), TII.get(TargetOpcode::COPY), VR) - .addReg(Src, getKillRegState(I->getOperand(0).isKill())); - TII.storeRegToStack(MBB, I, VR, true, FI, RC, &RegInfo, 0); -} - -void ExpandPseudo::expandLoadACC(MachineBasicBlock &MBB, Iter I, - unsigned RegSize) { - // load $vr0, FI - // copy lo, $vr0 - // load $vr1, FI + 4 - // copy hi, $vr1 - - assert(I->getOperand(0).isReg() && I->getOperand(1).isFI()); - - const TargetRegisterClass *RC = RegInfo.intRegClass(RegSize); - unsigned VR0 = MRI.createVirtualRegister(RC); - unsigned VR1 = MRI.createVirtualRegister(RC); - unsigned Dst = I->getOperand(0).getReg(), FI = I->getOperand(1).getIndex(); - unsigned Lo = RegInfo.getSubReg(Dst, Mips::sub_lo); - unsigned Hi = RegInfo.getSubReg(Dst, Mips::sub_hi); - DebugLoc DL = I->getDebugLoc(); - const MCInstrDesc &Desc = TII.get(TargetOpcode::COPY); - - TII.loadRegFromStack(MBB, I, VR0, FI, RC, &RegInfo, 0); - BuildMI(MBB, I, DL, Desc, Lo).addReg(VR0, RegState::Kill); - TII.loadRegFromStack(MBB, I, VR1, FI, RC, &RegInfo, RegSize); - BuildMI(MBB, I, DL, Desc, Hi).addReg(VR1, RegState::Kill); -} - -void ExpandPseudo::expandStoreACC(MachineBasicBlock &MBB, Iter I, - unsigned MFHiOpc, unsigned MFLoOpc, - unsigned RegSize) { - // mflo $vr0, src - // store $vr0, FI - // mfhi $vr1, src - // store $vr1, FI + 4 - - assert(I->getOperand(0).isReg() && I->getOperand(1).isFI()); - - const TargetRegisterClass *RC = RegInfo.intRegClass(RegSize); - unsigned VR0 = MRI.createVirtualRegister(RC); - unsigned VR1 = MRI.createVirtualRegister(RC); - unsigned Src = I->getOperand(0).getReg(), FI = I->getOperand(1).getIndex(); - unsigned SrcKill = getKillRegState(I->getOperand(0).isKill()); - DebugLoc DL = I->getDebugLoc(); - - BuildMI(MBB, I, DL, TII.get(MFLoOpc), VR0).addReg(Src); - TII.storeRegToStack(MBB, I, VR0, true, FI, RC, &RegInfo, 0); - BuildMI(MBB, I, DL, TII.get(MFHiOpc), VR1).addReg(Src, SrcKill); - TII.storeRegToStack(MBB, I, VR1, true, FI, RC, &RegInfo, RegSize); -} - -bool ExpandPseudo::expandCopy(MachineBasicBlock &MBB, Iter I) { - unsigned Src = I->getOperand(1).getReg(); - std::pair<unsigned, unsigned> Opcodes = getMFHiLoOpc(Src); - - if (!Opcodes.first) - return false; - - return expandCopyACC(MBB, I, Opcodes.first, Opcodes.second); -} - -bool ExpandPseudo::expandCopyACC(MachineBasicBlock &MBB, Iter I, - unsigned MFHiOpc, unsigned MFLoOpc) { - // mflo $vr0, src - // copy dst_lo, $vr0 - // mfhi $vr1, src - // copy dst_hi, $vr1 - - unsigned Dst = I->getOperand(0).getReg(), Src = I->getOperand(1).getReg(); - const TargetRegisterClass *DstRC = RegInfo.getMinimalPhysRegClass(Dst); - unsigned VRegSize = RegInfo.getRegSizeInBits(*DstRC) / 16; - const TargetRegisterClass *RC = RegInfo.intRegClass(VRegSize); - unsigned VR0 = MRI.createVirtualRegister(RC); - unsigned VR1 = MRI.createVirtualRegister(RC); - unsigned SrcKill = getKillRegState(I->getOperand(1).isKill()); - unsigned DstLo = RegInfo.getSubReg(Dst, Mips::sub_lo); - unsigned DstHi = RegInfo.getSubReg(Dst, Mips::sub_hi); - DebugLoc DL = I->getDebugLoc(); - - BuildMI(MBB, I, DL, TII.get(MFLoOpc), VR0).addReg(Src); - BuildMI(MBB, I, DL, TII.get(TargetOpcode::COPY), DstLo) - .addReg(VR0, RegState::Kill); - BuildMI(MBB, I, DL, TII.get(MFHiOpc), VR1).addReg(Src, SrcKill); - BuildMI(MBB, I, DL, TII.get(TargetOpcode::COPY), DstHi) - .addReg(VR1, RegState::Kill); - return true; -} - -/// This method expands the same instruction that MipsSEInstrInfo:: -/// expandBuildPairF64 does, for the case when ABI is fpxx and mthc1 is not -/// available and the case where the ABI is FP64A. It is implemented here -/// because frame indexes are eliminated before MipsSEInstrInfo:: -/// expandBuildPairF64 is called. -bool ExpandPseudo::expandBuildPairF64(MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, - bool FP64) const { - // For fpxx and when mthc1 is not available, use: - // spill + reload via ldc1 - // - // The case where dmtc1 is available doesn't need to be handled here - // because it never creates a BuildPairF64 node. - // - // The FP64A ABI (fp64 with nooddspreg) must also use a spill/reload sequence - // for odd-numbered double precision values (because the lower 32-bits is - // transferred with mtc1 which is redirected to the upper half of the even - // register). Unfortunately, we have to make this decision before register - // allocation so for now we use a spill/reload sequence for all - // double-precision values in regardless of being an odd/even register. - // - // For the cases that should be covered here MipsSEISelDAGToDAG adds $sp as - // implicit operand, so other passes (like ShrinkWrapping) are aware that - // stack is used. - if (I->getNumOperands() == 4 && I->getOperand(3).isReg() - && I->getOperand(3).getReg() == Mips::SP) { - unsigned DstReg = I->getOperand(0).getReg(); - unsigned LoReg = I->getOperand(1).getReg(); - unsigned HiReg = I->getOperand(2).getReg(); - - // It should be impossible to have FGR64 on MIPS-II or MIPS32r1 (which are - // the cases where mthc1 is not available). 64-bit architectures and - // MIPS32r2 or later can use FGR64 though. - assert(Subtarget.isGP64bit() || Subtarget.hasMTHC1() || - !Subtarget.isFP64bit()); - - const TargetRegisterClass *RC = &Mips::GPR32RegClass; - const TargetRegisterClass *RC2 = - FP64 ? &Mips::FGR64RegClass : &Mips::AFGR64RegClass; - - // We re-use the same spill slot each time so that the stack frame doesn't - // grow too much in functions with a large number of moves. - int FI = MF.getInfo<MipsFunctionInfo>()->getMoveF64ViaSpillFI(RC2); - if (!Subtarget.isLittle()) - std::swap(LoReg, HiReg); - TII.storeRegToStack(MBB, I, LoReg, I->getOperand(1).isKill(), FI, RC, - &RegInfo, 0); - TII.storeRegToStack(MBB, I, HiReg, I->getOperand(2).isKill(), FI, RC, - &RegInfo, 4); - TII.loadRegFromStack(MBB, I, DstReg, FI, RC2, &RegInfo, 0); - return true; - } - - return false; -} - -/// This method expands the same instruction that MipsSEInstrInfo:: -/// expandExtractElementF64 does, for the case when ABI is fpxx and mfhc1 is not -/// available and the case where the ABI is FP64A. It is implemented here -/// because frame indexes are eliminated before MipsSEInstrInfo:: -/// expandExtractElementF64 is called. -bool ExpandPseudo::expandExtractElementF64(MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, - bool FP64) const { - const MachineOperand &Op1 = I->getOperand(1); - const MachineOperand &Op2 = I->getOperand(2); - - if ((Op1.isReg() && Op1.isUndef()) || (Op2.isReg() && Op2.isUndef())) { - unsigned DstReg = I->getOperand(0).getReg(); - BuildMI(MBB, I, I->getDebugLoc(), TII.get(Mips::IMPLICIT_DEF), DstReg); - return true; - } - - // For fpxx and when mfhc1 is not available, use: - // spill + reload via ldc1 - // - // The case where dmfc1 is available doesn't need to be handled here - // because it never creates a ExtractElementF64 node. - // - // The FP64A ABI (fp64 with nooddspreg) must also use a spill/reload sequence - // for odd-numbered double precision values (because the lower 32-bits is - // transferred with mfc1 which is redirected to the upper half of the even - // register). Unfortunately, we have to make this decision before register - // allocation so for now we use a spill/reload sequence for all - // double-precision values in regardless of being an odd/even register. - // - // For the cases that should be covered here MipsSEISelDAGToDAG adds $sp as - // implicit operand, so other passes (like ShrinkWrapping) are aware that - // stack is used. - if (I->getNumOperands() == 4 && I->getOperand(3).isReg() - && I->getOperand(3).getReg() == Mips::SP) { - unsigned DstReg = I->getOperand(0).getReg(); - unsigned SrcReg = Op1.getReg(); - unsigned N = Op2.getImm(); - int64_t Offset = 4 * (Subtarget.isLittle() ? N : (1 - N)); - - // It should be impossible to have FGR64 on MIPS-II or MIPS32r1 (which are - // the cases where mfhc1 is not available). 64-bit architectures and - // MIPS32r2 or later can use FGR64 though. - assert(Subtarget.isGP64bit() || Subtarget.hasMTHC1() || - !Subtarget.isFP64bit()); - - const TargetRegisterClass *RC = - FP64 ? &Mips::FGR64RegClass : &Mips::AFGR64RegClass; - const TargetRegisterClass *RC2 = &Mips::GPR32RegClass; - - // We re-use the same spill slot each time so that the stack frame doesn't - // grow too much in functions with a large number of moves. - int FI = MF.getInfo<MipsFunctionInfo>()->getMoveF64ViaSpillFI(RC); - TII.storeRegToStack(MBB, I, SrcReg, Op1.isKill(), FI, RC, &RegInfo, 0); - TII.loadRegFromStack(MBB, I, DstReg, FI, RC2, &RegInfo, Offset); - return true; - } - - return false; -} - -MipsSEFrameLowering::MipsSEFrameLowering(const MipsSubtarget &STI) - : MipsFrameLowering(STI, STI.getStackAlignment()) {} - -void MipsSEFrameLowering::emitPrologue(MachineFunction &MF, - MachineBasicBlock &MBB) const { - MachineFrameInfo &MFI = MF.getFrameInfo(); - MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); - - const MipsSEInstrInfo &TII = - *static_cast<const MipsSEInstrInfo *>(STI.getInstrInfo()); - const MipsRegisterInfo &RegInfo = - *static_cast<const MipsRegisterInfo *>(STI.getRegisterInfo()); - - MachineBasicBlock::iterator MBBI = MBB.begin(); - DebugLoc dl; - MipsABIInfo ABI = STI.getABI(); - unsigned SP = ABI.GetStackPtr(); - unsigned FP = ABI.GetFramePtr(); - unsigned ZERO = ABI.GetNullPtr(); - unsigned MOVE = ABI.GetGPRMoveOp(); - unsigned ADDiu = ABI.GetPtrAddiuOp(); - unsigned AND = ABI.IsN64() ? Mips::AND64 : Mips::AND; - - const TargetRegisterClass *RC = ABI.ArePtrs64bit() ? - &Mips::GPR64RegClass : &Mips::GPR32RegClass; - - // First, compute final stack size. - uint64_t StackSize = MFI.getStackSize(); - - // No need to allocate space on the stack. - if (StackSize == 0 && !MFI.adjustsStack()) return; - - MachineModuleInfo &MMI = MF.getMMI(); - const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo(); - - // Adjust stack. - TII.adjustStackPtr(SP, -StackSize, MBB, MBBI); - - // emit ".cfi_def_cfa_offset StackSize" - unsigned CFIIndex = MF.addFrameInst( - MCCFIInstruction::createDefCfaOffset(nullptr, -StackSize)); - BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) - .addCFIIndex(CFIIndex); - - if (MF.getFunction().hasFnAttribute("interrupt")) - emitInterruptPrologueStub(MF, MBB); - - const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); - - if (!CSI.empty()) { - // Find the instruction past the last instruction that saves a callee-saved - // register to the stack. - for (unsigned i = 0; i < CSI.size(); ++i) - ++MBBI; - - // Iterate over list of callee-saved registers and emit .cfi_offset - // directives. - for (std::vector<CalleeSavedInfo>::const_iterator I = CSI.begin(), - E = CSI.end(); I != E; ++I) { - int64_t Offset = MFI.getObjectOffset(I->getFrameIdx()); - unsigned Reg = I->getReg(); - - // If Reg is a double precision register, emit two cfa_offsets, - // one for each of the paired single precision registers. - if (Mips::AFGR64RegClass.contains(Reg)) { - unsigned Reg0 = - MRI->getDwarfRegNum(RegInfo.getSubReg(Reg, Mips::sub_lo), true); - unsigned Reg1 = - MRI->getDwarfRegNum(RegInfo.getSubReg(Reg, Mips::sub_hi), true); - - if (!STI.isLittle()) - std::swap(Reg0, Reg1); - - unsigned CFIIndex = MF.addFrameInst( - MCCFIInstruction::createOffset(nullptr, Reg0, Offset)); - BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) - .addCFIIndex(CFIIndex); - - CFIIndex = MF.addFrameInst( - MCCFIInstruction::createOffset(nullptr, Reg1, Offset + 4)); - BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) - .addCFIIndex(CFIIndex); - } else if (Mips::FGR64RegClass.contains(Reg)) { - unsigned Reg0 = MRI->getDwarfRegNum(Reg, true); - unsigned Reg1 = MRI->getDwarfRegNum(Reg, true) + 1; - - if (!STI.isLittle()) - std::swap(Reg0, Reg1); - - unsigned CFIIndex = MF.addFrameInst( - MCCFIInstruction::createOffset(nullptr, Reg0, Offset)); - BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) - .addCFIIndex(CFIIndex); - - CFIIndex = MF.addFrameInst( - MCCFIInstruction::createOffset(nullptr, Reg1, Offset + 4)); - BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) - .addCFIIndex(CFIIndex); - } else { - // Reg is either in GPR32 or FGR32. - unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset( - nullptr, MRI->getDwarfRegNum(Reg, true), Offset)); - BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) - .addCFIIndex(CFIIndex); - } - } - } - - if (MipsFI->callsEhReturn()) { - // Insert instructions that spill eh data registers. - for (int I = 0; I < 4; ++I) { - if (!MBB.isLiveIn(ABI.GetEhDataReg(I))) - MBB.addLiveIn(ABI.GetEhDataReg(I)); - TII.storeRegToStackSlot(MBB, MBBI, ABI.GetEhDataReg(I), false, - MipsFI->getEhDataRegFI(I), RC, &RegInfo); - } - - // Emit .cfi_offset directives for eh data registers. - for (int I = 0; I < 4; ++I) { - int64_t Offset = MFI.getObjectOffset(MipsFI->getEhDataRegFI(I)); - unsigned Reg = MRI->getDwarfRegNum(ABI.GetEhDataReg(I), true); - unsigned CFIIndex = MF.addFrameInst( - MCCFIInstruction::createOffset(nullptr, Reg, Offset)); - BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) - .addCFIIndex(CFIIndex); - } - } - - // if framepointer enabled, set it to point to the stack pointer. - if (hasFP(MF)) { - // Insert instruction "move $fp, $sp" at this location. - BuildMI(MBB, MBBI, dl, TII.get(MOVE), FP).addReg(SP).addReg(ZERO) - .setMIFlag(MachineInstr::FrameSetup); - - // emit ".cfi_def_cfa_register $fp" - unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createDefCfaRegister( - nullptr, MRI->getDwarfRegNum(FP, true))); - BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) - .addCFIIndex(CFIIndex); - - if (RegInfo.needsStackRealignment(MF)) { - // addiu $Reg, $zero, -MaxAlignment - // andi $sp, $sp, $Reg - unsigned VR = MF.getRegInfo().createVirtualRegister(RC); - assert(isInt<16>(MFI.getMaxAlignment()) && - "Function's alignment size requirement is not supported."); - int MaxAlign = -(int)MFI.getMaxAlignment(); - - BuildMI(MBB, MBBI, dl, TII.get(ADDiu), VR).addReg(ZERO) .addImm(MaxAlign); - BuildMI(MBB, MBBI, dl, TII.get(AND), SP).addReg(SP).addReg(VR); - - if (hasBP(MF)) { - // move $s7, $sp - unsigned BP = STI.isABI_N64() ? Mips::S7_64 : Mips::S7; - BuildMI(MBB, MBBI, dl, TII.get(MOVE), BP) - .addReg(SP) - .addReg(ZERO); - } - } - } -} - -void MipsSEFrameLowering::emitInterruptPrologueStub( - MachineFunction &MF, MachineBasicBlock &MBB) const { - MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); - MachineBasicBlock::iterator MBBI = MBB.begin(); - DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); - - // Report an error the target doesn't support Mips32r2 or later. - // The epilogue relies on the use of the "ehb" to clear execution - // hazards. Pre R2 Mips relies on an implementation defined number - // of "ssnop"s to clear the execution hazard. Support for ssnop hazard - // clearing is not provided so reject that configuration. - if (!STI.hasMips32r2()) - report_fatal_error( - "\"interrupt\" attribute is not supported on pre-MIPS32R2 or " - "MIPS16 targets."); - - // The GP register contains the "user" value, so we cannot perform - // any gp relative loads until we restore the "kernel" or "system" gp - // value. Until support is written we shall only accept the static - // relocation model. - if ((STI.getRelocationModel() != Reloc::Static)) - report_fatal_error("\"interrupt\" attribute is only supported for the " - "static relocation model on MIPS at the present time."); - - if (!STI.isABI_O32() || STI.hasMips64()) - report_fatal_error("\"interrupt\" attribute is only supported for the " - "O32 ABI on MIPS32R2+ at the present time."); - - // Perform ISR handling like GCC - StringRef IntKind = - MF.getFunction().getFnAttribute("interrupt").getValueAsString(); - const TargetRegisterClass *PtrRC = &Mips::GPR32RegClass; - - // EIC interrupt handling needs to read the Cause register to disable - // interrupts. - if (IntKind == "eic") { - // Coprocessor registers are always live per se. - MBB.addLiveIn(Mips::COP013); - BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::MFC0), Mips::K0) - .addReg(Mips::COP013) - .addImm(0) - .setMIFlag(MachineInstr::FrameSetup); - - BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::EXT), Mips::K0) - .addReg(Mips::K0) - .addImm(10) - .addImm(6) - .setMIFlag(MachineInstr::FrameSetup); - } - - // Fetch and spill EPC - MBB.addLiveIn(Mips::COP014); - BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::MFC0), Mips::K1) - .addReg(Mips::COP014) - .addImm(0) - .setMIFlag(MachineInstr::FrameSetup); - - STI.getInstrInfo()->storeRegToStack(MBB, MBBI, Mips::K1, false, - MipsFI->getISRRegFI(0), PtrRC, - STI.getRegisterInfo(), 0); - - // Fetch and Spill Status - MBB.addLiveIn(Mips::COP012); - BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::MFC0), Mips::K1) - .addReg(Mips::COP012) - .addImm(0) - .setMIFlag(MachineInstr::FrameSetup); - - STI.getInstrInfo()->storeRegToStack(MBB, MBBI, Mips::K1, false, - MipsFI->getISRRegFI(1), PtrRC, - STI.getRegisterInfo(), 0); - - // Build the configuration for disabling lower priority interrupts. Non EIC - // interrupts need to be masked off with zero, EIC from the Cause register. - unsigned InsPosition = 8; - unsigned InsSize = 0; - unsigned SrcReg = Mips::ZERO; - - // If the interrupt we're tied to is the EIC, switch the source for the - // masking off interrupts to the cause register. - if (IntKind == "eic") { - SrcReg = Mips::K0; - InsPosition = 10; - InsSize = 6; - } else - InsSize = StringSwitch<unsigned>(IntKind) - .Case("sw0", 1) - .Case("sw1", 2) - .Case("hw0", 3) - .Case("hw1", 4) - .Case("hw2", 5) - .Case("hw3", 6) - .Case("hw4", 7) - .Case("hw5", 8) - .Default(0); - assert(InsSize != 0 && "Unknown interrupt type!"); - - BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::INS), Mips::K1) - .addReg(SrcReg) - .addImm(InsPosition) - .addImm(InsSize) - .addReg(Mips::K1) - .setMIFlag(MachineInstr::FrameSetup); - - // Mask off KSU, ERL, EXL - BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::INS), Mips::K1) - .addReg(Mips::ZERO) - .addImm(1) - .addImm(4) - .addReg(Mips::K1) - .setMIFlag(MachineInstr::FrameSetup); - - // Disable the FPU as we are not spilling those register sets. - if (!STI.useSoftFloat()) - BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::INS), Mips::K1) - .addReg(Mips::ZERO) - .addImm(29) - .addImm(1) - .addReg(Mips::K1) - .setMIFlag(MachineInstr::FrameSetup); - - // Set the new status - BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::MTC0), Mips::COP012) - .addReg(Mips::K1) - .addImm(0) - .setMIFlag(MachineInstr::FrameSetup); -} - -void MipsSEFrameLowering::emitEpilogue(MachineFunction &MF, - MachineBasicBlock &MBB) const { - MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator(); - MachineFrameInfo &MFI = MF.getFrameInfo(); - MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); - - const MipsSEInstrInfo &TII = - *static_cast<const MipsSEInstrInfo *>(STI.getInstrInfo()); - const MipsRegisterInfo &RegInfo = - *static_cast<const MipsRegisterInfo *>(STI.getRegisterInfo()); - - DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); - MipsABIInfo ABI = STI.getABI(); - unsigned SP = ABI.GetStackPtr(); - unsigned FP = ABI.GetFramePtr(); - unsigned ZERO = ABI.GetNullPtr(); - unsigned MOVE = ABI.GetGPRMoveOp(); - - // if framepointer enabled, restore the stack pointer. - if (hasFP(MF)) { - // Find the first instruction that restores a callee-saved register. - MachineBasicBlock::iterator I = MBBI; - - for (unsigned i = 0; i < MFI.getCalleeSavedInfo().size(); ++i) - --I; - - // Insert instruction "move $sp, $fp" at this location. - BuildMI(MBB, I, DL, TII.get(MOVE), SP).addReg(FP).addReg(ZERO); - } - - if (MipsFI->callsEhReturn()) { - const TargetRegisterClass *RC = - ABI.ArePtrs64bit() ? &Mips::GPR64RegClass : &Mips::GPR32RegClass; - - // Find first instruction that restores a callee-saved register. - MachineBasicBlock::iterator I = MBBI; - for (unsigned i = 0; i < MFI.getCalleeSavedInfo().size(); ++i) - --I; - - // Insert instructions that restore eh data registers. - for (int J = 0; J < 4; ++J) { - TII.loadRegFromStackSlot(MBB, I, ABI.GetEhDataReg(J), - MipsFI->getEhDataRegFI(J), RC, &RegInfo); - } - } - - if (MF.getFunction().hasFnAttribute("interrupt")) - emitInterruptEpilogueStub(MF, MBB); - - // Get the number of bytes from FrameInfo - uint64_t StackSize = MFI.getStackSize(); - - if (!StackSize) - return; - - // Adjust stack. - TII.adjustStackPtr(SP, StackSize, MBB, MBBI); -} - -void MipsSEFrameLowering::emitInterruptEpilogueStub( - MachineFunction &MF, MachineBasicBlock &MBB) const { - MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); - MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); - DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); - - // Perform ISR handling like GCC - const TargetRegisterClass *PtrRC = &Mips::GPR32RegClass; - - // Disable Interrupts. - BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::DI), Mips::ZERO); - BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::EHB)); - - // Restore EPC - STI.getInstrInfo()->loadRegFromStackSlot(MBB, MBBI, Mips::K1, - MipsFI->getISRRegFI(0), PtrRC, - STI.getRegisterInfo()); - BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::MTC0), Mips::COP014) - .addReg(Mips::K1) - .addImm(0); - - // Restore Status - STI.getInstrInfo()->loadRegFromStackSlot(MBB, MBBI, Mips::K1, - MipsFI->getISRRegFI(1), PtrRC, - STI.getRegisterInfo()); - BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::MTC0), Mips::COP012) - .addReg(Mips::K1) - .addImm(0); -} - -int MipsSEFrameLowering::getFrameIndexReference(const MachineFunction &MF, - int FI, - unsigned &FrameReg) const { - const MachineFrameInfo &MFI = MF.getFrameInfo(); - MipsABIInfo ABI = STI.getABI(); - - if (MFI.isFixedObjectIndex(FI)) - FrameReg = hasFP(MF) ? ABI.GetFramePtr() : ABI.GetStackPtr(); - else - FrameReg = hasBP(MF) ? ABI.GetBasePtr() : ABI.GetStackPtr(); - - return MFI.getObjectOffset(FI) + MFI.getStackSize() - - getOffsetOfLocalArea() + MFI.getOffsetAdjustment(); -} - -bool MipsSEFrameLowering:: -spillCalleeSavedRegisters(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - const std::vector<CalleeSavedInfo> &CSI, - const TargetRegisterInfo *TRI) const { - MachineFunction *MF = MBB.getParent(); - const TargetInstrInfo &TII = *STI.getInstrInfo(); - - for (unsigned i = 0, e = CSI.size(); i != e; ++i) { - // Add the callee-saved register as live-in. Do not add if the register is - // RA and return address is taken, because it has already been added in - // method MipsTargetLowering::lowerRETURNADDR. - // It's killed at the spill, unless the register is RA and return address - // is taken. - unsigned Reg = CSI[i].getReg(); - bool IsRAAndRetAddrIsTaken = (Reg == Mips::RA || Reg == Mips::RA_64) - && MF->getFrameInfo().isReturnAddressTaken(); - if (!IsRAAndRetAddrIsTaken) - MBB.addLiveIn(Reg); - - // ISRs require HI/LO to be spilled into kernel registers to be then - // spilled to the stack frame. - bool IsLOHI = (Reg == Mips::LO0 || Reg == Mips::LO0_64 || - Reg == Mips::HI0 || Reg == Mips::HI0_64); - const Function &Func = MBB.getParent()->getFunction(); - if (IsLOHI && Func.hasFnAttribute("interrupt")) { - DebugLoc DL = MI->getDebugLoc(); - - unsigned Op = 0; - if (!STI.getABI().ArePtrs64bit()) { - Op = (Reg == Mips::HI0) ? Mips::MFHI : Mips::MFLO; - Reg = Mips::K0; - } else { - Op = (Reg == Mips::HI0) ? Mips::MFHI64 : Mips::MFLO64; - Reg = Mips::K0_64; - } - BuildMI(MBB, MI, DL, TII.get(Op), Mips::K0) - .setMIFlag(MachineInstr::FrameSetup); - } - - // Insert the spill to the stack frame. - bool IsKill = !IsRAAndRetAddrIsTaken; - const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); - TII.storeRegToStackSlot(MBB, MI, Reg, IsKill, - CSI[i].getFrameIdx(), RC, TRI); - } - - return true; -} - -bool -MipsSEFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const { - const MachineFrameInfo &MFI = MF.getFrameInfo(); - // Reserve call frame if the size of the maximum call frame fits into 16-bit - // immediate field and there are no variable sized objects on the stack. - // Make sure the second register scavenger spill slot can be accessed with one - // instruction. - return isInt<16>(MFI.getMaxCallFrameSize() + getStackAlignment()) && - !MFI.hasVarSizedObjects(); -} - -/// Mark \p Reg and all registers aliasing it in the bitset. -static void setAliasRegs(MachineFunction &MF, BitVector &SavedRegs, - unsigned Reg) { - const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); - for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) - SavedRegs.set(*AI); -} - -void MipsSEFrameLowering::determineCalleeSaves(MachineFunction &MF, - BitVector &SavedRegs, - RegScavenger *RS) const { - TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); - const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); - MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); - MipsABIInfo ABI = STI.getABI(); - unsigned FP = ABI.GetFramePtr(); - unsigned BP = ABI.IsN64() ? Mips::S7_64 : Mips::S7; - - // Mark $fp as used if function has dedicated frame pointer. - if (hasFP(MF)) - setAliasRegs(MF, SavedRegs, FP); - // Mark $s7 as used if function has dedicated base pointer. - if (hasBP(MF)) - setAliasRegs(MF, SavedRegs, BP); - - // Create spill slots for eh data registers if function calls eh_return. - if (MipsFI->callsEhReturn()) - MipsFI->createEhDataRegsFI(); - - // Create spill slots for Coprocessor 0 registers if function is an ISR. - if (MipsFI->isISR()) - MipsFI->createISRRegFI(); - - // Expand pseudo instructions which load, store or copy accumulators. - // Add an emergency spill slot if a pseudo was expanded. - if (ExpandPseudo(MF).expand()) { - // The spill slot should be half the size of the accumulator. If target have - // general-purpose registers 64 bits wide, it should be 64-bit, otherwise - // it should be 32-bit. - const TargetRegisterClass &RC = STI.isGP64bit() ? - Mips::GPR64RegClass : Mips::GPR32RegClass; - int FI = MF.getFrameInfo().CreateStackObject(TRI->getSpillSize(RC), - TRI->getSpillAlignment(RC), - false); - RS->addScavengingFrameIndex(FI); - } - - // Set scavenging frame index if necessary. - uint64_t MaxSPOffset = estimateStackSize(MF); - - // MSA has a minimum offset of 10 bits signed. If there is a variable - // sized object on the stack, the estimation cannot account for it. - if (isIntN(STI.hasMSA() ? 10 : 16, MaxSPOffset) && - !MF.getFrameInfo().hasVarSizedObjects()) - return; - - const TargetRegisterClass &RC = - ABI.ArePtrs64bit() ? Mips::GPR64RegClass : Mips::GPR32RegClass; - int FI = MF.getFrameInfo().CreateStackObject(TRI->getSpillSize(RC), - TRI->getSpillAlignment(RC), - false); - RS->addScavengingFrameIndex(FI); -} - -const MipsFrameLowering * -llvm::createMipsSEFrameLowering(const MipsSubtarget &ST) { - return new MipsSEFrameLowering(ST); -} diff --git a/contrib/llvm/lib/Target/Mips/MipsSEFrameLowering.h b/contrib/llvm/lib/Target/Mips/MipsSEFrameLowering.h deleted file mode 100644 index 78ffe161d9c6..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsSEFrameLowering.h +++ /dev/null @@ -1,52 +0,0 @@ -//===- MipsSEFrameLowering.h - Mips32/64 frame lowering ---------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_MIPS_MIPSSEFRAMELOWERING_H -#define LLVM_LIB_TARGET_MIPS_MIPSSEFRAMELOWERING_H - -#include "MipsFrameLowering.h" -#include <vector> - -namespace llvm { - -class MachineBasicBlock; -class MachineFunction; -class MipsSubtarget; - -class MipsSEFrameLowering : public MipsFrameLowering { -public: - explicit MipsSEFrameLowering(const MipsSubtarget &STI); - - /// emitProlog/emitEpilog - These methods insert prolog and epilog code into - /// the function. - void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override; - void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override; - - int getFrameIndexReference(const MachineFunction &MF, int FI, - unsigned &FrameReg) const override; - - bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - const std::vector<CalleeSavedInfo> &CSI, - const TargetRegisterInfo *TRI) const override; - - bool hasReservedCallFrame(const MachineFunction &MF) const override; - - void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, - RegScavenger *RS) const override; - -private: - void emitInterruptEpilogueStub(MachineFunction &MF, - MachineBasicBlock &MBB) const; - void emitInterruptPrologueStub(MachineFunction &MF, - MachineBasicBlock &MBB) const; -}; - -} // end namespace llvm - -#endif // LLVM_LIB_TARGET_MIPS_MIPSSEFRAMELOWERING_H diff --git a/contrib/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp b/contrib/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp deleted file mode 100644 index 703f99f37dd1..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp +++ /dev/null @@ -1,1297 +0,0 @@ -//===-- MipsSEISelDAGToDAG.cpp - A Dag to Dag Inst Selector for MipsSE ----===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Subclass of MipsDAGToDAGISel specialized for mips32/64. -// -//===----------------------------------------------------------------------===// - -#include "MipsSEISelDAGToDAG.h" -#include "MCTargetDesc/MipsBaseInfo.h" -#include "Mips.h" -#include "MipsAnalyzeImmediate.h" -#include "MipsMachineFunction.h" -#include "MipsRegisterInfo.h" -#include "llvm/CodeGen/MachineConstantPool.h" -#include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/SelectionDAGNodes.h" -#include "llvm/IR/CFG.h" -#include "llvm/IR/Dominators.h" -#include "llvm/IR/GlobalValue.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/Intrinsics.h" -#include "llvm/IR/Type.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetMachine.h" -using namespace llvm; - -#define DEBUG_TYPE "mips-isel" - -bool MipsSEDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) { - Subtarget = &static_cast<const MipsSubtarget &>(MF.getSubtarget()); - if (Subtarget->inMips16Mode()) - return false; - return MipsDAGToDAGISel::runOnMachineFunction(MF); -} - -void MipsSEDAGToDAGISel::getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequired<DominatorTreeWrapperPass>(); - SelectionDAGISel::getAnalysisUsage(AU); -} - -void MipsSEDAGToDAGISel::addDSPCtrlRegOperands(bool IsDef, MachineInstr &MI, - MachineFunction &MF) { - MachineInstrBuilder MIB(MF, &MI); - unsigned Mask = MI.getOperand(1).getImm(); - unsigned Flag = - IsDef ? RegState::ImplicitDefine : RegState::Implicit | RegState::Undef; - - if (Mask & 1) - MIB.addReg(Mips::DSPPos, Flag); - - if (Mask & 2) - MIB.addReg(Mips::DSPSCount, Flag); - - if (Mask & 4) - MIB.addReg(Mips::DSPCarry, Flag); - - if (Mask & 8) - MIB.addReg(Mips::DSPOutFlag, Flag); - - if (Mask & 16) - MIB.addReg(Mips::DSPCCond, Flag); - - if (Mask & 32) - MIB.addReg(Mips::DSPEFI, Flag); -} - -unsigned MipsSEDAGToDAGISel::getMSACtrlReg(const SDValue RegIdx) const { - uint64_t RegNum = cast<ConstantSDNode>(RegIdx)->getZExtValue(); - return Mips::MSACtrlRegClass.getRegister(RegNum); -} - -bool MipsSEDAGToDAGISel::replaceUsesWithZeroReg(MachineRegisterInfo *MRI, - const MachineInstr& MI) { - unsigned DstReg = 0, ZeroReg = 0; - - // Check if MI is "addiu $dst, $zero, 0" or "daddiu $dst, $zero, 0". - if ((MI.getOpcode() == Mips::ADDiu) && - (MI.getOperand(1).getReg() == Mips::ZERO) && - (MI.getOperand(2).isImm()) && - (MI.getOperand(2).getImm() == 0)) { - DstReg = MI.getOperand(0).getReg(); - ZeroReg = Mips::ZERO; - } else if ((MI.getOpcode() == Mips::DADDiu) && - (MI.getOperand(1).getReg() == Mips::ZERO_64) && - (MI.getOperand(2).isImm()) && - (MI.getOperand(2).getImm() == 0)) { - DstReg = MI.getOperand(0).getReg(); - ZeroReg = Mips::ZERO_64; - } - - if (!DstReg) - return false; - - // Replace uses with ZeroReg. - for (MachineRegisterInfo::use_iterator U = MRI->use_begin(DstReg), - E = MRI->use_end(); U != E;) { - MachineOperand &MO = *U; - unsigned OpNo = U.getOperandNo(); - MachineInstr *MI = MO.getParent(); - ++U; - - // Do not replace if it is a phi's operand or is tied to def operand. - if (MI->isPHI() || MI->isRegTiedToDefOperand(OpNo) || MI->isPseudo()) - continue; - - // Also, we have to check that the register class of the operand - // contains the zero register. - if (!MRI->getRegClass(MO.getReg())->contains(ZeroReg)) - continue; - - MO.setReg(ZeroReg); - } - - return true; -} - -void MipsSEDAGToDAGISel::processFunctionAfterISel(MachineFunction &MF) { - MF.getInfo<MipsFunctionInfo>()->initGlobalBaseReg(); - - MachineRegisterInfo *MRI = &MF.getRegInfo(); - - for (auto &MBB: MF) { - for (auto &MI: MBB) { - switch (MI.getOpcode()) { - case Mips::RDDSP: - addDSPCtrlRegOperands(false, MI, MF); - break; - case Mips::WRDSP: - addDSPCtrlRegOperands(true, MI, MF); - break; - case Mips::BuildPairF64_64: - case Mips::ExtractElementF64_64: - if (!Subtarget->useOddSPReg()) { - MI.addOperand(MachineOperand::CreateReg(Mips::SP, false, true)); - break; - } - LLVM_FALLTHROUGH; - case Mips::BuildPairF64: - case Mips::ExtractElementF64: - if (Subtarget->isABI_FPXX() && !Subtarget->hasMTHC1()) - MI.addOperand(MachineOperand::CreateReg(Mips::SP, false, true)); - break; - default: - replaceUsesWithZeroReg(MRI, MI); - } - } - } -} - -void MipsSEDAGToDAGISel::selectAddE(SDNode *Node, const SDLoc &DL) const { - SDValue InFlag = Node->getOperand(2); - unsigned Opc = InFlag.getOpcode(); - SDValue LHS = Node->getOperand(0), RHS = Node->getOperand(1); - EVT VT = LHS.getValueType(); - - // In the base case, we can rely on the carry bit from the addsc - // instruction. - if (Opc == ISD::ADDC) { - SDValue Ops[3] = {LHS, RHS, InFlag}; - CurDAG->SelectNodeTo(Node, Mips::ADDWC, VT, MVT::Glue, Ops); - return; - } - - assert(Opc == ISD::ADDE && "ISD::ADDE not in a chain of ADDE nodes!"); - - // The more complex case is when there is a chain of ISD::ADDE nodes like: - // (adde (adde (adde (addc a b) c) d) e). - // - // The addwc instruction does not write to the carry bit, instead it writes - // to bit 20 of the dsp control register. To match this series of nodes, each - // intermediate adde node must be expanded to write the carry bit before the - // addition. - - // Start by reading the overflow field for addsc and moving the value to the - // carry field. The usage of 1 here with MipsISD::RDDSP / Mips::WRDSP - // corresponds to reading/writing the entire control register to/from a GPR. - - SDValue CstOne = CurDAG->getTargetConstant(1, DL, MVT::i32); - - SDValue OuFlag = CurDAG->getTargetConstant(20, DL, MVT::i32); - - SDNode *DSPCtrlField = - CurDAG->getMachineNode(Mips::RDDSP, DL, MVT::i32, MVT::Glue, CstOne, InFlag); - - SDNode *Carry = CurDAG->getMachineNode( - Mips::EXT, DL, MVT::i32, SDValue(DSPCtrlField, 0), OuFlag, CstOne); - - SDValue Ops[4] = {SDValue(DSPCtrlField, 0), - CurDAG->getTargetConstant(6, DL, MVT::i32), CstOne, - SDValue(Carry, 0)}; - SDNode *DSPCFWithCarry = CurDAG->getMachineNode(Mips::INS, DL, MVT::i32, Ops); - - // My reading of the MIPS DSP 3.01 specification isn't as clear as I - // would like about whether bit 20 always gets overwritten by addwc. - // Hence take an extremely conservative view and presume it's sticky. We - // therefore need to clear it. - - SDValue Zero = CurDAG->getRegister(Mips::ZERO, MVT::i32); - - SDValue InsOps[4] = {Zero, OuFlag, CstOne, SDValue(DSPCFWithCarry, 0)}; - SDNode *DSPCtrlFinal = CurDAG->getMachineNode(Mips::INS, DL, MVT::i32, InsOps); - - SDNode *WrDSP = CurDAG->getMachineNode(Mips::WRDSP, DL, MVT::Glue, - SDValue(DSPCtrlFinal, 0), CstOne); - - SDValue Operands[3] = {LHS, RHS, SDValue(WrDSP, 0)}; - CurDAG->SelectNodeTo(Node, Mips::ADDWC, VT, MVT::Glue, Operands); -} - -/// Match frameindex -bool MipsSEDAGToDAGISel::selectAddrFrameIndex(SDValue Addr, SDValue &Base, - SDValue &Offset) const { - if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { - EVT ValTy = Addr.getValueType(); - - Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy); - Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), ValTy); - return true; - } - return false; -} - -/// Match frameindex+offset and frameindex|offset -bool MipsSEDAGToDAGISel::selectAddrFrameIndexOffset( - SDValue Addr, SDValue &Base, SDValue &Offset, unsigned OffsetBits, - unsigned ShiftAmount = 0) const { - if (CurDAG->isBaseWithConstantOffset(Addr)) { - ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)); - if (isIntN(OffsetBits + ShiftAmount, CN->getSExtValue())) { - EVT ValTy = Addr.getValueType(); - - // If the first operand is a FI, get the TargetFI Node - if (FrameIndexSDNode *FIN = - dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) - Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy); - else { - Base = Addr.getOperand(0); - // If base is a FI, additional offset calculation is done in - // eliminateFrameIndex, otherwise we need to check the alignment - if (OffsetToAlignment(CN->getZExtValue(), 1ull << ShiftAmount) != 0) - return false; - } - - Offset = CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), - ValTy); - return true; - } - } - return false; -} - -/// ComplexPattern used on MipsInstrInfo -/// Used on Mips Load/Store instructions -bool MipsSEDAGToDAGISel::selectAddrRegImm(SDValue Addr, SDValue &Base, - SDValue &Offset) const { - // if Address is FI, get the TargetFrameIndex. - if (selectAddrFrameIndex(Addr, Base, Offset)) - return true; - - // on PIC code Load GA - if (Addr.getOpcode() == MipsISD::Wrapper) { - Base = Addr.getOperand(0); - Offset = Addr.getOperand(1); - return true; - } - - if (!TM.isPositionIndependent()) { - if ((Addr.getOpcode() == ISD::TargetExternalSymbol || - Addr.getOpcode() == ISD::TargetGlobalAddress)) - return false; - } - - // Addresses of the form FI+const or FI|const - if (selectAddrFrameIndexOffset(Addr, Base, Offset, 16)) - return true; - - // Operand is a result from an ADD. - if (Addr.getOpcode() == ISD::ADD) { - // When loading from constant pools, load the lower address part in - // the instruction itself. Example, instead of: - // lui $2, %hi($CPI1_0) - // addiu $2, $2, %lo($CPI1_0) - // lwc1 $f0, 0($2) - // Generate: - // lui $2, %hi($CPI1_0) - // lwc1 $f0, %lo($CPI1_0)($2) - if (Addr.getOperand(1).getOpcode() == MipsISD::Lo || - Addr.getOperand(1).getOpcode() == MipsISD::GPRel) { - SDValue Opnd0 = Addr.getOperand(1).getOperand(0); - if (isa<ConstantPoolSDNode>(Opnd0) || isa<GlobalAddressSDNode>(Opnd0) || - isa<JumpTableSDNode>(Opnd0)) { - Base = Addr.getOperand(0); - Offset = Opnd0; - return true; - } - } - } - - return false; -} - -/// ComplexPattern used on MipsInstrInfo -/// Used on Mips Load/Store instructions -bool MipsSEDAGToDAGISel::selectAddrDefault(SDValue Addr, SDValue &Base, - SDValue &Offset) const { - Base = Addr; - Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), Addr.getValueType()); - return true; -} - -bool MipsSEDAGToDAGISel::selectIntAddr(SDValue Addr, SDValue &Base, - SDValue &Offset) const { - return selectAddrRegImm(Addr, Base, Offset) || - selectAddrDefault(Addr, Base, Offset); -} - -bool MipsSEDAGToDAGISel::selectAddrRegImm9(SDValue Addr, SDValue &Base, - SDValue &Offset) const { - if (selectAddrFrameIndex(Addr, Base, Offset)) - return true; - - if (selectAddrFrameIndexOffset(Addr, Base, Offset, 9)) - return true; - - return false; -} - -/// Used on microMIPS LWC2, LDC2, SWC2 and SDC2 instructions (11-bit offset) -bool MipsSEDAGToDAGISel::selectAddrRegImm11(SDValue Addr, SDValue &Base, - SDValue &Offset) const { - if (selectAddrFrameIndex(Addr, Base, Offset)) - return true; - - if (selectAddrFrameIndexOffset(Addr, Base, Offset, 11)) - return true; - - return false; -} - -/// Used on microMIPS Load/Store unaligned instructions (12-bit offset) -bool MipsSEDAGToDAGISel::selectAddrRegImm12(SDValue Addr, SDValue &Base, - SDValue &Offset) const { - if (selectAddrFrameIndex(Addr, Base, Offset)) - return true; - - if (selectAddrFrameIndexOffset(Addr, Base, Offset, 12)) - return true; - - return false; -} - -bool MipsSEDAGToDAGISel::selectAddrRegImm16(SDValue Addr, SDValue &Base, - SDValue &Offset) const { - if (selectAddrFrameIndex(Addr, Base, Offset)) - return true; - - if (selectAddrFrameIndexOffset(Addr, Base, Offset, 16)) - return true; - - return false; -} - -bool MipsSEDAGToDAGISel::selectIntAddr11MM(SDValue Addr, SDValue &Base, - SDValue &Offset) const { - return selectAddrRegImm11(Addr, Base, Offset) || - selectAddrDefault(Addr, Base, Offset); -} - -bool MipsSEDAGToDAGISel::selectIntAddr12MM(SDValue Addr, SDValue &Base, - SDValue &Offset) const { - return selectAddrRegImm12(Addr, Base, Offset) || - selectAddrDefault(Addr, Base, Offset); -} - -bool MipsSEDAGToDAGISel::selectIntAddr16MM(SDValue Addr, SDValue &Base, - SDValue &Offset) const { - return selectAddrRegImm16(Addr, Base, Offset) || - selectAddrDefault(Addr, Base, Offset); -} - -bool MipsSEDAGToDAGISel::selectIntAddrLSL2MM(SDValue Addr, SDValue &Base, - SDValue &Offset) const { - if (selectAddrFrameIndexOffset(Addr, Base, Offset, 7)) { - if (isa<FrameIndexSDNode>(Base)) - return false; - - if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Offset)) { - unsigned CnstOff = CN->getZExtValue(); - return (CnstOff == (CnstOff & 0x3c)); - } - - return false; - } - - // For all other cases where "lw" would be selected, don't select "lw16" - // because it would result in additional instructions to prepare operands. - if (selectAddrRegImm(Addr, Base, Offset)) - return false; - - return selectAddrDefault(Addr, Base, Offset); -} - -bool MipsSEDAGToDAGISel::selectIntAddrSImm10(SDValue Addr, SDValue &Base, - SDValue &Offset) const { - - if (selectAddrFrameIndex(Addr, Base, Offset)) - return true; - - if (selectAddrFrameIndexOffset(Addr, Base, Offset, 10)) - return true; - - return selectAddrDefault(Addr, Base, Offset); -} - -bool MipsSEDAGToDAGISel::selectIntAddrSImm10Lsl1(SDValue Addr, SDValue &Base, - SDValue &Offset) const { - if (selectAddrFrameIndex(Addr, Base, Offset)) - return true; - - if (selectAddrFrameIndexOffset(Addr, Base, Offset, 10, 1)) - return true; - - return selectAddrDefault(Addr, Base, Offset); -} - -bool MipsSEDAGToDAGISel::selectIntAddrSImm10Lsl2(SDValue Addr, SDValue &Base, - SDValue &Offset) const { - if (selectAddrFrameIndex(Addr, Base, Offset)) - return true; - - if (selectAddrFrameIndexOffset(Addr, Base, Offset, 10, 2)) - return true; - - return selectAddrDefault(Addr, Base, Offset); -} - -bool MipsSEDAGToDAGISel::selectIntAddrSImm10Lsl3(SDValue Addr, SDValue &Base, - SDValue &Offset) const { - if (selectAddrFrameIndex(Addr, Base, Offset)) - return true; - - if (selectAddrFrameIndexOffset(Addr, Base, Offset, 10, 3)) - return true; - - return selectAddrDefault(Addr, Base, Offset); -} - -// Select constant vector splats. -// -// Returns true and sets Imm if: -// * MSA is enabled -// * N is a ISD::BUILD_VECTOR representing a constant splat -bool MipsSEDAGToDAGISel::selectVSplat(SDNode *N, APInt &Imm, - unsigned MinSizeInBits) const { - if (!Subtarget->hasMSA()) - return false; - - BuildVectorSDNode *Node = dyn_cast<BuildVectorSDNode>(N); - - if (!Node) - return false; - - APInt SplatValue, SplatUndef; - unsigned SplatBitSize; - bool HasAnyUndefs; - - if (!Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs, - MinSizeInBits, !Subtarget->isLittle())) - return false; - - Imm = SplatValue; - - return true; -} - -// Select constant vector splats. -// -// In addition to the requirements of selectVSplat(), this function returns -// true and sets Imm if: -// * The splat value is the same width as the elements of the vector -// * The splat value fits in an integer with the specified signed-ness and -// width. -// -// This function looks through ISD::BITCAST nodes. -// TODO: This might not be appropriate for big-endian MSA since BITCAST is -// sometimes a shuffle in big-endian mode. -// -// It's worth noting that this function is not used as part of the selection -// of ldi.[bhwd] since it does not permit using the wrong-typed ldi.[bhwd] -// instruction to achieve the desired bit pattern. ldi.[bhwd] is selected in -// MipsSEDAGToDAGISel::selectNode. -bool MipsSEDAGToDAGISel:: -selectVSplatCommon(SDValue N, SDValue &Imm, bool Signed, - unsigned ImmBitSize) const { - APInt ImmValue; - EVT EltTy = N->getValueType(0).getVectorElementType(); - - if (N->getOpcode() == ISD::BITCAST) - N = N->getOperand(0); - - if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) && - ImmValue.getBitWidth() == EltTy.getSizeInBits()) { - - if (( Signed && ImmValue.isSignedIntN(ImmBitSize)) || - (!Signed && ImmValue.isIntN(ImmBitSize))) { - Imm = CurDAG->getTargetConstant(ImmValue, SDLoc(N), EltTy); - return true; - } - } - - return false; -} - -// Select constant vector splats. -bool MipsSEDAGToDAGISel:: -selectVSplatUimm1(SDValue N, SDValue &Imm) const { - return selectVSplatCommon(N, Imm, false, 1); -} - -bool MipsSEDAGToDAGISel:: -selectVSplatUimm2(SDValue N, SDValue &Imm) const { - return selectVSplatCommon(N, Imm, false, 2); -} - -bool MipsSEDAGToDAGISel:: -selectVSplatUimm3(SDValue N, SDValue &Imm) const { - return selectVSplatCommon(N, Imm, false, 3); -} - -// Select constant vector splats. -bool MipsSEDAGToDAGISel:: -selectVSplatUimm4(SDValue N, SDValue &Imm) const { - return selectVSplatCommon(N, Imm, false, 4); -} - -// Select constant vector splats. -bool MipsSEDAGToDAGISel:: -selectVSplatUimm5(SDValue N, SDValue &Imm) const { - return selectVSplatCommon(N, Imm, false, 5); -} - -// Select constant vector splats. -bool MipsSEDAGToDAGISel:: -selectVSplatUimm6(SDValue N, SDValue &Imm) const { - return selectVSplatCommon(N, Imm, false, 6); -} - -// Select constant vector splats. -bool MipsSEDAGToDAGISel:: -selectVSplatUimm8(SDValue N, SDValue &Imm) const { - return selectVSplatCommon(N, Imm, false, 8); -} - -// Select constant vector splats. -bool MipsSEDAGToDAGISel:: -selectVSplatSimm5(SDValue N, SDValue &Imm) const { - return selectVSplatCommon(N, Imm, true, 5); -} - -// Select constant vector splats whose value is a power of 2. -// -// In addition to the requirements of selectVSplat(), this function returns -// true and sets Imm if: -// * The splat value is the same width as the elements of the vector -// * The splat value is a power of two. -// -// This function looks through ISD::BITCAST nodes. -// TODO: This might not be appropriate for big-endian MSA since BITCAST is -// sometimes a shuffle in big-endian mode. -bool MipsSEDAGToDAGISel::selectVSplatUimmPow2(SDValue N, SDValue &Imm) const { - APInt ImmValue; - EVT EltTy = N->getValueType(0).getVectorElementType(); - - if (N->getOpcode() == ISD::BITCAST) - N = N->getOperand(0); - - if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) && - ImmValue.getBitWidth() == EltTy.getSizeInBits()) { - int32_t Log2 = ImmValue.exactLogBase2(); - - if (Log2 != -1) { - Imm = CurDAG->getTargetConstant(Log2, SDLoc(N), EltTy); - return true; - } - } - - return false; -} - -// Select constant vector splats whose value only has a consecutive sequence -// of left-most bits set (e.g. 0b11...1100...00). -// -// In addition to the requirements of selectVSplat(), this function returns -// true and sets Imm if: -// * The splat value is the same width as the elements of the vector -// * The splat value is a consecutive sequence of left-most bits. -// -// This function looks through ISD::BITCAST nodes. -// TODO: This might not be appropriate for big-endian MSA since BITCAST is -// sometimes a shuffle in big-endian mode. -bool MipsSEDAGToDAGISel::selectVSplatMaskL(SDValue N, SDValue &Imm) const { - APInt ImmValue; - EVT EltTy = N->getValueType(0).getVectorElementType(); - - if (N->getOpcode() == ISD::BITCAST) - N = N->getOperand(0); - - if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) && - ImmValue.getBitWidth() == EltTy.getSizeInBits()) { - // Extract the run of set bits starting with bit zero from the bitwise - // inverse of ImmValue, and test that the inverse of this is the same - // as the original value. - if (ImmValue == ~(~ImmValue & ~(~ImmValue + 1))) { - - Imm = CurDAG->getTargetConstant(ImmValue.countPopulation() - 1, SDLoc(N), - EltTy); - return true; - } - } - - return false; -} - -// Select constant vector splats whose value only has a consecutive sequence -// of right-most bits set (e.g. 0b00...0011...11). -// -// In addition to the requirements of selectVSplat(), this function returns -// true and sets Imm if: -// * The splat value is the same width as the elements of the vector -// * The splat value is a consecutive sequence of right-most bits. -// -// This function looks through ISD::BITCAST nodes. -// TODO: This might not be appropriate for big-endian MSA since BITCAST is -// sometimes a shuffle in big-endian mode. -bool MipsSEDAGToDAGISel::selectVSplatMaskR(SDValue N, SDValue &Imm) const { - APInt ImmValue; - EVT EltTy = N->getValueType(0).getVectorElementType(); - - if (N->getOpcode() == ISD::BITCAST) - N = N->getOperand(0); - - if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) && - ImmValue.getBitWidth() == EltTy.getSizeInBits()) { - // Extract the run of set bits starting with bit zero, and test that the - // result is the same as the original value - if (ImmValue == (ImmValue & ~(ImmValue + 1))) { - Imm = CurDAG->getTargetConstant(ImmValue.countPopulation() - 1, SDLoc(N), - EltTy); - return true; - } - } - - return false; -} - -bool MipsSEDAGToDAGISel::selectVSplatUimmInvPow2(SDValue N, - SDValue &Imm) const { - APInt ImmValue; - EVT EltTy = N->getValueType(0).getVectorElementType(); - - if (N->getOpcode() == ISD::BITCAST) - N = N->getOperand(0); - - if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) && - ImmValue.getBitWidth() == EltTy.getSizeInBits()) { - int32_t Log2 = (~ImmValue).exactLogBase2(); - - if (Log2 != -1) { - Imm = CurDAG->getTargetConstant(Log2, SDLoc(N), EltTy); - return true; - } - } - - return false; -} - -bool MipsSEDAGToDAGISel::trySelect(SDNode *Node) { - unsigned Opcode = Node->getOpcode(); - SDLoc DL(Node); - - /// - // Instruction Selection not handled by the auto-generated - // tablegen selection should be handled here. - /// - switch(Opcode) { - default: break; - - case Mips::PseudoD_SELECT_I: - case Mips::PseudoD_SELECT_I64: { - MVT VT = Subtarget->isGP64bit() ? MVT::i64 : MVT::i32; - SDValue cond = Node->getOperand(0); - SDValue Hi1 = Node->getOperand(1); - SDValue Lo1 = Node->getOperand(2); - SDValue Hi2 = Node->getOperand(3); - SDValue Lo2 = Node->getOperand(4); - - SDValue ops[] = {cond, Hi1, Lo1, Hi2, Lo2}; - EVT NodeTys[] = {VT, VT}; - ReplaceNode(Node, CurDAG->getMachineNode(Subtarget->isGP64bit() - ? Mips::PseudoD_SELECT_I64 - : Mips::PseudoD_SELECT_I, - DL, NodeTys, ops)); - return true; - } - - case ISD::ADDE: { - selectAddE(Node, DL); - return true; - } - - case ISD::ConstantFP: { - ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(Node); - if (Node->getValueType(0) == MVT::f64 && CN->isExactlyValue(+0.0)) { - if (Subtarget->isGP64bit()) { - SDValue Zero = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL, - Mips::ZERO_64, MVT::i64); - ReplaceNode(Node, - CurDAG->getMachineNode(Mips::DMTC1, DL, MVT::f64, Zero)); - } else if (Subtarget->isFP64bit()) { - SDValue Zero = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL, - Mips::ZERO, MVT::i32); - ReplaceNode(Node, CurDAG->getMachineNode(Mips::BuildPairF64_64, DL, - MVT::f64, Zero, Zero)); - } else { - SDValue Zero = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL, - Mips::ZERO, MVT::i32); - ReplaceNode(Node, CurDAG->getMachineNode(Mips::BuildPairF64, DL, - MVT::f64, Zero, Zero)); - } - return true; - } - break; - } - - case ISD::Constant: { - const ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Node); - int64_t Imm = CN->getSExtValue(); - unsigned Size = CN->getValueSizeInBits(0); - - if (isInt<32>(Imm)) - break; - - MipsAnalyzeImmediate AnalyzeImm; - - const MipsAnalyzeImmediate::InstSeq &Seq = - AnalyzeImm.Analyze(Imm, Size, false); - - MipsAnalyzeImmediate::InstSeq::const_iterator Inst = Seq.begin(); - SDLoc DL(CN); - SDNode *RegOpnd; - SDValue ImmOpnd = CurDAG->getTargetConstant(SignExtend64<16>(Inst->ImmOpnd), - DL, MVT::i64); - - // The first instruction can be a LUi which is different from other - // instructions (ADDiu, ORI and SLL) in that it does not have a register - // operand. - if (Inst->Opc == Mips::LUi64) - RegOpnd = CurDAG->getMachineNode(Inst->Opc, DL, MVT::i64, ImmOpnd); - else - RegOpnd = - CurDAG->getMachineNode(Inst->Opc, DL, MVT::i64, - CurDAG->getRegister(Mips::ZERO_64, MVT::i64), - ImmOpnd); - - // The remaining instructions in the sequence are handled here. - for (++Inst; Inst != Seq.end(); ++Inst) { - ImmOpnd = CurDAG->getTargetConstant(SignExtend64<16>(Inst->ImmOpnd), DL, - MVT::i64); - RegOpnd = CurDAG->getMachineNode(Inst->Opc, DL, MVT::i64, - SDValue(RegOpnd, 0), ImmOpnd); - } - - ReplaceNode(Node, RegOpnd); - return true; - } - - case ISD::INTRINSIC_W_CHAIN: { - switch (cast<ConstantSDNode>(Node->getOperand(1))->getZExtValue()) { - default: - break; - - case Intrinsic::mips_cfcmsa: { - SDValue ChainIn = Node->getOperand(0); - SDValue RegIdx = Node->getOperand(2); - SDValue Reg = CurDAG->getCopyFromReg(ChainIn, DL, - getMSACtrlReg(RegIdx), MVT::i32); - ReplaceNode(Node, Reg.getNode()); - return true; - } - } - break; - } - - case ISD::INTRINSIC_WO_CHAIN: { - switch (cast<ConstantSDNode>(Node->getOperand(0))->getZExtValue()) { - default: - break; - - case Intrinsic::mips_move_v: - // Like an assignment but will always produce a move.v even if - // unnecessary. - ReplaceNode(Node, CurDAG->getMachineNode(Mips::MOVE_V, DL, - Node->getValueType(0), - Node->getOperand(1))); - return true; - } - break; - } - - case ISD::INTRINSIC_VOID: { - switch (cast<ConstantSDNode>(Node->getOperand(1))->getZExtValue()) { - default: - break; - - case Intrinsic::mips_ctcmsa: { - SDValue ChainIn = Node->getOperand(0); - SDValue RegIdx = Node->getOperand(2); - SDValue Value = Node->getOperand(3); - SDValue ChainOut = CurDAG->getCopyToReg(ChainIn, DL, - getMSACtrlReg(RegIdx), Value); - ReplaceNode(Node, ChainOut.getNode()); - return true; - } - } - break; - } - - // Manually match MipsISD::Ins nodes to get the correct instruction. It has - // to be done in this fashion so that we respect the differences between - // dins and dinsm, as the difference is that the size operand has the range - // 0 < size <= 32 for dins while dinsm has the range 2 <= size <= 64 which - // means SelectionDAGISel would have to test all the operands at once to - // match the instruction. - case MipsISD::Ins: { - - // Sanity checking for the node operands. - if (Node->getValueType(0) != MVT::i32 && Node->getValueType(0) != MVT::i64) - return false; - - if (Node->getNumOperands() != 4) - return false; - - if (Node->getOperand(1)->getOpcode() != ISD::Constant || - Node->getOperand(2)->getOpcode() != ISD::Constant) - return false; - - MVT ResTy = Node->getSimpleValueType(0); - uint64_t Pos = Node->getConstantOperandVal(1); - uint64_t Size = Node->getConstantOperandVal(2); - - // Size has to be >0 for 'ins', 'dins' and 'dinsu'. - if (!Size) - return false; - - if (Pos + Size > 64) - return false; - - if (ResTy != MVT::i32 && ResTy != MVT::i64) - return false; - - unsigned Opcode = 0; - if (ResTy == MVT::i32) { - if (Pos + Size <= 32) - Opcode = Mips::INS; - } else { - if (Pos + Size <= 32) - Opcode = Mips::DINS; - else if (Pos < 32 && 1 < Size) - Opcode = Mips::DINSM; - else - Opcode = Mips::DINSU; - } - - if (Opcode) { - SDValue Ops[4] = { - Node->getOperand(0), CurDAG->getTargetConstant(Pos, DL, MVT::i32), - CurDAG->getTargetConstant(Size, DL, MVT::i32), Node->getOperand(3)}; - - ReplaceNode(Node, CurDAG->getMachineNode(Opcode, DL, ResTy, Ops)); - return true; - } - - return false; - } - - case MipsISD::ThreadPointer: { - EVT PtrVT = getTargetLowering()->getPointerTy(CurDAG->getDataLayout()); - unsigned RdhwrOpc, DestReg; - - if (PtrVT == MVT::i32) { - RdhwrOpc = Mips::RDHWR; - DestReg = Mips::V1; - } else { - RdhwrOpc = Mips::RDHWR64; - DestReg = Mips::V1_64; - } - - SDNode *Rdhwr = - CurDAG->getMachineNode(RdhwrOpc, DL, Node->getValueType(0), - CurDAG->getRegister(Mips::HWR29, MVT::i32), - CurDAG->getTargetConstant(0, DL, MVT::i32)); - SDValue Chain = CurDAG->getCopyToReg(CurDAG->getEntryNode(), DL, DestReg, - SDValue(Rdhwr, 0)); - SDValue ResNode = CurDAG->getCopyFromReg(Chain, DL, DestReg, PtrVT); - ReplaceNode(Node, ResNode.getNode()); - return true; - } - - case ISD::BUILD_VECTOR: { - // Select appropriate ldi.[bhwd] instructions for constant splats of - // 128-bit when MSA is enabled. Fixup any register class mismatches that - // occur as a result. - // - // This allows the compiler to use a wider range of immediates than would - // otherwise be allowed. If, for example, v4i32 could only use ldi.h then - // it would not be possible to load { 0x01010101, 0x01010101, 0x01010101, - // 0x01010101 } without using a constant pool. This would be sub-optimal - // when // 'ldi.b wd, 1' is capable of producing that bit-pattern in the - // same set/ of registers. Similarly, ldi.h isn't capable of producing { - // 0x00000000, 0x00000001, 0x00000000, 0x00000001 } but 'ldi.d wd, 1' can. - - const MipsABIInfo &ABI = - static_cast<const MipsTargetMachine &>(TM).getABI(); - - BuildVectorSDNode *BVN = cast<BuildVectorSDNode>(Node); - APInt SplatValue, SplatUndef; - unsigned SplatBitSize; - bool HasAnyUndefs; - unsigned LdiOp; - EVT ResVecTy = BVN->getValueType(0); - EVT ViaVecTy; - - if (!Subtarget->hasMSA() || !BVN->getValueType(0).is128BitVector()) - return false; - - if (!BVN->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, - HasAnyUndefs, 8, - !Subtarget->isLittle())) - return false; - - switch (SplatBitSize) { - default: - return false; - case 8: - LdiOp = Mips::LDI_B; - ViaVecTy = MVT::v16i8; - break; - case 16: - LdiOp = Mips::LDI_H; - ViaVecTy = MVT::v8i16; - break; - case 32: - LdiOp = Mips::LDI_W; - ViaVecTy = MVT::v4i32; - break; - case 64: - LdiOp = Mips::LDI_D; - ViaVecTy = MVT::v2i64; - break; - } - - SDNode *Res; - - // If we have a signed 10 bit integer, we can splat it directly. - // - // If we have something bigger we can synthesize the value into a GPR and - // splat from there. - if (SplatValue.isSignedIntN(10)) { - SDValue Imm = CurDAG->getTargetConstant(SplatValue, DL, - ViaVecTy.getVectorElementType()); - - Res = CurDAG->getMachineNode(LdiOp, DL, ViaVecTy, Imm); - } else if (SplatValue.isSignedIntN(16) && - ((ABI.IsO32() && SplatBitSize < 64) || - (ABI.IsN32() || ABI.IsN64()))) { - // Only handle signed 16 bit values when the element size is GPR width. - // MIPS64 can handle all the cases but MIPS32 would need to handle - // negative cases specifically here. Instead, handle those cases as - // 64bit values. - - bool Is32BitSplat = ABI.IsO32() || SplatBitSize < 64; - const unsigned ADDiuOp = Is32BitSplat ? Mips::ADDiu : Mips::DADDiu; - const MVT SplatMVT = Is32BitSplat ? MVT::i32 : MVT::i64; - SDValue ZeroVal = CurDAG->getRegister( - Is32BitSplat ? Mips::ZERO : Mips::ZERO_64, SplatMVT); - - const unsigned FILLOp = - SplatBitSize == 16 - ? Mips::FILL_H - : (SplatBitSize == 32 ? Mips::FILL_W - : (SplatBitSize == 64 ? Mips::FILL_D : 0)); - - assert(FILLOp != 0 && "Unknown FILL Op for splat synthesis!"); - assert((!ABI.IsO32() || (FILLOp != Mips::FILL_D)) && - "Attempting to use fill.d on MIPS32!"); - - const unsigned Lo = SplatValue.getLoBits(16).getZExtValue(); - SDValue LoVal = CurDAG->getTargetConstant(Lo, DL, SplatMVT); - - Res = CurDAG->getMachineNode(ADDiuOp, DL, SplatMVT, ZeroVal, LoVal); - Res = CurDAG->getMachineNode(FILLOp, DL, ViaVecTy, SDValue(Res, 0)); - - } else if (SplatValue.isSignedIntN(32) && SplatBitSize == 32) { - // Only handle the cases where the splat size agrees with the size - // of the SplatValue here. - const unsigned Lo = SplatValue.getLoBits(16).getZExtValue(); - const unsigned Hi = SplatValue.lshr(16).getLoBits(16).getZExtValue(); - SDValue ZeroVal = CurDAG->getRegister(Mips::ZERO, MVT::i32); - - SDValue LoVal = CurDAG->getTargetConstant(Lo, DL, MVT::i32); - SDValue HiVal = CurDAG->getTargetConstant(Hi, DL, MVT::i32); - - if (Hi) - Res = CurDAG->getMachineNode(Mips::LUi, DL, MVT::i32, HiVal); - - if (Lo) - Res = CurDAG->getMachineNode(Mips::ORi, DL, MVT::i32, - Hi ? SDValue(Res, 0) : ZeroVal, LoVal); - - assert((Hi || Lo) && "Zero case reached 32 bit case splat synthesis!"); - Res = CurDAG->getMachineNode(Mips::FILL_W, DL, MVT::v4i32, SDValue(Res, 0)); - - } else if (SplatValue.isSignedIntN(32) && SplatBitSize == 64 && - (ABI.IsN32() || ABI.IsN64())) { - // N32 and N64 can perform some tricks that O32 can't for signed 32 bit - // integers due to having 64bit registers. lui will cause the necessary - // zero/sign extension. - const unsigned Lo = SplatValue.getLoBits(16).getZExtValue(); - const unsigned Hi = SplatValue.lshr(16).getLoBits(16).getZExtValue(); - SDValue ZeroVal = CurDAG->getRegister(Mips::ZERO, MVT::i32); - - SDValue LoVal = CurDAG->getTargetConstant(Lo, DL, MVT::i32); - SDValue HiVal = CurDAG->getTargetConstant(Hi, DL, MVT::i32); - - if (Hi) - Res = CurDAG->getMachineNode(Mips::LUi, DL, MVT::i32, HiVal); - - if (Lo) - Res = CurDAG->getMachineNode(Mips::ORi, DL, MVT::i32, - Hi ? SDValue(Res, 0) : ZeroVal, LoVal); - - Res = CurDAG->getMachineNode( - Mips::SUBREG_TO_REG, DL, MVT::i64, - CurDAG->getTargetConstant(((Hi >> 15) & 0x1), DL, MVT::i64), - SDValue(Res, 0), - CurDAG->getTargetConstant(Mips::sub_32, DL, MVT::i64)); - - Res = - CurDAG->getMachineNode(Mips::FILL_D, DL, MVT::v2i64, SDValue(Res, 0)); - - } else if (SplatValue.isSignedIntN(64)) { - // If we have a 64 bit Splat value, we perform a similar sequence to the - // above: - // - // MIPS32: MIPS64: - // lui $res, %highest(val) lui $res, %highest(val) - // ori $res, $res, %higher(val) ori $res, $res, %higher(val) - // lui $res2, %hi(val) lui $res2, %hi(val) - // ori $res2, %res2, %lo(val) ori $res2, %res2, %lo(val) - // $res3 = fill $res2 dinsu $res, $res2, 0, 32 - // $res4 = insert.w $res3[1], $res fill.d $res - // splat.d $res4, 0 - // - // The ability to use dinsu is guaranteed as MSA requires MIPSR5. This saves - // having to materialize the value by shifts and ors. - // - // FIXME: Implement the preferred sequence for MIPS64R6: - // - // MIPS64R6: - // ori $res, $zero, %lo(val) - // daui $res, $res, %hi(val) - // dahi $res, $res, %higher(val) - // dati $res, $res, %highest(cal) - // fill.d $res - // - - const unsigned Lo = SplatValue.getLoBits(16).getZExtValue(); - const unsigned Hi = SplatValue.lshr(16).getLoBits(16).getZExtValue(); - const unsigned Higher = SplatValue.lshr(32).getLoBits(16).getZExtValue(); - const unsigned Highest = SplatValue.lshr(48).getLoBits(16).getZExtValue(); - - SDValue LoVal = CurDAG->getTargetConstant(Lo, DL, MVT::i32); - SDValue HiVal = CurDAG->getTargetConstant(Hi, DL, MVT::i32); - SDValue HigherVal = CurDAG->getTargetConstant(Higher, DL, MVT::i32); - SDValue HighestVal = CurDAG->getTargetConstant(Highest, DL, MVT::i32); - SDValue ZeroVal = CurDAG->getRegister(Mips::ZERO, MVT::i32); - - // Independent of whether we're targeting MIPS64 or not, the basic - // operations are the same. Also, directly use the $zero register if - // the 16 bit chunk is zero. - // - // For optimization purposes we always synthesize the splat value as - // an i32 value, then if we're targetting MIPS64, use SUBREG_TO_REG - // just before combining the values with dinsu to produce an i64. This - // enables SelectionDAG to aggressively share components of splat values - // where possible. - // - // FIXME: This is the general constant synthesis problem. This code - // should be factored out into a class shared between all the - // classes that need it. Specifically, for a splat size of 64 - // bits that's a negative number we can do better than LUi/ORi - // for the upper 32bits. - - if (Hi) - Res = CurDAG->getMachineNode(Mips::LUi, DL, MVT::i32, HiVal); - - if (Lo) - Res = CurDAG->getMachineNode(Mips::ORi, DL, MVT::i32, - Hi ? SDValue(Res, 0) : ZeroVal, LoVal); - - SDNode *HiRes; - if (Highest) - HiRes = CurDAG->getMachineNode(Mips::LUi, DL, MVT::i32, HighestVal); - - if (Higher) - HiRes = CurDAG->getMachineNode(Mips::ORi, DL, MVT::i32, - Highest ? SDValue(HiRes, 0) : ZeroVal, - HigherVal); - - - if (ABI.IsO32()) { - Res = CurDAG->getMachineNode(Mips::FILL_W, DL, MVT::v4i32, - (Hi || Lo) ? SDValue(Res, 0) : ZeroVal); - - Res = CurDAG->getMachineNode( - Mips::INSERT_W, DL, MVT::v4i32, SDValue(Res, 0), - (Highest || Higher) ? SDValue(HiRes, 0) : ZeroVal, - CurDAG->getTargetConstant(1, DL, MVT::i32)); - - const TargetLowering *TLI = getTargetLowering(); - const TargetRegisterClass *RC = - TLI->getRegClassFor(ViaVecTy.getSimpleVT()); - - Res = CurDAG->getMachineNode( - Mips::COPY_TO_REGCLASS, DL, ViaVecTy, SDValue(Res, 0), - CurDAG->getTargetConstant(RC->getID(), DL, MVT::i32)); - - Res = CurDAG->getMachineNode( - Mips::SPLATI_D, DL, MVT::v2i64, SDValue(Res, 0), - CurDAG->getTargetConstant(0, DL, MVT::i32)); - } else if (ABI.IsN64() || ABI.IsN32()) { - - SDValue Zero64Val = CurDAG->getRegister(Mips::ZERO_64, MVT::i64); - const bool HiResNonZero = Highest || Higher; - const bool ResNonZero = Hi || Lo; - - if (HiResNonZero) - HiRes = CurDAG->getMachineNode( - Mips::SUBREG_TO_REG, DL, MVT::i64, - CurDAG->getTargetConstant(((Highest >> 15) & 0x1), DL, MVT::i64), - SDValue(HiRes, 0), - CurDAG->getTargetConstant(Mips::sub_32, DL, MVT::i64)); - - if (ResNonZero) - Res = CurDAG->getMachineNode( - Mips::SUBREG_TO_REG, DL, MVT::i64, - CurDAG->getTargetConstant(((Hi >> 15) & 0x1), DL, MVT::i64), - SDValue(Res, 0), - CurDAG->getTargetConstant(Mips::sub_32, DL, MVT::i64)); - - // We have 3 cases: - // The HiRes is nonzero but Res is $zero => dsll32 HiRes, 0 - // The Res is nonzero but HiRes is $zero => dinsu Res, $zero, 32, 32 - // Both are non zero => dinsu Res, HiRes, 32, 32 - // - // The obvious "missing" case is when both are zero, but that case is - // handled by the ldi case. - if (ResNonZero) { - IntegerType *Int32Ty = - IntegerType::get(MF->getFunction().getContext(), 32); - const ConstantInt *Const32 = ConstantInt::get(Int32Ty, 32); - SDValue Ops[4] = {HiResNonZero ? SDValue(HiRes, 0) : Zero64Val, - CurDAG->getConstant(*Const32, DL, MVT::i32), - CurDAG->getConstant(*Const32, DL, MVT::i32), - SDValue(Res, 0)}; - - Res = CurDAG->getMachineNode(Mips::DINSU, DL, MVT::i64, Ops); - } else if (HiResNonZero) { - Res = CurDAG->getMachineNode( - Mips::DSLL32, DL, MVT::i64, SDValue(HiRes, 0), - CurDAG->getTargetConstant(0, DL, MVT::i32)); - } else - llvm_unreachable( - "Zero splat value handled by non-zero 64bit splat synthesis!"); - - Res = CurDAG->getMachineNode(Mips::FILL_D, DL, MVT::v2i64, SDValue(Res, 0)); - } else - llvm_unreachable("Unknown ABI in MipsISelDAGToDAG!"); - - } else - return false; - - if (ResVecTy != ViaVecTy) { - // If LdiOp is writing to a different register class to ResVecTy, then - // fix it up here. This COPY_TO_REGCLASS should never cause a move.v - // since the source and destination register sets contain the same - // registers. - const TargetLowering *TLI = getTargetLowering(); - MVT ResVecTySimple = ResVecTy.getSimpleVT(); - const TargetRegisterClass *RC = TLI->getRegClassFor(ResVecTySimple); - Res = CurDAG->getMachineNode(Mips::COPY_TO_REGCLASS, DL, - ResVecTy, SDValue(Res, 0), - CurDAG->getTargetConstant(RC->getID(), DL, - MVT::i32)); - } - - ReplaceNode(Node, Res); - return true; - } - - } - - return false; -} - -bool MipsSEDAGToDAGISel:: -SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID, - std::vector<SDValue> &OutOps) { - SDValue Base, Offset; - - switch(ConstraintID) { - default: - llvm_unreachable("Unexpected asm memory constraint"); - // All memory constraints can at least accept raw pointers. - case InlineAsm::Constraint_i: - OutOps.push_back(Op); - OutOps.push_back(CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i32)); - return false; - case InlineAsm::Constraint_m: - case InlineAsm::Constraint_o: - if (selectAddrRegImm16(Op, Base, Offset)) { - OutOps.push_back(Base); - OutOps.push_back(Offset); - return false; - } - OutOps.push_back(Op); - OutOps.push_back(CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i32)); - return false; - case InlineAsm::Constraint_R: - // The 'R' constraint is supposed to be much more complicated than this. - // However, it's becoming less useful due to architectural changes and - // ought to be replaced by other constraints such as 'ZC'. - // For now, support 9-bit signed offsets which is supportable by all - // subtargets for all instructions. - if (selectAddrRegImm9(Op, Base, Offset)) { - OutOps.push_back(Base); - OutOps.push_back(Offset); - return false; - } - OutOps.push_back(Op); - OutOps.push_back(CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i32)); - return false; - case InlineAsm::Constraint_ZC: - // ZC matches whatever the pref, ll, and sc instructions can handle for the - // given subtarget. - if (Subtarget->inMicroMipsMode()) { - // On microMIPS, they can handle 12-bit offsets. - if (selectAddrRegImm12(Op, Base, Offset)) { - OutOps.push_back(Base); - OutOps.push_back(Offset); - return false; - } - } else if (Subtarget->hasMips32r6()) { - // On MIPS32r6/MIPS64r6, they can only handle 9-bit offsets. - if (selectAddrRegImm9(Op, Base, Offset)) { - OutOps.push_back(Base); - OutOps.push_back(Offset); - return false; - } - } else if (selectAddrRegImm16(Op, Base, Offset)) { - // Prior to MIPS32r6/MIPS64r6, they can handle 16-bit offsets. - OutOps.push_back(Base); - OutOps.push_back(Offset); - return false; - } - // In all cases, 0-bit offsets are acceptable. - OutOps.push_back(Op); - OutOps.push_back(CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i32)); - return false; - } - return true; -} - -FunctionPass *llvm::createMipsSEISelDag(MipsTargetMachine &TM, - CodeGenOpt::Level OptLevel) { - return new MipsSEDAGToDAGISel(TM, OptLevel); -} diff --git a/contrib/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.h b/contrib/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.h deleted file mode 100644 index ce594e1fb4fa..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.h +++ /dev/null @@ -1,142 +0,0 @@ -//===-- MipsSEISelDAGToDAG.h - A Dag to Dag Inst Selector for MipsSE -----===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Subclass of MipsDAGToDAGISel specialized for mips32/64. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_MIPS_MIPSSEISELDAGTODAG_H -#define LLVM_LIB_TARGET_MIPS_MIPSSEISELDAGTODAG_H - -#include "MipsISelDAGToDAG.h" - -namespace llvm { - -class MipsSEDAGToDAGISel : public MipsDAGToDAGISel { - -public: - explicit MipsSEDAGToDAGISel(MipsTargetMachine &TM, CodeGenOpt::Level OL) - : MipsDAGToDAGISel(TM, OL) {} - -private: - - bool runOnMachineFunction(MachineFunction &MF) override; - - void getAnalysisUsage(AnalysisUsage &AU) const override; - - void addDSPCtrlRegOperands(bool IsDef, MachineInstr &MI, - MachineFunction &MF); - - unsigned getMSACtrlReg(const SDValue RegIdx) const; - - bool replaceUsesWithZeroReg(MachineRegisterInfo *MRI, const MachineInstr&); - - std::pair<SDNode *, SDNode *> selectMULT(SDNode *N, unsigned Opc, - const SDLoc &dl, EVT Ty, bool HasLo, - bool HasHi); - - void selectAddE(SDNode *Node, const SDLoc &DL) const; - - bool selectAddrFrameIndex(SDValue Addr, SDValue &Base, SDValue &Offset) const; - bool selectAddrFrameIndexOffset(SDValue Addr, SDValue &Base, SDValue &Offset, - unsigned OffsetBits, - unsigned ShiftAmount) const; - - bool selectAddrRegImm(SDValue Addr, SDValue &Base, - SDValue &Offset) const override; - - bool selectAddrDefault(SDValue Addr, SDValue &Base, - SDValue &Offset) const override; - - bool selectIntAddr(SDValue Addr, SDValue &Base, - SDValue &Offset) const override; - - bool selectAddrRegImm9(SDValue Addr, SDValue &Base, - SDValue &Offset) const; - - bool selectAddrRegImm11(SDValue Addr, SDValue &Base, - SDValue &Offset) const; - - bool selectAddrRegImm12(SDValue Addr, SDValue &Base, - SDValue &Offset) const; - - bool selectAddrRegImm16(SDValue Addr, SDValue &Base, - SDValue &Offset) const; - - bool selectIntAddr11MM(SDValue Addr, SDValue &Base, - SDValue &Offset) const override; - - bool selectIntAddr12MM(SDValue Addr, SDValue &Base, - SDValue &Offset) const override; - - bool selectIntAddr16MM(SDValue Addr, SDValue &Base, - SDValue &Offset) const override; - - bool selectIntAddrLSL2MM(SDValue Addr, SDValue &Base, - SDValue &Offset) const override; - - bool selectIntAddrSImm10(SDValue Addr, SDValue &Base, - SDValue &Offset) const override; - - bool selectIntAddrSImm10Lsl1(SDValue Addr, SDValue &Base, - SDValue &Offset) const override; - - bool selectIntAddrSImm10Lsl2(SDValue Addr, SDValue &Base, - SDValue &Offset) const override; - - bool selectIntAddrSImm10Lsl3(SDValue Addr, SDValue &Base, - SDValue &Offset) const override; - - /// Select constant vector splats. - bool selectVSplat(SDNode *N, APInt &Imm, - unsigned MinSizeInBits) const override; - /// Select constant vector splats whose value fits in a given integer. - bool selectVSplatCommon(SDValue N, SDValue &Imm, bool Signed, - unsigned ImmBitSize) const; - /// Select constant vector splats whose value fits in a uimm1. - bool selectVSplatUimm1(SDValue N, SDValue &Imm) const override; - /// Select constant vector splats whose value fits in a uimm2. - bool selectVSplatUimm2(SDValue N, SDValue &Imm) const override; - /// Select constant vector splats whose value fits in a uimm3. - bool selectVSplatUimm3(SDValue N, SDValue &Imm) const override; - /// Select constant vector splats whose value fits in a uimm4. - bool selectVSplatUimm4(SDValue N, SDValue &Imm) const override; - /// Select constant vector splats whose value fits in a uimm5. - bool selectVSplatUimm5(SDValue N, SDValue &Imm) const override; - /// Select constant vector splats whose value fits in a uimm6. - bool selectVSplatUimm6(SDValue N, SDValue &Imm) const override; - /// Select constant vector splats whose value fits in a uimm8. - bool selectVSplatUimm8(SDValue N, SDValue &Imm) const override; - /// Select constant vector splats whose value fits in a simm5. - bool selectVSplatSimm5(SDValue N, SDValue &Imm) const override; - /// Select constant vector splats whose value is a power of 2. - bool selectVSplatUimmPow2(SDValue N, SDValue &Imm) const override; - /// Select constant vector splats whose value is the inverse of a - /// power of 2. - bool selectVSplatUimmInvPow2(SDValue N, SDValue &Imm) const override; - /// Select constant vector splats whose value is a run of set bits - /// ending at the most significant bit - bool selectVSplatMaskL(SDValue N, SDValue &Imm) const override; - /// Select constant vector splats whose value is a run of set bits - /// starting at bit zero. - bool selectVSplatMaskR(SDValue N, SDValue &Imm) const override; - - bool trySelect(SDNode *Node) override; - - void processFunctionAfterISel(MachineFunction &MF) override; - - bool SelectInlineAsmMemoryOperand(const SDValue &Op, - unsigned ConstraintID, - std::vector<SDValue> &OutOps) override; -}; - -FunctionPass *createMipsSEISelDag(MipsTargetMachine &TM, - CodeGenOpt::Level OptLevel); -} - -#endif diff --git a/contrib/llvm/lib/Target/Mips/MipsSEISelLowering.cpp b/contrib/llvm/lib/Target/Mips/MipsSEISelLowering.cpp deleted file mode 100644 index edf57a3840d1..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsSEISelLowering.cpp +++ /dev/null @@ -1,3864 +0,0 @@ -//===- MipsSEISelLowering.cpp - MipsSE DAG Lowering Interface -------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Subclass of MipsTargetLowering specialized for mips32/64. -// -//===----------------------------------------------------------------------===// - -#include "MipsSEISelLowering.h" -#include "MipsMachineFunction.h" -#include "MipsRegisterInfo.h" -#include "MipsSubtarget.h" -#include "llvm/ADT/APInt.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/Triple.h" -#include "llvm/CodeGen/CallingConvLower.h" -#include "llvm/CodeGen/ISDOpcodes.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/MachineMemOperand.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/SelectionDAG.h" -#include "llvm/CodeGen/SelectionDAGNodes.h" -#include "llvm/CodeGen/TargetInstrInfo.h" -#include "llvm/CodeGen/TargetSubtargetInfo.h" -#include "llvm/CodeGen/ValueTypes.h" -#include "llvm/IR/DebugLoc.h" -#include "llvm/IR/Intrinsics.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MachineValueType.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/raw_ostream.h" -#include <algorithm> -#include <cassert> -#include <cstdint> -#include <iterator> -#include <utility> - -using namespace llvm; - -#define DEBUG_TYPE "mips-isel" - -static cl::opt<bool> -UseMipsTailCalls("mips-tail-calls", cl::Hidden, - cl::desc("MIPS: permit tail calls."), cl::init(false)); - -static cl::opt<bool> NoDPLoadStore("mno-ldc1-sdc1", cl::init(false), - cl::desc("Expand double precision loads and " - "stores to their single precision " - "counterparts")); - -MipsSETargetLowering::MipsSETargetLowering(const MipsTargetMachine &TM, - const MipsSubtarget &STI) - : MipsTargetLowering(TM, STI) { - // Set up the register classes - addRegisterClass(MVT::i32, &Mips::GPR32RegClass); - - if (Subtarget.isGP64bit()) - addRegisterClass(MVT::i64, &Mips::GPR64RegClass); - - if (Subtarget.hasDSP() || Subtarget.hasMSA()) { - // Expand all truncating stores and extending loads. - for (MVT VT0 : MVT::vector_valuetypes()) { - for (MVT VT1 : MVT::vector_valuetypes()) { - setTruncStoreAction(VT0, VT1, Expand); - setLoadExtAction(ISD::SEXTLOAD, VT0, VT1, Expand); - setLoadExtAction(ISD::ZEXTLOAD, VT0, VT1, Expand); - setLoadExtAction(ISD::EXTLOAD, VT0, VT1, Expand); - } - } - } - - if (Subtarget.hasDSP()) { - MVT::SimpleValueType VecTys[2] = {MVT::v2i16, MVT::v4i8}; - - for (unsigned i = 0; i < array_lengthof(VecTys); ++i) { - addRegisterClass(VecTys[i], &Mips::DSPRRegClass); - - // Expand all builtin opcodes. - for (unsigned Opc = 0; Opc < ISD::BUILTIN_OP_END; ++Opc) - setOperationAction(Opc, VecTys[i], Expand); - - setOperationAction(ISD::ADD, VecTys[i], Legal); - setOperationAction(ISD::SUB, VecTys[i], Legal); - setOperationAction(ISD::LOAD, VecTys[i], Legal); - setOperationAction(ISD::STORE, VecTys[i], Legal); - setOperationAction(ISD::BITCAST, VecTys[i], Legal); - } - - setTargetDAGCombine(ISD::SHL); - setTargetDAGCombine(ISD::SRA); - setTargetDAGCombine(ISD::SRL); - setTargetDAGCombine(ISD::SETCC); - setTargetDAGCombine(ISD::VSELECT); - - if (Subtarget.hasMips32r2()) { - setOperationAction(ISD::ADDC, MVT::i32, Legal); - setOperationAction(ISD::ADDE, MVT::i32, Legal); - } - } - - if (Subtarget.hasDSPR2()) - setOperationAction(ISD::MUL, MVT::v2i16, Legal); - - if (Subtarget.hasMSA()) { - addMSAIntType(MVT::v16i8, &Mips::MSA128BRegClass); - addMSAIntType(MVT::v8i16, &Mips::MSA128HRegClass); - addMSAIntType(MVT::v4i32, &Mips::MSA128WRegClass); - addMSAIntType(MVT::v2i64, &Mips::MSA128DRegClass); - addMSAFloatType(MVT::v8f16, &Mips::MSA128HRegClass); - addMSAFloatType(MVT::v4f32, &Mips::MSA128WRegClass); - addMSAFloatType(MVT::v2f64, &Mips::MSA128DRegClass); - - // f16 is a storage-only type, always promote it to f32. - addRegisterClass(MVT::f16, &Mips::MSA128HRegClass); - setOperationAction(ISD::SETCC, MVT::f16, Promote); - setOperationAction(ISD::BR_CC, MVT::f16, Promote); - setOperationAction(ISD::SELECT_CC, MVT::f16, Promote); - setOperationAction(ISD::SELECT, MVT::f16, Promote); - setOperationAction(ISD::FADD, MVT::f16, Promote); - setOperationAction(ISD::FSUB, MVT::f16, Promote); - setOperationAction(ISD::FMUL, MVT::f16, Promote); - setOperationAction(ISD::FDIV, MVT::f16, Promote); - setOperationAction(ISD::FREM, MVT::f16, Promote); - setOperationAction(ISD::FMA, MVT::f16, Promote); - setOperationAction(ISD::FNEG, MVT::f16, Promote); - setOperationAction(ISD::FABS, MVT::f16, Promote); - setOperationAction(ISD::FCEIL, MVT::f16, Promote); - setOperationAction(ISD::FCOPYSIGN, MVT::f16, Promote); - setOperationAction(ISD::FCOS, MVT::f16, Promote); - setOperationAction(ISD::FP_EXTEND, MVT::f16, Promote); - setOperationAction(ISD::FFLOOR, MVT::f16, Promote); - setOperationAction(ISD::FNEARBYINT, MVT::f16, Promote); - setOperationAction(ISD::FPOW, MVT::f16, Promote); - setOperationAction(ISD::FPOWI, MVT::f16, Promote); - setOperationAction(ISD::FRINT, MVT::f16, Promote); - setOperationAction(ISD::FSIN, MVT::f16, Promote); - setOperationAction(ISD::FSINCOS, MVT::f16, Promote); - setOperationAction(ISD::FSQRT, MVT::f16, Promote); - setOperationAction(ISD::FEXP, MVT::f16, Promote); - setOperationAction(ISD::FEXP2, MVT::f16, Promote); - setOperationAction(ISD::FLOG, MVT::f16, Promote); - setOperationAction(ISD::FLOG2, MVT::f16, Promote); - setOperationAction(ISD::FLOG10, MVT::f16, Promote); - setOperationAction(ISD::FROUND, MVT::f16, Promote); - setOperationAction(ISD::FTRUNC, MVT::f16, Promote); - setOperationAction(ISD::FMINNUM, MVT::f16, Promote); - setOperationAction(ISD::FMAXNUM, MVT::f16, Promote); - setOperationAction(ISD::FMINIMUM, MVT::f16, Promote); - setOperationAction(ISD::FMAXIMUM, MVT::f16, Promote); - - setTargetDAGCombine(ISD::AND); - setTargetDAGCombine(ISD::OR); - setTargetDAGCombine(ISD::SRA); - setTargetDAGCombine(ISD::VSELECT); - setTargetDAGCombine(ISD::XOR); - } - - if (!Subtarget.useSoftFloat()) { - addRegisterClass(MVT::f32, &Mips::FGR32RegClass); - - // When dealing with single precision only, use libcalls - if (!Subtarget.isSingleFloat()) { - if (Subtarget.isFP64bit()) - addRegisterClass(MVT::f64, &Mips::FGR64RegClass); - else - addRegisterClass(MVT::f64, &Mips::AFGR64RegClass); - } - } - - setOperationAction(ISD::SMUL_LOHI, MVT::i32, Custom); - setOperationAction(ISD::UMUL_LOHI, MVT::i32, Custom); - setOperationAction(ISD::MULHS, MVT::i32, Custom); - setOperationAction(ISD::MULHU, MVT::i32, Custom); - - if (Subtarget.hasCnMips()) - setOperationAction(ISD::MUL, MVT::i64, Legal); - else if (Subtarget.isGP64bit()) - setOperationAction(ISD::MUL, MVT::i64, Custom); - - if (Subtarget.isGP64bit()) { - setOperationAction(ISD::SMUL_LOHI, MVT::i64, Custom); - setOperationAction(ISD::UMUL_LOHI, MVT::i64, Custom); - setOperationAction(ISD::MULHS, MVT::i64, Custom); - setOperationAction(ISD::MULHU, MVT::i64, Custom); - setOperationAction(ISD::SDIVREM, MVT::i64, Custom); - setOperationAction(ISD::UDIVREM, MVT::i64, Custom); - } - - setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::i64, Custom); - setOperationAction(ISD::INTRINSIC_W_CHAIN, MVT::i64, Custom); - - setOperationAction(ISD::SDIVREM, MVT::i32, Custom); - setOperationAction(ISD::UDIVREM, MVT::i32, Custom); - setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom); - setOperationAction(ISD::LOAD, MVT::i32, Custom); - setOperationAction(ISD::STORE, MVT::i32, Custom); - - setTargetDAGCombine(ISD::MUL); - - setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom); - setOperationAction(ISD::INTRINSIC_W_CHAIN, MVT::Other, Custom); - setOperationAction(ISD::INTRINSIC_VOID, MVT::Other, Custom); - - if (Subtarget.hasMips32r2() && !Subtarget.useSoftFloat() && - !Subtarget.hasMips64()) { - setOperationAction(ISD::BITCAST, MVT::i64, Custom); - } - - if (NoDPLoadStore) { - setOperationAction(ISD::LOAD, MVT::f64, Custom); - setOperationAction(ISD::STORE, MVT::f64, Custom); - } - - if (Subtarget.hasMips32r6()) { - // MIPS32r6 replaces the accumulator-based multiplies with a three register - // instruction - setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand); - setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand); - setOperationAction(ISD::MUL, MVT::i32, Legal); - setOperationAction(ISD::MULHS, MVT::i32, Legal); - setOperationAction(ISD::MULHU, MVT::i32, Legal); - - // MIPS32r6 replaces the accumulator-based division/remainder with separate - // three register division and remainder instructions. - setOperationAction(ISD::SDIVREM, MVT::i32, Expand); - setOperationAction(ISD::UDIVREM, MVT::i32, Expand); - setOperationAction(ISD::SDIV, MVT::i32, Legal); - setOperationAction(ISD::UDIV, MVT::i32, Legal); - setOperationAction(ISD::SREM, MVT::i32, Legal); - setOperationAction(ISD::UREM, MVT::i32, Legal); - - // MIPS32r6 replaces conditional moves with an equivalent that removes the - // need for three GPR read ports. - setOperationAction(ISD::SETCC, MVT::i32, Legal); - setOperationAction(ISD::SELECT, MVT::i32, Legal); - setOperationAction(ISD::SELECT_CC, MVT::i32, Expand); - - setOperationAction(ISD::SETCC, MVT::f32, Legal); - setOperationAction(ISD::SELECT, MVT::f32, Legal); - setOperationAction(ISD::SELECT_CC, MVT::f32, Expand); - - assert(Subtarget.isFP64bit() && "FR=1 is required for MIPS32r6"); - setOperationAction(ISD::SETCC, MVT::f64, Legal); - setOperationAction(ISD::SELECT, MVT::f64, Custom); - setOperationAction(ISD::SELECT_CC, MVT::f64, Expand); - - setOperationAction(ISD::BRCOND, MVT::Other, Legal); - - // Floating point > and >= are supported via < and <= - setCondCodeAction(ISD::SETOGE, MVT::f32, Expand); - setCondCodeAction(ISD::SETOGT, MVT::f32, Expand); - setCondCodeAction(ISD::SETUGE, MVT::f32, Expand); - setCondCodeAction(ISD::SETUGT, MVT::f32, Expand); - - setCondCodeAction(ISD::SETOGE, MVT::f64, Expand); - setCondCodeAction(ISD::SETOGT, MVT::f64, Expand); - setCondCodeAction(ISD::SETUGE, MVT::f64, Expand); - setCondCodeAction(ISD::SETUGT, MVT::f64, Expand); - } - - if (Subtarget.hasMips64r6()) { - // MIPS64r6 replaces the accumulator-based multiplies with a three register - // instruction - setOperationAction(ISD::SMUL_LOHI, MVT::i64, Expand); - setOperationAction(ISD::UMUL_LOHI, MVT::i64, Expand); - setOperationAction(ISD::MUL, MVT::i64, Legal); - setOperationAction(ISD::MULHS, MVT::i64, Legal); - setOperationAction(ISD::MULHU, MVT::i64, Legal); - - // MIPS32r6 replaces the accumulator-based division/remainder with separate - // three register division and remainder instructions. - setOperationAction(ISD::SDIVREM, MVT::i64, Expand); - setOperationAction(ISD::UDIVREM, MVT::i64, Expand); - setOperationAction(ISD::SDIV, MVT::i64, Legal); - setOperationAction(ISD::UDIV, MVT::i64, Legal); - setOperationAction(ISD::SREM, MVT::i64, Legal); - setOperationAction(ISD::UREM, MVT::i64, Legal); - - // MIPS64r6 replaces conditional moves with an equivalent that removes the - // need for three GPR read ports. - setOperationAction(ISD::SETCC, MVT::i64, Legal); - setOperationAction(ISD::SELECT, MVT::i64, Legal); - setOperationAction(ISD::SELECT_CC, MVT::i64, Expand); - } - - computeRegisterProperties(Subtarget.getRegisterInfo()); -} - -const MipsTargetLowering * -llvm::createMipsSETargetLowering(const MipsTargetMachine &TM, - const MipsSubtarget &STI) { - return new MipsSETargetLowering(TM, STI); -} - -const TargetRegisterClass * -MipsSETargetLowering::getRepRegClassFor(MVT VT) const { - if (VT == MVT::Untyped) - return Subtarget.hasDSP() ? &Mips::ACC64DSPRegClass : &Mips::ACC64RegClass; - - return TargetLowering::getRepRegClassFor(VT); -} - -// Enable MSA support for the given integer type and Register class. -void MipsSETargetLowering:: -addMSAIntType(MVT::SimpleValueType Ty, const TargetRegisterClass *RC) { - addRegisterClass(Ty, RC); - - // Expand all builtin opcodes. - for (unsigned Opc = 0; Opc < ISD::BUILTIN_OP_END; ++Opc) - setOperationAction(Opc, Ty, Expand); - - setOperationAction(ISD::BITCAST, Ty, Legal); - setOperationAction(ISD::LOAD, Ty, Legal); - setOperationAction(ISD::STORE, Ty, Legal); - setOperationAction(ISD::EXTRACT_VECTOR_ELT, Ty, Custom); - setOperationAction(ISD::INSERT_VECTOR_ELT, Ty, Legal); - setOperationAction(ISD::BUILD_VECTOR, Ty, Custom); - - setOperationAction(ISD::ADD, Ty, Legal); - setOperationAction(ISD::AND, Ty, Legal); - setOperationAction(ISD::CTLZ, Ty, Legal); - setOperationAction(ISD::CTPOP, Ty, Legal); - setOperationAction(ISD::MUL, Ty, Legal); - setOperationAction(ISD::OR, Ty, Legal); - setOperationAction(ISD::SDIV, Ty, Legal); - setOperationAction(ISD::SREM, Ty, Legal); - setOperationAction(ISD::SHL, Ty, Legal); - setOperationAction(ISD::SRA, Ty, Legal); - setOperationAction(ISD::SRL, Ty, Legal); - setOperationAction(ISD::SUB, Ty, Legal); - setOperationAction(ISD::SMAX, Ty, Legal); - setOperationAction(ISD::SMIN, Ty, Legal); - setOperationAction(ISD::UDIV, Ty, Legal); - setOperationAction(ISD::UREM, Ty, Legal); - setOperationAction(ISD::UMAX, Ty, Legal); - setOperationAction(ISD::UMIN, Ty, Legal); - setOperationAction(ISD::VECTOR_SHUFFLE, Ty, Custom); - setOperationAction(ISD::VSELECT, Ty, Legal); - setOperationAction(ISD::XOR, Ty, Legal); - - if (Ty == MVT::v4i32 || Ty == MVT::v2i64) { - setOperationAction(ISD::FP_TO_SINT, Ty, Legal); - setOperationAction(ISD::FP_TO_UINT, Ty, Legal); - setOperationAction(ISD::SINT_TO_FP, Ty, Legal); - setOperationAction(ISD::UINT_TO_FP, Ty, Legal); - } - - setOperationAction(ISD::SETCC, Ty, Legal); - setCondCodeAction(ISD::SETNE, Ty, Expand); - setCondCodeAction(ISD::SETGE, Ty, Expand); - setCondCodeAction(ISD::SETGT, Ty, Expand); - setCondCodeAction(ISD::SETUGE, Ty, Expand); - setCondCodeAction(ISD::SETUGT, Ty, Expand); -} - -// Enable MSA support for the given floating-point type and Register class. -void MipsSETargetLowering:: -addMSAFloatType(MVT::SimpleValueType Ty, const TargetRegisterClass *RC) { - addRegisterClass(Ty, RC); - - // Expand all builtin opcodes. - for (unsigned Opc = 0; Opc < ISD::BUILTIN_OP_END; ++Opc) - setOperationAction(Opc, Ty, Expand); - - setOperationAction(ISD::LOAD, Ty, Legal); - setOperationAction(ISD::STORE, Ty, Legal); - setOperationAction(ISD::BITCAST, Ty, Legal); - setOperationAction(ISD::EXTRACT_VECTOR_ELT, Ty, Legal); - setOperationAction(ISD::INSERT_VECTOR_ELT, Ty, Legal); - setOperationAction(ISD::BUILD_VECTOR, Ty, Custom); - - if (Ty != MVT::v8f16) { - setOperationAction(ISD::FABS, Ty, Legal); - setOperationAction(ISD::FADD, Ty, Legal); - setOperationAction(ISD::FDIV, Ty, Legal); - setOperationAction(ISD::FEXP2, Ty, Legal); - setOperationAction(ISD::FLOG2, Ty, Legal); - setOperationAction(ISD::FMA, Ty, Legal); - setOperationAction(ISD::FMUL, Ty, Legal); - setOperationAction(ISD::FRINT, Ty, Legal); - setOperationAction(ISD::FSQRT, Ty, Legal); - setOperationAction(ISD::FSUB, Ty, Legal); - setOperationAction(ISD::VSELECT, Ty, Legal); - - setOperationAction(ISD::SETCC, Ty, Legal); - setCondCodeAction(ISD::SETOGE, Ty, Expand); - setCondCodeAction(ISD::SETOGT, Ty, Expand); - setCondCodeAction(ISD::SETUGE, Ty, Expand); - setCondCodeAction(ISD::SETUGT, Ty, Expand); - setCondCodeAction(ISD::SETGE, Ty, Expand); - setCondCodeAction(ISD::SETGT, Ty, Expand); - } -} - -SDValue MipsSETargetLowering::lowerSELECT(SDValue Op, SelectionDAG &DAG) const { - if(!Subtarget.hasMips32r6()) - return MipsTargetLowering::LowerOperation(Op, DAG); - - EVT ResTy = Op->getValueType(0); - SDLoc DL(Op); - - // Although MTC1_D64 takes an i32 and writes an f64, the upper 32 bits of the - // floating point register are undefined. Not really an issue as sel.d, which - // is produced from an FSELECT node, only looks at bit 0. - SDValue Tmp = DAG.getNode(MipsISD::MTC1_D64, DL, MVT::f64, Op->getOperand(0)); - return DAG.getNode(MipsISD::FSELECT, DL, ResTy, Tmp, Op->getOperand(1), - Op->getOperand(2)); -} - -bool MipsSETargetLowering::allowsMisalignedMemoryAccesses( - EVT VT, unsigned, unsigned, MachineMemOperand::Flags, bool *Fast) const { - MVT::SimpleValueType SVT = VT.getSimpleVT().SimpleTy; - - if (Subtarget.systemSupportsUnalignedAccess()) { - // MIPS32r6/MIPS64r6 is required to support unaligned access. It's - // implementation defined whether this is handled by hardware, software, or - // a hybrid of the two but it's expected that most implementations will - // handle the majority of cases in hardware. - if (Fast) - *Fast = true; - return true; - } - - switch (SVT) { - case MVT::i64: - case MVT::i32: - if (Fast) - *Fast = true; - return true; - default: - return false; - } -} - -SDValue MipsSETargetLowering::LowerOperation(SDValue Op, - SelectionDAG &DAG) const { - switch(Op.getOpcode()) { - case ISD::LOAD: return lowerLOAD(Op, DAG); - case ISD::STORE: return lowerSTORE(Op, DAG); - case ISD::SMUL_LOHI: return lowerMulDiv(Op, MipsISD::Mult, true, true, DAG); - case ISD::UMUL_LOHI: return lowerMulDiv(Op, MipsISD::Multu, true, true, DAG); - case ISD::MULHS: return lowerMulDiv(Op, MipsISD::Mult, false, true, DAG); - case ISD::MULHU: return lowerMulDiv(Op, MipsISD::Multu, false, true, DAG); - case ISD::MUL: return lowerMulDiv(Op, MipsISD::Mult, true, false, DAG); - case ISD::SDIVREM: return lowerMulDiv(Op, MipsISD::DivRem, true, true, DAG); - case ISD::UDIVREM: return lowerMulDiv(Op, MipsISD::DivRemU, true, true, - DAG); - case ISD::INTRINSIC_WO_CHAIN: return lowerINTRINSIC_WO_CHAIN(Op, DAG); - case ISD::INTRINSIC_W_CHAIN: return lowerINTRINSIC_W_CHAIN(Op, DAG); - case ISD::INTRINSIC_VOID: return lowerINTRINSIC_VOID(Op, DAG); - case ISD::EXTRACT_VECTOR_ELT: return lowerEXTRACT_VECTOR_ELT(Op, DAG); - case ISD::BUILD_VECTOR: return lowerBUILD_VECTOR(Op, DAG); - case ISD::VECTOR_SHUFFLE: return lowerVECTOR_SHUFFLE(Op, DAG); - case ISD::SELECT: return lowerSELECT(Op, DAG); - case ISD::BITCAST: return lowerBITCAST(Op, DAG); - } - - return MipsTargetLowering::LowerOperation(Op, DAG); -} - -// Fold zero extensions into MipsISD::VEXTRACT_[SZ]EXT_ELT -// -// Performs the following transformations: -// - Changes MipsISD::VEXTRACT_[SZ]EXT_ELT to zero extension if its -// sign/zero-extension is completely overwritten by the new one performed by -// the ISD::AND. -// - Removes redundant zero extensions performed by an ISD::AND. -static SDValue performANDCombine(SDNode *N, SelectionDAG &DAG, - TargetLowering::DAGCombinerInfo &DCI, - const MipsSubtarget &Subtarget) { - if (!Subtarget.hasMSA()) - return SDValue(); - - SDValue Op0 = N->getOperand(0); - SDValue Op1 = N->getOperand(1); - unsigned Op0Opcode = Op0->getOpcode(); - - // (and (MipsVExtract[SZ]Ext $a, $b, $c), imm:$d) - // where $d + 1 == 2^n and n == 32 - // or $d + 1 == 2^n and n <= 32 and ZExt - // -> (MipsVExtractZExt $a, $b, $c) - if (Op0Opcode == MipsISD::VEXTRACT_SEXT_ELT || - Op0Opcode == MipsISD::VEXTRACT_ZEXT_ELT) { - ConstantSDNode *Mask = dyn_cast<ConstantSDNode>(Op1); - - if (!Mask) - return SDValue(); - - int32_t Log2IfPositive = (Mask->getAPIntValue() + 1).exactLogBase2(); - - if (Log2IfPositive <= 0) - return SDValue(); // Mask+1 is not a power of 2 - - SDValue Op0Op2 = Op0->getOperand(2); - EVT ExtendTy = cast<VTSDNode>(Op0Op2)->getVT(); - unsigned ExtendTySize = ExtendTy.getSizeInBits(); - unsigned Log2 = Log2IfPositive; - - if ((Op0Opcode == MipsISD::VEXTRACT_ZEXT_ELT && Log2 >= ExtendTySize) || - Log2 == ExtendTySize) { - SDValue Ops[] = { Op0->getOperand(0), Op0->getOperand(1), Op0Op2 }; - return DAG.getNode(MipsISD::VEXTRACT_ZEXT_ELT, SDLoc(Op0), - Op0->getVTList(), - makeArrayRef(Ops, Op0->getNumOperands())); - } - } - - return SDValue(); -} - -// Determine if the specified node is a constant vector splat. -// -// Returns true and sets Imm if: -// * N is a ISD::BUILD_VECTOR representing a constant splat -// -// This function is quite similar to MipsSEDAGToDAGISel::selectVSplat. The -// differences are that it assumes the MSA has already been checked and the -// arbitrary requirement for a maximum of 32-bit integers isn't applied (and -// must not be in order for binsri.d to be selectable). -static bool isVSplat(SDValue N, APInt &Imm, bool IsLittleEndian) { - BuildVectorSDNode *Node = dyn_cast<BuildVectorSDNode>(N.getNode()); - - if (!Node) - return false; - - APInt SplatValue, SplatUndef; - unsigned SplatBitSize; - bool HasAnyUndefs; - - if (!Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs, - 8, !IsLittleEndian)) - return false; - - Imm = SplatValue; - - return true; -} - -// Test whether the given node is an all-ones build_vector. -static bool isVectorAllOnes(SDValue N) { - // Look through bitcasts. Endianness doesn't matter because we are looking - // for an all-ones value. - if (N->getOpcode() == ISD::BITCAST) - N = N->getOperand(0); - - BuildVectorSDNode *BVN = dyn_cast<BuildVectorSDNode>(N); - - if (!BVN) - return false; - - APInt SplatValue, SplatUndef; - unsigned SplatBitSize; - bool HasAnyUndefs; - - // Endianness doesn't matter in this context because we are looking for - // an all-ones value. - if (BVN->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs)) - return SplatValue.isAllOnesValue(); - - return false; -} - -// Test whether N is the bitwise inverse of OfNode. -static bool isBitwiseInverse(SDValue N, SDValue OfNode) { - if (N->getOpcode() != ISD::XOR) - return false; - - if (isVectorAllOnes(N->getOperand(0))) - return N->getOperand(1) == OfNode; - - if (isVectorAllOnes(N->getOperand(1))) - return N->getOperand(0) == OfNode; - - return false; -} - -// Perform combines where ISD::OR is the root node. -// -// Performs the following transformations: -// - (or (and $a, $mask), (and $b, $inv_mask)) => (vselect $mask, $a, $b) -// where $inv_mask is the bitwise inverse of $mask and the 'or' has a 128-bit -// vector type. -static SDValue performORCombine(SDNode *N, SelectionDAG &DAG, - TargetLowering::DAGCombinerInfo &DCI, - const MipsSubtarget &Subtarget) { - if (!Subtarget.hasMSA()) - return SDValue(); - - EVT Ty = N->getValueType(0); - - if (!Ty.is128BitVector()) - return SDValue(); - - SDValue Op0 = N->getOperand(0); - SDValue Op1 = N->getOperand(1); - - if (Op0->getOpcode() == ISD::AND && Op1->getOpcode() == ISD::AND) { - SDValue Op0Op0 = Op0->getOperand(0); - SDValue Op0Op1 = Op0->getOperand(1); - SDValue Op1Op0 = Op1->getOperand(0); - SDValue Op1Op1 = Op1->getOperand(1); - bool IsLittleEndian = !Subtarget.isLittle(); - - SDValue IfSet, IfClr, Cond; - bool IsConstantMask = false; - APInt Mask, InvMask; - - // If Op0Op0 is an appropriate mask, try to find it's inverse in either - // Op1Op0, or Op1Op1. Keep track of the Cond, IfSet, and IfClr nodes, while - // looking. - // IfClr will be set if we find a valid match. - if (isVSplat(Op0Op0, Mask, IsLittleEndian)) { - Cond = Op0Op0; - IfSet = Op0Op1; - - if (isVSplat(Op1Op0, InvMask, IsLittleEndian) && - Mask.getBitWidth() == InvMask.getBitWidth() && Mask == ~InvMask) - IfClr = Op1Op1; - else if (isVSplat(Op1Op1, InvMask, IsLittleEndian) && - Mask.getBitWidth() == InvMask.getBitWidth() && Mask == ~InvMask) - IfClr = Op1Op0; - - IsConstantMask = true; - } - - // If IfClr is not yet set, and Op0Op1 is an appropriate mask, try the same - // thing again using this mask. - // IfClr will be set if we find a valid match. - if (!IfClr.getNode() && isVSplat(Op0Op1, Mask, IsLittleEndian)) { - Cond = Op0Op1; - IfSet = Op0Op0; - - if (isVSplat(Op1Op0, InvMask, IsLittleEndian) && - Mask.getBitWidth() == InvMask.getBitWidth() && Mask == ~InvMask) - IfClr = Op1Op1; - else if (isVSplat(Op1Op1, InvMask, IsLittleEndian) && - Mask.getBitWidth() == InvMask.getBitWidth() && Mask == ~InvMask) - IfClr = Op1Op0; - - IsConstantMask = true; - } - - // If IfClr is not yet set, try looking for a non-constant match. - // IfClr will be set if we find a valid match amongst the eight - // possibilities. - if (!IfClr.getNode()) { - if (isBitwiseInverse(Op0Op0, Op1Op0)) { - Cond = Op1Op0; - IfSet = Op1Op1; - IfClr = Op0Op1; - } else if (isBitwiseInverse(Op0Op1, Op1Op0)) { - Cond = Op1Op0; - IfSet = Op1Op1; - IfClr = Op0Op0; - } else if (isBitwiseInverse(Op0Op0, Op1Op1)) { - Cond = Op1Op1; - IfSet = Op1Op0; - IfClr = Op0Op1; - } else if (isBitwiseInverse(Op0Op1, Op1Op1)) { - Cond = Op1Op1; - IfSet = Op1Op0; - IfClr = Op0Op0; - } else if (isBitwiseInverse(Op1Op0, Op0Op0)) { - Cond = Op0Op0; - IfSet = Op0Op1; - IfClr = Op1Op1; - } else if (isBitwiseInverse(Op1Op1, Op0Op0)) { - Cond = Op0Op0; - IfSet = Op0Op1; - IfClr = Op1Op0; - } else if (isBitwiseInverse(Op1Op0, Op0Op1)) { - Cond = Op0Op1; - IfSet = Op0Op0; - IfClr = Op1Op1; - } else if (isBitwiseInverse(Op1Op1, Op0Op1)) { - Cond = Op0Op1; - IfSet = Op0Op0; - IfClr = Op1Op0; - } - } - - // At this point, IfClr will be set if we have a valid match. - if (!IfClr.getNode()) - return SDValue(); - - assert(Cond.getNode() && IfSet.getNode()); - - // Fold degenerate cases. - if (IsConstantMask) { - if (Mask.isAllOnesValue()) - return IfSet; - else if (Mask == 0) - return IfClr; - } - - // Transform the DAG into an equivalent VSELECT. - return DAG.getNode(ISD::VSELECT, SDLoc(N), Ty, Cond, IfSet, IfClr); - } - - return SDValue(); -} - -static bool shouldTransformMulToShiftsAddsSubs(APInt C, EVT VT, - SelectionDAG &DAG, - const MipsSubtarget &Subtarget) { - // Estimate the number of operations the below transform will turn a - // constant multiply into. The number is approximately equal to the minimal - // number of powers of two that constant can be broken down to by adding - // or subtracting them. - // - // If we have taken more than 12[1] / 8[2] steps to attempt the - // optimization for a native sized value, it is more than likely that this - // optimization will make things worse. - // - // [1] MIPS64 requires 6 instructions at most to materialize any constant, - // multiplication requires at least 4 cycles, but another cycle (or two) - // to retrieve the result from the HI/LO registers. - // - // [2] For MIPS32, more than 8 steps is expensive as the constant could be - // materialized in 2 instructions, multiplication requires at least 4 - // cycles, but another cycle (or two) to retrieve the result from the - // HI/LO registers. - // - // TODO: - // - MaxSteps needs to consider the `VT` of the constant for the current - // target. - // - Consider to perform this optimization after type legalization. - // That allows to remove a workaround for types not supported natively. - // - Take in account `-Os, -Oz` flags because this optimization - // increases code size. - unsigned MaxSteps = Subtarget.isABI_O32() ? 8 : 12; - - SmallVector<APInt, 16> WorkStack(1, C); - unsigned Steps = 0; - unsigned BitWidth = C.getBitWidth(); - - while (!WorkStack.empty()) { - APInt Val = WorkStack.pop_back_val(); - - if (Val == 0 || Val == 1) - continue; - - if (Steps >= MaxSteps) - return false; - - if (Val.isPowerOf2()) { - ++Steps; - continue; - } - - APInt Floor = APInt(BitWidth, 1) << Val.logBase2(); - APInt Ceil = Val.isNegative() ? APInt(BitWidth, 0) - : APInt(BitWidth, 1) << C.ceilLogBase2(); - if ((Val - Floor).ule(Ceil - Val)) { - WorkStack.push_back(Floor); - WorkStack.push_back(Val - Floor); - } else { - WorkStack.push_back(Ceil); - WorkStack.push_back(Ceil - Val); - } - - ++Steps; - } - - // If the value being multiplied is not supported natively, we have to pay - // an additional legalization cost, conservatively assume an increase in the - // cost of 3 instructions per step. This values for this heuristic were - // determined experimentally. - unsigned RegisterSize = DAG.getTargetLoweringInfo() - .getRegisterType(*DAG.getContext(), VT) - .getSizeInBits(); - Steps *= (VT.getSizeInBits() != RegisterSize) * 3; - if (Steps > 27) - return false; - - return true; -} - -static SDValue genConstMult(SDValue X, APInt C, const SDLoc &DL, EVT VT, - EVT ShiftTy, SelectionDAG &DAG) { - // Return 0. - if (C == 0) - return DAG.getConstant(0, DL, VT); - - // Return x. - if (C == 1) - return X; - - // If c is power of 2, return (shl x, log2(c)). - if (C.isPowerOf2()) - return DAG.getNode(ISD::SHL, DL, VT, X, - DAG.getConstant(C.logBase2(), DL, ShiftTy)); - - unsigned BitWidth = C.getBitWidth(); - APInt Floor = APInt(BitWidth, 1) << C.logBase2(); - APInt Ceil = C.isNegative() ? APInt(BitWidth, 0) : - APInt(BitWidth, 1) << C.ceilLogBase2(); - - // If |c - floor_c| <= |c - ceil_c|, - // where floor_c = pow(2, floor(log2(c))) and ceil_c = pow(2, ceil(log2(c))), - // return (add constMult(x, floor_c), constMult(x, c - floor_c)). - if ((C - Floor).ule(Ceil - C)) { - SDValue Op0 = genConstMult(X, Floor, DL, VT, ShiftTy, DAG); - SDValue Op1 = genConstMult(X, C - Floor, DL, VT, ShiftTy, DAG); - return DAG.getNode(ISD::ADD, DL, VT, Op0, Op1); - } - - // If |c - floor_c| > |c - ceil_c|, - // return (sub constMult(x, ceil_c), constMult(x, ceil_c - c)). - SDValue Op0 = genConstMult(X, Ceil, DL, VT, ShiftTy, DAG); - SDValue Op1 = genConstMult(X, Ceil - C, DL, VT, ShiftTy, DAG); - return DAG.getNode(ISD::SUB, DL, VT, Op0, Op1); -} - -static SDValue performMULCombine(SDNode *N, SelectionDAG &DAG, - const TargetLowering::DAGCombinerInfo &DCI, - const MipsSETargetLowering *TL, - const MipsSubtarget &Subtarget) { - EVT VT = N->getValueType(0); - - if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(1))) - if (!VT.isVector() && shouldTransformMulToShiftsAddsSubs( - C->getAPIntValue(), VT, DAG, Subtarget)) - return genConstMult(N->getOperand(0), C->getAPIntValue(), SDLoc(N), VT, - TL->getScalarShiftAmountTy(DAG.getDataLayout(), VT), - DAG); - - return SDValue(N, 0); -} - -static SDValue performDSPShiftCombine(unsigned Opc, SDNode *N, EVT Ty, - SelectionDAG &DAG, - const MipsSubtarget &Subtarget) { - // See if this is a vector splat immediate node. - APInt SplatValue, SplatUndef; - unsigned SplatBitSize; - bool HasAnyUndefs; - unsigned EltSize = Ty.getScalarSizeInBits(); - BuildVectorSDNode *BV = dyn_cast<BuildVectorSDNode>(N->getOperand(1)); - - if (!Subtarget.hasDSP()) - return SDValue(); - - if (!BV || - !BV->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs, - EltSize, !Subtarget.isLittle()) || - (SplatBitSize != EltSize) || - (SplatValue.getZExtValue() >= EltSize)) - return SDValue(); - - SDLoc DL(N); - return DAG.getNode(Opc, DL, Ty, N->getOperand(0), - DAG.getConstant(SplatValue.getZExtValue(), DL, MVT::i32)); -} - -static SDValue performSHLCombine(SDNode *N, SelectionDAG &DAG, - TargetLowering::DAGCombinerInfo &DCI, - const MipsSubtarget &Subtarget) { - EVT Ty = N->getValueType(0); - - if ((Ty != MVT::v2i16) && (Ty != MVT::v4i8)) - return SDValue(); - - return performDSPShiftCombine(MipsISD::SHLL_DSP, N, Ty, DAG, Subtarget); -} - -// Fold sign-extensions into MipsISD::VEXTRACT_[SZ]EXT_ELT for MSA and fold -// constant splats into MipsISD::SHRA_DSP for DSPr2. -// -// Performs the following transformations: -// - Changes MipsISD::VEXTRACT_[SZ]EXT_ELT to sign extension if its -// sign/zero-extension is completely overwritten by the new one performed by -// the ISD::SRA and ISD::SHL nodes. -// - Removes redundant sign extensions performed by an ISD::SRA and ISD::SHL -// sequence. -// -// See performDSPShiftCombine for more information about the transformation -// used for DSPr2. -static SDValue performSRACombine(SDNode *N, SelectionDAG &DAG, - TargetLowering::DAGCombinerInfo &DCI, - const MipsSubtarget &Subtarget) { - EVT Ty = N->getValueType(0); - - if (Subtarget.hasMSA()) { - SDValue Op0 = N->getOperand(0); - SDValue Op1 = N->getOperand(1); - - // (sra (shl (MipsVExtract[SZ]Ext $a, $b, $c), imm:$d), imm:$d) - // where $d + sizeof($c) == 32 - // or $d + sizeof($c) <= 32 and SExt - // -> (MipsVExtractSExt $a, $b, $c) - if (Op0->getOpcode() == ISD::SHL && Op1 == Op0->getOperand(1)) { - SDValue Op0Op0 = Op0->getOperand(0); - ConstantSDNode *ShAmount = dyn_cast<ConstantSDNode>(Op1); - - if (!ShAmount) - return SDValue(); - - if (Op0Op0->getOpcode() != MipsISD::VEXTRACT_SEXT_ELT && - Op0Op0->getOpcode() != MipsISD::VEXTRACT_ZEXT_ELT) - return SDValue(); - - EVT ExtendTy = cast<VTSDNode>(Op0Op0->getOperand(2))->getVT(); - unsigned TotalBits = ShAmount->getZExtValue() + ExtendTy.getSizeInBits(); - - if (TotalBits == 32 || - (Op0Op0->getOpcode() == MipsISD::VEXTRACT_SEXT_ELT && - TotalBits <= 32)) { - SDValue Ops[] = { Op0Op0->getOperand(0), Op0Op0->getOperand(1), - Op0Op0->getOperand(2) }; - return DAG.getNode(MipsISD::VEXTRACT_SEXT_ELT, SDLoc(Op0Op0), - Op0Op0->getVTList(), - makeArrayRef(Ops, Op0Op0->getNumOperands())); - } - } - } - - if ((Ty != MVT::v2i16) && ((Ty != MVT::v4i8) || !Subtarget.hasDSPR2())) - return SDValue(); - - return performDSPShiftCombine(MipsISD::SHRA_DSP, N, Ty, DAG, Subtarget); -} - - -static SDValue performSRLCombine(SDNode *N, SelectionDAG &DAG, - TargetLowering::DAGCombinerInfo &DCI, - const MipsSubtarget &Subtarget) { - EVT Ty = N->getValueType(0); - - if (((Ty != MVT::v2i16) || !Subtarget.hasDSPR2()) && (Ty != MVT::v4i8)) - return SDValue(); - - return performDSPShiftCombine(MipsISD::SHRL_DSP, N, Ty, DAG, Subtarget); -} - -static bool isLegalDSPCondCode(EVT Ty, ISD::CondCode CC) { - bool IsV216 = (Ty == MVT::v2i16); - - switch (CC) { - case ISD::SETEQ: - case ISD::SETNE: return true; - case ISD::SETLT: - case ISD::SETLE: - case ISD::SETGT: - case ISD::SETGE: return IsV216; - case ISD::SETULT: - case ISD::SETULE: - case ISD::SETUGT: - case ISD::SETUGE: return !IsV216; - default: return false; - } -} - -static SDValue performSETCCCombine(SDNode *N, SelectionDAG &DAG) { - EVT Ty = N->getValueType(0); - - if ((Ty != MVT::v2i16) && (Ty != MVT::v4i8)) - return SDValue(); - - if (!isLegalDSPCondCode(Ty, cast<CondCodeSDNode>(N->getOperand(2))->get())) - return SDValue(); - - return DAG.getNode(MipsISD::SETCC_DSP, SDLoc(N), Ty, N->getOperand(0), - N->getOperand(1), N->getOperand(2)); -} - -static SDValue performVSELECTCombine(SDNode *N, SelectionDAG &DAG) { - EVT Ty = N->getValueType(0); - - if (Ty == MVT::v2i16 || Ty == MVT::v4i8) { - SDValue SetCC = N->getOperand(0); - - if (SetCC.getOpcode() != MipsISD::SETCC_DSP) - return SDValue(); - - return DAG.getNode(MipsISD::SELECT_CC_DSP, SDLoc(N), Ty, - SetCC.getOperand(0), SetCC.getOperand(1), - N->getOperand(1), N->getOperand(2), SetCC.getOperand(2)); - } - - return SDValue(); -} - -static SDValue performXORCombine(SDNode *N, SelectionDAG &DAG, - const MipsSubtarget &Subtarget) { - EVT Ty = N->getValueType(0); - - if (Subtarget.hasMSA() && Ty.is128BitVector() && Ty.isInteger()) { - // Try the following combines: - // (xor (or $a, $b), (build_vector allones)) - // (xor (or $a, $b), (bitcast (build_vector allones))) - SDValue Op0 = N->getOperand(0); - SDValue Op1 = N->getOperand(1); - SDValue NotOp; - - if (ISD::isBuildVectorAllOnes(Op0.getNode())) - NotOp = Op1; - else if (ISD::isBuildVectorAllOnes(Op1.getNode())) - NotOp = Op0; - else - return SDValue(); - - if (NotOp->getOpcode() == ISD::OR) - return DAG.getNode(MipsISD::VNOR, SDLoc(N), Ty, NotOp->getOperand(0), - NotOp->getOperand(1)); - } - - return SDValue(); -} - -SDValue -MipsSETargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const { - SelectionDAG &DAG = DCI.DAG; - SDValue Val; - - switch (N->getOpcode()) { - case ISD::AND: - Val = performANDCombine(N, DAG, DCI, Subtarget); - break; - case ISD::OR: - Val = performORCombine(N, DAG, DCI, Subtarget); - break; - case ISD::MUL: - return performMULCombine(N, DAG, DCI, this, Subtarget); - case ISD::SHL: - Val = performSHLCombine(N, DAG, DCI, Subtarget); - break; - case ISD::SRA: - return performSRACombine(N, DAG, DCI, Subtarget); - case ISD::SRL: - return performSRLCombine(N, DAG, DCI, Subtarget); - case ISD::VSELECT: - return performVSELECTCombine(N, DAG); - case ISD::XOR: - Val = performXORCombine(N, DAG, Subtarget); - break; - case ISD::SETCC: - Val = performSETCCCombine(N, DAG); - break; - } - - if (Val.getNode()) { - LLVM_DEBUG(dbgs() << "\nMipsSE DAG Combine:\n"; - N->printrWithDepth(dbgs(), &DAG); dbgs() << "\n=> \n"; - Val.getNode()->printrWithDepth(dbgs(), &DAG); dbgs() << "\n"); - return Val; - } - - return MipsTargetLowering::PerformDAGCombine(N, DCI); -} - -MachineBasicBlock * -MipsSETargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, - MachineBasicBlock *BB) const { - switch (MI.getOpcode()) { - default: - return MipsTargetLowering::EmitInstrWithCustomInserter(MI, BB); - case Mips::BPOSGE32_PSEUDO: - return emitBPOSGE32(MI, BB); - case Mips::SNZ_B_PSEUDO: - return emitMSACBranchPseudo(MI, BB, Mips::BNZ_B); - case Mips::SNZ_H_PSEUDO: - return emitMSACBranchPseudo(MI, BB, Mips::BNZ_H); - case Mips::SNZ_W_PSEUDO: - return emitMSACBranchPseudo(MI, BB, Mips::BNZ_W); - case Mips::SNZ_D_PSEUDO: - return emitMSACBranchPseudo(MI, BB, Mips::BNZ_D); - case Mips::SNZ_V_PSEUDO: - return emitMSACBranchPseudo(MI, BB, Mips::BNZ_V); - case Mips::SZ_B_PSEUDO: - return emitMSACBranchPseudo(MI, BB, Mips::BZ_B); - case Mips::SZ_H_PSEUDO: - return emitMSACBranchPseudo(MI, BB, Mips::BZ_H); - case Mips::SZ_W_PSEUDO: - return emitMSACBranchPseudo(MI, BB, Mips::BZ_W); - case Mips::SZ_D_PSEUDO: - return emitMSACBranchPseudo(MI, BB, Mips::BZ_D); - case Mips::SZ_V_PSEUDO: - return emitMSACBranchPseudo(MI, BB, Mips::BZ_V); - case Mips::COPY_FW_PSEUDO: - return emitCOPY_FW(MI, BB); - case Mips::COPY_FD_PSEUDO: - return emitCOPY_FD(MI, BB); - case Mips::INSERT_FW_PSEUDO: - return emitINSERT_FW(MI, BB); - case Mips::INSERT_FD_PSEUDO: - return emitINSERT_FD(MI, BB); - case Mips::INSERT_B_VIDX_PSEUDO: - case Mips::INSERT_B_VIDX64_PSEUDO: - return emitINSERT_DF_VIDX(MI, BB, 1, false); - case Mips::INSERT_H_VIDX_PSEUDO: - case Mips::INSERT_H_VIDX64_PSEUDO: - return emitINSERT_DF_VIDX(MI, BB, 2, false); - case Mips::INSERT_W_VIDX_PSEUDO: - case Mips::INSERT_W_VIDX64_PSEUDO: - return emitINSERT_DF_VIDX(MI, BB, 4, false); - case Mips::INSERT_D_VIDX_PSEUDO: - case Mips::INSERT_D_VIDX64_PSEUDO: - return emitINSERT_DF_VIDX(MI, BB, 8, false); - case Mips::INSERT_FW_VIDX_PSEUDO: - case Mips::INSERT_FW_VIDX64_PSEUDO: - return emitINSERT_DF_VIDX(MI, BB, 4, true); - case Mips::INSERT_FD_VIDX_PSEUDO: - case Mips::INSERT_FD_VIDX64_PSEUDO: - return emitINSERT_DF_VIDX(MI, BB, 8, true); - case Mips::FILL_FW_PSEUDO: - return emitFILL_FW(MI, BB); - case Mips::FILL_FD_PSEUDO: - return emitFILL_FD(MI, BB); - case Mips::FEXP2_W_1_PSEUDO: - return emitFEXP2_W_1(MI, BB); - case Mips::FEXP2_D_1_PSEUDO: - return emitFEXP2_D_1(MI, BB); - case Mips::ST_F16: - return emitST_F16_PSEUDO(MI, BB); - case Mips::LD_F16: - return emitLD_F16_PSEUDO(MI, BB); - case Mips::MSA_FP_EXTEND_W_PSEUDO: - return emitFPEXTEND_PSEUDO(MI, BB, false); - case Mips::MSA_FP_ROUND_W_PSEUDO: - return emitFPROUND_PSEUDO(MI, BB, false); - case Mips::MSA_FP_EXTEND_D_PSEUDO: - return emitFPEXTEND_PSEUDO(MI, BB, true); - case Mips::MSA_FP_ROUND_D_PSEUDO: - return emitFPROUND_PSEUDO(MI, BB, true); - } -} - -bool MipsSETargetLowering::isEligibleForTailCallOptimization( - const CCState &CCInfo, unsigned NextStackOffset, - const MipsFunctionInfo &FI) const { - if (!UseMipsTailCalls) - return false; - - // Exception has to be cleared with eret. - if (FI.isISR()) - return false; - - // Return false if either the callee or caller has a byval argument. - if (CCInfo.getInRegsParamsCount() > 0 || FI.hasByvalArg()) - return false; - - // Return true if the callee's argument area is no larger than the - // caller's. - return NextStackOffset <= FI.getIncomingArgSize(); -} - -void MipsSETargetLowering:: -getOpndList(SmallVectorImpl<SDValue> &Ops, - std::deque<std::pair<unsigned, SDValue>> &RegsToPass, - bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage, - bool IsCallReloc, CallLoweringInfo &CLI, SDValue Callee, - SDValue Chain) const { - Ops.push_back(Callee); - MipsTargetLowering::getOpndList(Ops, RegsToPass, IsPICCall, GlobalOrExternal, - InternalLinkage, IsCallReloc, CLI, Callee, - Chain); -} - -SDValue MipsSETargetLowering::lowerLOAD(SDValue Op, SelectionDAG &DAG) const { - LoadSDNode &Nd = *cast<LoadSDNode>(Op); - - if (Nd.getMemoryVT() != MVT::f64 || !NoDPLoadStore) - return MipsTargetLowering::lowerLOAD(Op, DAG); - - // Replace a double precision load with two i32 loads and a buildpair64. - SDLoc DL(Op); - SDValue Ptr = Nd.getBasePtr(), Chain = Nd.getChain(); - EVT PtrVT = Ptr.getValueType(); - - // i32 load from lower address. - SDValue Lo = DAG.getLoad(MVT::i32, DL, Chain, Ptr, MachinePointerInfo(), - Nd.getAlignment(), Nd.getMemOperand()->getFlags()); - - // i32 load from higher address. - Ptr = DAG.getNode(ISD::ADD, DL, PtrVT, Ptr, DAG.getConstant(4, DL, PtrVT)); - SDValue Hi = DAG.getLoad( - MVT::i32, DL, Lo.getValue(1), Ptr, MachinePointerInfo(), - std::min(Nd.getAlignment(), 4U), Nd.getMemOperand()->getFlags()); - - if (!Subtarget.isLittle()) - std::swap(Lo, Hi); - - SDValue BP = DAG.getNode(MipsISD::BuildPairF64, DL, MVT::f64, Lo, Hi); - SDValue Ops[2] = {BP, Hi.getValue(1)}; - return DAG.getMergeValues(Ops, DL); -} - -SDValue MipsSETargetLowering::lowerSTORE(SDValue Op, SelectionDAG &DAG) const { - StoreSDNode &Nd = *cast<StoreSDNode>(Op); - - if (Nd.getMemoryVT() != MVT::f64 || !NoDPLoadStore) - return MipsTargetLowering::lowerSTORE(Op, DAG); - - // Replace a double precision store with two extractelement64s and i32 stores. - SDLoc DL(Op); - SDValue Val = Nd.getValue(), Ptr = Nd.getBasePtr(), Chain = Nd.getChain(); - EVT PtrVT = Ptr.getValueType(); - SDValue Lo = DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32, - Val, DAG.getConstant(0, DL, MVT::i32)); - SDValue Hi = DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32, - Val, DAG.getConstant(1, DL, MVT::i32)); - - if (!Subtarget.isLittle()) - std::swap(Lo, Hi); - - // i32 store to lower address. - Chain = - DAG.getStore(Chain, DL, Lo, Ptr, MachinePointerInfo(), Nd.getAlignment(), - Nd.getMemOperand()->getFlags(), Nd.getAAInfo()); - - // i32 store to higher address. - Ptr = DAG.getNode(ISD::ADD, DL, PtrVT, Ptr, DAG.getConstant(4, DL, PtrVT)); - return DAG.getStore(Chain, DL, Hi, Ptr, MachinePointerInfo(), - std::min(Nd.getAlignment(), 4U), - Nd.getMemOperand()->getFlags(), Nd.getAAInfo()); -} - -SDValue MipsSETargetLowering::lowerBITCAST(SDValue Op, - SelectionDAG &DAG) const { - SDLoc DL(Op); - MVT Src = Op.getOperand(0).getValueType().getSimpleVT(); - MVT Dest = Op.getValueType().getSimpleVT(); - - // Bitcast i64 to double. - if (Src == MVT::i64 && Dest == MVT::f64) { - SDValue Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, - Op.getOperand(0), DAG.getIntPtrConstant(0, DL)); - SDValue Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, - Op.getOperand(0), DAG.getIntPtrConstant(1, DL)); - return DAG.getNode(MipsISD::BuildPairF64, DL, MVT::f64, Lo, Hi); - } - - // Bitcast double to i64. - if (Src == MVT::f64 && Dest == MVT::i64) { - SDValue Lo = - DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32, Op.getOperand(0), - DAG.getConstant(0, DL, MVT::i32)); - SDValue Hi = - DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32, Op.getOperand(0), - DAG.getConstant(1, DL, MVT::i32)); - return DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, Lo, Hi); - } - - // Skip other cases of bitcast and use default lowering. - return SDValue(); -} - -SDValue MipsSETargetLowering::lowerMulDiv(SDValue Op, unsigned NewOpc, - bool HasLo, bool HasHi, - SelectionDAG &DAG) const { - // MIPS32r6/MIPS64r6 removed accumulator based multiplies. - assert(!Subtarget.hasMips32r6()); - - EVT Ty = Op.getOperand(0).getValueType(); - SDLoc DL(Op); - SDValue Mult = DAG.getNode(NewOpc, DL, MVT::Untyped, - Op.getOperand(0), Op.getOperand(1)); - SDValue Lo, Hi; - - if (HasLo) - Lo = DAG.getNode(MipsISD::MFLO, DL, Ty, Mult); - if (HasHi) - Hi = DAG.getNode(MipsISD::MFHI, DL, Ty, Mult); - - if (!HasLo || !HasHi) - return HasLo ? Lo : Hi; - - SDValue Vals[] = { Lo, Hi }; - return DAG.getMergeValues(Vals, DL); -} - -static SDValue initAccumulator(SDValue In, const SDLoc &DL, SelectionDAG &DAG) { - SDValue InLo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, In, - DAG.getConstant(0, DL, MVT::i32)); - SDValue InHi = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, In, - DAG.getConstant(1, DL, MVT::i32)); - return DAG.getNode(MipsISD::MTLOHI, DL, MVT::Untyped, InLo, InHi); -} - -static SDValue extractLOHI(SDValue Op, const SDLoc &DL, SelectionDAG &DAG) { - SDValue Lo = DAG.getNode(MipsISD::MFLO, DL, MVT::i32, Op); - SDValue Hi = DAG.getNode(MipsISD::MFHI, DL, MVT::i32, Op); - return DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, Lo, Hi); -} - -// This function expands mips intrinsic nodes which have 64-bit input operands -// or output values. -// -// out64 = intrinsic-node in64 -// => -// lo = copy (extract-element (in64, 0)) -// hi = copy (extract-element (in64, 1)) -// mips-specific-node -// v0 = copy lo -// v1 = copy hi -// out64 = merge-values (v0, v1) -// -static SDValue lowerDSPIntr(SDValue Op, SelectionDAG &DAG, unsigned Opc) { - SDLoc DL(Op); - bool HasChainIn = Op->getOperand(0).getValueType() == MVT::Other; - SmallVector<SDValue, 3> Ops; - unsigned OpNo = 0; - - // See if Op has a chain input. - if (HasChainIn) - Ops.push_back(Op->getOperand(OpNo++)); - - // The next operand is the intrinsic opcode. - assert(Op->getOperand(OpNo).getOpcode() == ISD::TargetConstant); - - // See if the next operand has type i64. - SDValue Opnd = Op->getOperand(++OpNo), In64; - - if (Opnd.getValueType() == MVT::i64) - In64 = initAccumulator(Opnd, DL, DAG); - else - Ops.push_back(Opnd); - - // Push the remaining operands. - for (++OpNo ; OpNo < Op->getNumOperands(); ++OpNo) - Ops.push_back(Op->getOperand(OpNo)); - - // Add In64 to the end of the list. - if (In64.getNode()) - Ops.push_back(In64); - - // Scan output. - SmallVector<EVT, 2> ResTys; - - for (SDNode::value_iterator I = Op->value_begin(), E = Op->value_end(); - I != E; ++I) - ResTys.push_back((*I == MVT::i64) ? MVT::Untyped : *I); - - // Create node. - SDValue Val = DAG.getNode(Opc, DL, ResTys, Ops); - SDValue Out = (ResTys[0] == MVT::Untyped) ? extractLOHI(Val, DL, DAG) : Val; - - if (!HasChainIn) - return Out; - - assert(Val->getValueType(1) == MVT::Other); - SDValue Vals[] = { Out, SDValue(Val.getNode(), 1) }; - return DAG.getMergeValues(Vals, DL); -} - -// Lower an MSA copy intrinsic into the specified SelectionDAG node -static SDValue lowerMSACopyIntr(SDValue Op, SelectionDAG &DAG, unsigned Opc) { - SDLoc DL(Op); - SDValue Vec = Op->getOperand(1); - SDValue Idx = Op->getOperand(2); - EVT ResTy = Op->getValueType(0); - EVT EltTy = Vec->getValueType(0).getVectorElementType(); - - SDValue Result = DAG.getNode(Opc, DL, ResTy, Vec, Idx, - DAG.getValueType(EltTy)); - - return Result; -} - -static SDValue lowerMSASplatZExt(SDValue Op, unsigned OpNr, SelectionDAG &DAG) { - EVT ResVecTy = Op->getValueType(0); - EVT ViaVecTy = ResVecTy; - bool BigEndian = !DAG.getSubtarget().getTargetTriple().isLittleEndian(); - SDLoc DL(Op); - - // When ResVecTy == MVT::v2i64, LaneA is the upper 32 bits of the lane and - // LaneB is the lower 32-bits. Otherwise LaneA and LaneB are alternating - // lanes. - SDValue LaneA = Op->getOperand(OpNr); - SDValue LaneB; - - if (ResVecTy == MVT::v2i64) { - // In case of the index being passed as an immediate value, set the upper - // lane to 0 so that the splati.d instruction can be matched. - if (isa<ConstantSDNode>(LaneA)) - LaneB = DAG.getConstant(0, DL, MVT::i32); - // Having the index passed in a register, set the upper lane to the same - // value as the lower - this results in the BUILD_VECTOR node not being - // expanded through stack. This way we are able to pattern match the set of - // nodes created here to splat.d. - else - LaneB = LaneA; - ViaVecTy = MVT::v4i32; - if(BigEndian) - std::swap(LaneA, LaneB); - } else - LaneB = LaneA; - - SDValue Ops[16] = { LaneA, LaneB, LaneA, LaneB, LaneA, LaneB, LaneA, LaneB, - LaneA, LaneB, LaneA, LaneB, LaneA, LaneB, LaneA, LaneB }; - - SDValue Result = DAG.getBuildVector( - ViaVecTy, DL, makeArrayRef(Ops, ViaVecTy.getVectorNumElements())); - - if (ViaVecTy != ResVecTy) { - SDValue One = DAG.getConstant(1, DL, ViaVecTy); - Result = DAG.getNode(ISD::BITCAST, DL, ResVecTy, - DAG.getNode(ISD::AND, DL, ViaVecTy, Result, One)); - } - - return Result; -} - -static SDValue lowerMSASplatImm(SDValue Op, unsigned ImmOp, SelectionDAG &DAG, - bool IsSigned = false) { - auto *CImm = cast<ConstantSDNode>(Op->getOperand(ImmOp)); - return DAG.getConstant( - APInt(Op->getValueType(0).getScalarType().getSizeInBits(), - IsSigned ? CImm->getSExtValue() : CImm->getZExtValue(), IsSigned), - SDLoc(Op), Op->getValueType(0)); -} - -static SDValue getBuildVectorSplat(EVT VecTy, SDValue SplatValue, - bool BigEndian, SelectionDAG &DAG) { - EVT ViaVecTy = VecTy; - SDValue SplatValueA = SplatValue; - SDValue SplatValueB = SplatValue; - SDLoc DL(SplatValue); - - if (VecTy == MVT::v2i64) { - // v2i64 BUILD_VECTOR must be performed via v4i32 so split into i32's. - ViaVecTy = MVT::v4i32; - - SplatValueA = DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, SplatValue); - SplatValueB = DAG.getNode(ISD::SRL, DL, MVT::i64, SplatValue, - DAG.getConstant(32, DL, MVT::i32)); - SplatValueB = DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, SplatValueB); - } - - // We currently hold the parts in little endian order. Swap them if - // necessary. - if (BigEndian) - std::swap(SplatValueA, SplatValueB); - - SDValue Ops[16] = { SplatValueA, SplatValueB, SplatValueA, SplatValueB, - SplatValueA, SplatValueB, SplatValueA, SplatValueB, - SplatValueA, SplatValueB, SplatValueA, SplatValueB, - SplatValueA, SplatValueB, SplatValueA, SplatValueB }; - - SDValue Result = DAG.getBuildVector( - ViaVecTy, DL, makeArrayRef(Ops, ViaVecTy.getVectorNumElements())); - - if (VecTy != ViaVecTy) - Result = DAG.getNode(ISD::BITCAST, DL, VecTy, Result); - - return Result; -} - -static SDValue lowerMSABinaryBitImmIntr(SDValue Op, SelectionDAG &DAG, - unsigned Opc, SDValue Imm, - bool BigEndian) { - EVT VecTy = Op->getValueType(0); - SDValue Exp2Imm; - SDLoc DL(Op); - - // The DAG Combiner can't constant fold bitcasted vectors yet so we must do it - // here for now. - if (VecTy == MVT::v2i64) { - if (ConstantSDNode *CImm = dyn_cast<ConstantSDNode>(Imm)) { - APInt BitImm = APInt(64, 1) << CImm->getAPIntValue(); - - SDValue BitImmHiOp = DAG.getConstant(BitImm.lshr(32).trunc(32), DL, - MVT::i32); - SDValue BitImmLoOp = DAG.getConstant(BitImm.trunc(32), DL, MVT::i32); - - if (BigEndian) - std::swap(BitImmLoOp, BitImmHiOp); - - Exp2Imm = DAG.getNode( - ISD::BITCAST, DL, MVT::v2i64, - DAG.getBuildVector(MVT::v4i32, DL, - {BitImmLoOp, BitImmHiOp, BitImmLoOp, BitImmHiOp})); - } - } - - if (!Exp2Imm.getNode()) { - // We couldnt constant fold, do a vector shift instead - - // Extend i32 to i64 if necessary. Sign or zero extend doesn't matter since - // only values 0-63 are valid. - if (VecTy == MVT::v2i64) - Imm = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i64, Imm); - - Exp2Imm = getBuildVectorSplat(VecTy, Imm, BigEndian, DAG); - - Exp2Imm = DAG.getNode(ISD::SHL, DL, VecTy, DAG.getConstant(1, DL, VecTy), - Exp2Imm); - } - - return DAG.getNode(Opc, DL, VecTy, Op->getOperand(1), Exp2Imm); -} - -static SDValue truncateVecElts(SDValue Op, SelectionDAG &DAG) { - SDLoc DL(Op); - EVT ResTy = Op->getValueType(0); - SDValue Vec = Op->getOperand(2); - bool BigEndian = !DAG.getSubtarget().getTargetTriple().isLittleEndian(); - MVT ResEltTy = ResTy == MVT::v2i64 ? MVT::i64 : MVT::i32; - SDValue ConstValue = DAG.getConstant(Vec.getScalarValueSizeInBits() - 1, - DL, ResEltTy); - SDValue SplatVec = getBuildVectorSplat(ResTy, ConstValue, BigEndian, DAG); - - return DAG.getNode(ISD::AND, DL, ResTy, Vec, SplatVec); -} - -static SDValue lowerMSABitClear(SDValue Op, SelectionDAG &DAG) { - EVT ResTy = Op->getValueType(0); - SDLoc DL(Op); - SDValue One = DAG.getConstant(1, DL, ResTy); - SDValue Bit = DAG.getNode(ISD::SHL, DL, ResTy, One, truncateVecElts(Op, DAG)); - - return DAG.getNode(ISD::AND, DL, ResTy, Op->getOperand(1), - DAG.getNOT(DL, Bit, ResTy)); -} - -static SDValue lowerMSABitClearImm(SDValue Op, SelectionDAG &DAG) { - SDLoc DL(Op); - EVT ResTy = Op->getValueType(0); - APInt BitImm = APInt(ResTy.getScalarSizeInBits(), 1) - << cast<ConstantSDNode>(Op->getOperand(2))->getAPIntValue(); - SDValue BitMask = DAG.getConstant(~BitImm, DL, ResTy); - - return DAG.getNode(ISD::AND, DL, ResTy, Op->getOperand(1), BitMask); -} - -SDValue MipsSETargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op, - SelectionDAG &DAG) const { - SDLoc DL(Op); - unsigned Intrinsic = cast<ConstantSDNode>(Op->getOperand(0))->getZExtValue(); - switch (Intrinsic) { - default: - return SDValue(); - case Intrinsic::mips_shilo: - return lowerDSPIntr(Op, DAG, MipsISD::SHILO); - case Intrinsic::mips_dpau_h_qbl: - return lowerDSPIntr(Op, DAG, MipsISD::DPAU_H_QBL); - case Intrinsic::mips_dpau_h_qbr: - return lowerDSPIntr(Op, DAG, MipsISD::DPAU_H_QBR); - case Intrinsic::mips_dpsu_h_qbl: - return lowerDSPIntr(Op, DAG, MipsISD::DPSU_H_QBL); - case Intrinsic::mips_dpsu_h_qbr: - return lowerDSPIntr(Op, DAG, MipsISD::DPSU_H_QBR); - case Intrinsic::mips_dpa_w_ph: - return lowerDSPIntr(Op, DAG, MipsISD::DPA_W_PH); - case Intrinsic::mips_dps_w_ph: - return lowerDSPIntr(Op, DAG, MipsISD::DPS_W_PH); - case Intrinsic::mips_dpax_w_ph: - return lowerDSPIntr(Op, DAG, MipsISD::DPAX_W_PH); - case Intrinsic::mips_dpsx_w_ph: - return lowerDSPIntr(Op, DAG, MipsISD::DPSX_W_PH); - case Intrinsic::mips_mulsa_w_ph: - return lowerDSPIntr(Op, DAG, MipsISD::MULSA_W_PH); - case Intrinsic::mips_mult: - return lowerDSPIntr(Op, DAG, MipsISD::Mult); - case Intrinsic::mips_multu: - return lowerDSPIntr(Op, DAG, MipsISD::Multu); - case Intrinsic::mips_madd: - return lowerDSPIntr(Op, DAG, MipsISD::MAdd); - case Intrinsic::mips_maddu: - return lowerDSPIntr(Op, DAG, MipsISD::MAddu); - case Intrinsic::mips_msub: - return lowerDSPIntr(Op, DAG, MipsISD::MSub); - case Intrinsic::mips_msubu: - return lowerDSPIntr(Op, DAG, MipsISD::MSubu); - case Intrinsic::mips_addv_b: - case Intrinsic::mips_addv_h: - case Intrinsic::mips_addv_w: - case Intrinsic::mips_addv_d: - return DAG.getNode(ISD::ADD, DL, Op->getValueType(0), Op->getOperand(1), - Op->getOperand(2)); - case Intrinsic::mips_addvi_b: - case Intrinsic::mips_addvi_h: - case Intrinsic::mips_addvi_w: - case Intrinsic::mips_addvi_d: - return DAG.getNode(ISD::ADD, DL, Op->getValueType(0), Op->getOperand(1), - lowerMSASplatImm(Op, 2, DAG)); - case Intrinsic::mips_and_v: - return DAG.getNode(ISD::AND, DL, Op->getValueType(0), Op->getOperand(1), - Op->getOperand(2)); - case Intrinsic::mips_andi_b: - return DAG.getNode(ISD::AND, DL, Op->getValueType(0), Op->getOperand(1), - lowerMSASplatImm(Op, 2, DAG)); - case Intrinsic::mips_bclr_b: - case Intrinsic::mips_bclr_h: - case Intrinsic::mips_bclr_w: - case Intrinsic::mips_bclr_d: - return lowerMSABitClear(Op, DAG); - case Intrinsic::mips_bclri_b: - case Intrinsic::mips_bclri_h: - case Intrinsic::mips_bclri_w: - case Intrinsic::mips_bclri_d: - return lowerMSABitClearImm(Op, DAG); - case Intrinsic::mips_binsli_b: - case Intrinsic::mips_binsli_h: - case Intrinsic::mips_binsli_w: - case Intrinsic::mips_binsli_d: { - // binsli_x(IfClear, IfSet, nbits) -> (vselect LBitsMask, IfSet, IfClear) - EVT VecTy = Op->getValueType(0); - EVT EltTy = VecTy.getVectorElementType(); - if (Op->getConstantOperandVal(3) >= EltTy.getSizeInBits()) - report_fatal_error("Immediate out of range"); - APInt Mask = APInt::getHighBitsSet(EltTy.getSizeInBits(), - Op->getConstantOperandVal(3) + 1); - return DAG.getNode(ISD::VSELECT, DL, VecTy, - DAG.getConstant(Mask, DL, VecTy, true), - Op->getOperand(2), Op->getOperand(1)); - } - case Intrinsic::mips_binsri_b: - case Intrinsic::mips_binsri_h: - case Intrinsic::mips_binsri_w: - case Intrinsic::mips_binsri_d: { - // binsri_x(IfClear, IfSet, nbits) -> (vselect RBitsMask, IfSet, IfClear) - EVT VecTy = Op->getValueType(0); - EVT EltTy = VecTy.getVectorElementType(); - if (Op->getConstantOperandVal(3) >= EltTy.getSizeInBits()) - report_fatal_error("Immediate out of range"); - APInt Mask = APInt::getLowBitsSet(EltTy.getSizeInBits(), - Op->getConstantOperandVal(3) + 1); - return DAG.getNode(ISD::VSELECT, DL, VecTy, - DAG.getConstant(Mask, DL, VecTy, true), - Op->getOperand(2), Op->getOperand(1)); - } - case Intrinsic::mips_bmnz_v: - return DAG.getNode(ISD::VSELECT, DL, Op->getValueType(0), Op->getOperand(3), - Op->getOperand(2), Op->getOperand(1)); - case Intrinsic::mips_bmnzi_b: - return DAG.getNode(ISD::VSELECT, DL, Op->getValueType(0), - lowerMSASplatImm(Op, 3, DAG), Op->getOperand(2), - Op->getOperand(1)); - case Intrinsic::mips_bmz_v: - return DAG.getNode(ISD::VSELECT, DL, Op->getValueType(0), Op->getOperand(3), - Op->getOperand(1), Op->getOperand(2)); - case Intrinsic::mips_bmzi_b: - return DAG.getNode(ISD::VSELECT, DL, Op->getValueType(0), - lowerMSASplatImm(Op, 3, DAG), Op->getOperand(1), - Op->getOperand(2)); - case Intrinsic::mips_bneg_b: - case Intrinsic::mips_bneg_h: - case Intrinsic::mips_bneg_w: - case Intrinsic::mips_bneg_d: { - EVT VecTy = Op->getValueType(0); - SDValue One = DAG.getConstant(1, DL, VecTy); - - return DAG.getNode(ISD::XOR, DL, VecTy, Op->getOperand(1), - DAG.getNode(ISD::SHL, DL, VecTy, One, - truncateVecElts(Op, DAG))); - } - case Intrinsic::mips_bnegi_b: - case Intrinsic::mips_bnegi_h: - case Intrinsic::mips_bnegi_w: - case Intrinsic::mips_bnegi_d: - return lowerMSABinaryBitImmIntr(Op, DAG, ISD::XOR, Op->getOperand(2), - !Subtarget.isLittle()); - case Intrinsic::mips_bnz_b: - case Intrinsic::mips_bnz_h: - case Intrinsic::mips_bnz_w: - case Intrinsic::mips_bnz_d: - return DAG.getNode(MipsISD::VALL_NONZERO, DL, Op->getValueType(0), - Op->getOperand(1)); - case Intrinsic::mips_bnz_v: - return DAG.getNode(MipsISD::VANY_NONZERO, DL, Op->getValueType(0), - Op->getOperand(1)); - case Intrinsic::mips_bsel_v: - // bsel_v(Mask, IfClear, IfSet) -> (vselect Mask, IfSet, IfClear) - return DAG.getNode(ISD::VSELECT, DL, Op->getValueType(0), - Op->getOperand(1), Op->getOperand(3), - Op->getOperand(2)); - case Intrinsic::mips_bseli_b: - // bseli_v(Mask, IfClear, IfSet) -> (vselect Mask, IfSet, IfClear) - return DAG.getNode(ISD::VSELECT, DL, Op->getValueType(0), - Op->getOperand(1), lowerMSASplatImm(Op, 3, DAG), - Op->getOperand(2)); - case Intrinsic::mips_bset_b: - case Intrinsic::mips_bset_h: - case Intrinsic::mips_bset_w: - case Intrinsic::mips_bset_d: { - EVT VecTy = Op->getValueType(0); - SDValue One = DAG.getConstant(1, DL, VecTy); - - return DAG.getNode(ISD::OR, DL, VecTy, Op->getOperand(1), - DAG.getNode(ISD::SHL, DL, VecTy, One, - truncateVecElts(Op, DAG))); - } - case Intrinsic::mips_bseti_b: - case Intrinsic::mips_bseti_h: - case Intrinsic::mips_bseti_w: - case Intrinsic::mips_bseti_d: - return lowerMSABinaryBitImmIntr(Op, DAG, ISD::OR, Op->getOperand(2), - !Subtarget.isLittle()); - case Intrinsic::mips_bz_b: - case Intrinsic::mips_bz_h: - case Intrinsic::mips_bz_w: - case Intrinsic::mips_bz_d: - return DAG.getNode(MipsISD::VALL_ZERO, DL, Op->getValueType(0), - Op->getOperand(1)); - case Intrinsic::mips_bz_v: - return DAG.getNode(MipsISD::VANY_ZERO, DL, Op->getValueType(0), - Op->getOperand(1)); - case Intrinsic::mips_ceq_b: - case Intrinsic::mips_ceq_h: - case Intrinsic::mips_ceq_w: - case Intrinsic::mips_ceq_d: - return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1), - Op->getOperand(2), ISD::SETEQ); - case Intrinsic::mips_ceqi_b: - case Intrinsic::mips_ceqi_h: - case Intrinsic::mips_ceqi_w: - case Intrinsic::mips_ceqi_d: - return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1), - lowerMSASplatImm(Op, 2, DAG, true), ISD::SETEQ); - case Intrinsic::mips_cle_s_b: - case Intrinsic::mips_cle_s_h: - case Intrinsic::mips_cle_s_w: - case Intrinsic::mips_cle_s_d: - return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1), - Op->getOperand(2), ISD::SETLE); - case Intrinsic::mips_clei_s_b: - case Intrinsic::mips_clei_s_h: - case Intrinsic::mips_clei_s_w: - case Intrinsic::mips_clei_s_d: - return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1), - lowerMSASplatImm(Op, 2, DAG, true), ISD::SETLE); - case Intrinsic::mips_cle_u_b: - case Intrinsic::mips_cle_u_h: - case Intrinsic::mips_cle_u_w: - case Intrinsic::mips_cle_u_d: - return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1), - Op->getOperand(2), ISD::SETULE); - case Intrinsic::mips_clei_u_b: - case Intrinsic::mips_clei_u_h: - case Intrinsic::mips_clei_u_w: - case Intrinsic::mips_clei_u_d: - return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1), - lowerMSASplatImm(Op, 2, DAG), ISD::SETULE); - case Intrinsic::mips_clt_s_b: - case Intrinsic::mips_clt_s_h: - case Intrinsic::mips_clt_s_w: - case Intrinsic::mips_clt_s_d: - return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1), - Op->getOperand(2), ISD::SETLT); - case Intrinsic::mips_clti_s_b: - case Intrinsic::mips_clti_s_h: - case Intrinsic::mips_clti_s_w: - case Intrinsic::mips_clti_s_d: - return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1), - lowerMSASplatImm(Op, 2, DAG, true), ISD::SETLT); - case Intrinsic::mips_clt_u_b: - case Intrinsic::mips_clt_u_h: - case Intrinsic::mips_clt_u_w: - case Intrinsic::mips_clt_u_d: - return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1), - Op->getOperand(2), ISD::SETULT); - case Intrinsic::mips_clti_u_b: - case Intrinsic::mips_clti_u_h: - case Intrinsic::mips_clti_u_w: - case Intrinsic::mips_clti_u_d: - return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1), - lowerMSASplatImm(Op, 2, DAG), ISD::SETULT); - case Intrinsic::mips_copy_s_b: - case Intrinsic::mips_copy_s_h: - case Intrinsic::mips_copy_s_w: - return lowerMSACopyIntr(Op, DAG, MipsISD::VEXTRACT_SEXT_ELT); - case Intrinsic::mips_copy_s_d: - if (Subtarget.hasMips64()) - // Lower directly into VEXTRACT_SEXT_ELT since i64 is legal on Mips64. - return lowerMSACopyIntr(Op, DAG, MipsISD::VEXTRACT_SEXT_ELT); - else { - // Lower into the generic EXTRACT_VECTOR_ELT node and let the type - // legalizer and EXTRACT_VECTOR_ELT lowering sort it out. - return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SDLoc(Op), - Op->getValueType(0), Op->getOperand(1), - Op->getOperand(2)); - } - case Intrinsic::mips_copy_u_b: - case Intrinsic::mips_copy_u_h: - case Intrinsic::mips_copy_u_w: - return lowerMSACopyIntr(Op, DAG, MipsISD::VEXTRACT_ZEXT_ELT); - case Intrinsic::mips_copy_u_d: - if (Subtarget.hasMips64()) - // Lower directly into VEXTRACT_ZEXT_ELT since i64 is legal on Mips64. - return lowerMSACopyIntr(Op, DAG, MipsISD::VEXTRACT_ZEXT_ELT); - else { - // Lower into the generic EXTRACT_VECTOR_ELT node and let the type - // legalizer and EXTRACT_VECTOR_ELT lowering sort it out. - // Note: When i64 is illegal, this results in copy_s.w instructions - // instead of copy_u.w instructions. This makes no difference to the - // behaviour since i64 is only illegal when the register file is 32-bit. - return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SDLoc(Op), - Op->getValueType(0), Op->getOperand(1), - Op->getOperand(2)); - } - case Intrinsic::mips_div_s_b: - case Intrinsic::mips_div_s_h: - case Intrinsic::mips_div_s_w: - case Intrinsic::mips_div_s_d: - return DAG.getNode(ISD::SDIV, DL, Op->getValueType(0), Op->getOperand(1), - Op->getOperand(2)); - case Intrinsic::mips_div_u_b: - case Intrinsic::mips_div_u_h: - case Intrinsic::mips_div_u_w: - case Intrinsic::mips_div_u_d: - return DAG.getNode(ISD::UDIV, DL, Op->getValueType(0), Op->getOperand(1), - Op->getOperand(2)); - case Intrinsic::mips_fadd_w: - case Intrinsic::mips_fadd_d: - // TODO: If intrinsics have fast-math-flags, propagate them. - return DAG.getNode(ISD::FADD, DL, Op->getValueType(0), Op->getOperand(1), - Op->getOperand(2)); - // Don't lower mips_fcaf_[wd] since LLVM folds SETFALSE condcodes away - case Intrinsic::mips_fceq_w: - case Intrinsic::mips_fceq_d: - return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1), - Op->getOperand(2), ISD::SETOEQ); - case Intrinsic::mips_fcle_w: - case Intrinsic::mips_fcle_d: - return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1), - Op->getOperand(2), ISD::SETOLE); - case Intrinsic::mips_fclt_w: - case Intrinsic::mips_fclt_d: - return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1), - Op->getOperand(2), ISD::SETOLT); - case Intrinsic::mips_fcne_w: - case Intrinsic::mips_fcne_d: - return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1), - Op->getOperand(2), ISD::SETONE); - case Intrinsic::mips_fcor_w: - case Intrinsic::mips_fcor_d: - return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1), - Op->getOperand(2), ISD::SETO); - case Intrinsic::mips_fcueq_w: - case Intrinsic::mips_fcueq_d: - return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1), - Op->getOperand(2), ISD::SETUEQ); - case Intrinsic::mips_fcule_w: - case Intrinsic::mips_fcule_d: - return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1), - Op->getOperand(2), ISD::SETULE); - case Intrinsic::mips_fcult_w: - case Intrinsic::mips_fcult_d: - return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1), - Op->getOperand(2), ISD::SETULT); - case Intrinsic::mips_fcun_w: - case Intrinsic::mips_fcun_d: - return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1), - Op->getOperand(2), ISD::SETUO); - case Intrinsic::mips_fcune_w: - case Intrinsic::mips_fcune_d: - return DAG.getSetCC(DL, Op->getValueType(0), Op->getOperand(1), - Op->getOperand(2), ISD::SETUNE); - case Intrinsic::mips_fdiv_w: - case Intrinsic::mips_fdiv_d: - // TODO: If intrinsics have fast-math-flags, propagate them. - return DAG.getNode(ISD::FDIV, DL, Op->getValueType(0), Op->getOperand(1), - Op->getOperand(2)); - case Intrinsic::mips_ffint_u_w: - case Intrinsic::mips_ffint_u_d: - return DAG.getNode(ISD::UINT_TO_FP, DL, Op->getValueType(0), - Op->getOperand(1)); - case Intrinsic::mips_ffint_s_w: - case Intrinsic::mips_ffint_s_d: - return DAG.getNode(ISD::SINT_TO_FP, DL, Op->getValueType(0), - Op->getOperand(1)); - case Intrinsic::mips_fill_b: - case Intrinsic::mips_fill_h: - case Intrinsic::mips_fill_w: - case Intrinsic::mips_fill_d: { - EVT ResTy = Op->getValueType(0); - SmallVector<SDValue, 16> Ops(ResTy.getVectorNumElements(), - Op->getOperand(1)); - - // If ResTy is v2i64 then the type legalizer will break this node down into - // an equivalent v4i32. - return DAG.getBuildVector(ResTy, DL, Ops); - } - case Intrinsic::mips_fexp2_w: - case Intrinsic::mips_fexp2_d: { - // TODO: If intrinsics have fast-math-flags, propagate them. - EVT ResTy = Op->getValueType(0); - return DAG.getNode( - ISD::FMUL, SDLoc(Op), ResTy, Op->getOperand(1), - DAG.getNode(ISD::FEXP2, SDLoc(Op), ResTy, Op->getOperand(2))); - } - case Intrinsic::mips_flog2_w: - case Intrinsic::mips_flog2_d: - return DAG.getNode(ISD::FLOG2, DL, Op->getValueType(0), Op->getOperand(1)); - case Intrinsic::mips_fmadd_w: - case Intrinsic::mips_fmadd_d: - return DAG.getNode(ISD::FMA, SDLoc(Op), Op->getValueType(0), - Op->getOperand(1), Op->getOperand(2), Op->getOperand(3)); - case Intrinsic::mips_fmul_w: - case Intrinsic::mips_fmul_d: - // TODO: If intrinsics have fast-math-flags, propagate them. - return DAG.getNode(ISD::FMUL, DL, Op->getValueType(0), Op->getOperand(1), - Op->getOperand(2)); - case Intrinsic::mips_fmsub_w: - case Intrinsic::mips_fmsub_d: { - // TODO: If intrinsics have fast-math-flags, propagate them. - return DAG.getNode(MipsISD::FMS, SDLoc(Op), Op->getValueType(0), - Op->getOperand(1), Op->getOperand(2), Op->getOperand(3)); - } - case Intrinsic::mips_frint_w: - case Intrinsic::mips_frint_d: - return DAG.getNode(ISD::FRINT, DL, Op->getValueType(0), Op->getOperand(1)); - case Intrinsic::mips_fsqrt_w: - case Intrinsic::mips_fsqrt_d: - return DAG.getNode(ISD::FSQRT, DL, Op->getValueType(0), Op->getOperand(1)); - case Intrinsic::mips_fsub_w: - case Intrinsic::mips_fsub_d: - // TODO: If intrinsics have fast-math-flags, propagate them. - return DAG.getNode(ISD::FSUB, DL, Op->getValueType(0), Op->getOperand(1), - Op->getOperand(2)); - case Intrinsic::mips_ftrunc_u_w: - case Intrinsic::mips_ftrunc_u_d: - return DAG.getNode(ISD::FP_TO_UINT, DL, Op->getValueType(0), - Op->getOperand(1)); - case Intrinsic::mips_ftrunc_s_w: - case Intrinsic::mips_ftrunc_s_d: - return DAG.getNode(ISD::FP_TO_SINT, DL, Op->getValueType(0), - Op->getOperand(1)); - case Intrinsic::mips_ilvev_b: - case Intrinsic::mips_ilvev_h: - case Intrinsic::mips_ilvev_w: - case Intrinsic::mips_ilvev_d: - return DAG.getNode(MipsISD::ILVEV, DL, Op->getValueType(0), - Op->getOperand(1), Op->getOperand(2)); - case Intrinsic::mips_ilvl_b: - case Intrinsic::mips_ilvl_h: - case Intrinsic::mips_ilvl_w: - case Intrinsic::mips_ilvl_d: - return DAG.getNode(MipsISD::ILVL, DL, Op->getValueType(0), - Op->getOperand(1), Op->getOperand(2)); - case Intrinsic::mips_ilvod_b: - case Intrinsic::mips_ilvod_h: - case Intrinsic::mips_ilvod_w: - case Intrinsic::mips_ilvod_d: - return DAG.getNode(MipsISD::ILVOD, DL, Op->getValueType(0), - Op->getOperand(1), Op->getOperand(2)); - case Intrinsic::mips_ilvr_b: - case Intrinsic::mips_ilvr_h: - case Intrinsic::mips_ilvr_w: - case Intrinsic::mips_ilvr_d: - return DAG.getNode(MipsISD::ILVR, DL, Op->getValueType(0), - Op->getOperand(1), Op->getOperand(2)); - case Intrinsic::mips_insert_b: - case Intrinsic::mips_insert_h: - case Intrinsic::mips_insert_w: - case Intrinsic::mips_insert_d: - return DAG.getNode(ISD::INSERT_VECTOR_ELT, SDLoc(Op), Op->getValueType(0), - Op->getOperand(1), Op->getOperand(3), Op->getOperand(2)); - case Intrinsic::mips_insve_b: - case Intrinsic::mips_insve_h: - case Intrinsic::mips_insve_w: - case Intrinsic::mips_insve_d: { - // Report an error for out of range values. - int64_t Max; - switch (Intrinsic) { - case Intrinsic::mips_insve_b: Max = 15; break; - case Intrinsic::mips_insve_h: Max = 7; break; - case Intrinsic::mips_insve_w: Max = 3; break; - case Intrinsic::mips_insve_d: Max = 1; break; - default: llvm_unreachable("Unmatched intrinsic"); - } - int64_t Value = cast<ConstantSDNode>(Op->getOperand(2))->getSExtValue(); - if (Value < 0 || Value > Max) - report_fatal_error("Immediate out of range"); - return DAG.getNode(MipsISD::INSVE, DL, Op->getValueType(0), - Op->getOperand(1), Op->getOperand(2), Op->getOperand(3), - DAG.getConstant(0, DL, MVT::i32)); - } - case Intrinsic::mips_ldi_b: - case Intrinsic::mips_ldi_h: - case Intrinsic::mips_ldi_w: - case Intrinsic::mips_ldi_d: - return lowerMSASplatImm(Op, 1, DAG, true); - case Intrinsic::mips_lsa: - case Intrinsic::mips_dlsa: { - EVT ResTy = Op->getValueType(0); - return DAG.getNode(ISD::ADD, SDLoc(Op), ResTy, Op->getOperand(1), - DAG.getNode(ISD::SHL, SDLoc(Op), ResTy, - Op->getOperand(2), Op->getOperand(3))); - } - case Intrinsic::mips_maddv_b: - case Intrinsic::mips_maddv_h: - case Intrinsic::mips_maddv_w: - case Intrinsic::mips_maddv_d: { - EVT ResTy = Op->getValueType(0); - return DAG.getNode(ISD::ADD, SDLoc(Op), ResTy, Op->getOperand(1), - DAG.getNode(ISD::MUL, SDLoc(Op), ResTy, - Op->getOperand(2), Op->getOperand(3))); - } - case Intrinsic::mips_max_s_b: - case Intrinsic::mips_max_s_h: - case Intrinsic::mips_max_s_w: - case Intrinsic::mips_max_s_d: - return DAG.getNode(ISD::SMAX, DL, Op->getValueType(0), - Op->getOperand(1), Op->getOperand(2)); - case Intrinsic::mips_max_u_b: - case Intrinsic::mips_max_u_h: - case Intrinsic::mips_max_u_w: - case Intrinsic::mips_max_u_d: - return DAG.getNode(ISD::UMAX, DL, Op->getValueType(0), - Op->getOperand(1), Op->getOperand(2)); - case Intrinsic::mips_maxi_s_b: - case Intrinsic::mips_maxi_s_h: - case Intrinsic::mips_maxi_s_w: - case Intrinsic::mips_maxi_s_d: - return DAG.getNode(ISD::SMAX, DL, Op->getValueType(0), - Op->getOperand(1), lowerMSASplatImm(Op, 2, DAG, true)); - case Intrinsic::mips_maxi_u_b: - case Intrinsic::mips_maxi_u_h: - case Intrinsic::mips_maxi_u_w: - case Intrinsic::mips_maxi_u_d: - return DAG.getNode(ISD::UMAX, DL, Op->getValueType(0), - Op->getOperand(1), lowerMSASplatImm(Op, 2, DAG)); - case Intrinsic::mips_min_s_b: - case Intrinsic::mips_min_s_h: - case Intrinsic::mips_min_s_w: - case Intrinsic::mips_min_s_d: - return DAG.getNode(ISD::SMIN, DL, Op->getValueType(0), - Op->getOperand(1), Op->getOperand(2)); - case Intrinsic::mips_min_u_b: - case Intrinsic::mips_min_u_h: - case Intrinsic::mips_min_u_w: - case Intrinsic::mips_min_u_d: - return DAG.getNode(ISD::UMIN, DL, Op->getValueType(0), - Op->getOperand(1), Op->getOperand(2)); - case Intrinsic::mips_mini_s_b: - case Intrinsic::mips_mini_s_h: - case Intrinsic::mips_mini_s_w: - case Intrinsic::mips_mini_s_d: - return DAG.getNode(ISD::SMIN, DL, Op->getValueType(0), - Op->getOperand(1), lowerMSASplatImm(Op, 2, DAG, true)); - case Intrinsic::mips_mini_u_b: - case Intrinsic::mips_mini_u_h: - case Intrinsic::mips_mini_u_w: - case Intrinsic::mips_mini_u_d: - return DAG.getNode(ISD::UMIN, DL, Op->getValueType(0), - Op->getOperand(1), lowerMSASplatImm(Op, 2, DAG)); - case Intrinsic::mips_mod_s_b: - case Intrinsic::mips_mod_s_h: - case Intrinsic::mips_mod_s_w: - case Intrinsic::mips_mod_s_d: - return DAG.getNode(ISD::SREM, DL, Op->getValueType(0), Op->getOperand(1), - Op->getOperand(2)); - case Intrinsic::mips_mod_u_b: - case Intrinsic::mips_mod_u_h: - case Intrinsic::mips_mod_u_w: - case Intrinsic::mips_mod_u_d: - return DAG.getNode(ISD::UREM, DL, Op->getValueType(0), Op->getOperand(1), - Op->getOperand(2)); - case Intrinsic::mips_mulv_b: - case Intrinsic::mips_mulv_h: - case Intrinsic::mips_mulv_w: - case Intrinsic::mips_mulv_d: - return DAG.getNode(ISD::MUL, DL, Op->getValueType(0), Op->getOperand(1), - Op->getOperand(2)); - case Intrinsic::mips_msubv_b: - case Intrinsic::mips_msubv_h: - case Intrinsic::mips_msubv_w: - case Intrinsic::mips_msubv_d: { - EVT ResTy = Op->getValueType(0); - return DAG.getNode(ISD::SUB, SDLoc(Op), ResTy, Op->getOperand(1), - DAG.getNode(ISD::MUL, SDLoc(Op), ResTy, - Op->getOperand(2), Op->getOperand(3))); - } - case Intrinsic::mips_nlzc_b: - case Intrinsic::mips_nlzc_h: - case Intrinsic::mips_nlzc_w: - case Intrinsic::mips_nlzc_d: - return DAG.getNode(ISD::CTLZ, DL, Op->getValueType(0), Op->getOperand(1)); - case Intrinsic::mips_nor_v: { - SDValue Res = DAG.getNode(ISD::OR, DL, Op->getValueType(0), - Op->getOperand(1), Op->getOperand(2)); - return DAG.getNOT(DL, Res, Res->getValueType(0)); - } - case Intrinsic::mips_nori_b: { - SDValue Res = DAG.getNode(ISD::OR, DL, Op->getValueType(0), - Op->getOperand(1), - lowerMSASplatImm(Op, 2, DAG)); - return DAG.getNOT(DL, Res, Res->getValueType(0)); - } - case Intrinsic::mips_or_v: - return DAG.getNode(ISD::OR, DL, Op->getValueType(0), Op->getOperand(1), - Op->getOperand(2)); - case Intrinsic::mips_ori_b: - return DAG.getNode(ISD::OR, DL, Op->getValueType(0), - Op->getOperand(1), lowerMSASplatImm(Op, 2, DAG)); - case Intrinsic::mips_pckev_b: - case Intrinsic::mips_pckev_h: - case Intrinsic::mips_pckev_w: - case Intrinsic::mips_pckev_d: - return DAG.getNode(MipsISD::PCKEV, DL, Op->getValueType(0), - Op->getOperand(1), Op->getOperand(2)); - case Intrinsic::mips_pckod_b: - case Intrinsic::mips_pckod_h: - case Intrinsic::mips_pckod_w: - case Intrinsic::mips_pckod_d: - return DAG.getNode(MipsISD::PCKOD, DL, Op->getValueType(0), - Op->getOperand(1), Op->getOperand(2)); - case Intrinsic::mips_pcnt_b: - case Intrinsic::mips_pcnt_h: - case Intrinsic::mips_pcnt_w: - case Intrinsic::mips_pcnt_d: - return DAG.getNode(ISD::CTPOP, DL, Op->getValueType(0), Op->getOperand(1)); - case Intrinsic::mips_sat_s_b: - case Intrinsic::mips_sat_s_h: - case Intrinsic::mips_sat_s_w: - case Intrinsic::mips_sat_s_d: - case Intrinsic::mips_sat_u_b: - case Intrinsic::mips_sat_u_h: - case Intrinsic::mips_sat_u_w: - case Intrinsic::mips_sat_u_d: { - // Report an error for out of range values. - int64_t Max; - switch (Intrinsic) { - case Intrinsic::mips_sat_s_b: - case Intrinsic::mips_sat_u_b: Max = 7; break; - case Intrinsic::mips_sat_s_h: - case Intrinsic::mips_sat_u_h: Max = 15; break; - case Intrinsic::mips_sat_s_w: - case Intrinsic::mips_sat_u_w: Max = 31; break; - case Intrinsic::mips_sat_s_d: - case Intrinsic::mips_sat_u_d: Max = 63; break; - default: llvm_unreachable("Unmatched intrinsic"); - } - int64_t Value = cast<ConstantSDNode>(Op->getOperand(2))->getSExtValue(); - if (Value < 0 || Value > Max) - report_fatal_error("Immediate out of range"); - return SDValue(); - } - case Intrinsic::mips_shf_b: - case Intrinsic::mips_shf_h: - case Intrinsic::mips_shf_w: { - int64_t Value = cast<ConstantSDNode>(Op->getOperand(2))->getSExtValue(); - if (Value < 0 || Value > 255) - report_fatal_error("Immediate out of range"); - return DAG.getNode(MipsISD::SHF, DL, Op->getValueType(0), - Op->getOperand(2), Op->getOperand(1)); - } - case Intrinsic::mips_sldi_b: - case Intrinsic::mips_sldi_h: - case Intrinsic::mips_sldi_w: - case Intrinsic::mips_sldi_d: { - // Report an error for out of range values. - int64_t Max; - switch (Intrinsic) { - case Intrinsic::mips_sldi_b: Max = 15; break; - case Intrinsic::mips_sldi_h: Max = 7; break; - case Intrinsic::mips_sldi_w: Max = 3; break; - case Intrinsic::mips_sldi_d: Max = 1; break; - default: llvm_unreachable("Unmatched intrinsic"); - } - int64_t Value = cast<ConstantSDNode>(Op->getOperand(3))->getSExtValue(); - if (Value < 0 || Value > Max) - report_fatal_error("Immediate out of range"); - return SDValue(); - } - case Intrinsic::mips_sll_b: - case Intrinsic::mips_sll_h: - case Intrinsic::mips_sll_w: - case Intrinsic::mips_sll_d: - return DAG.getNode(ISD::SHL, DL, Op->getValueType(0), Op->getOperand(1), - truncateVecElts(Op, DAG)); - case Intrinsic::mips_slli_b: - case Intrinsic::mips_slli_h: - case Intrinsic::mips_slli_w: - case Intrinsic::mips_slli_d: - return DAG.getNode(ISD::SHL, DL, Op->getValueType(0), - Op->getOperand(1), lowerMSASplatImm(Op, 2, DAG)); - case Intrinsic::mips_splat_b: - case Intrinsic::mips_splat_h: - case Intrinsic::mips_splat_w: - case Intrinsic::mips_splat_d: - // We can't lower via VECTOR_SHUFFLE because it requires constant shuffle - // masks, nor can we lower via BUILD_VECTOR & EXTRACT_VECTOR_ELT because - // EXTRACT_VECTOR_ELT can't extract i64's on MIPS32. - // Instead we lower to MipsISD::VSHF and match from there. - return DAG.getNode(MipsISD::VSHF, DL, Op->getValueType(0), - lowerMSASplatZExt(Op, 2, DAG), Op->getOperand(1), - Op->getOperand(1)); - case Intrinsic::mips_splati_b: - case Intrinsic::mips_splati_h: - case Intrinsic::mips_splati_w: - case Intrinsic::mips_splati_d: - return DAG.getNode(MipsISD::VSHF, DL, Op->getValueType(0), - lowerMSASplatImm(Op, 2, DAG), Op->getOperand(1), - Op->getOperand(1)); - case Intrinsic::mips_sra_b: - case Intrinsic::mips_sra_h: - case Intrinsic::mips_sra_w: - case Intrinsic::mips_sra_d: - return DAG.getNode(ISD::SRA, DL, Op->getValueType(0), Op->getOperand(1), - truncateVecElts(Op, DAG)); - case Intrinsic::mips_srai_b: - case Intrinsic::mips_srai_h: - case Intrinsic::mips_srai_w: - case Intrinsic::mips_srai_d: - return DAG.getNode(ISD::SRA, DL, Op->getValueType(0), - Op->getOperand(1), lowerMSASplatImm(Op, 2, DAG)); - case Intrinsic::mips_srari_b: - case Intrinsic::mips_srari_h: - case Intrinsic::mips_srari_w: - case Intrinsic::mips_srari_d: { - // Report an error for out of range values. - int64_t Max; - switch (Intrinsic) { - case Intrinsic::mips_srari_b: Max = 7; break; - case Intrinsic::mips_srari_h: Max = 15; break; - case Intrinsic::mips_srari_w: Max = 31; break; - case Intrinsic::mips_srari_d: Max = 63; break; - default: llvm_unreachable("Unmatched intrinsic"); - } - int64_t Value = cast<ConstantSDNode>(Op->getOperand(2))->getSExtValue(); - if (Value < 0 || Value > Max) - report_fatal_error("Immediate out of range"); - return SDValue(); - } - case Intrinsic::mips_srl_b: - case Intrinsic::mips_srl_h: - case Intrinsic::mips_srl_w: - case Intrinsic::mips_srl_d: - return DAG.getNode(ISD::SRL, DL, Op->getValueType(0), Op->getOperand(1), - truncateVecElts(Op, DAG)); - case Intrinsic::mips_srli_b: - case Intrinsic::mips_srli_h: - case Intrinsic::mips_srli_w: - case Intrinsic::mips_srli_d: - return DAG.getNode(ISD::SRL, DL, Op->getValueType(0), - Op->getOperand(1), lowerMSASplatImm(Op, 2, DAG)); - case Intrinsic::mips_srlri_b: - case Intrinsic::mips_srlri_h: - case Intrinsic::mips_srlri_w: - case Intrinsic::mips_srlri_d: { - // Report an error for out of range values. - int64_t Max; - switch (Intrinsic) { - case Intrinsic::mips_srlri_b: Max = 7; break; - case Intrinsic::mips_srlri_h: Max = 15; break; - case Intrinsic::mips_srlri_w: Max = 31; break; - case Intrinsic::mips_srlri_d: Max = 63; break; - default: llvm_unreachable("Unmatched intrinsic"); - } - int64_t Value = cast<ConstantSDNode>(Op->getOperand(2))->getSExtValue(); - if (Value < 0 || Value > Max) - report_fatal_error("Immediate out of range"); - return SDValue(); - } - case Intrinsic::mips_subv_b: - case Intrinsic::mips_subv_h: - case Intrinsic::mips_subv_w: - case Intrinsic::mips_subv_d: - return DAG.getNode(ISD::SUB, DL, Op->getValueType(0), Op->getOperand(1), - Op->getOperand(2)); - case Intrinsic::mips_subvi_b: - case Intrinsic::mips_subvi_h: - case Intrinsic::mips_subvi_w: - case Intrinsic::mips_subvi_d: - return DAG.getNode(ISD::SUB, DL, Op->getValueType(0), - Op->getOperand(1), lowerMSASplatImm(Op, 2, DAG)); - case Intrinsic::mips_vshf_b: - case Intrinsic::mips_vshf_h: - case Intrinsic::mips_vshf_w: - case Intrinsic::mips_vshf_d: - return DAG.getNode(MipsISD::VSHF, DL, Op->getValueType(0), - Op->getOperand(1), Op->getOperand(2), Op->getOperand(3)); - case Intrinsic::mips_xor_v: - return DAG.getNode(ISD::XOR, DL, Op->getValueType(0), Op->getOperand(1), - Op->getOperand(2)); - case Intrinsic::mips_xori_b: - return DAG.getNode(ISD::XOR, DL, Op->getValueType(0), - Op->getOperand(1), lowerMSASplatImm(Op, 2, DAG)); - case Intrinsic::thread_pointer: { - EVT PtrVT = getPointerTy(DAG.getDataLayout()); - return DAG.getNode(MipsISD::ThreadPointer, DL, PtrVT); - } - } -} - -static SDValue lowerMSALoadIntr(SDValue Op, SelectionDAG &DAG, unsigned Intr, - const MipsSubtarget &Subtarget) { - SDLoc DL(Op); - SDValue ChainIn = Op->getOperand(0); - SDValue Address = Op->getOperand(2); - SDValue Offset = Op->getOperand(3); - EVT ResTy = Op->getValueType(0); - EVT PtrTy = Address->getValueType(0); - - // For N64 addresses have the underlying type MVT::i64. This intrinsic - // however takes an i32 signed constant offset. The actual type of the - // intrinsic is a scaled signed i10. - if (Subtarget.isABI_N64()) - Offset = DAG.getNode(ISD::SIGN_EXTEND, DL, PtrTy, Offset); - - Address = DAG.getNode(ISD::ADD, DL, PtrTy, Address, Offset); - return DAG.getLoad(ResTy, DL, ChainIn, Address, MachinePointerInfo(), - /* Alignment = */ 16); -} - -SDValue MipsSETargetLowering::lowerINTRINSIC_W_CHAIN(SDValue Op, - SelectionDAG &DAG) const { - unsigned Intr = cast<ConstantSDNode>(Op->getOperand(1))->getZExtValue(); - switch (Intr) { - default: - return SDValue(); - case Intrinsic::mips_extp: - return lowerDSPIntr(Op, DAG, MipsISD::EXTP); - case Intrinsic::mips_extpdp: - return lowerDSPIntr(Op, DAG, MipsISD::EXTPDP); - case Intrinsic::mips_extr_w: - return lowerDSPIntr(Op, DAG, MipsISD::EXTR_W); - case Intrinsic::mips_extr_r_w: - return lowerDSPIntr(Op, DAG, MipsISD::EXTR_R_W); - case Intrinsic::mips_extr_rs_w: - return lowerDSPIntr(Op, DAG, MipsISD::EXTR_RS_W); - case Intrinsic::mips_extr_s_h: - return lowerDSPIntr(Op, DAG, MipsISD::EXTR_S_H); - case Intrinsic::mips_mthlip: - return lowerDSPIntr(Op, DAG, MipsISD::MTHLIP); - case Intrinsic::mips_mulsaq_s_w_ph: - return lowerDSPIntr(Op, DAG, MipsISD::MULSAQ_S_W_PH); - case Intrinsic::mips_maq_s_w_phl: - return lowerDSPIntr(Op, DAG, MipsISD::MAQ_S_W_PHL); - case Intrinsic::mips_maq_s_w_phr: - return lowerDSPIntr(Op, DAG, MipsISD::MAQ_S_W_PHR); - case Intrinsic::mips_maq_sa_w_phl: - return lowerDSPIntr(Op, DAG, MipsISD::MAQ_SA_W_PHL); - case Intrinsic::mips_maq_sa_w_phr: - return lowerDSPIntr(Op, DAG, MipsISD::MAQ_SA_W_PHR); - case Intrinsic::mips_dpaq_s_w_ph: - return lowerDSPIntr(Op, DAG, MipsISD::DPAQ_S_W_PH); - case Intrinsic::mips_dpsq_s_w_ph: - return lowerDSPIntr(Op, DAG, MipsISD::DPSQ_S_W_PH); - case Intrinsic::mips_dpaq_sa_l_w: - return lowerDSPIntr(Op, DAG, MipsISD::DPAQ_SA_L_W); - case Intrinsic::mips_dpsq_sa_l_w: - return lowerDSPIntr(Op, DAG, MipsISD::DPSQ_SA_L_W); - case Intrinsic::mips_dpaqx_s_w_ph: - return lowerDSPIntr(Op, DAG, MipsISD::DPAQX_S_W_PH); - case Intrinsic::mips_dpaqx_sa_w_ph: - return lowerDSPIntr(Op, DAG, MipsISD::DPAQX_SA_W_PH); - case Intrinsic::mips_dpsqx_s_w_ph: - return lowerDSPIntr(Op, DAG, MipsISD::DPSQX_S_W_PH); - case Intrinsic::mips_dpsqx_sa_w_ph: - return lowerDSPIntr(Op, DAG, MipsISD::DPSQX_SA_W_PH); - case Intrinsic::mips_ld_b: - case Intrinsic::mips_ld_h: - case Intrinsic::mips_ld_w: - case Intrinsic::mips_ld_d: - return lowerMSALoadIntr(Op, DAG, Intr, Subtarget); - } -} - -static SDValue lowerMSAStoreIntr(SDValue Op, SelectionDAG &DAG, unsigned Intr, - const MipsSubtarget &Subtarget) { - SDLoc DL(Op); - SDValue ChainIn = Op->getOperand(0); - SDValue Value = Op->getOperand(2); - SDValue Address = Op->getOperand(3); - SDValue Offset = Op->getOperand(4); - EVT PtrTy = Address->getValueType(0); - - // For N64 addresses have the underlying type MVT::i64. This intrinsic - // however takes an i32 signed constant offset. The actual type of the - // intrinsic is a scaled signed i10. - if (Subtarget.isABI_N64()) - Offset = DAG.getNode(ISD::SIGN_EXTEND, DL, PtrTy, Offset); - - Address = DAG.getNode(ISD::ADD, DL, PtrTy, Address, Offset); - - return DAG.getStore(ChainIn, DL, Value, Address, MachinePointerInfo(), - /* Alignment = */ 16); -} - -SDValue MipsSETargetLowering::lowerINTRINSIC_VOID(SDValue Op, - SelectionDAG &DAG) const { - unsigned Intr = cast<ConstantSDNode>(Op->getOperand(1))->getZExtValue(); - switch (Intr) { - default: - return SDValue(); - case Intrinsic::mips_st_b: - case Intrinsic::mips_st_h: - case Intrinsic::mips_st_w: - case Intrinsic::mips_st_d: - return lowerMSAStoreIntr(Op, DAG, Intr, Subtarget); - } -} - -// Lower ISD::EXTRACT_VECTOR_ELT into MipsISD::VEXTRACT_SEXT_ELT. -// -// The non-value bits resulting from ISD::EXTRACT_VECTOR_ELT are undefined. We -// choose to sign-extend but we could have equally chosen zero-extend. The -// DAGCombiner will fold any sign/zero extension of the ISD::EXTRACT_VECTOR_ELT -// result into this node later (possibly changing it to a zero-extend in the -// process). -SDValue MipsSETargetLowering:: -lowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const { - SDLoc DL(Op); - EVT ResTy = Op->getValueType(0); - SDValue Op0 = Op->getOperand(0); - EVT VecTy = Op0->getValueType(0); - - if (!VecTy.is128BitVector()) - return SDValue(); - - if (ResTy.isInteger()) { - SDValue Op1 = Op->getOperand(1); - EVT EltTy = VecTy.getVectorElementType(); - return DAG.getNode(MipsISD::VEXTRACT_SEXT_ELT, DL, ResTy, Op0, Op1, - DAG.getValueType(EltTy)); - } - - return Op; -} - -static bool isConstantOrUndef(const SDValue Op) { - if (Op->isUndef()) - return true; - if (isa<ConstantSDNode>(Op)) - return true; - if (isa<ConstantFPSDNode>(Op)) - return true; - return false; -} - -static bool isConstantOrUndefBUILD_VECTOR(const BuildVectorSDNode *Op) { - for (unsigned i = 0; i < Op->getNumOperands(); ++i) - if (isConstantOrUndef(Op->getOperand(i))) - return true; - return false; -} - -// Lowers ISD::BUILD_VECTOR into appropriate SelectionDAG nodes for the -// backend. -// -// Lowers according to the following rules: -// - Constant splats are legal as-is as long as the SplatBitSize is a power of -// 2 less than or equal to 64 and the value fits into a signed 10-bit -// immediate -// - Constant splats are lowered to bitconverted BUILD_VECTORs if SplatBitSize -// is a power of 2 less than or equal to 64 and the value does not fit into a -// signed 10-bit immediate -// - Non-constant splats are legal as-is. -// - Non-constant non-splats are lowered to sequences of INSERT_VECTOR_ELT. -// - All others are illegal and must be expanded. -SDValue MipsSETargetLowering::lowerBUILD_VECTOR(SDValue Op, - SelectionDAG &DAG) const { - BuildVectorSDNode *Node = cast<BuildVectorSDNode>(Op); - EVT ResTy = Op->getValueType(0); - SDLoc DL(Op); - APInt SplatValue, SplatUndef; - unsigned SplatBitSize; - bool HasAnyUndefs; - - if (!Subtarget.hasMSA() || !ResTy.is128BitVector()) - return SDValue(); - - if (Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, - HasAnyUndefs, 8, - !Subtarget.isLittle()) && SplatBitSize <= 64) { - // We can only cope with 8, 16, 32, or 64-bit elements - if (SplatBitSize != 8 && SplatBitSize != 16 && SplatBitSize != 32 && - SplatBitSize != 64) - return SDValue(); - - // If the value isn't an integer type we will have to bitcast - // from an integer type first. Also, if there are any undefs, we must - // lower them to defined values first. - if (ResTy.isInteger() && !HasAnyUndefs) - return Op; - - EVT ViaVecTy; - - switch (SplatBitSize) { - default: - return SDValue(); - case 8: - ViaVecTy = MVT::v16i8; - break; - case 16: - ViaVecTy = MVT::v8i16; - break; - case 32: - ViaVecTy = MVT::v4i32; - break; - case 64: - // There's no fill.d to fall back on for 64-bit values - return SDValue(); - } - - // SelectionDAG::getConstant will promote SplatValue appropriately. - SDValue Result = DAG.getConstant(SplatValue, DL, ViaVecTy); - - // Bitcast to the type we originally wanted - if (ViaVecTy != ResTy) - Result = DAG.getNode(ISD::BITCAST, SDLoc(Node), ResTy, Result); - - return Result; - } else if (DAG.isSplatValue(Op, /* AllowUndefs */ false)) - return Op; - else if (!isConstantOrUndefBUILD_VECTOR(Node)) { - // Use INSERT_VECTOR_ELT operations rather than expand to stores. - // The resulting code is the same length as the expansion, but it doesn't - // use memory operations - EVT ResTy = Node->getValueType(0); - - assert(ResTy.isVector()); - - unsigned NumElts = ResTy.getVectorNumElements(); - SDValue Vector = DAG.getUNDEF(ResTy); - for (unsigned i = 0; i < NumElts; ++i) { - Vector = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, ResTy, Vector, - Node->getOperand(i), - DAG.getConstant(i, DL, MVT::i32)); - } - return Vector; - } - - return SDValue(); -} - -// Lower VECTOR_SHUFFLE into SHF (if possible). -// -// SHF splits the vector into blocks of four elements, then shuffles these -// elements according to a <4 x i2> constant (encoded as an integer immediate). -// -// It is therefore possible to lower into SHF when the mask takes the form: -// <a, b, c, d, a+4, b+4, c+4, d+4, a+8, b+8, c+8, d+8, ...> -// When undef's appear they are treated as if they were whatever value is -// necessary in order to fit the above forms. -// -// For example: -// %2 = shufflevector <8 x i16> %0, <8 x i16> undef, -// <8 x i32> <i32 3, i32 2, i32 1, i32 0, -// i32 7, i32 6, i32 5, i32 4> -// is lowered to: -// (SHF_H $w0, $w1, 27) -// where the 27 comes from: -// 3 + (2 << 2) + (1 << 4) + (0 << 6) -static SDValue lowerVECTOR_SHUFFLE_SHF(SDValue Op, EVT ResTy, - SmallVector<int, 16> Indices, - SelectionDAG &DAG) { - int SHFIndices[4] = { -1, -1, -1, -1 }; - - if (Indices.size() < 4) - return SDValue(); - - for (unsigned i = 0; i < 4; ++i) { - for (unsigned j = i; j < Indices.size(); j += 4) { - int Idx = Indices[j]; - - // Convert from vector index to 4-element subvector index - // If an index refers to an element outside of the subvector then give up - if (Idx != -1) { - Idx -= 4 * (j / 4); - if (Idx < 0 || Idx >= 4) - return SDValue(); - } - - // If the mask has an undef, replace it with the current index. - // Note that it might still be undef if the current index is also undef - if (SHFIndices[i] == -1) - SHFIndices[i] = Idx; - - // Check that non-undef values are the same as in the mask. If they - // aren't then give up - if (!(Idx == -1 || Idx == SHFIndices[i])) - return SDValue(); - } - } - - // Calculate the immediate. Replace any remaining undefs with zero - APInt Imm(32, 0); - for (int i = 3; i >= 0; --i) { - int Idx = SHFIndices[i]; - - if (Idx == -1) - Idx = 0; - - Imm <<= 2; - Imm |= Idx & 0x3; - } - - SDLoc DL(Op); - return DAG.getNode(MipsISD::SHF, DL, ResTy, - DAG.getConstant(Imm, DL, MVT::i32), Op->getOperand(0)); -} - -/// Determine whether a range fits a regular pattern of values. -/// This function accounts for the possibility of jumping over the End iterator. -template <typename ValType> -static bool -fitsRegularPattern(typename SmallVectorImpl<ValType>::const_iterator Begin, - unsigned CheckStride, - typename SmallVectorImpl<ValType>::const_iterator End, - ValType ExpectedIndex, unsigned ExpectedIndexStride) { - auto &I = Begin; - - while (I != End) { - if (*I != -1 && *I != ExpectedIndex) - return false; - ExpectedIndex += ExpectedIndexStride; - - // Incrementing past End is undefined behaviour so we must increment one - // step at a time and check for End at each step. - for (unsigned n = 0; n < CheckStride && I != End; ++n, ++I) - ; // Empty loop body. - } - return true; -} - -// Determine whether VECTOR_SHUFFLE is a SPLATI. -// -// It is a SPLATI when the mask is: -// <x, x, x, ...> -// where x is any valid index. -// -// When undef's appear in the mask they are treated as if they were whatever -// value is necessary in order to fit the above form. -static bool isVECTOR_SHUFFLE_SPLATI(SDValue Op, EVT ResTy, - SmallVector<int, 16> Indices, - SelectionDAG &DAG) { - assert((Indices.size() % 2) == 0); - - int SplatIndex = -1; - for (const auto &V : Indices) { - if (V != -1) { - SplatIndex = V; - break; - } - } - - return fitsRegularPattern<int>(Indices.begin(), 1, Indices.end(), SplatIndex, - 0); -} - -// Lower VECTOR_SHUFFLE into ILVEV (if possible). -// -// ILVEV interleaves the even elements from each vector. -// -// It is possible to lower into ILVEV when the mask consists of two of the -// following forms interleaved: -// <0, 2, 4, ...> -// <n, n+2, n+4, ...> -// where n is the number of elements in the vector. -// For example: -// <0, 0, 2, 2, 4, 4, ...> -// <0, n, 2, n+2, 4, n+4, ...> -// -// When undef's appear in the mask they are treated as if they were whatever -// value is necessary in order to fit the above forms. -static SDValue lowerVECTOR_SHUFFLE_ILVEV(SDValue Op, EVT ResTy, - SmallVector<int, 16> Indices, - SelectionDAG &DAG) { - assert((Indices.size() % 2) == 0); - - SDValue Wt; - SDValue Ws; - const auto &Begin = Indices.begin(); - const auto &End = Indices.end(); - - // Check even elements are taken from the even elements of one half or the - // other and pick an operand accordingly. - if (fitsRegularPattern<int>(Begin, 2, End, 0, 2)) - Wt = Op->getOperand(0); - else if (fitsRegularPattern<int>(Begin, 2, End, Indices.size(), 2)) - Wt = Op->getOperand(1); - else - return SDValue(); - - // Check odd elements are taken from the even elements of one half or the - // other and pick an operand accordingly. - if (fitsRegularPattern<int>(Begin + 1, 2, End, 0, 2)) - Ws = Op->getOperand(0); - else if (fitsRegularPattern<int>(Begin + 1, 2, End, Indices.size(), 2)) - Ws = Op->getOperand(1); - else - return SDValue(); - - return DAG.getNode(MipsISD::ILVEV, SDLoc(Op), ResTy, Ws, Wt); -} - -// Lower VECTOR_SHUFFLE into ILVOD (if possible). -// -// ILVOD interleaves the odd elements from each vector. -// -// It is possible to lower into ILVOD when the mask consists of two of the -// following forms interleaved: -// <1, 3, 5, ...> -// <n+1, n+3, n+5, ...> -// where n is the number of elements in the vector. -// For example: -// <1, 1, 3, 3, 5, 5, ...> -// <1, n+1, 3, n+3, 5, n+5, ...> -// -// When undef's appear in the mask they are treated as if they were whatever -// value is necessary in order to fit the above forms. -static SDValue lowerVECTOR_SHUFFLE_ILVOD(SDValue Op, EVT ResTy, - SmallVector<int, 16> Indices, - SelectionDAG &DAG) { - assert((Indices.size() % 2) == 0); - - SDValue Wt; - SDValue Ws; - const auto &Begin = Indices.begin(); - const auto &End = Indices.end(); - - // Check even elements are taken from the odd elements of one half or the - // other and pick an operand accordingly. - if (fitsRegularPattern<int>(Begin, 2, End, 1, 2)) - Wt = Op->getOperand(0); - else if (fitsRegularPattern<int>(Begin, 2, End, Indices.size() + 1, 2)) - Wt = Op->getOperand(1); - else - return SDValue(); - - // Check odd elements are taken from the odd elements of one half or the - // other and pick an operand accordingly. - if (fitsRegularPattern<int>(Begin + 1, 2, End, 1, 2)) - Ws = Op->getOperand(0); - else if (fitsRegularPattern<int>(Begin + 1, 2, End, Indices.size() + 1, 2)) - Ws = Op->getOperand(1); - else - return SDValue(); - - return DAG.getNode(MipsISD::ILVOD, SDLoc(Op), ResTy, Wt, Ws); -} - -// Lower VECTOR_SHUFFLE into ILVR (if possible). -// -// ILVR interleaves consecutive elements from the right (lowest-indexed) half of -// each vector. -// -// It is possible to lower into ILVR when the mask consists of two of the -// following forms interleaved: -// <0, 1, 2, ...> -// <n, n+1, n+2, ...> -// where n is the number of elements in the vector. -// For example: -// <0, 0, 1, 1, 2, 2, ...> -// <0, n, 1, n+1, 2, n+2, ...> -// -// When undef's appear in the mask they are treated as if they were whatever -// value is necessary in order to fit the above forms. -static SDValue lowerVECTOR_SHUFFLE_ILVR(SDValue Op, EVT ResTy, - SmallVector<int, 16> Indices, - SelectionDAG &DAG) { - assert((Indices.size() % 2) == 0); - - SDValue Wt; - SDValue Ws; - const auto &Begin = Indices.begin(); - const auto &End = Indices.end(); - - // Check even elements are taken from the right (lowest-indexed) elements of - // one half or the other and pick an operand accordingly. - if (fitsRegularPattern<int>(Begin, 2, End, 0, 1)) - Wt = Op->getOperand(0); - else if (fitsRegularPattern<int>(Begin, 2, End, Indices.size(), 1)) - Wt = Op->getOperand(1); - else - return SDValue(); - - // Check odd elements are taken from the right (lowest-indexed) elements of - // one half or the other and pick an operand accordingly. - if (fitsRegularPattern<int>(Begin + 1, 2, End, 0, 1)) - Ws = Op->getOperand(0); - else if (fitsRegularPattern<int>(Begin + 1, 2, End, Indices.size(), 1)) - Ws = Op->getOperand(1); - else - return SDValue(); - - return DAG.getNode(MipsISD::ILVR, SDLoc(Op), ResTy, Ws, Wt); -} - -// Lower VECTOR_SHUFFLE into ILVL (if possible). -// -// ILVL interleaves consecutive elements from the left (highest-indexed) half -// of each vector. -// -// It is possible to lower into ILVL when the mask consists of two of the -// following forms interleaved: -// <x, x+1, x+2, ...> -// <n+x, n+x+1, n+x+2, ...> -// where n is the number of elements in the vector and x is half n. -// For example: -// <x, x, x+1, x+1, x+2, x+2, ...> -// <x, n+x, x+1, n+x+1, x+2, n+x+2, ...> -// -// When undef's appear in the mask they are treated as if they were whatever -// value is necessary in order to fit the above forms. -static SDValue lowerVECTOR_SHUFFLE_ILVL(SDValue Op, EVT ResTy, - SmallVector<int, 16> Indices, - SelectionDAG &DAG) { - assert((Indices.size() % 2) == 0); - - unsigned HalfSize = Indices.size() / 2; - SDValue Wt; - SDValue Ws; - const auto &Begin = Indices.begin(); - const auto &End = Indices.end(); - - // Check even elements are taken from the left (highest-indexed) elements of - // one half or the other and pick an operand accordingly. - if (fitsRegularPattern<int>(Begin, 2, End, HalfSize, 1)) - Wt = Op->getOperand(0); - else if (fitsRegularPattern<int>(Begin, 2, End, Indices.size() + HalfSize, 1)) - Wt = Op->getOperand(1); - else - return SDValue(); - - // Check odd elements are taken from the left (highest-indexed) elements of - // one half or the other and pick an operand accordingly. - if (fitsRegularPattern<int>(Begin + 1, 2, End, HalfSize, 1)) - Ws = Op->getOperand(0); - else if (fitsRegularPattern<int>(Begin + 1, 2, End, Indices.size() + HalfSize, - 1)) - Ws = Op->getOperand(1); - else - return SDValue(); - - return DAG.getNode(MipsISD::ILVL, SDLoc(Op), ResTy, Ws, Wt); -} - -// Lower VECTOR_SHUFFLE into PCKEV (if possible). -// -// PCKEV copies the even elements of each vector into the result vector. -// -// It is possible to lower into PCKEV when the mask consists of two of the -// following forms concatenated: -// <0, 2, 4, ...> -// <n, n+2, n+4, ...> -// where n is the number of elements in the vector. -// For example: -// <0, 2, 4, ..., 0, 2, 4, ...> -// <0, 2, 4, ..., n, n+2, n+4, ...> -// -// When undef's appear in the mask they are treated as if they were whatever -// value is necessary in order to fit the above forms. -static SDValue lowerVECTOR_SHUFFLE_PCKEV(SDValue Op, EVT ResTy, - SmallVector<int, 16> Indices, - SelectionDAG &DAG) { - assert((Indices.size() % 2) == 0); - - SDValue Wt; - SDValue Ws; - const auto &Begin = Indices.begin(); - const auto &Mid = Indices.begin() + Indices.size() / 2; - const auto &End = Indices.end(); - - if (fitsRegularPattern<int>(Begin, 1, Mid, 0, 2)) - Wt = Op->getOperand(0); - else if (fitsRegularPattern<int>(Begin, 1, Mid, Indices.size(), 2)) - Wt = Op->getOperand(1); - else - return SDValue(); - - if (fitsRegularPattern<int>(Mid, 1, End, 0, 2)) - Ws = Op->getOperand(0); - else if (fitsRegularPattern<int>(Mid, 1, End, Indices.size(), 2)) - Ws = Op->getOperand(1); - else - return SDValue(); - - return DAG.getNode(MipsISD::PCKEV, SDLoc(Op), ResTy, Ws, Wt); -} - -// Lower VECTOR_SHUFFLE into PCKOD (if possible). -// -// PCKOD copies the odd elements of each vector into the result vector. -// -// It is possible to lower into PCKOD when the mask consists of two of the -// following forms concatenated: -// <1, 3, 5, ...> -// <n+1, n+3, n+5, ...> -// where n is the number of elements in the vector. -// For example: -// <1, 3, 5, ..., 1, 3, 5, ...> -// <1, 3, 5, ..., n+1, n+3, n+5, ...> -// -// When undef's appear in the mask they are treated as if they were whatever -// value is necessary in order to fit the above forms. -static SDValue lowerVECTOR_SHUFFLE_PCKOD(SDValue Op, EVT ResTy, - SmallVector<int, 16> Indices, - SelectionDAG &DAG) { - assert((Indices.size() % 2) == 0); - - SDValue Wt; - SDValue Ws; - const auto &Begin = Indices.begin(); - const auto &Mid = Indices.begin() + Indices.size() / 2; - const auto &End = Indices.end(); - - if (fitsRegularPattern<int>(Begin, 1, Mid, 1, 2)) - Wt = Op->getOperand(0); - else if (fitsRegularPattern<int>(Begin, 1, Mid, Indices.size() + 1, 2)) - Wt = Op->getOperand(1); - else - return SDValue(); - - if (fitsRegularPattern<int>(Mid, 1, End, 1, 2)) - Ws = Op->getOperand(0); - else if (fitsRegularPattern<int>(Mid, 1, End, Indices.size() + 1, 2)) - Ws = Op->getOperand(1); - else - return SDValue(); - - return DAG.getNode(MipsISD::PCKOD, SDLoc(Op), ResTy, Ws, Wt); -} - -// Lower VECTOR_SHUFFLE into VSHF. -// -// This mostly consists of converting the shuffle indices in Indices into a -// BUILD_VECTOR and adding it as an operand to the resulting VSHF. There is -// also code to eliminate unused operands of the VECTOR_SHUFFLE. For example, -// if the type is v8i16 and all the indices are less than 8 then the second -// operand is unused and can be replaced with anything. We choose to replace it -// with the used operand since this reduces the number of instructions overall. -static SDValue lowerVECTOR_SHUFFLE_VSHF(SDValue Op, EVT ResTy, - SmallVector<int, 16> Indices, - SelectionDAG &DAG) { - SmallVector<SDValue, 16> Ops; - SDValue Op0; - SDValue Op1; - EVT MaskVecTy = ResTy.changeVectorElementTypeToInteger(); - EVT MaskEltTy = MaskVecTy.getVectorElementType(); - bool Using1stVec = false; - bool Using2ndVec = false; - SDLoc DL(Op); - int ResTyNumElts = ResTy.getVectorNumElements(); - - for (int i = 0; i < ResTyNumElts; ++i) { - // Idx == -1 means UNDEF - int Idx = Indices[i]; - - if (0 <= Idx && Idx < ResTyNumElts) - Using1stVec = true; - if (ResTyNumElts <= Idx && Idx < ResTyNumElts * 2) - Using2ndVec = true; - } - - for (SmallVector<int, 16>::iterator I = Indices.begin(); I != Indices.end(); - ++I) - Ops.push_back(DAG.getTargetConstant(*I, DL, MaskEltTy)); - - SDValue MaskVec = DAG.getBuildVector(MaskVecTy, DL, Ops); - - if (Using1stVec && Using2ndVec) { - Op0 = Op->getOperand(0); - Op1 = Op->getOperand(1); - } else if (Using1stVec) - Op0 = Op1 = Op->getOperand(0); - else if (Using2ndVec) - Op0 = Op1 = Op->getOperand(1); - else - llvm_unreachable("shuffle vector mask references neither vector operand?"); - - // VECTOR_SHUFFLE concatenates the vectors in an vectorwise fashion. - // <0b00, 0b01> + <0b10, 0b11> -> <0b00, 0b01, 0b10, 0b11> - // VSHF concatenates the vectors in a bitwise fashion: - // <0b00, 0b01> + <0b10, 0b11> -> - // 0b0100 + 0b1110 -> 0b01001110 - // <0b10, 0b11, 0b00, 0b01> - // We must therefore swap the operands to get the correct result. - return DAG.getNode(MipsISD::VSHF, DL, ResTy, MaskVec, Op1, Op0); -} - -// Lower VECTOR_SHUFFLE into one of a number of instructions depending on the -// indices in the shuffle. -SDValue MipsSETargetLowering::lowerVECTOR_SHUFFLE(SDValue Op, - SelectionDAG &DAG) const { - ShuffleVectorSDNode *Node = cast<ShuffleVectorSDNode>(Op); - EVT ResTy = Op->getValueType(0); - - if (!ResTy.is128BitVector()) - return SDValue(); - - int ResTyNumElts = ResTy.getVectorNumElements(); - SmallVector<int, 16> Indices; - - for (int i = 0; i < ResTyNumElts; ++i) - Indices.push_back(Node->getMaskElt(i)); - - // splati.[bhwd] is preferable to the others but is matched from - // MipsISD::VSHF. - if (isVECTOR_SHUFFLE_SPLATI(Op, ResTy, Indices, DAG)) - return lowerVECTOR_SHUFFLE_VSHF(Op, ResTy, Indices, DAG); - SDValue Result; - if ((Result = lowerVECTOR_SHUFFLE_ILVEV(Op, ResTy, Indices, DAG))) - return Result; - if ((Result = lowerVECTOR_SHUFFLE_ILVOD(Op, ResTy, Indices, DAG))) - return Result; - if ((Result = lowerVECTOR_SHUFFLE_ILVL(Op, ResTy, Indices, DAG))) - return Result; - if ((Result = lowerVECTOR_SHUFFLE_ILVR(Op, ResTy, Indices, DAG))) - return Result; - if ((Result = lowerVECTOR_SHUFFLE_PCKEV(Op, ResTy, Indices, DAG))) - return Result; - if ((Result = lowerVECTOR_SHUFFLE_PCKOD(Op, ResTy, Indices, DAG))) - return Result; - if ((Result = lowerVECTOR_SHUFFLE_SHF(Op, ResTy, Indices, DAG))) - return Result; - return lowerVECTOR_SHUFFLE_VSHF(Op, ResTy, Indices, DAG); -} - -MachineBasicBlock * -MipsSETargetLowering::emitBPOSGE32(MachineInstr &MI, - MachineBasicBlock *BB) const { - // $bb: - // bposge32_pseudo $vr0 - // => - // $bb: - // bposge32 $tbb - // $fbb: - // li $vr2, 0 - // b $sink - // $tbb: - // li $vr1, 1 - // $sink: - // $vr0 = phi($vr2, $fbb, $vr1, $tbb) - - MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); - const TargetInstrInfo *TII = Subtarget.getInstrInfo(); - const TargetRegisterClass *RC = &Mips::GPR32RegClass; - DebugLoc DL = MI.getDebugLoc(); - const BasicBlock *LLVM_BB = BB->getBasicBlock(); - MachineFunction::iterator It = std::next(MachineFunction::iterator(BB)); - MachineFunction *F = BB->getParent(); - MachineBasicBlock *FBB = F->CreateMachineBasicBlock(LLVM_BB); - MachineBasicBlock *TBB = F->CreateMachineBasicBlock(LLVM_BB); - MachineBasicBlock *Sink = F->CreateMachineBasicBlock(LLVM_BB); - F->insert(It, FBB); - F->insert(It, TBB); - F->insert(It, Sink); - - // Transfer the remainder of BB and its successor edges to Sink. - Sink->splice(Sink->begin(), BB, std::next(MachineBasicBlock::iterator(MI)), - BB->end()); - Sink->transferSuccessorsAndUpdatePHIs(BB); - - // Add successors. - BB->addSuccessor(FBB); - BB->addSuccessor(TBB); - FBB->addSuccessor(Sink); - TBB->addSuccessor(Sink); - - // Insert the real bposge32 instruction to $BB. - BuildMI(BB, DL, TII->get(Mips::BPOSGE32)).addMBB(TBB); - // Insert the real bposge32c instruction to $BB. - BuildMI(BB, DL, TII->get(Mips::BPOSGE32C_MMR3)).addMBB(TBB); - - // Fill $FBB. - unsigned VR2 = RegInfo.createVirtualRegister(RC); - BuildMI(*FBB, FBB->end(), DL, TII->get(Mips::ADDiu), VR2) - .addReg(Mips::ZERO).addImm(0); - BuildMI(*FBB, FBB->end(), DL, TII->get(Mips::B)).addMBB(Sink); - - // Fill $TBB. - unsigned VR1 = RegInfo.createVirtualRegister(RC); - BuildMI(*TBB, TBB->end(), DL, TII->get(Mips::ADDiu), VR1) - .addReg(Mips::ZERO).addImm(1); - - // Insert phi function to $Sink. - BuildMI(*Sink, Sink->begin(), DL, TII->get(Mips::PHI), - MI.getOperand(0).getReg()) - .addReg(VR2) - .addMBB(FBB) - .addReg(VR1) - .addMBB(TBB); - - MI.eraseFromParent(); // The pseudo instruction is gone now. - return Sink; -} - -MachineBasicBlock *MipsSETargetLowering::emitMSACBranchPseudo( - MachineInstr &MI, MachineBasicBlock *BB, unsigned BranchOp) const { - // $bb: - // vany_nonzero $rd, $ws - // => - // $bb: - // bnz.b $ws, $tbb - // b $fbb - // $fbb: - // li $rd1, 0 - // b $sink - // $tbb: - // li $rd2, 1 - // $sink: - // $rd = phi($rd1, $fbb, $rd2, $tbb) - - MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); - const TargetInstrInfo *TII = Subtarget.getInstrInfo(); - const TargetRegisterClass *RC = &Mips::GPR32RegClass; - DebugLoc DL = MI.getDebugLoc(); - const BasicBlock *LLVM_BB = BB->getBasicBlock(); - MachineFunction::iterator It = std::next(MachineFunction::iterator(BB)); - MachineFunction *F = BB->getParent(); - MachineBasicBlock *FBB = F->CreateMachineBasicBlock(LLVM_BB); - MachineBasicBlock *TBB = F->CreateMachineBasicBlock(LLVM_BB); - MachineBasicBlock *Sink = F->CreateMachineBasicBlock(LLVM_BB); - F->insert(It, FBB); - F->insert(It, TBB); - F->insert(It, Sink); - - // Transfer the remainder of BB and its successor edges to Sink. - Sink->splice(Sink->begin(), BB, std::next(MachineBasicBlock::iterator(MI)), - BB->end()); - Sink->transferSuccessorsAndUpdatePHIs(BB); - - // Add successors. - BB->addSuccessor(FBB); - BB->addSuccessor(TBB); - FBB->addSuccessor(Sink); - TBB->addSuccessor(Sink); - - // Insert the real bnz.b instruction to $BB. - BuildMI(BB, DL, TII->get(BranchOp)) - .addReg(MI.getOperand(1).getReg()) - .addMBB(TBB); - - // Fill $FBB. - unsigned RD1 = RegInfo.createVirtualRegister(RC); - BuildMI(*FBB, FBB->end(), DL, TII->get(Mips::ADDiu), RD1) - .addReg(Mips::ZERO).addImm(0); - BuildMI(*FBB, FBB->end(), DL, TII->get(Mips::B)).addMBB(Sink); - - // Fill $TBB. - unsigned RD2 = RegInfo.createVirtualRegister(RC); - BuildMI(*TBB, TBB->end(), DL, TII->get(Mips::ADDiu), RD2) - .addReg(Mips::ZERO).addImm(1); - - // Insert phi function to $Sink. - BuildMI(*Sink, Sink->begin(), DL, TII->get(Mips::PHI), - MI.getOperand(0).getReg()) - .addReg(RD1) - .addMBB(FBB) - .addReg(RD2) - .addMBB(TBB); - - MI.eraseFromParent(); // The pseudo instruction is gone now. - return Sink; -} - -// Emit the COPY_FW pseudo instruction. -// -// copy_fw_pseudo $fd, $ws, n -// => -// copy_u_w $rt, $ws, $n -// mtc1 $rt, $fd -// -// When n is zero, the equivalent operation can be performed with (potentially) -// zero instructions due to register overlaps. This optimization is never valid -// for lane 1 because it would require FR=0 mode which isn't supported by MSA. -MachineBasicBlock * -MipsSETargetLowering::emitCOPY_FW(MachineInstr &MI, - MachineBasicBlock *BB) const { - const TargetInstrInfo *TII = Subtarget.getInstrInfo(); - MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); - DebugLoc DL = MI.getDebugLoc(); - unsigned Fd = MI.getOperand(0).getReg(); - unsigned Ws = MI.getOperand(1).getReg(); - unsigned Lane = MI.getOperand(2).getImm(); - - if (Lane == 0) { - unsigned Wt = Ws; - if (!Subtarget.useOddSPReg()) { - // We must copy to an even-numbered MSA register so that the - // single-precision sub-register is also guaranteed to be even-numbered. - Wt = RegInfo.createVirtualRegister(&Mips::MSA128WEvensRegClass); - - BuildMI(*BB, MI, DL, TII->get(Mips::COPY), Wt).addReg(Ws); - } - - BuildMI(*BB, MI, DL, TII->get(Mips::COPY), Fd).addReg(Wt, 0, Mips::sub_lo); - } else { - unsigned Wt = RegInfo.createVirtualRegister( - Subtarget.useOddSPReg() ? &Mips::MSA128WRegClass : - &Mips::MSA128WEvensRegClass); - - BuildMI(*BB, MI, DL, TII->get(Mips::SPLATI_W), Wt).addReg(Ws).addImm(Lane); - BuildMI(*BB, MI, DL, TII->get(Mips::COPY), Fd).addReg(Wt, 0, Mips::sub_lo); - } - - MI.eraseFromParent(); // The pseudo instruction is gone now. - return BB; -} - -// Emit the COPY_FD pseudo instruction. -// -// copy_fd_pseudo $fd, $ws, n -// => -// splati.d $wt, $ws, $n -// copy $fd, $wt:sub_64 -// -// When n is zero, the equivalent operation can be performed with (potentially) -// zero instructions due to register overlaps. This optimization is always -// valid because FR=1 mode which is the only supported mode in MSA. -MachineBasicBlock * -MipsSETargetLowering::emitCOPY_FD(MachineInstr &MI, - MachineBasicBlock *BB) const { - assert(Subtarget.isFP64bit()); - - const TargetInstrInfo *TII = Subtarget.getInstrInfo(); - MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); - unsigned Fd = MI.getOperand(0).getReg(); - unsigned Ws = MI.getOperand(1).getReg(); - unsigned Lane = MI.getOperand(2).getImm() * 2; - DebugLoc DL = MI.getDebugLoc(); - - if (Lane == 0) - BuildMI(*BB, MI, DL, TII->get(Mips::COPY), Fd).addReg(Ws, 0, Mips::sub_64); - else { - unsigned Wt = RegInfo.createVirtualRegister(&Mips::MSA128DRegClass); - - BuildMI(*BB, MI, DL, TII->get(Mips::SPLATI_D), Wt).addReg(Ws).addImm(1); - BuildMI(*BB, MI, DL, TII->get(Mips::COPY), Fd).addReg(Wt, 0, Mips::sub_64); - } - - MI.eraseFromParent(); // The pseudo instruction is gone now. - return BB; -} - -// Emit the INSERT_FW pseudo instruction. -// -// insert_fw_pseudo $wd, $wd_in, $n, $fs -// => -// subreg_to_reg $wt:sub_lo, $fs -// insve_w $wd[$n], $wd_in, $wt[0] -MachineBasicBlock * -MipsSETargetLowering::emitINSERT_FW(MachineInstr &MI, - MachineBasicBlock *BB) const { - const TargetInstrInfo *TII = Subtarget.getInstrInfo(); - MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); - DebugLoc DL = MI.getDebugLoc(); - unsigned Wd = MI.getOperand(0).getReg(); - unsigned Wd_in = MI.getOperand(1).getReg(); - unsigned Lane = MI.getOperand(2).getImm(); - unsigned Fs = MI.getOperand(3).getReg(); - unsigned Wt = RegInfo.createVirtualRegister( - Subtarget.useOddSPReg() ? &Mips::MSA128WRegClass : - &Mips::MSA128WEvensRegClass); - - BuildMI(*BB, MI, DL, TII->get(Mips::SUBREG_TO_REG), Wt) - .addImm(0) - .addReg(Fs) - .addImm(Mips::sub_lo); - BuildMI(*BB, MI, DL, TII->get(Mips::INSVE_W), Wd) - .addReg(Wd_in) - .addImm(Lane) - .addReg(Wt) - .addImm(0); - - MI.eraseFromParent(); // The pseudo instruction is gone now. - return BB; -} - -// Emit the INSERT_FD pseudo instruction. -// -// insert_fd_pseudo $wd, $fs, n -// => -// subreg_to_reg $wt:sub_64, $fs -// insve_d $wd[$n], $wd_in, $wt[0] -MachineBasicBlock * -MipsSETargetLowering::emitINSERT_FD(MachineInstr &MI, - MachineBasicBlock *BB) const { - assert(Subtarget.isFP64bit()); - - const TargetInstrInfo *TII = Subtarget.getInstrInfo(); - MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); - DebugLoc DL = MI.getDebugLoc(); - unsigned Wd = MI.getOperand(0).getReg(); - unsigned Wd_in = MI.getOperand(1).getReg(); - unsigned Lane = MI.getOperand(2).getImm(); - unsigned Fs = MI.getOperand(3).getReg(); - unsigned Wt = RegInfo.createVirtualRegister(&Mips::MSA128DRegClass); - - BuildMI(*BB, MI, DL, TII->get(Mips::SUBREG_TO_REG), Wt) - .addImm(0) - .addReg(Fs) - .addImm(Mips::sub_64); - BuildMI(*BB, MI, DL, TII->get(Mips::INSVE_D), Wd) - .addReg(Wd_in) - .addImm(Lane) - .addReg(Wt) - .addImm(0); - - MI.eraseFromParent(); // The pseudo instruction is gone now. - return BB; -} - -// Emit the INSERT_([BHWD]|F[WD])_VIDX pseudo instruction. -// -// For integer: -// (INSERT_([BHWD]|F[WD])_PSEUDO $wd, $wd_in, $n, $rs) -// => -// (SLL $lanetmp1, $lane, <log2size) -// (SLD_B $wdtmp1, $wd_in, $wd_in, $lanetmp1) -// (INSERT_[BHWD], $wdtmp2, $wdtmp1, 0, $rs) -// (NEG $lanetmp2, $lanetmp1) -// (SLD_B $wd, $wdtmp2, $wdtmp2, $lanetmp2) -// -// For floating point: -// (INSERT_([BHWD]|F[WD])_PSEUDO $wd, $wd_in, $n, $fs) -// => -// (SUBREG_TO_REG $wt, $fs, <subreg>) -// (SLL $lanetmp1, $lane, <log2size) -// (SLD_B $wdtmp1, $wd_in, $wd_in, $lanetmp1) -// (INSVE_[WD], $wdtmp2, 0, $wdtmp1, 0) -// (NEG $lanetmp2, $lanetmp1) -// (SLD_B $wd, $wdtmp2, $wdtmp2, $lanetmp2) -MachineBasicBlock *MipsSETargetLowering::emitINSERT_DF_VIDX( - MachineInstr &MI, MachineBasicBlock *BB, unsigned EltSizeInBytes, - bool IsFP) const { - const TargetInstrInfo *TII = Subtarget.getInstrInfo(); - MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); - DebugLoc DL = MI.getDebugLoc(); - unsigned Wd = MI.getOperand(0).getReg(); - unsigned SrcVecReg = MI.getOperand(1).getReg(); - unsigned LaneReg = MI.getOperand(2).getReg(); - unsigned SrcValReg = MI.getOperand(3).getReg(); - - const TargetRegisterClass *VecRC = nullptr; - // FIXME: This should be true for N32 too. - const TargetRegisterClass *GPRRC = - Subtarget.isABI_N64() ? &Mips::GPR64RegClass : &Mips::GPR32RegClass; - unsigned SubRegIdx = Subtarget.isABI_N64() ? Mips::sub_32 : 0; - unsigned ShiftOp = Subtarget.isABI_N64() ? Mips::DSLL : Mips::SLL; - unsigned EltLog2Size; - unsigned InsertOp = 0; - unsigned InsveOp = 0; - switch (EltSizeInBytes) { - default: - llvm_unreachable("Unexpected size"); - case 1: - EltLog2Size = 0; - InsertOp = Mips::INSERT_B; - InsveOp = Mips::INSVE_B; - VecRC = &Mips::MSA128BRegClass; - break; - case 2: - EltLog2Size = 1; - InsertOp = Mips::INSERT_H; - InsveOp = Mips::INSVE_H; - VecRC = &Mips::MSA128HRegClass; - break; - case 4: - EltLog2Size = 2; - InsertOp = Mips::INSERT_W; - InsveOp = Mips::INSVE_W; - VecRC = &Mips::MSA128WRegClass; - break; - case 8: - EltLog2Size = 3; - InsertOp = Mips::INSERT_D; - InsveOp = Mips::INSVE_D; - VecRC = &Mips::MSA128DRegClass; - break; - } - - if (IsFP) { - unsigned Wt = RegInfo.createVirtualRegister(VecRC); - BuildMI(*BB, MI, DL, TII->get(Mips::SUBREG_TO_REG), Wt) - .addImm(0) - .addReg(SrcValReg) - .addImm(EltSizeInBytes == 8 ? Mips::sub_64 : Mips::sub_lo); - SrcValReg = Wt; - } - - // Convert the lane index into a byte index - if (EltSizeInBytes != 1) { - unsigned LaneTmp1 = RegInfo.createVirtualRegister(GPRRC); - BuildMI(*BB, MI, DL, TII->get(ShiftOp), LaneTmp1) - .addReg(LaneReg) - .addImm(EltLog2Size); - LaneReg = LaneTmp1; - } - - // Rotate bytes around so that the desired lane is element zero - unsigned WdTmp1 = RegInfo.createVirtualRegister(VecRC); - BuildMI(*BB, MI, DL, TII->get(Mips::SLD_B), WdTmp1) - .addReg(SrcVecReg) - .addReg(SrcVecReg) - .addReg(LaneReg, 0, SubRegIdx); - - unsigned WdTmp2 = RegInfo.createVirtualRegister(VecRC); - if (IsFP) { - // Use insve.df to insert to element zero - BuildMI(*BB, MI, DL, TII->get(InsveOp), WdTmp2) - .addReg(WdTmp1) - .addImm(0) - .addReg(SrcValReg) - .addImm(0); - } else { - // Use insert.df to insert to element zero - BuildMI(*BB, MI, DL, TII->get(InsertOp), WdTmp2) - .addReg(WdTmp1) - .addReg(SrcValReg) - .addImm(0); - } - - // Rotate elements the rest of the way for a full rotation. - // sld.df inteprets $rt modulo the number of columns so we only need to negate - // the lane index to do this. - unsigned LaneTmp2 = RegInfo.createVirtualRegister(GPRRC); - BuildMI(*BB, MI, DL, TII->get(Subtarget.isABI_N64() ? Mips::DSUB : Mips::SUB), - LaneTmp2) - .addReg(Subtarget.isABI_N64() ? Mips::ZERO_64 : Mips::ZERO) - .addReg(LaneReg); - BuildMI(*BB, MI, DL, TII->get(Mips::SLD_B), Wd) - .addReg(WdTmp2) - .addReg(WdTmp2) - .addReg(LaneTmp2, 0, SubRegIdx); - - MI.eraseFromParent(); // The pseudo instruction is gone now. - return BB; -} - -// Emit the FILL_FW pseudo instruction. -// -// fill_fw_pseudo $wd, $fs -// => -// implicit_def $wt1 -// insert_subreg $wt2:subreg_lo, $wt1, $fs -// splati.w $wd, $wt2[0] -MachineBasicBlock * -MipsSETargetLowering::emitFILL_FW(MachineInstr &MI, - MachineBasicBlock *BB) const { - const TargetInstrInfo *TII = Subtarget.getInstrInfo(); - MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); - DebugLoc DL = MI.getDebugLoc(); - unsigned Wd = MI.getOperand(0).getReg(); - unsigned Fs = MI.getOperand(1).getReg(); - unsigned Wt1 = RegInfo.createVirtualRegister( - Subtarget.useOddSPReg() ? &Mips::MSA128WRegClass - : &Mips::MSA128WEvensRegClass); - unsigned Wt2 = RegInfo.createVirtualRegister( - Subtarget.useOddSPReg() ? &Mips::MSA128WRegClass - : &Mips::MSA128WEvensRegClass); - - BuildMI(*BB, MI, DL, TII->get(Mips::IMPLICIT_DEF), Wt1); - BuildMI(*BB, MI, DL, TII->get(Mips::INSERT_SUBREG), Wt2) - .addReg(Wt1) - .addReg(Fs) - .addImm(Mips::sub_lo); - BuildMI(*BB, MI, DL, TII->get(Mips::SPLATI_W), Wd).addReg(Wt2).addImm(0); - - MI.eraseFromParent(); // The pseudo instruction is gone now. - return BB; -} - -// Emit the FILL_FD pseudo instruction. -// -// fill_fd_pseudo $wd, $fs -// => -// implicit_def $wt1 -// insert_subreg $wt2:subreg_64, $wt1, $fs -// splati.d $wd, $wt2[0] -MachineBasicBlock * -MipsSETargetLowering::emitFILL_FD(MachineInstr &MI, - MachineBasicBlock *BB) const { - assert(Subtarget.isFP64bit()); - - const TargetInstrInfo *TII = Subtarget.getInstrInfo(); - MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); - DebugLoc DL = MI.getDebugLoc(); - unsigned Wd = MI.getOperand(0).getReg(); - unsigned Fs = MI.getOperand(1).getReg(); - unsigned Wt1 = RegInfo.createVirtualRegister(&Mips::MSA128DRegClass); - unsigned Wt2 = RegInfo.createVirtualRegister(&Mips::MSA128DRegClass); - - BuildMI(*BB, MI, DL, TII->get(Mips::IMPLICIT_DEF), Wt1); - BuildMI(*BB, MI, DL, TII->get(Mips::INSERT_SUBREG), Wt2) - .addReg(Wt1) - .addReg(Fs) - .addImm(Mips::sub_64); - BuildMI(*BB, MI, DL, TII->get(Mips::SPLATI_D), Wd).addReg(Wt2).addImm(0); - - MI.eraseFromParent(); // The pseudo instruction is gone now. - return BB; -} - -// Emit the ST_F16_PSEDUO instruction to store a f16 value from an MSA -// register. -// -// STF16 MSA128F16:$wd, mem_simm10:$addr -// => -// copy_u.h $rtemp,$wd[0] -// sh $rtemp, $addr -// -// Safety: We can't use st.h & co as they would over write the memory after -// the destination. It would require half floats be allocated 16 bytes(!) of -// space. -MachineBasicBlock * -MipsSETargetLowering::emitST_F16_PSEUDO(MachineInstr &MI, - MachineBasicBlock *BB) const { - - const TargetInstrInfo *TII = Subtarget.getInstrInfo(); - MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); - DebugLoc DL = MI.getDebugLoc(); - unsigned Ws = MI.getOperand(0).getReg(); - unsigned Rt = MI.getOperand(1).getReg(); - const MachineMemOperand &MMO = **MI.memoperands_begin(); - unsigned Imm = MMO.getOffset(); - - // Caution: A load via the GOT can expand to a GPR32 operand, a load via - // spill and reload can expand as a GPR64 operand. Examine the - // operand in detail and default to ABI. - const TargetRegisterClass *RC = - MI.getOperand(1).isReg() ? RegInfo.getRegClass(MI.getOperand(1).getReg()) - : (Subtarget.isABI_O32() ? &Mips::GPR32RegClass - : &Mips::GPR64RegClass); - const bool UsingMips32 = RC == &Mips::GPR32RegClass; - unsigned Rs = RegInfo.createVirtualRegister(&Mips::GPR32RegClass); - - BuildMI(*BB, MI, DL, TII->get(Mips::COPY_U_H), Rs).addReg(Ws).addImm(0); - if(!UsingMips32) { - unsigned Tmp = RegInfo.createVirtualRegister(&Mips::GPR64RegClass); - BuildMI(*BB, MI, DL, TII->get(Mips::SUBREG_TO_REG), Tmp) - .addImm(0) - .addReg(Rs) - .addImm(Mips::sub_32); - Rs = Tmp; - } - BuildMI(*BB, MI, DL, TII->get(UsingMips32 ? Mips::SH : Mips::SH64)) - .addReg(Rs) - .addReg(Rt) - .addImm(Imm) - .addMemOperand(BB->getParent()->getMachineMemOperand( - &MMO, MMO.getOffset(), MMO.getSize())); - - MI.eraseFromParent(); - return BB; -} - -// Emit the LD_F16_PSEDUO instruction to load a f16 value into an MSA register. -// -// LD_F16 MSA128F16:$wd, mem_simm10:$addr -// => -// lh $rtemp, $addr -// fill.h $wd, $rtemp -// -// Safety: We can't use ld.h & co as they over-read from the source. -// Additionally, if the address is not modulo 16, 2 cases can occur: -// a) Segmentation fault as the load instruction reads from a memory page -// memory it's not supposed to. -// b) The load crosses an implementation specific boundary, requiring OS -// intervention. -MachineBasicBlock * -MipsSETargetLowering::emitLD_F16_PSEUDO(MachineInstr &MI, - MachineBasicBlock *BB) const { - - const TargetInstrInfo *TII = Subtarget.getInstrInfo(); - MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); - DebugLoc DL = MI.getDebugLoc(); - unsigned Wd = MI.getOperand(0).getReg(); - - // Caution: A load via the GOT can expand to a GPR32 operand, a load via - // spill and reload can expand as a GPR64 operand. Examine the - // operand in detail and default to ABI. - const TargetRegisterClass *RC = - MI.getOperand(1).isReg() ? RegInfo.getRegClass(MI.getOperand(1).getReg()) - : (Subtarget.isABI_O32() ? &Mips::GPR32RegClass - : &Mips::GPR64RegClass); - - const bool UsingMips32 = RC == &Mips::GPR32RegClass; - unsigned Rt = RegInfo.createVirtualRegister(RC); - - MachineInstrBuilder MIB = - BuildMI(*BB, MI, DL, TII->get(UsingMips32 ? Mips::LH : Mips::LH64), Rt); - for (unsigned i = 1; i < MI.getNumOperands(); i++) - MIB.add(MI.getOperand(i)); - - if(!UsingMips32) { - unsigned Tmp = RegInfo.createVirtualRegister(&Mips::GPR32RegClass); - BuildMI(*BB, MI, DL, TII->get(Mips::COPY), Tmp).addReg(Rt, 0, Mips::sub_32); - Rt = Tmp; - } - - BuildMI(*BB, MI, DL, TII->get(Mips::FILL_H), Wd).addReg(Rt); - - MI.eraseFromParent(); - return BB; -} - -// Emit the FPROUND_PSEUDO instruction. -// -// Round an FGR64Opnd, FGR32Opnd to an f16. -// -// Safety: Cycle the operand through the GPRs so the result always ends up -// the correct MSA register. -// -// FIXME: This copying is strictly unnecessary. If we could tie FGR32Opnd:$Fs -// / FGR64Opnd:$Fs and MSA128F16:$Wd to the same physical register -// (which they can be, as the MSA registers are defined to alias the -// FPU's 64 bit and 32 bit registers) the result can be accessed using -// the correct register class. That requires operands be tie-able across -// register classes which have a sub/super register class relationship. -// -// For FPG32Opnd: -// -// FPROUND MSA128F16:$wd, FGR32Opnd:$fs -// => -// mfc1 $rtemp, $fs -// fill.w $rtemp, $wtemp -// fexdo.w $wd, $wtemp, $wtemp -// -// For FPG64Opnd on mips32r2+: -// -// FPROUND MSA128F16:$wd, FGR64Opnd:$fs -// => -// mfc1 $rtemp, $fs -// fill.w $rtemp, $wtemp -// mfhc1 $rtemp2, $fs -// insert.w $wtemp[1], $rtemp2 -// insert.w $wtemp[3], $rtemp2 -// fexdo.w $wtemp2, $wtemp, $wtemp -// fexdo.h $wd, $temp2, $temp2 -// -// For FGR64Opnd on mips64r2+: -// -// FPROUND MSA128F16:$wd, FGR64Opnd:$fs -// => -// dmfc1 $rtemp, $fs -// fill.d $rtemp, $wtemp -// fexdo.w $wtemp2, $wtemp, $wtemp -// fexdo.h $wd, $wtemp2, $wtemp2 -// -// Safety note: As $wtemp is UNDEF, we may provoke a spurious exception if the -// undef bits are "just right" and the exception enable bits are -// set. By using fill.w to replicate $fs into all elements over -// insert.w for one element, we avoid that potiential case. If -// fexdo.[hw] causes an exception in, the exception is valid and it -// occurs for all elements. -MachineBasicBlock * -MipsSETargetLowering::emitFPROUND_PSEUDO(MachineInstr &MI, - MachineBasicBlock *BB, - bool IsFGR64) const { - - // Strictly speaking, we need MIPS32R5 to support MSA. We'll be generous - // here. It's technically doable to support MIPS32 here, but the ISA forbids - // it. - assert(Subtarget.hasMSA() && Subtarget.hasMips32r2()); - - bool IsFGR64onMips64 = Subtarget.hasMips64() && IsFGR64; - bool IsFGR64onMips32 = !Subtarget.hasMips64() && IsFGR64; - - const TargetInstrInfo *TII = Subtarget.getInstrInfo(); - DebugLoc DL = MI.getDebugLoc(); - unsigned Wd = MI.getOperand(0).getReg(); - unsigned Fs = MI.getOperand(1).getReg(); - - MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); - unsigned Wtemp = RegInfo.createVirtualRegister(&Mips::MSA128WRegClass); - const TargetRegisterClass *GPRRC = - IsFGR64onMips64 ? &Mips::GPR64RegClass : &Mips::GPR32RegClass; - unsigned MFC1Opc = IsFGR64onMips64 - ? Mips::DMFC1 - : (IsFGR64onMips32 ? Mips::MFC1_D64 : Mips::MFC1); - unsigned FILLOpc = IsFGR64onMips64 ? Mips::FILL_D : Mips::FILL_W; - - // Perform the register class copy as mentioned above. - unsigned Rtemp = RegInfo.createVirtualRegister(GPRRC); - BuildMI(*BB, MI, DL, TII->get(MFC1Opc), Rtemp).addReg(Fs); - BuildMI(*BB, MI, DL, TII->get(FILLOpc), Wtemp).addReg(Rtemp); - unsigned WPHI = Wtemp; - - if (IsFGR64onMips32) { - unsigned Rtemp2 = RegInfo.createVirtualRegister(GPRRC); - BuildMI(*BB, MI, DL, TII->get(Mips::MFHC1_D64), Rtemp2).addReg(Fs); - unsigned Wtemp2 = RegInfo.createVirtualRegister(&Mips::MSA128WRegClass); - unsigned Wtemp3 = RegInfo.createVirtualRegister(&Mips::MSA128WRegClass); - BuildMI(*BB, MI, DL, TII->get(Mips::INSERT_W), Wtemp2) - .addReg(Wtemp) - .addReg(Rtemp2) - .addImm(1); - BuildMI(*BB, MI, DL, TII->get(Mips::INSERT_W), Wtemp3) - .addReg(Wtemp2) - .addReg(Rtemp2) - .addImm(3); - WPHI = Wtemp3; - } - - if (IsFGR64) { - unsigned Wtemp2 = RegInfo.createVirtualRegister(&Mips::MSA128WRegClass); - BuildMI(*BB, MI, DL, TII->get(Mips::FEXDO_W), Wtemp2) - .addReg(WPHI) - .addReg(WPHI); - WPHI = Wtemp2; - } - - BuildMI(*BB, MI, DL, TII->get(Mips::FEXDO_H), Wd).addReg(WPHI).addReg(WPHI); - - MI.eraseFromParent(); - return BB; -} - -// Emit the FPEXTEND_PSEUDO instruction. -// -// Expand an f16 to either a FGR32Opnd or FGR64Opnd. -// -// Safety: Cycle the result through the GPRs so the result always ends up -// the correct floating point register. -// -// FIXME: This copying is strictly unnecessary. If we could tie FGR32Opnd:$Fd -// / FGR64Opnd:$Fd and MSA128F16:$Ws to the same physical register -// (which they can be, as the MSA registers are defined to alias the -// FPU's 64 bit and 32 bit registers) the result can be accessed using -// the correct register class. That requires operands be tie-able across -// register classes which have a sub/super register class relationship. I -// haven't checked. -// -// For FGR32Opnd: -// -// FPEXTEND FGR32Opnd:$fd, MSA128F16:$ws -// => -// fexupr.w $wtemp, $ws -// copy_s.w $rtemp, $ws[0] -// mtc1 $rtemp, $fd -// -// For FGR64Opnd on Mips64: -// -// FPEXTEND FGR64Opnd:$fd, MSA128F16:$ws -// => -// fexupr.w $wtemp, $ws -// fexupr.d $wtemp2, $wtemp -// copy_s.d $rtemp, $wtemp2s[0] -// dmtc1 $rtemp, $fd -// -// For FGR64Opnd on Mips32: -// -// FPEXTEND FGR64Opnd:$fd, MSA128F16:$ws -// => -// fexupr.w $wtemp, $ws -// fexupr.d $wtemp2, $wtemp -// copy_s.w $rtemp, $wtemp2[0] -// mtc1 $rtemp, $ftemp -// copy_s.w $rtemp2, $wtemp2[1] -// $fd = mthc1 $rtemp2, $ftemp -MachineBasicBlock * -MipsSETargetLowering::emitFPEXTEND_PSEUDO(MachineInstr &MI, - MachineBasicBlock *BB, - bool IsFGR64) const { - - // Strictly speaking, we need MIPS32R5 to support MSA. We'll be generous - // here. It's technically doable to support MIPS32 here, but the ISA forbids - // it. - assert(Subtarget.hasMSA() && Subtarget.hasMips32r2()); - - bool IsFGR64onMips64 = Subtarget.hasMips64() && IsFGR64; - bool IsFGR64onMips32 = !Subtarget.hasMips64() && IsFGR64; - - const TargetInstrInfo *TII = Subtarget.getInstrInfo(); - DebugLoc DL = MI.getDebugLoc(); - Register Fd = MI.getOperand(0).getReg(); - Register Ws = MI.getOperand(1).getReg(); - - MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); - const TargetRegisterClass *GPRRC = - IsFGR64onMips64 ? &Mips::GPR64RegClass : &Mips::GPR32RegClass; - unsigned MTC1Opc = IsFGR64onMips64 - ? Mips::DMTC1 - : (IsFGR64onMips32 ? Mips::MTC1_D64 : Mips::MTC1); - Register COPYOpc = IsFGR64onMips64 ? Mips::COPY_S_D : Mips::COPY_S_W; - - Register Wtemp = RegInfo.createVirtualRegister(&Mips::MSA128WRegClass); - Register WPHI = Wtemp; - - BuildMI(*BB, MI, DL, TII->get(Mips::FEXUPR_W), Wtemp).addReg(Ws); - if (IsFGR64) { - WPHI = RegInfo.createVirtualRegister(&Mips::MSA128DRegClass); - BuildMI(*BB, MI, DL, TII->get(Mips::FEXUPR_D), WPHI).addReg(Wtemp); - } - - // Perform the safety regclass copy mentioned above. - Register Rtemp = RegInfo.createVirtualRegister(GPRRC); - Register FPRPHI = IsFGR64onMips32 - ? RegInfo.createVirtualRegister(&Mips::FGR64RegClass) - : Fd; - BuildMI(*BB, MI, DL, TII->get(COPYOpc), Rtemp).addReg(WPHI).addImm(0); - BuildMI(*BB, MI, DL, TII->get(MTC1Opc), FPRPHI).addReg(Rtemp); - - if (IsFGR64onMips32) { - Register Rtemp2 = RegInfo.createVirtualRegister(GPRRC); - BuildMI(*BB, MI, DL, TII->get(Mips::COPY_S_W), Rtemp2) - .addReg(WPHI) - .addImm(1); - BuildMI(*BB, MI, DL, TII->get(Mips::MTHC1_D64), Fd) - .addReg(FPRPHI) - .addReg(Rtemp2); - } - - MI.eraseFromParent(); - return BB; -} - -// Emit the FEXP2_W_1 pseudo instructions. -// -// fexp2_w_1_pseudo $wd, $wt -// => -// ldi.w $ws, 1 -// fexp2.w $wd, $ws, $wt -MachineBasicBlock * -MipsSETargetLowering::emitFEXP2_W_1(MachineInstr &MI, - MachineBasicBlock *BB) const { - const TargetInstrInfo *TII = Subtarget.getInstrInfo(); - MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); - const TargetRegisterClass *RC = &Mips::MSA128WRegClass; - unsigned Ws1 = RegInfo.createVirtualRegister(RC); - unsigned Ws2 = RegInfo.createVirtualRegister(RC); - DebugLoc DL = MI.getDebugLoc(); - - // Splat 1.0 into a vector - BuildMI(*BB, MI, DL, TII->get(Mips::LDI_W), Ws1).addImm(1); - BuildMI(*BB, MI, DL, TII->get(Mips::FFINT_U_W), Ws2).addReg(Ws1); - - // Emit 1.0 * fexp2(Wt) - BuildMI(*BB, MI, DL, TII->get(Mips::FEXP2_W), MI.getOperand(0).getReg()) - .addReg(Ws2) - .addReg(MI.getOperand(1).getReg()); - - MI.eraseFromParent(); // The pseudo instruction is gone now. - return BB; -} - -// Emit the FEXP2_D_1 pseudo instructions. -// -// fexp2_d_1_pseudo $wd, $wt -// => -// ldi.d $ws, 1 -// fexp2.d $wd, $ws, $wt -MachineBasicBlock * -MipsSETargetLowering::emitFEXP2_D_1(MachineInstr &MI, - MachineBasicBlock *BB) const { - const TargetInstrInfo *TII = Subtarget.getInstrInfo(); - MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); - const TargetRegisterClass *RC = &Mips::MSA128DRegClass; - unsigned Ws1 = RegInfo.createVirtualRegister(RC); - unsigned Ws2 = RegInfo.createVirtualRegister(RC); - DebugLoc DL = MI.getDebugLoc(); - - // Splat 1.0 into a vector - BuildMI(*BB, MI, DL, TII->get(Mips::LDI_D), Ws1).addImm(1); - BuildMI(*BB, MI, DL, TII->get(Mips::FFINT_U_D), Ws2).addReg(Ws1); - - // Emit 1.0 * fexp2(Wt) - BuildMI(*BB, MI, DL, TII->get(Mips::FEXP2_D), MI.getOperand(0).getReg()) - .addReg(Ws2) - .addReg(MI.getOperand(1).getReg()); - - MI.eraseFromParent(); // The pseudo instruction is gone now. - return BB; -} diff --git a/contrib/llvm/lib/Target/Mips/MipsSEISelLowering.h b/contrib/llvm/lib/Target/Mips/MipsSEISelLowering.h deleted file mode 100644 index 433d019332cf..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsSEISelLowering.h +++ /dev/null @@ -1,143 +0,0 @@ -//===- MipsSEISelLowering.h - MipsSE DAG Lowering Interface -----*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Subclass of MipsTargetLowering specialized for mips32/64. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_MIPS_MIPSSEISELLOWERING_H -#define LLVM_LIB_TARGET_MIPS_MIPSSEISELLOWERING_H - -#include "MipsISelLowering.h" -#include "llvm/CodeGen/SelectionDAGNodes.h" -#include "llvm/Support/MachineValueType.h" - -namespace llvm { - -class MachineBasicBlock; -class MachineInstr; -class MipsSubtarget; -class MipsTargetMachine; -class SelectionDAG; -class TargetRegisterClass; - - class MipsSETargetLowering : public MipsTargetLowering { - public: - explicit MipsSETargetLowering(const MipsTargetMachine &TM, - const MipsSubtarget &STI); - - /// Enable MSA support for the given integer type and Register - /// class. - void addMSAIntType(MVT::SimpleValueType Ty, const TargetRegisterClass *RC); - - /// Enable MSA support for the given floating-point type and - /// Register class. - void addMSAFloatType(MVT::SimpleValueType Ty, - const TargetRegisterClass *RC); - - bool allowsMisalignedMemoryAccesses( - EVT VT, unsigned AS = 0, unsigned Align = 1, - MachineMemOperand::Flags Flags = MachineMemOperand::MONone, - bool *Fast = nullptr) const override; - - SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override; - - SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override; - - MachineBasicBlock * - EmitInstrWithCustomInserter(MachineInstr &MI, - MachineBasicBlock *MBB) const override; - - bool isShuffleMaskLegal(ArrayRef<int> Mask, EVT VT) const override { - return false; - } - - const TargetRegisterClass *getRepRegClassFor(MVT VT) const override; - - private: - bool isEligibleForTailCallOptimization( - const CCState &CCInfo, unsigned NextStackOffset, - const MipsFunctionInfo &FI) const override; - - void - getOpndList(SmallVectorImpl<SDValue> &Ops, - std::deque<std::pair<unsigned, SDValue>> &RegsToPass, - bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage, - bool IsCallReloc, CallLoweringInfo &CLI, SDValue Callee, - SDValue Chain) const override; - - SDValue lowerLOAD(SDValue Op, SelectionDAG &DAG) const; - SDValue lowerSTORE(SDValue Op, SelectionDAG &DAG) const; - SDValue lowerBITCAST(SDValue Op, SelectionDAG &DAG) const; - - SDValue lowerMulDiv(SDValue Op, unsigned NewOpc, bool HasLo, bool HasHi, - SelectionDAG &DAG) const; - - SDValue lowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const; - SDValue lowerINTRINSIC_W_CHAIN(SDValue Op, SelectionDAG &DAG) const; - SDValue lowerINTRINSIC_VOID(SDValue Op, SelectionDAG &DAG) const; - SDValue lowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const; - SDValue lowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const; - /// Lower VECTOR_SHUFFLE into one of a number of instructions - /// depending on the indices in the shuffle. - SDValue lowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) const; - SDValue lowerSELECT(SDValue Op, SelectionDAG &DAG) const; - - MachineBasicBlock *emitBPOSGE32(MachineInstr &MI, - MachineBasicBlock *BB) const; - MachineBasicBlock *emitMSACBranchPseudo(MachineInstr &MI, - MachineBasicBlock *BB, - unsigned BranchOp) const; - /// Emit the COPY_FW pseudo instruction - MachineBasicBlock *emitCOPY_FW(MachineInstr &MI, - MachineBasicBlock *BB) const; - /// Emit the COPY_FD pseudo instruction - MachineBasicBlock *emitCOPY_FD(MachineInstr &MI, - MachineBasicBlock *BB) const; - /// Emit the INSERT_FW pseudo instruction - MachineBasicBlock *emitINSERT_FW(MachineInstr &MI, - MachineBasicBlock *BB) const; - /// Emit the INSERT_FD pseudo instruction - MachineBasicBlock *emitINSERT_FD(MachineInstr &MI, - MachineBasicBlock *BB) const; - /// Emit the INSERT_([BHWD]|F[WD])_VIDX pseudo instruction - MachineBasicBlock *emitINSERT_DF_VIDX(MachineInstr &MI, - MachineBasicBlock *BB, - unsigned EltSizeInBytes, - bool IsFP) const; - /// Emit the FILL_FW pseudo instruction - MachineBasicBlock *emitFILL_FW(MachineInstr &MI, - MachineBasicBlock *BB) const; - /// Emit the FILL_FD pseudo instruction - MachineBasicBlock *emitFILL_FD(MachineInstr &MI, - MachineBasicBlock *BB) const; - /// Emit the FEXP2_W_1 pseudo instructions. - MachineBasicBlock *emitFEXP2_W_1(MachineInstr &MI, - MachineBasicBlock *BB) const; - /// Emit the FEXP2_D_1 pseudo instructions. - MachineBasicBlock *emitFEXP2_D_1(MachineInstr &MI, - MachineBasicBlock *BB) const; - /// Emit the FILL_FW pseudo instruction - MachineBasicBlock *emitLD_F16_PSEUDO(MachineInstr &MI, - MachineBasicBlock *BB) const; - /// Emit the FILL_FD pseudo instruction - MachineBasicBlock *emitST_F16_PSEUDO(MachineInstr &MI, - MachineBasicBlock *BB) const; - /// Emit the FEXP2_W_1 pseudo instructions. - MachineBasicBlock *emitFPEXTEND_PSEUDO(MachineInstr &MI, - MachineBasicBlock *BB, - bool IsFGR64) const; - /// Emit the FEXP2_D_1 pseudo instructions. - MachineBasicBlock *emitFPROUND_PSEUDO(MachineInstr &MI, - MachineBasicBlock *BBi, - bool IsFGR64) const; - }; - -} // end namespace llvm - -#endif // LLVM_LIB_TARGET_MIPS_MIPSSEISELLOWERING_H diff --git a/contrib/llvm/lib/Target/Mips/MipsSEInstrInfo.cpp b/contrib/llvm/lib/Target/Mips/MipsSEInstrInfo.cpp deleted file mode 100644 index 4e49f5e7d9d1..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsSEInstrInfo.cpp +++ /dev/null @@ -1,906 +0,0 @@ -//===-- MipsSEInstrInfo.cpp - Mips32/64 Instruction Information -----------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains the Mips32/64 implementation of the TargetInstrInfo class. -// -//===----------------------------------------------------------------------===// - -#include "MipsSEInstrInfo.h" -#include "MCTargetDesc/MipsInstPrinter.h" -#include "MipsAnalyzeImmediate.h" -#include "MipsMachineFunction.h" -#include "MipsTargetMachine.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/TargetRegistry.h" - -using namespace llvm; - -static unsigned getUnconditionalBranch(const MipsSubtarget &STI) { - if (STI.inMicroMipsMode()) - return STI.isPositionIndependent() ? Mips::B_MM : Mips::J_MM; - return STI.isPositionIndependent() ? Mips::B : Mips::J; -} - -MipsSEInstrInfo::MipsSEInstrInfo(const MipsSubtarget &STI) - : MipsInstrInfo(STI, getUnconditionalBranch(STI)), RI() {} - -const MipsRegisterInfo &MipsSEInstrInfo::getRegisterInfo() const { - return RI; -} - -/// isLoadFromStackSlot - If the specified machine instruction is a direct -/// load from a stack slot, return the virtual or physical register number of -/// the destination along with the FrameIndex of the loaded stack slot. If -/// not, return 0. This predicate must return 0 if the instruction has -/// any side effects other than loading from the stack slot. -unsigned MipsSEInstrInfo::isLoadFromStackSlot(const MachineInstr &MI, - int &FrameIndex) const { - unsigned Opc = MI.getOpcode(); - - if ((Opc == Mips::LW) || (Opc == Mips::LD) || - (Opc == Mips::LWC1) || (Opc == Mips::LDC1) || (Opc == Mips::LDC164)) { - if ((MI.getOperand(1).isFI()) && // is a stack slot - (MI.getOperand(2).isImm()) && // the imm is zero - (isZeroImm(MI.getOperand(2)))) { - FrameIndex = MI.getOperand(1).getIndex(); - return MI.getOperand(0).getReg(); - } - } - - return 0; -} - -/// isStoreToStackSlot - If the specified machine instruction is a direct -/// store to a stack slot, return the virtual or physical register number of -/// the source reg along with the FrameIndex of the loaded stack slot. If -/// not, return 0. This predicate must return 0 if the instruction has -/// any side effects other than storing to the stack slot. -unsigned MipsSEInstrInfo::isStoreToStackSlot(const MachineInstr &MI, - int &FrameIndex) const { - unsigned Opc = MI.getOpcode(); - - if ((Opc == Mips::SW) || (Opc == Mips::SD) || - (Opc == Mips::SWC1) || (Opc == Mips::SDC1) || (Opc == Mips::SDC164)) { - if ((MI.getOperand(1).isFI()) && // is a stack slot - (MI.getOperand(2).isImm()) && // the imm is zero - (isZeroImm(MI.getOperand(2)))) { - FrameIndex = MI.getOperand(1).getIndex(); - return MI.getOperand(0).getReg(); - } - } - return 0; -} - -void MipsSEInstrInfo::copyPhysReg(MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, - const DebugLoc &DL, unsigned DestReg, - unsigned SrcReg, bool KillSrc) const { - unsigned Opc = 0, ZeroReg = 0; - bool isMicroMips = Subtarget.inMicroMipsMode(); - - if (Mips::GPR32RegClass.contains(DestReg)) { // Copy to CPU Reg. - if (Mips::GPR32RegClass.contains(SrcReg)) { - if (isMicroMips) - Opc = Mips::MOVE16_MM; - else - Opc = Mips::OR, ZeroReg = Mips::ZERO; - } else if (Mips::CCRRegClass.contains(SrcReg)) - Opc = Mips::CFC1; - else if (Mips::FGR32RegClass.contains(SrcReg)) - Opc = Mips::MFC1; - else if (Mips::HI32RegClass.contains(SrcReg)) { - Opc = isMicroMips ? Mips::MFHI16_MM : Mips::MFHI; - SrcReg = 0; - } else if (Mips::LO32RegClass.contains(SrcReg)) { - Opc = isMicroMips ? Mips::MFLO16_MM : Mips::MFLO; - SrcReg = 0; - } else if (Mips::HI32DSPRegClass.contains(SrcReg)) - Opc = Mips::MFHI_DSP; - else if (Mips::LO32DSPRegClass.contains(SrcReg)) - Opc = Mips::MFLO_DSP; - else if (Mips::DSPCCRegClass.contains(SrcReg)) { - BuildMI(MBB, I, DL, get(Mips::RDDSP), DestReg).addImm(1 << 4) - .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc)); - return; - } - else if (Mips::MSACtrlRegClass.contains(SrcReg)) - Opc = Mips::CFCMSA; - } - else if (Mips::GPR32RegClass.contains(SrcReg)) { // Copy from CPU Reg. - if (Mips::CCRRegClass.contains(DestReg)) - Opc = Mips::CTC1; - else if (Mips::FGR32RegClass.contains(DestReg)) - Opc = Mips::MTC1; - else if (Mips::HI32RegClass.contains(DestReg)) - Opc = Mips::MTHI, DestReg = 0; - else if (Mips::LO32RegClass.contains(DestReg)) - Opc = Mips::MTLO, DestReg = 0; - else if (Mips::HI32DSPRegClass.contains(DestReg)) - Opc = Mips::MTHI_DSP; - else if (Mips::LO32DSPRegClass.contains(DestReg)) - Opc = Mips::MTLO_DSP; - else if (Mips::DSPCCRegClass.contains(DestReg)) { - BuildMI(MBB, I, DL, get(Mips::WRDSP)) - .addReg(SrcReg, getKillRegState(KillSrc)).addImm(1 << 4) - .addReg(DestReg, RegState::ImplicitDefine); - return; - } else if (Mips::MSACtrlRegClass.contains(DestReg)) { - BuildMI(MBB, I, DL, get(Mips::CTCMSA)) - .addReg(DestReg) - .addReg(SrcReg, getKillRegState(KillSrc)); - return; - } - } - else if (Mips::FGR32RegClass.contains(DestReg, SrcReg)) - Opc = Mips::FMOV_S; - else if (Mips::AFGR64RegClass.contains(DestReg, SrcReg)) - Opc = Mips::FMOV_D32; - else if (Mips::FGR64RegClass.contains(DestReg, SrcReg)) - Opc = Mips::FMOV_D64; - else if (Mips::GPR64RegClass.contains(DestReg)) { // Copy to CPU64 Reg. - if (Mips::GPR64RegClass.contains(SrcReg)) - Opc = Mips::OR64, ZeroReg = Mips::ZERO_64; - else if (Mips::HI64RegClass.contains(SrcReg)) - Opc = Mips::MFHI64, SrcReg = 0; - else if (Mips::LO64RegClass.contains(SrcReg)) - Opc = Mips::MFLO64, SrcReg = 0; - else if (Mips::FGR64RegClass.contains(SrcReg)) - Opc = Mips::DMFC1; - } - else if (Mips::GPR64RegClass.contains(SrcReg)) { // Copy from CPU64 Reg. - if (Mips::HI64RegClass.contains(DestReg)) - Opc = Mips::MTHI64, DestReg = 0; - else if (Mips::LO64RegClass.contains(DestReg)) - Opc = Mips::MTLO64, DestReg = 0; - else if (Mips::FGR64RegClass.contains(DestReg)) - Opc = Mips::DMTC1; - } - else if (Mips::MSA128BRegClass.contains(DestReg)) { // Copy to MSA reg - if (Mips::MSA128BRegClass.contains(SrcReg)) - Opc = Mips::MOVE_V; - } - - assert(Opc && "Cannot copy registers"); - - MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(Opc)); - - if (DestReg) - MIB.addReg(DestReg, RegState::Define); - - if (SrcReg) - MIB.addReg(SrcReg, getKillRegState(KillSrc)); - - if (ZeroReg) - MIB.addReg(ZeroReg); -} - -static bool isORCopyInst(const MachineInstr &MI) { - switch (MI.getOpcode()) { - default: - break; - case Mips::OR_MM: - case Mips::OR: - if (MI.getOperand(2).getReg() == Mips::ZERO) - return true; - break; - case Mips::OR64: - if (MI.getOperand(2).getReg() == Mips::ZERO_64) - return true; - break; - } - return false; -} - -/// If @MI is WRDSP/RRDSP instruction return true with @isWrite set to true -/// if it is WRDSP instruction. -static bool isReadOrWriteToDSPReg(const MachineInstr &MI, bool &isWrite) { - switch (MI.getOpcode()) { - default: - return false; - case Mips::WRDSP: - case Mips::WRDSP_MM: - isWrite = true; - break; - case Mips::RDDSP: - case Mips::RDDSP_MM: - isWrite = false; - break; - } - return true; -} - -/// We check for the common case of 'or', as it's MIPS' preferred instruction -/// for GPRs but we have to check the operands to ensure that is the case. -/// Other move instructions for MIPS are directly identifiable. -bool MipsSEInstrInfo::isCopyInstrImpl(const MachineInstr &MI, - const MachineOperand *&Src, - const MachineOperand *&Dest) const { - bool isDSPControlWrite = false; - // Condition is made to match the creation of WRDSP/RDDSP copy instruction - // from copyPhysReg function. - if (isReadOrWriteToDSPReg(MI, isDSPControlWrite)) { - if (!MI.getOperand(1).isImm() || MI.getOperand(1).getImm() != (1<<4)) - return false; - else if (isDSPControlWrite) { - Src = &MI.getOperand(0); - Dest = &MI.getOperand(2); - } else { - Dest = &MI.getOperand(0); - Src = &MI.getOperand(2); - } - return true; - } else if (MI.isMoveReg() || isORCopyInst(MI)) { - Dest = &MI.getOperand(0); - Src = &MI.getOperand(1); - return true; - } - return false; -} - -void MipsSEInstrInfo:: -storeRegToStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, - unsigned SrcReg, bool isKill, int FI, - const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, - int64_t Offset) const { - DebugLoc DL; - MachineMemOperand *MMO = GetMemOperand(MBB, FI, MachineMemOperand::MOStore); - - unsigned Opc = 0; - - if (Mips::GPR32RegClass.hasSubClassEq(RC)) - Opc = Mips::SW; - else if (Mips::GPR64RegClass.hasSubClassEq(RC)) - Opc = Mips::SD; - else if (Mips::ACC64RegClass.hasSubClassEq(RC)) - Opc = Mips::STORE_ACC64; - else if (Mips::ACC64DSPRegClass.hasSubClassEq(RC)) - Opc = Mips::STORE_ACC64DSP; - else if (Mips::ACC128RegClass.hasSubClassEq(RC)) - Opc = Mips::STORE_ACC128; - else if (Mips::DSPCCRegClass.hasSubClassEq(RC)) - Opc = Mips::STORE_CCOND_DSP; - else if (Mips::FGR32RegClass.hasSubClassEq(RC)) - Opc = Mips::SWC1; - else if (Mips::AFGR64RegClass.hasSubClassEq(RC)) - Opc = Mips::SDC1; - else if (Mips::FGR64RegClass.hasSubClassEq(RC)) - Opc = Mips::SDC164; - else if (TRI->isTypeLegalForClass(*RC, MVT::v16i8)) - Opc = Mips::ST_B; - else if (TRI->isTypeLegalForClass(*RC, MVT::v8i16) || - TRI->isTypeLegalForClass(*RC, MVT::v8f16)) - Opc = Mips::ST_H; - else if (TRI->isTypeLegalForClass(*RC, MVT::v4i32) || - TRI->isTypeLegalForClass(*RC, MVT::v4f32)) - Opc = Mips::ST_W; - else if (TRI->isTypeLegalForClass(*RC, MVT::v2i64) || - TRI->isTypeLegalForClass(*RC, MVT::v2f64)) - Opc = Mips::ST_D; - else if (Mips::LO32RegClass.hasSubClassEq(RC)) - Opc = Mips::SW; - else if (Mips::LO64RegClass.hasSubClassEq(RC)) - Opc = Mips::SD; - else if (Mips::HI32RegClass.hasSubClassEq(RC)) - Opc = Mips::SW; - else if (Mips::HI64RegClass.hasSubClassEq(RC)) - Opc = Mips::SD; - else if (Mips::DSPRRegClass.hasSubClassEq(RC)) - Opc = Mips::SWDSP; - - // Hi, Lo are normally caller save but they are callee save - // for interrupt handling. - const Function &Func = MBB.getParent()->getFunction(); - if (Func.hasFnAttribute("interrupt")) { - if (Mips::HI32RegClass.hasSubClassEq(RC)) { - BuildMI(MBB, I, DL, get(Mips::MFHI), Mips::K0); - SrcReg = Mips::K0; - } else if (Mips::HI64RegClass.hasSubClassEq(RC)) { - BuildMI(MBB, I, DL, get(Mips::MFHI64), Mips::K0_64); - SrcReg = Mips::K0_64; - } else if (Mips::LO32RegClass.hasSubClassEq(RC)) { - BuildMI(MBB, I, DL, get(Mips::MFLO), Mips::K0); - SrcReg = Mips::K0; - } else if (Mips::LO64RegClass.hasSubClassEq(RC)) { - BuildMI(MBB, I, DL, get(Mips::MFLO64), Mips::K0_64); - SrcReg = Mips::K0_64; - } - } - - assert(Opc && "Register class not handled!"); - BuildMI(MBB, I, DL, get(Opc)).addReg(SrcReg, getKillRegState(isKill)) - .addFrameIndex(FI).addImm(Offset).addMemOperand(MMO); -} - -void MipsSEInstrInfo:: -loadRegFromStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, - unsigned DestReg, int FI, const TargetRegisterClass *RC, - const TargetRegisterInfo *TRI, int64_t Offset) const { - DebugLoc DL; - if (I != MBB.end()) DL = I->getDebugLoc(); - MachineMemOperand *MMO = GetMemOperand(MBB, FI, MachineMemOperand::MOLoad); - unsigned Opc = 0; - - const Function &Func = MBB.getParent()->getFunction(); - bool ReqIndirectLoad = Func.hasFnAttribute("interrupt") && - (DestReg == Mips::LO0 || DestReg == Mips::LO0_64 || - DestReg == Mips::HI0 || DestReg == Mips::HI0_64); - - if (Mips::GPR32RegClass.hasSubClassEq(RC)) - Opc = Mips::LW; - else if (Mips::GPR64RegClass.hasSubClassEq(RC)) - Opc = Mips::LD; - else if (Mips::ACC64RegClass.hasSubClassEq(RC)) - Opc = Mips::LOAD_ACC64; - else if (Mips::ACC64DSPRegClass.hasSubClassEq(RC)) - Opc = Mips::LOAD_ACC64DSP; - else if (Mips::ACC128RegClass.hasSubClassEq(RC)) - Opc = Mips::LOAD_ACC128; - else if (Mips::DSPCCRegClass.hasSubClassEq(RC)) - Opc = Mips::LOAD_CCOND_DSP; - else if (Mips::FGR32RegClass.hasSubClassEq(RC)) - Opc = Mips::LWC1; - else if (Mips::AFGR64RegClass.hasSubClassEq(RC)) - Opc = Mips::LDC1; - else if (Mips::FGR64RegClass.hasSubClassEq(RC)) - Opc = Mips::LDC164; - else if (TRI->isTypeLegalForClass(*RC, MVT::v16i8)) - Opc = Mips::LD_B; - else if (TRI->isTypeLegalForClass(*RC, MVT::v8i16) || - TRI->isTypeLegalForClass(*RC, MVT::v8f16)) - Opc = Mips::LD_H; - else if (TRI->isTypeLegalForClass(*RC, MVT::v4i32) || - TRI->isTypeLegalForClass(*RC, MVT::v4f32)) - Opc = Mips::LD_W; - else if (TRI->isTypeLegalForClass(*RC, MVT::v2i64) || - TRI->isTypeLegalForClass(*RC, MVT::v2f64)) - Opc = Mips::LD_D; - else if (Mips::HI32RegClass.hasSubClassEq(RC)) - Opc = Mips::LW; - else if (Mips::HI64RegClass.hasSubClassEq(RC)) - Opc = Mips::LD; - else if (Mips::LO32RegClass.hasSubClassEq(RC)) - Opc = Mips::LW; - else if (Mips::LO64RegClass.hasSubClassEq(RC)) - Opc = Mips::LD; - else if (Mips::DSPRRegClass.hasSubClassEq(RC)) - Opc = Mips::LWDSP; - - assert(Opc && "Register class not handled!"); - - if (!ReqIndirectLoad) - BuildMI(MBB, I, DL, get(Opc), DestReg) - .addFrameIndex(FI) - .addImm(Offset) - .addMemOperand(MMO); - else { - // Load HI/LO through K0. Notably the DestReg is encoded into the - // instruction itself. - unsigned Reg = Mips::K0; - unsigned LdOp = Mips::MTLO; - if (DestReg == Mips::HI0) - LdOp = Mips::MTHI; - - if (Subtarget.getABI().ArePtrs64bit()) { - Reg = Mips::K0_64; - if (DestReg == Mips::HI0_64) - LdOp = Mips::MTHI64; - else - LdOp = Mips::MTLO64; - } - - BuildMI(MBB, I, DL, get(Opc), Reg) - .addFrameIndex(FI) - .addImm(Offset) - .addMemOperand(MMO); - BuildMI(MBB, I, DL, get(LdOp)).addReg(Reg); - } -} - -bool MipsSEInstrInfo::expandPostRAPseudo(MachineInstr &MI) const { - MachineBasicBlock &MBB = *MI.getParent(); - bool isMicroMips = Subtarget.inMicroMipsMode(); - unsigned Opc; - - switch (MI.getDesc().getOpcode()) { - default: - return false; - case Mips::RetRA: - expandRetRA(MBB, MI); - break; - case Mips::ERet: - expandERet(MBB, MI); - break; - case Mips::PseudoMFHI: - expandPseudoMFHiLo(MBB, MI, Mips::MFHI); - break; - case Mips::PseudoMFHI_MM: - expandPseudoMFHiLo(MBB, MI, Mips::MFHI16_MM); - break; - case Mips::PseudoMFLO: - expandPseudoMFHiLo(MBB, MI, Mips::MFLO); - break; - case Mips::PseudoMFLO_MM: - expandPseudoMFHiLo(MBB, MI, Mips::MFLO16_MM); - break; - case Mips::PseudoMFHI64: - expandPseudoMFHiLo(MBB, MI, Mips::MFHI64); - break; - case Mips::PseudoMFLO64: - expandPseudoMFHiLo(MBB, MI, Mips::MFLO64); - break; - case Mips::PseudoMTLOHI: - expandPseudoMTLoHi(MBB, MI, Mips::MTLO, Mips::MTHI, false); - break; - case Mips::PseudoMTLOHI64: - expandPseudoMTLoHi(MBB, MI, Mips::MTLO64, Mips::MTHI64, false); - break; - case Mips::PseudoMTLOHI_DSP: - expandPseudoMTLoHi(MBB, MI, Mips::MTLO_DSP, Mips::MTHI_DSP, true); - break; - case Mips::PseudoMTLOHI_MM: - expandPseudoMTLoHi(MBB, MI, Mips::MTLO_MM, Mips::MTHI_MM, false); - break; - case Mips::PseudoCVT_S_W: - expandCvtFPInt(MBB, MI, Mips::CVT_S_W, Mips::MTC1, false); - break; - case Mips::PseudoCVT_D32_W: - Opc = isMicroMips ? Mips::CVT_D32_W_MM : Mips::CVT_D32_W; - expandCvtFPInt(MBB, MI, Opc, Mips::MTC1, false); - break; - case Mips::PseudoCVT_S_L: - expandCvtFPInt(MBB, MI, Mips::CVT_S_L, Mips::DMTC1, true); - break; - case Mips::PseudoCVT_D64_W: - Opc = isMicroMips ? Mips::CVT_D64_W_MM : Mips::CVT_D64_W; - expandCvtFPInt(MBB, MI, Opc, Mips::MTC1, true); - break; - case Mips::PseudoCVT_D64_L: - expandCvtFPInt(MBB, MI, Mips::CVT_D64_L, Mips::DMTC1, true); - break; - case Mips::BuildPairF64: - expandBuildPairF64(MBB, MI, isMicroMips, false); - break; - case Mips::BuildPairF64_64: - expandBuildPairF64(MBB, MI, isMicroMips, true); - break; - case Mips::ExtractElementF64: - expandExtractElementF64(MBB, MI, isMicroMips, false); - break; - case Mips::ExtractElementF64_64: - expandExtractElementF64(MBB, MI, isMicroMips, true); - break; - case Mips::MIPSeh_return32: - case Mips::MIPSeh_return64: - expandEhReturn(MBB, MI); - break; - } - - MBB.erase(MI); - return true; -} - -/// getOppositeBranchOpc - Return the inverse of the specified -/// opcode, e.g. turning BEQ to BNE. -unsigned MipsSEInstrInfo::getOppositeBranchOpc(unsigned Opc) const { - switch (Opc) { - default: llvm_unreachable("Illegal opcode!"); - case Mips::BEQ: return Mips::BNE; - case Mips::BEQ_MM: return Mips::BNE_MM; - case Mips::BNE: return Mips::BEQ; - case Mips::BNE_MM: return Mips::BEQ_MM; - case Mips::BGTZ: return Mips::BLEZ; - case Mips::BGEZ: return Mips::BLTZ; - case Mips::BLTZ: return Mips::BGEZ; - case Mips::BLEZ: return Mips::BGTZ; - case Mips::BGTZ_MM: return Mips::BLEZ_MM; - case Mips::BGEZ_MM: return Mips::BLTZ_MM; - case Mips::BLTZ_MM: return Mips::BGEZ_MM; - case Mips::BLEZ_MM: return Mips::BGTZ_MM; - case Mips::BEQ64: return Mips::BNE64; - case Mips::BNE64: return Mips::BEQ64; - case Mips::BGTZ64: return Mips::BLEZ64; - case Mips::BGEZ64: return Mips::BLTZ64; - case Mips::BLTZ64: return Mips::BGEZ64; - case Mips::BLEZ64: return Mips::BGTZ64; - case Mips::BC1T: return Mips::BC1F; - case Mips::BC1F: return Mips::BC1T; - case Mips::BC1T_MM: return Mips::BC1F_MM; - case Mips::BC1F_MM: return Mips::BC1T_MM; - case Mips::BEQZ16_MM: return Mips::BNEZ16_MM; - case Mips::BNEZ16_MM: return Mips::BEQZ16_MM; - case Mips::BEQZC_MM: return Mips::BNEZC_MM; - case Mips::BNEZC_MM: return Mips::BEQZC_MM; - case Mips::BEQZC: return Mips::BNEZC; - case Mips::BNEZC: return Mips::BEQZC; - case Mips::BLEZC: return Mips::BGTZC; - case Mips::BGEZC: return Mips::BLTZC; - case Mips::BGEC: return Mips::BLTC; - case Mips::BGTZC: return Mips::BLEZC; - case Mips::BLTZC: return Mips::BGEZC; - case Mips::BLTC: return Mips::BGEC; - case Mips::BGEUC: return Mips::BLTUC; - case Mips::BLTUC: return Mips::BGEUC; - case Mips::BEQC: return Mips::BNEC; - case Mips::BNEC: return Mips::BEQC; - case Mips::BC1EQZ: return Mips::BC1NEZ; - case Mips::BC1NEZ: return Mips::BC1EQZ; - case Mips::BEQZC_MMR6: return Mips::BNEZC_MMR6; - case Mips::BNEZC_MMR6: return Mips::BEQZC_MMR6; - case Mips::BLEZC_MMR6: return Mips::BGTZC_MMR6; - case Mips::BGEZC_MMR6: return Mips::BLTZC_MMR6; - case Mips::BGEC_MMR6: return Mips::BLTC_MMR6; - case Mips::BGTZC_MMR6: return Mips::BLEZC_MMR6; - case Mips::BLTZC_MMR6: return Mips::BGEZC_MMR6; - case Mips::BLTC_MMR6: return Mips::BGEC_MMR6; - case Mips::BGEUC_MMR6: return Mips::BLTUC_MMR6; - case Mips::BLTUC_MMR6: return Mips::BGEUC_MMR6; - case Mips::BEQC_MMR6: return Mips::BNEC_MMR6; - case Mips::BNEC_MMR6: return Mips::BEQC_MMR6; - case Mips::BC1EQZC_MMR6: return Mips::BC1NEZC_MMR6; - case Mips::BC1NEZC_MMR6: return Mips::BC1EQZC_MMR6; - case Mips::BEQZC64: return Mips::BNEZC64; - case Mips::BNEZC64: return Mips::BEQZC64; - case Mips::BEQC64: return Mips::BNEC64; - case Mips::BNEC64: return Mips::BEQC64; - case Mips::BGEC64: return Mips::BLTC64; - case Mips::BGEUC64: return Mips::BLTUC64; - case Mips::BLTC64: return Mips::BGEC64; - case Mips::BLTUC64: return Mips::BGEUC64; - case Mips::BGTZC64: return Mips::BLEZC64; - case Mips::BGEZC64: return Mips::BLTZC64; - case Mips::BLTZC64: return Mips::BGEZC64; - case Mips::BLEZC64: return Mips::BGTZC64; - case Mips::BBIT0: return Mips::BBIT1; - case Mips::BBIT1: return Mips::BBIT0; - case Mips::BBIT032: return Mips::BBIT132; - case Mips::BBIT132: return Mips::BBIT032; - case Mips::BZ_B: return Mips::BNZ_B; - case Mips::BZ_H: return Mips::BNZ_H; - case Mips::BZ_W: return Mips::BNZ_W; - case Mips::BZ_D: return Mips::BNZ_D; - case Mips::BZ_V: return Mips::BNZ_V; - case Mips::BNZ_B: return Mips::BZ_B; - case Mips::BNZ_H: return Mips::BZ_H; - case Mips::BNZ_W: return Mips::BZ_W; - case Mips::BNZ_D: return Mips::BZ_D; - case Mips::BNZ_V: return Mips::BZ_V; - } -} - -/// Adjust SP by Amount bytes. -void MipsSEInstrInfo::adjustStackPtr(unsigned SP, int64_t Amount, - MachineBasicBlock &MBB, - MachineBasicBlock::iterator I) const { - MipsABIInfo ABI = Subtarget.getABI(); - DebugLoc DL; - unsigned ADDiu = ABI.GetPtrAddiuOp(); - - if (Amount == 0) - return; - - if (isInt<16>(Amount)) { - // addi sp, sp, amount - BuildMI(MBB, I, DL, get(ADDiu), SP).addReg(SP).addImm(Amount); - } else { - // For numbers which are not 16bit integers we synthesize Amount inline - // then add or subtract it from sp. - unsigned Opc = ABI.GetPtrAdduOp(); - if (Amount < 0) { - Opc = ABI.GetPtrSubuOp(); - Amount = -Amount; - } - unsigned Reg = loadImmediate(Amount, MBB, I, DL, nullptr); - BuildMI(MBB, I, DL, get(Opc), SP).addReg(SP).addReg(Reg, RegState::Kill); - } -} - -/// This function generates the sequence of instructions needed to get the -/// result of adding register REG and immediate IMM. -unsigned MipsSEInstrInfo::loadImmediate(int64_t Imm, MachineBasicBlock &MBB, - MachineBasicBlock::iterator II, - const DebugLoc &DL, - unsigned *NewImm) const { - MipsAnalyzeImmediate AnalyzeImm; - const MipsSubtarget &STI = Subtarget; - MachineRegisterInfo &RegInfo = MBB.getParent()->getRegInfo(); - unsigned Size = STI.isABI_N64() ? 64 : 32; - unsigned LUi = STI.isABI_N64() ? Mips::LUi64 : Mips::LUi; - unsigned ZEROReg = STI.isABI_N64() ? Mips::ZERO_64 : Mips::ZERO; - const TargetRegisterClass *RC = STI.isABI_N64() ? - &Mips::GPR64RegClass : &Mips::GPR32RegClass; - bool LastInstrIsADDiu = NewImm; - - const MipsAnalyzeImmediate::InstSeq &Seq = - AnalyzeImm.Analyze(Imm, Size, LastInstrIsADDiu); - MipsAnalyzeImmediate::InstSeq::const_iterator Inst = Seq.begin(); - - assert(Seq.size() && (!LastInstrIsADDiu || (Seq.size() > 1))); - - // The first instruction can be a LUi, which is different from other - // instructions (ADDiu, ORI and SLL) in that it does not have a register - // operand. - unsigned Reg = RegInfo.createVirtualRegister(RC); - - if (Inst->Opc == LUi) - BuildMI(MBB, II, DL, get(LUi), Reg).addImm(SignExtend64<16>(Inst->ImmOpnd)); - else - BuildMI(MBB, II, DL, get(Inst->Opc), Reg).addReg(ZEROReg) - .addImm(SignExtend64<16>(Inst->ImmOpnd)); - - // Build the remaining instructions in Seq. - for (++Inst; Inst != Seq.end() - LastInstrIsADDiu; ++Inst) - BuildMI(MBB, II, DL, get(Inst->Opc), Reg).addReg(Reg, RegState::Kill) - .addImm(SignExtend64<16>(Inst->ImmOpnd)); - - if (LastInstrIsADDiu) - *NewImm = Inst->ImmOpnd; - - return Reg; -} - -unsigned MipsSEInstrInfo::getAnalyzableBrOpc(unsigned Opc) const { - return (Opc == Mips::BEQ || Opc == Mips::BEQ_MM || Opc == Mips::BNE || - Opc == Mips::BNE_MM || Opc == Mips::BGTZ || Opc == Mips::BGEZ || - Opc == Mips::BLTZ || Opc == Mips::BLEZ || Opc == Mips::BEQ64 || - Opc == Mips::BNE64 || Opc == Mips::BGTZ64 || Opc == Mips::BGEZ64 || - Opc == Mips::BLTZ64 || Opc == Mips::BLEZ64 || Opc == Mips::BC1T || - Opc == Mips::BC1F || Opc == Mips::B || Opc == Mips::J || - Opc == Mips::J_MM || Opc == Mips::B_MM || Opc == Mips::BEQZC_MM || - Opc == Mips::BNEZC_MM || Opc == Mips::BEQC || Opc == Mips::BNEC || - Opc == Mips::BLTC || Opc == Mips::BGEC || Opc == Mips::BLTUC || - Opc == Mips::BGEUC || Opc == Mips::BGTZC || Opc == Mips::BLEZC || - Opc == Mips::BGEZC || Opc == Mips::BLTZC || Opc == Mips::BEQZC || - Opc == Mips::BNEZC || Opc == Mips::BEQZC64 || Opc == Mips::BNEZC64 || - Opc == Mips::BEQC64 || Opc == Mips::BNEC64 || Opc == Mips::BGEC64 || - Opc == Mips::BGEUC64 || Opc == Mips::BLTC64 || Opc == Mips::BLTUC64 || - Opc == Mips::BGTZC64 || Opc == Mips::BGEZC64 || - Opc == Mips::BLTZC64 || Opc == Mips::BLEZC64 || Opc == Mips::BC || - Opc == Mips::BBIT0 || Opc == Mips::BBIT1 || Opc == Mips::BBIT032 || - Opc == Mips::BBIT132 || Opc == Mips::BC_MMR6 || - Opc == Mips::BEQC_MMR6 || Opc == Mips::BNEC_MMR6 || - Opc == Mips::BLTC_MMR6 || Opc == Mips::BGEC_MMR6 || - Opc == Mips::BLTUC_MMR6 || Opc == Mips::BGEUC_MMR6 || - Opc == Mips::BGTZC_MMR6 || Opc == Mips::BLEZC_MMR6 || - Opc == Mips::BGEZC_MMR6 || Opc == Mips::BLTZC_MMR6 || - Opc == Mips::BEQZC_MMR6 || Opc == Mips::BNEZC_MMR6) ? Opc : 0; -} - -void MipsSEInstrInfo::expandRetRA(MachineBasicBlock &MBB, - MachineBasicBlock::iterator I) const { - - MachineInstrBuilder MIB; - if (Subtarget.isGP64bit()) - MIB = BuildMI(MBB, I, I->getDebugLoc(), get(Mips::PseudoReturn64)) - .addReg(Mips::RA_64, RegState::Undef); - else - MIB = BuildMI(MBB, I, I->getDebugLoc(), get(Mips::PseudoReturn)) - .addReg(Mips::RA, RegState::Undef); - - // Retain any imp-use flags. - for (auto & MO : I->operands()) { - if (MO.isImplicit()) - MIB.add(MO); - } -} - -void MipsSEInstrInfo::expandERet(MachineBasicBlock &MBB, - MachineBasicBlock::iterator I) const { - BuildMI(MBB, I, I->getDebugLoc(), get(Mips::ERET)); -} - -std::pair<bool, bool> -MipsSEInstrInfo::compareOpndSize(unsigned Opc, - const MachineFunction &MF) const { - const MCInstrDesc &Desc = get(Opc); - assert(Desc.NumOperands == 2 && "Unary instruction expected."); - const MipsRegisterInfo *RI = &getRegisterInfo(); - unsigned DstRegSize = RI->getRegSizeInBits(*getRegClass(Desc, 0, RI, MF)); - unsigned SrcRegSize = RI->getRegSizeInBits(*getRegClass(Desc, 1, RI, MF)); - - return std::make_pair(DstRegSize > SrcRegSize, DstRegSize < SrcRegSize); -} - -void MipsSEInstrInfo::expandPseudoMFHiLo(MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, - unsigned NewOpc) const { - BuildMI(MBB, I, I->getDebugLoc(), get(NewOpc), I->getOperand(0).getReg()); -} - -void MipsSEInstrInfo::expandPseudoMTLoHi(MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, - unsigned LoOpc, - unsigned HiOpc, - bool HasExplicitDef) const { - // Expand - // lo_hi pseudomtlohi $gpr0, $gpr1 - // to these two instructions: - // mtlo $gpr0 - // mthi $gpr1 - - DebugLoc DL = I->getDebugLoc(); - const MachineOperand &SrcLo = I->getOperand(1), &SrcHi = I->getOperand(2); - MachineInstrBuilder LoInst = BuildMI(MBB, I, DL, get(LoOpc)); - MachineInstrBuilder HiInst = BuildMI(MBB, I, DL, get(HiOpc)); - - // Add lo/hi registers if the mtlo/hi instructions created have explicit - // def registers. - if (HasExplicitDef) { - unsigned DstReg = I->getOperand(0).getReg(); - unsigned DstLo = getRegisterInfo().getSubReg(DstReg, Mips::sub_lo); - unsigned DstHi = getRegisterInfo().getSubReg(DstReg, Mips::sub_hi); - LoInst.addReg(DstLo, RegState::Define); - HiInst.addReg(DstHi, RegState::Define); - } - - LoInst.addReg(SrcLo.getReg(), getKillRegState(SrcLo.isKill())); - HiInst.addReg(SrcHi.getReg(), getKillRegState(SrcHi.isKill())); -} - -void MipsSEInstrInfo::expandCvtFPInt(MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, - unsigned CvtOpc, unsigned MovOpc, - bool IsI64) const { - const MCInstrDesc &CvtDesc = get(CvtOpc), &MovDesc = get(MovOpc); - const MachineOperand &Dst = I->getOperand(0), &Src = I->getOperand(1); - unsigned DstReg = Dst.getReg(), SrcReg = Src.getReg(), TmpReg = DstReg; - unsigned KillSrc = getKillRegState(Src.isKill()); - DebugLoc DL = I->getDebugLoc(); - bool DstIsLarger, SrcIsLarger; - - std::tie(DstIsLarger, SrcIsLarger) = - compareOpndSize(CvtOpc, *MBB.getParent()); - - if (DstIsLarger) - TmpReg = getRegisterInfo().getSubReg(DstReg, Mips::sub_lo); - - if (SrcIsLarger) - DstReg = getRegisterInfo().getSubReg(DstReg, Mips::sub_lo); - - BuildMI(MBB, I, DL, MovDesc, TmpReg).addReg(SrcReg, KillSrc); - BuildMI(MBB, I, DL, CvtDesc, DstReg).addReg(TmpReg, RegState::Kill); -} - -void MipsSEInstrInfo::expandExtractElementF64(MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, - bool isMicroMips, - bool FP64) const { - unsigned DstReg = I->getOperand(0).getReg(); - unsigned SrcReg = I->getOperand(1).getReg(); - unsigned N = I->getOperand(2).getImm(); - DebugLoc dl = I->getDebugLoc(); - - assert(N < 2 && "Invalid immediate"); - unsigned SubIdx = N ? Mips::sub_hi : Mips::sub_lo; - unsigned SubReg = getRegisterInfo().getSubReg(SrcReg, SubIdx); - - // FPXX on MIPS-II or MIPS32r1 should have been handled with a spill/reload - // in MipsSEFrameLowering.cpp. - assert(!(Subtarget.isABI_FPXX() && !Subtarget.hasMips32r2())); - - // FP64A (FP64 with nooddspreg) should have been handled with a spill/reload - // in MipsSEFrameLowering.cpp. - assert(!(Subtarget.isFP64bit() && !Subtarget.useOddSPReg())); - - if (SubIdx == Mips::sub_hi && Subtarget.hasMTHC1()) { - // FIXME: Strictly speaking MFHC1 only reads the top 32-bits however, we - // claim to read the whole 64-bits as part of a white lie used to - // temporarily work around a widespread bug in the -mfp64 support. - // The problem is that none of the 32-bit fpu ops mention the fact - // that they clobber the upper 32-bits of the 64-bit FPR. Fixing that - // requires a major overhaul of the FPU implementation which can't - // be done right now due to time constraints. - // MFHC1 is one of two instructions that are affected since they are - // the only instructions that don't read the lower 32-bits. - // We therefore pretend that it reads the bottom 32-bits to - // artificially create a dependency and prevent the scheduler - // changing the behaviour of the code. - BuildMI(MBB, I, dl, - get(isMicroMips ? (FP64 ? Mips::MFHC1_D64_MM : Mips::MFHC1_D32_MM) - : (FP64 ? Mips::MFHC1_D64 : Mips::MFHC1_D32)), - DstReg) - .addReg(SrcReg); - } else - BuildMI(MBB, I, dl, get(Mips::MFC1), DstReg).addReg(SubReg); -} - -void MipsSEInstrInfo::expandBuildPairF64(MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, - bool isMicroMips, bool FP64) const { - unsigned DstReg = I->getOperand(0).getReg(); - unsigned LoReg = I->getOperand(1).getReg(), HiReg = I->getOperand(2).getReg(); - const MCInstrDesc& Mtc1Tdd = get(Mips::MTC1); - DebugLoc dl = I->getDebugLoc(); - const TargetRegisterInfo &TRI = getRegisterInfo(); - - // When mthc1 is available, use: - // mtc1 Lo, $fp - // mthc1 Hi, $fp - // - // Otherwise, for O32 FPXX ABI: - // spill + reload via ldc1 - // This case is handled by the frame lowering code. - // - // Otherwise, for FP32: - // mtc1 Lo, $fp - // mtc1 Hi, $fp + 1 - // - // The case where dmtc1 is available doesn't need to be handled here - // because it never creates a BuildPairF64 node. - - // FPXX on MIPS-II or MIPS32r1 should have been handled with a spill/reload - // in MipsSEFrameLowering.cpp. - assert(!(Subtarget.isABI_FPXX() && !Subtarget.hasMips32r2())); - - // FP64A (FP64 with nooddspreg) should have been handled with a spill/reload - // in MipsSEFrameLowering.cpp. - assert(!(Subtarget.isFP64bit() && !Subtarget.useOddSPReg())); - - BuildMI(MBB, I, dl, Mtc1Tdd, TRI.getSubReg(DstReg, Mips::sub_lo)) - .addReg(LoReg); - - if (Subtarget.hasMTHC1()) { - // FIXME: The .addReg(DstReg) is a white lie used to temporarily work - // around a widespread bug in the -mfp64 support. - // The problem is that none of the 32-bit fpu ops mention the fact - // that they clobber the upper 32-bits of the 64-bit FPR. Fixing that - // requires a major overhaul of the FPU implementation which can't - // be done right now due to time constraints. - // MTHC1 is one of two instructions that are affected since they are - // the only instructions that don't read the lower 32-bits. - // We therefore pretend that it reads the bottom 32-bits to - // artificially create a dependency and prevent the scheduler - // changing the behaviour of the code. - BuildMI(MBB, I, dl, - get(isMicroMips ? (FP64 ? Mips::MTHC1_D64_MM : Mips::MTHC1_D32_MM) - : (FP64 ? Mips::MTHC1_D64 : Mips::MTHC1_D32)), - DstReg) - .addReg(DstReg) - .addReg(HiReg); - } else if (Subtarget.isABI_FPXX()) - llvm_unreachable("BuildPairF64 not expanded in frame lowering code!"); - else - BuildMI(MBB, I, dl, Mtc1Tdd, TRI.getSubReg(DstReg, Mips::sub_hi)) - .addReg(HiReg); -} - -void MipsSEInstrInfo::expandEhReturn(MachineBasicBlock &MBB, - MachineBasicBlock::iterator I) const { - // This pseudo instruction is generated as part of the lowering of - // ISD::EH_RETURN. We convert it to a stack increment by OffsetReg, and - // indirect jump to TargetReg - MipsABIInfo ABI = Subtarget.getABI(); - unsigned ADDU = ABI.GetPtrAdduOp(); - unsigned SP = Subtarget.isGP64bit() ? Mips::SP_64 : Mips::SP; - unsigned RA = Subtarget.isGP64bit() ? Mips::RA_64 : Mips::RA; - unsigned T9 = Subtarget.isGP64bit() ? Mips::T9_64 : Mips::T9; - unsigned ZERO = Subtarget.isGP64bit() ? Mips::ZERO_64 : Mips::ZERO; - unsigned OffsetReg = I->getOperand(0).getReg(); - unsigned TargetReg = I->getOperand(1).getReg(); - - // addu $ra, $v0, $zero - // addu $sp, $sp, $v1 - // jr $ra (via RetRA) - const TargetMachine &TM = MBB.getParent()->getTarget(); - if (TM.isPositionIndependent()) - BuildMI(MBB, I, I->getDebugLoc(), get(ADDU), T9) - .addReg(TargetReg) - .addReg(ZERO); - BuildMI(MBB, I, I->getDebugLoc(), get(ADDU), RA) - .addReg(TargetReg) - .addReg(ZERO); - BuildMI(MBB, I, I->getDebugLoc(), get(ADDU), SP).addReg(SP).addReg(OffsetReg); - expandRetRA(MBB, I); -} - -const MipsInstrInfo *llvm::createMipsSEInstrInfo(const MipsSubtarget &STI) { - return new MipsSEInstrInfo(STI); -} diff --git a/contrib/llvm/lib/Target/Mips/MipsSEInstrInfo.h b/contrib/llvm/lib/Target/Mips/MipsSEInstrInfo.h deleted file mode 100644 index 3111d1c21a0a..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsSEInstrInfo.h +++ /dev/null @@ -1,127 +0,0 @@ -//===-- MipsSEInstrInfo.h - Mips32/64 Instruction Information ---*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains the Mips32/64 implementation of the TargetInstrInfo class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_MIPS_MIPSSEINSTRINFO_H -#define LLVM_LIB_TARGET_MIPS_MIPSSEINSTRINFO_H - -#include "MipsInstrInfo.h" -#include "MipsSERegisterInfo.h" - -namespace llvm { - -class MipsSEInstrInfo : public MipsInstrInfo { - const MipsSERegisterInfo RI; - -public: - explicit MipsSEInstrInfo(const MipsSubtarget &STI); - - const MipsRegisterInfo &getRegisterInfo() const override; - - /// isLoadFromStackSlot - If the specified machine instruction is a direct - /// load from a stack slot, return the virtual or physical register number of - /// the destination along with the FrameIndex of the loaded stack slot. If - /// not, return 0. This predicate must return 0 if the instruction has - /// any side effects other than loading from the stack slot. - unsigned isLoadFromStackSlot(const MachineInstr &MI, - int &FrameIndex) const override; - - /// isStoreToStackSlot - If the specified machine instruction is a direct - /// store to a stack slot, return the virtual or physical register number of - /// the source reg along with the FrameIndex of the loaded stack slot. If - /// not, return 0. This predicate must return 0 if the instruction has - /// any side effects other than storing to the stack slot. - unsigned isStoreToStackSlot(const MachineInstr &MI, - int &FrameIndex) const override; - - void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, - const DebugLoc &DL, unsigned DestReg, unsigned SrcReg, - bool KillSrc) const override; - - void storeRegToStack(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - unsigned SrcReg, bool isKill, int FrameIndex, - const TargetRegisterClass *RC, - const TargetRegisterInfo *TRI, - int64_t Offset) const override; - - void loadRegFromStack(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - unsigned DestReg, int FrameIndex, - const TargetRegisterClass *RC, - const TargetRegisterInfo *TRI, - int64_t Offset) const override; - - bool expandPostRAPseudo(MachineInstr &MI) const override; - - unsigned getOppositeBranchOpc(unsigned Opc) const override; - - /// Adjust SP by Amount bytes. - void adjustStackPtr(unsigned SP, int64_t Amount, MachineBasicBlock &MBB, - MachineBasicBlock::iterator I) const override; - - /// Emit a series of instructions to load an immediate. If NewImm is a - /// non-NULL parameter, the last instruction is not emitted, but instead - /// its immediate operand is returned in NewImm. - unsigned loadImmediate(int64_t Imm, MachineBasicBlock &MBB, - MachineBasicBlock::iterator II, const DebugLoc &DL, - unsigned *NewImm) const; - -protected: - /// If the specific machine instruction is a instruction that moves/copies - /// value from one register to another register return true along with - /// @Source machine operand and @Destination machine operand. - bool isCopyInstrImpl(const MachineInstr &MI, const MachineOperand *&Source, - const MachineOperand *&Destination) const override; - -private: - unsigned getAnalyzableBrOpc(unsigned Opc) const override; - - void expandRetRA(MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const; - - void expandERet(MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const; - - std::pair<bool, bool> compareOpndSize(unsigned Opc, - const MachineFunction &MF) const; - - void expandPseudoMFHiLo(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, - unsigned NewOpc) const; - - void expandPseudoMTLoHi(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, - unsigned LoOpc, unsigned HiOpc, - bool HasExplicitDef) const; - - /// Expand pseudo Int-to-FP conversion instructions. - /// - /// For example, the following pseudo instruction - /// PseudoCVT_D32_W D2, A5 - /// gets expanded into these two instructions: - /// MTC1 F4, A5 - /// CVT_D32_W D2, F4 - /// - /// We do this expansion post-RA to avoid inserting a floating point copy - /// instruction between MTC1 and CVT_D32_W. - void expandCvtFPInt(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, - unsigned CvtOpc, unsigned MovOpc, bool IsI64) const; - - void expandExtractElementF64(MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, bool isMicroMips, - bool FP64) const; - void expandBuildPairF64(MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, bool isMicroMips, - bool FP64) const; - void expandEhReturn(MachineBasicBlock &MBB, - MachineBasicBlock::iterator I) const; -}; - -} - -#endif diff --git a/contrib/llvm/lib/Target/Mips/MipsSERegisterInfo.cpp b/contrib/llvm/lib/Target/Mips/MipsSERegisterInfo.cpp deleted file mode 100644 index f4b164d5c0ab..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsSERegisterInfo.cpp +++ /dev/null @@ -1,260 +0,0 @@ -//===-- MipsSERegisterInfo.cpp - MIPS32/64 Register Information -== -------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains the MIPS32/64 implementation of the TargetRegisterInfo -// class. -// -//===----------------------------------------------------------------------===// - -#include "MipsSERegisterInfo.h" -#include "Mips.h" -#include "MipsMachineFunction.h" -#include "MipsSEInstrInfo.h" -#include "MipsSubtarget.h" -#include "MipsTargetMachine.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/TargetFrameLowering.h" -#include "llvm/CodeGen/TargetInstrInfo.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/DebugInfo.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/Type.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetOptions.h" - -using namespace llvm; - -#define DEBUG_TYPE "mips-reg-info" - -MipsSERegisterInfo::MipsSERegisterInfo() : MipsRegisterInfo() {} - -bool MipsSERegisterInfo:: -requiresRegisterScavenging(const MachineFunction &MF) const { - return true; -} - -bool MipsSERegisterInfo:: -requiresFrameIndexScavenging(const MachineFunction &MF) const { - return true; -} - -const TargetRegisterClass * -MipsSERegisterInfo::intRegClass(unsigned Size) const { - if (Size == 4) - return &Mips::GPR32RegClass; - - assert(Size == 8); - return &Mips::GPR64RegClass; -} - -/// Get the size of the offset supported by the given load/store/inline asm. -/// The result includes the effects of any scale factors applied to the -/// instruction immediate. -static inline unsigned getLoadStoreOffsetSizeInBits(const unsigned Opcode, - MachineOperand MO) { - switch (Opcode) { - case Mips::LD_B: - case Mips::ST_B: - return 10; - case Mips::LD_H: - case Mips::ST_H: - return 10 + 1 /* scale factor */; - case Mips::LD_W: - case Mips::ST_W: - return 10 + 2 /* scale factor */; - case Mips::LD_D: - case Mips::ST_D: - return 10 + 3 /* scale factor */; - case Mips::LL: - case Mips::LL64: - case Mips::LLD: - case Mips::LLE: - case Mips::SC: - case Mips::SC64: - case Mips::SCD: - case Mips::SCE: - return 16; - case Mips::LLE_MM: - case Mips::LL_MM: - case Mips::SCE_MM: - case Mips::SC_MM: - return 12; - case Mips::LL64_R6: - case Mips::LL_R6: - case Mips::LLD_R6: - case Mips::SC64_R6: - case Mips::SCD_R6: - case Mips::SC_R6: - case Mips::LL_MMR6: - case Mips::SC_MMR6: - return 9; - case Mips::INLINEASM: { - unsigned ConstraintID = InlineAsm::getMemoryConstraintID(MO.getImm()); - switch (ConstraintID) { - case InlineAsm::Constraint_ZC: { - const MipsSubtarget &Subtarget = MO.getParent() - ->getParent() - ->getParent() - ->getSubtarget<MipsSubtarget>(); - if (Subtarget.inMicroMipsMode()) - return 12; - - if (Subtarget.hasMips32r6()) - return 9; - - return 16; - } - default: - return 16; - } - } - default: - return 16; - } -} - -/// Get the scale factor applied to the immediate in the given load/store. -static inline unsigned getLoadStoreOffsetAlign(const unsigned Opcode) { - switch (Opcode) { - case Mips::LD_H: - case Mips::ST_H: - return 2; - case Mips::LD_W: - case Mips::ST_W: - return 4; - case Mips::LD_D: - case Mips::ST_D: - return 8; - default: - return 1; - } -} - -void MipsSERegisterInfo::eliminateFI(MachineBasicBlock::iterator II, - unsigned OpNo, int FrameIndex, - uint64_t StackSize, - int64_t SPOffset) const { - MachineInstr &MI = *II; - MachineFunction &MF = *MI.getParent()->getParent(); - MachineFrameInfo &MFI = MF.getFrameInfo(); - MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); - - MipsABIInfo ABI = - static_cast<const MipsTargetMachine &>(MF.getTarget()).getABI(); - const MipsRegisterInfo *RegInfo = - static_cast<const MipsRegisterInfo *>(MF.getSubtarget().getRegisterInfo()); - - const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); - int MinCSFI = 0; - int MaxCSFI = -1; - - if (CSI.size()) { - MinCSFI = CSI[0].getFrameIdx(); - MaxCSFI = CSI[CSI.size() - 1].getFrameIdx(); - } - - bool EhDataRegFI = MipsFI->isEhDataRegFI(FrameIndex); - bool IsISRRegFI = MipsFI->isISRRegFI(FrameIndex); - // The following stack frame objects are always referenced relative to $sp: - // 1. Outgoing arguments. - // 2. Pointer to dynamically allocated stack space. - // 3. Locations for callee-saved registers. - // 4. Locations for eh data registers. - // 5. Locations for ISR saved Coprocessor 0 registers 12 & 14. - // Everything else is referenced relative to whatever register - // getFrameRegister() returns. - unsigned FrameReg; - - if ((FrameIndex >= MinCSFI && FrameIndex <= MaxCSFI) || EhDataRegFI || - IsISRRegFI) - FrameReg = ABI.GetStackPtr(); - else if (RegInfo->needsStackRealignment(MF)) { - if (MFI.hasVarSizedObjects() && !MFI.isFixedObjectIndex(FrameIndex)) - FrameReg = ABI.GetBasePtr(); - else if (MFI.isFixedObjectIndex(FrameIndex)) - FrameReg = getFrameRegister(MF); - else - FrameReg = ABI.GetStackPtr(); - } else - FrameReg = getFrameRegister(MF); - - // Calculate final offset. - // - There is no need to change the offset if the frame object is one of the - // following: an outgoing argument, pointer to a dynamically allocated - // stack space or a $gp restore location, - // - If the frame object is any of the following, its offset must be adjusted - // by adding the size of the stack: - // incoming argument, callee-saved register location or local variable. - bool IsKill = false; - int64_t Offset; - - Offset = SPOffset + (int64_t)StackSize; - Offset += MI.getOperand(OpNo + 1).getImm(); - - LLVM_DEBUG(errs() << "Offset : " << Offset << "\n" - << "<--------->\n"); - - if (!MI.isDebugValue()) { - // Make sure Offset fits within the field available. - // For MSA instructions, this is a 10-bit signed immediate (scaled by - // element size), otherwise it is a 16-bit signed immediate. - unsigned OffsetBitSize = - getLoadStoreOffsetSizeInBits(MI.getOpcode(), MI.getOperand(OpNo - 1)); - unsigned OffsetAlign = getLoadStoreOffsetAlign(MI.getOpcode()); - - if (OffsetBitSize < 16 && isInt<16>(Offset) && - (!isIntN(OffsetBitSize, Offset) || - OffsetToAlignment(Offset, OffsetAlign) != 0)) { - // If we have an offset that needs to fit into a signed n-bit immediate - // (where n < 16) and doesn't, but does fit into 16-bits then use an ADDiu - MachineBasicBlock &MBB = *MI.getParent(); - DebugLoc DL = II->getDebugLoc(); - const TargetRegisterClass *PtrRC = - ABI.ArePtrs64bit() ? &Mips::GPR64RegClass : &Mips::GPR32RegClass; - MachineRegisterInfo &RegInfo = MBB.getParent()->getRegInfo(); - unsigned Reg = RegInfo.createVirtualRegister(PtrRC); - const MipsSEInstrInfo &TII = - *static_cast<const MipsSEInstrInfo *>( - MBB.getParent()->getSubtarget().getInstrInfo()); - BuildMI(MBB, II, DL, TII.get(ABI.GetPtrAddiuOp()), Reg) - .addReg(FrameReg) - .addImm(Offset); - - FrameReg = Reg; - Offset = 0; - IsKill = true; - } else if (!isInt<16>(Offset)) { - // Otherwise split the offset into 16-bit pieces and add it in multiple - // instructions. - MachineBasicBlock &MBB = *MI.getParent(); - DebugLoc DL = II->getDebugLoc(); - unsigned NewImm = 0; - const MipsSEInstrInfo &TII = - *static_cast<const MipsSEInstrInfo *>( - MBB.getParent()->getSubtarget().getInstrInfo()); - unsigned Reg = TII.loadImmediate(Offset, MBB, II, DL, - OffsetBitSize == 16 ? &NewImm : nullptr); - BuildMI(MBB, II, DL, TII.get(ABI.GetPtrAdduOp()), Reg).addReg(FrameReg) - .addReg(Reg, RegState::Kill); - - FrameReg = Reg; - Offset = SignExtend64<16>(NewImm); - IsKill = true; - } - } - - MI.getOperand(OpNo).ChangeToRegister(FrameReg, false, false, IsKill); - MI.getOperand(OpNo + 1).ChangeToImmediate(Offset); -} diff --git a/contrib/llvm/lib/Target/Mips/MipsSERegisterInfo.h b/contrib/llvm/lib/Target/Mips/MipsSERegisterInfo.h deleted file mode 100644 index 82ddf40f56a7..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsSERegisterInfo.h +++ /dev/null @@ -1,40 +0,0 @@ -//===-- MipsSERegisterInfo.h - Mips32/64 Register Information ---*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains the Mips32/64 implementation of the TargetRegisterInfo -// class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_MIPS_MIPSSEREGISTERINFO_H -#define LLVM_LIB_TARGET_MIPS_MIPSSEREGISTERINFO_H - -#include "MipsRegisterInfo.h" - -namespace llvm { -class MipsSEInstrInfo; - -class MipsSERegisterInfo : public MipsRegisterInfo { -public: - MipsSERegisterInfo(); - - bool requiresRegisterScavenging(const MachineFunction &MF) const override; - - bool requiresFrameIndexScavenging(const MachineFunction &MF) const override; - - const TargetRegisterClass *intRegClass(unsigned Size) const override; - -private: - void eliminateFI(MachineBasicBlock::iterator II, unsigned OpNo, - int FrameIndex, uint64_t StackSize, - int64_t SPOffset) const override; -}; - -} // end namespace llvm - -#endif diff --git a/contrib/llvm/lib/Target/Mips/MipsSchedule.td b/contrib/llvm/lib/Target/Mips/MipsSchedule.td deleted file mode 100644 index 0c0ddeab22c4..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsSchedule.td +++ /dev/null @@ -1,737 +0,0 @@ -//===-- MipsSchedule.td - Mips Scheduling Definitions ------*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// Functional units across Mips chips sets. Based on GCC/Mips backend files. -//===----------------------------------------------------------------------===// -def ALU : FuncUnit; -def IMULDIV : FuncUnit; - -//===----------------------------------------------------------------------===// -// Instruction Itinerary classes used for Mips -//===----------------------------------------------------------------------===// -// IIM16Alu is a placeholder class for most MIPS16 instructions. -def IIM16Alu : InstrItinClass; -def IIPseudo : InstrItinClass; - -def II_ABS : InstrItinClass; -def II_ADDI : InstrItinClass; -def II_ADDIU : InstrItinClass; -def II_ADDIUPC : InstrItinClass; -def II_ADD : InstrItinClass; -def II_ADDU : InstrItinClass; -def II_ADD_D : InstrItinClass; -def II_ADD_S : InstrItinClass; -def II_ALIGN : InstrItinClass; -def II_AND : InstrItinClass; -def II_ANDI : InstrItinClass; -def II_ALUIPC : InstrItinClass; -def II_AUI : InstrItinClass; -def II_AUIPC : InstrItinClass; -def II_B : InstrItinClass; -def II_BADDU : InstrItinClass; -def II_BBIT : InstrItinClass; // bbit[01], bbit[01]32 -def II_BALC : InstrItinClass; -def II_BC : InstrItinClass; -def II_BC1F : InstrItinClass; -def II_BC1FL : InstrItinClass; -def II_BC1T : InstrItinClass; -def II_BC1TL : InstrItinClass; -def II_BC1CCZ : InstrItinClass; -def II_BC2CCZ : InstrItinClass; -def II_BCC : InstrItinClass; // beq and bne -def II_BCCZ : InstrItinClass; // b[gl][et]z -def II_BCCC : InstrItinClass; // b<cc>c -def II_BCCZAL : InstrItinClass; // bgezal and bltzal -def II_BCCZALS : InstrItinClass; // bgezals and bltzals -def II_BCCZC : InstrItinClass; // beqzc, bnezc -def II_BITSWAP : InstrItinClass; -def II_CEIL : InstrItinClass; -def II_CFC1 : InstrItinClass; -def II_CFC2 : InstrItinClass; -def II_CLO : InstrItinClass; -def II_CLZ : InstrItinClass; -def II_CRC32B : InstrItinClass; -def II_CRC32CB : InstrItinClass; -def II_CRC32CD : InstrItinClass; -def II_CRC32CH : InstrItinClass; -def II_CRC32CW : InstrItinClass; -def II_CRC32D : InstrItinClass; -def II_CRC32H : InstrItinClass; -def II_CRC32W : InstrItinClass; -def II_CTC1 : InstrItinClass; -def II_CTC2 : InstrItinClass; -def II_CVT : InstrItinClass; -def II_C_CC_D : InstrItinClass; // Any c.<cc>.d instruction -def II_C_CC_S : InstrItinClass; // Any c.<cc>.s instruction -def II_CMP_CC_D : InstrItinClass; // Any cmp.<cc>.d instruction -def II_CMP_CC_S : InstrItinClass; // Any cmp.<cc>.s instruction -def II_CLASS_D : InstrItinClass; -def II_CLASS_S : InstrItinClass; -def II_DADDIU : InstrItinClass; -def II_DADDU : InstrItinClass; -def II_DADDI : InstrItinClass; -def II_DADD : InstrItinClass; -def II_DAHI : InstrItinClass; -def II_DATI : InstrItinClass; -def II_DAUI : InstrItinClass; -def II_DALIGN : InstrItinClass; -def II_DBITSWAP : InstrItinClass; -def II_DCLO : InstrItinClass; -def II_DCLZ : InstrItinClass; -def II_DDIV : InstrItinClass; -def II_DDIVU : InstrItinClass; -def II_DIV : InstrItinClass; -def II_DIVU : InstrItinClass; -def II_DIV_D : InstrItinClass; -def II_DIV_S : InstrItinClass; -def II_DMFC0 : InstrItinClass; -def II_DMFGC0 : InstrItinClass; -def II_DMT : InstrItinClass; -def II_DMTC0 : InstrItinClass; -def II_DMTGC0 : InstrItinClass; -def II_DMFC1 : InstrItinClass; -def II_DMTC1 : InstrItinClass; -def II_DMOD : InstrItinClass; -def II_DMODU : InstrItinClass; -def II_DMUH : InstrItinClass; -def II_DMUHU : InstrItinClass; -def II_DMFC2 : InstrItinClass; -def II_DMTC2 : InstrItinClass; -def II_DMUL : InstrItinClass; -def II_DMULU : InstrItinClass; -def II_DMULT : InstrItinClass; -def II_DMULTU : InstrItinClass; -def II_DROTR : InstrItinClass; -def II_DROTR32 : InstrItinClass; -def II_DROTRV : InstrItinClass; -def II_DSLL : InstrItinClass; -def II_DSLL32 : InstrItinClass; -def II_DSLLV : InstrItinClass; -def II_DSRA : InstrItinClass; -def II_DSRA32 : InstrItinClass; -def II_DSRAV : InstrItinClass; -def II_DSRL : InstrItinClass; -def II_DSRL32 : InstrItinClass; -def II_DSRLV : InstrItinClass; -def II_DSBH : InstrItinClass; -def II_DSHD : InstrItinClass; -def II_DSUBU : InstrItinClass; -def II_DSUB : InstrItinClass; -def II_DVPE : InstrItinClass; -def II_EMT : InstrItinClass; -def II_EVPE : InstrItinClass; -def II_EXT : InstrItinClass; // Any EXT instruction -def II_FLOOR : InstrItinClass; -def II_FORK : InstrItinClass; -def II_GINVI : InstrItinClass; -def II_GINVT : InstrItinClass; -def II_HYPCALL : InstrItinClass; -def II_INS : InstrItinClass; // Any INS instruction -def II_IndirectBranchPseudo : InstrItinClass; // Indirect branch pseudo. -def II_J : InstrItinClass; -def II_JAL : InstrItinClass; -def II_JALR : InstrItinClass; -def II_JALR_HB : InstrItinClass; -def II_JALRC : InstrItinClass; -def II_JALRS : InstrItinClass; -def II_JALS : InstrItinClass; -def II_JIC : InstrItinClass; -def II_JIALC : InstrItinClass; -def II_JR : InstrItinClass; -def II_JR_HB : InstrItinClass; -def II_JRADDIUSP : InstrItinClass; -def II_JRC : InstrItinClass; -def II_ReturnPseudo : InstrItinClass; // Return pseudo. -def II_ERET : InstrItinClass; -def II_DERET : InstrItinClass; -def II_ERETNC : InstrItinClass; -def II_EHB : InstrItinClass; -def II_SDBBP : InstrItinClass; -def II_SIGRIE : InstrItinClass; -def II_SSNOP : InstrItinClass; -def II_SYSCALL : InstrItinClass; -def II_PAUSE : InstrItinClass; -def II_WAIT : InstrItinClass; -def II_EI : InstrItinClass; -def II_DI : InstrItinClass; -def II_TEQ : InstrItinClass; -def II_TEQI : InstrItinClass; -def II_TGE : InstrItinClass; -def II_TGEI : InstrItinClass; -def II_TGEIU : InstrItinClass; -def II_TGEU : InstrItinClass; -def II_TNE : InstrItinClass; -def II_TNEI : InstrItinClass; -def II_TLT : InstrItinClass; -def II_TLTI : InstrItinClass; -def II_TLTU : InstrItinClass; -def II_TTLTIU : InstrItinClass; -def II_TLBP : InstrItinClass; -def II_TLBR : InstrItinClass; -def II_TLBWI : InstrItinClass; -def II_TLBWR : InstrItinClass; -def II_TRAP : InstrItinClass; -def II_BREAK : InstrItinClass; -def II_SYNC : InstrItinClass; -def II_SYNCI : InstrItinClass; -def II_LB : InstrItinClass; -def II_LBE : InstrItinClass; -def II_LBU : InstrItinClass; -def II_LBUE : InstrItinClass; -def II_LD : InstrItinClass; -def II_LDC1 : InstrItinClass; -def II_LDC2 : InstrItinClass; -def II_LDC3 : InstrItinClass; -def II_LDL : InstrItinClass; -def II_LDR : InstrItinClass; -def II_LDPC : InstrItinClass; -def II_LDXC1 : InstrItinClass; -def II_LH : InstrItinClass; -def II_LHE : InstrItinClass; -def II_LHU : InstrItinClass; -def II_LHUE : InstrItinClass; -def II_LL : InstrItinClass; -def II_LI : InstrItinClass; -def II_LLD : InstrItinClass; -def II_LUI : InstrItinClass; -def II_LUXC1 : InstrItinClass; -def II_LW : InstrItinClass; -def II_LWE : InstrItinClass; -def II_LWC1 : InstrItinClass; -def II_LWC2 : InstrItinClass; -def II_LWC3 : InstrItinClass; -def II_LWM : InstrItinClass; -def II_LWL : InstrItinClass; -def II_LWLE : InstrItinClass; -def II_LWPC : InstrItinClass; -def II_LWP : InstrItinClass; -def II_LWR : InstrItinClass; -def II_LWRE : InstrItinClass; -def II_LWU : InstrItinClass; -def II_LWUPC : InstrItinClass; -def II_LWXC1 : InstrItinClass; -def II_LWXS : InstrItinClass; -def II_LSA : InstrItinClass; -def II_DLSA : InstrItinClass; -def II_MADD : InstrItinClass; -def II_MADDU : InstrItinClass; -def II_MADD_D : InstrItinClass; -def II_MADD_S : InstrItinClass; -def II_MADDF_D : InstrItinClass; -def II_MADDF_S : InstrItinClass; -def II_MAX_D : InstrItinClass; -def II_MAX_S : InstrItinClass; -def II_MAXA_D : InstrItinClass; -def II_MAXA_S : InstrItinClass; -def II_MIN_D : InstrItinClass; -def II_MIN_S : InstrItinClass; -def II_MINA_D : InstrItinClass; -def II_MINA_S : InstrItinClass; -def II_MFC0 : InstrItinClass; -def II_MFHC0 : InstrItinClass; -def II_MFC1 : InstrItinClass; -def II_MFHC1 : InstrItinClass; -def II_MFC2 : InstrItinClass; -def II_MFGC0 : InstrItinClass; -def II_MFHGC0 : InstrItinClass; -def II_MFHI_MFLO : InstrItinClass; // mfhi and mflo -def II_MFTR : InstrItinClass; -def II_MOD : InstrItinClass; -def II_MODU : InstrItinClass; -def II_MOVE : InstrItinClass; -def II_MOVF : InstrItinClass; -def II_MOVF_D : InstrItinClass; -def II_MOVF_S : InstrItinClass; -def II_MOVN : InstrItinClass; -def II_MOVN_D : InstrItinClass; -def II_MOVN_S : InstrItinClass; -def II_MOVT : InstrItinClass; -def II_MOVT_D : InstrItinClass; -def II_MOVT_S : InstrItinClass; -def II_MOVZ : InstrItinClass; -def II_MOVZ_D : InstrItinClass; -def II_MOVZ_S : InstrItinClass; -def II_MOV_D : InstrItinClass; -def II_MOV_S : InstrItinClass; -def II_MSUB : InstrItinClass; -def II_MSUBU : InstrItinClass; -def II_MSUB_D : InstrItinClass; -def II_MSUB_S : InstrItinClass; -def II_MSUBF_D : InstrItinClass; -def II_MSUBF_S : InstrItinClass; -def II_MTC0 : InstrItinClass; -def II_MTHC0 : InstrItinClass; -def II_MTC1 : InstrItinClass; -def II_MTHC1 : InstrItinClass; -def II_MTC2 : InstrItinClass; -def II_MTGC0 : InstrItinClass; -def II_MTHGC0 : InstrItinClass; -def II_MTHI_MTLO : InstrItinClass; // mthi and mtlo -def II_MTTR : InstrItinClass; -def II_MUL : InstrItinClass; -def II_MUH : InstrItinClass; -def II_MUHU : InstrItinClass; -def II_MULU : InstrItinClass; -def II_MULT : InstrItinClass; -def II_MULTU : InstrItinClass; -def II_MUL_D : InstrItinClass; -def II_MUL_S : InstrItinClass; -def II_NEG : InstrItinClass; -def II_NMADD_D : InstrItinClass; -def II_NMADD_S : InstrItinClass; -def II_NMSUB_D : InstrItinClass; -def II_NMSUB_S : InstrItinClass; -def II_NOR : InstrItinClass; -def II_NOT : InstrItinClass; -def II_OR : InstrItinClass; -def II_ORI : InstrItinClass; -def II_POP : InstrItinClass; -def II_RDHWR : InstrItinClass; -def II_RESTORE : InstrItinClass; -def II_RECIP_S : InstrItinClass; -def II_RECIP_D : InstrItinClass; -def II_RINT_S : InstrItinClass; -def II_RINT_D : InstrItinClass; -def II_ROTR : InstrItinClass; -def II_ROTRV : InstrItinClass; -def II_ROUND : InstrItinClass; -def II_RSQRT_S : InstrItinClass; -def II_RSQRT_D : InstrItinClass; -def II_SAVE : InstrItinClass; -def II_SC : InstrItinClass; -def II_SCD : InstrItinClass; -def II_SB : InstrItinClass; -def II_SBE : InstrItinClass; -def II_SD : InstrItinClass; -def II_SDC1 : InstrItinClass; -def II_SDC2 : InstrItinClass; -def II_SDC3 : InstrItinClass; -def II_SDL : InstrItinClass; -def II_SDR : InstrItinClass; -def II_SDXC1 : InstrItinClass; -def II_SEB : InstrItinClass; -def II_SEH : InstrItinClass; -def II_SELCCZ : InstrItinClass; -def II_SELCCZ_D : InstrItinClass; -def II_SELCCZ_S : InstrItinClass; -def II_SEQ_SNE : InstrItinClass; // seq and sne -def II_SEQI_SNEI : InstrItinClass; // seqi and snei -def II_SH : InstrItinClass; -def II_SHE : InstrItinClass; -def II_SLL : InstrItinClass; -def II_SLLV : InstrItinClass; -def II_SLTI_SLTIU : InstrItinClass; // slti and sltiu -def II_SLT_SLTU : InstrItinClass; // slt and sltu -def II_SQRT_D : InstrItinClass; -def II_SQRT_S : InstrItinClass; -def II_SEL_D : InstrItinClass; -def II_SEL_S : InstrItinClass; -def II_SRA : InstrItinClass; -def II_SRAV : InstrItinClass; -def II_SRL : InstrItinClass; -def II_SRLV : InstrItinClass; -def II_SUB : InstrItinClass; -def II_SUBU : InstrItinClass; -def II_SUB_D : InstrItinClass; -def II_SUB_S : InstrItinClass; -def II_SUXC1 : InstrItinClass; -def II_SW : InstrItinClass; -def II_SWE : InstrItinClass; -def II_SWC1 : InstrItinClass; -def II_SWC2 : InstrItinClass; -def II_SWC3 : InstrItinClass; -def II_SWL : InstrItinClass; -def II_SWLE : InstrItinClass; -def II_SWM : InstrItinClass; -def II_SWP : InstrItinClass; -def II_SWR : InstrItinClass; -def II_SWRE : InstrItinClass; -def II_SWXC1 : InstrItinClass; -def II_TRUNC : InstrItinClass; -def II_WSBH : InstrItinClass; -def II_XOR : InstrItinClass; -def II_XORI : InstrItinClass; -def II_CACHE : InstrItinClass; -def II_PREF : InstrItinClass; -def II_CACHEE : InstrItinClass; -def II_PREFE : InstrItinClass; -def II_LLE : InstrItinClass; -def II_SCE : InstrItinClass; -def II_TLBGINV : InstrItinClass; -def II_TLBGINVF : InstrItinClass; -def II_TLBGP : InstrItinClass; -def II_TLBGR : InstrItinClass; -def II_TLBGWI : InstrItinClass; -def II_TLBGWR : InstrItinClass; -def II_TLBINV : InstrItinClass; -def II_TLBINVF : InstrItinClass; -def II_WRPGPR : InstrItinClass; -def II_RDPGPR : InstrItinClass; -def II_DVP : InstrItinClass; -def II_EVP : InstrItinClass; -def II_YIELD : InstrItinClass; - -//===----------------------------------------------------------------------===// -// Mips Generic instruction itineraries. -//===----------------------------------------------------------------------===// -def MipsGenericItineraries : ProcessorItineraries<[ALU, IMULDIV], [], [ - InstrItinData<IIM16Alu , [InstrStage<1, [ALU]>]>, - InstrItinData<II_ADDI , [InstrStage<1, [ALU]>]>, - InstrItinData<II_ADDIU , [InstrStage<1, [ALU]>]>, - InstrItinData<II_ADDIUPC , [InstrStage<1, [ALU]>]>, - InstrItinData<II_ADD , [InstrStage<1, [ALU]>]>, - InstrItinData<II_ADDU , [InstrStage<1, [ALU]>]>, - InstrItinData<II_AUI , [InstrStage<1, [ALU]>]>, - InstrItinData<II_AND , [InstrStage<1, [ALU]>]>, - InstrItinData<II_ALUIPC , [InstrStage<1, [ALU]>]>, - InstrItinData<II_AUIPC , [InstrStage<1, [ALU]>]>, - InstrItinData<II_ALIGN , [InstrStage<1, [ALU]>]>, - InstrItinData<II_BADDU , [InstrStage<1, [ALU]>]>, - InstrItinData<II_BITSWAP , [InstrStage<1, [ALU]>]>, - InstrItinData<II_SLL , [InstrStage<1, [ALU]>]>, - InstrItinData<II_SRA , [InstrStage<1, [ALU]>]>, - InstrItinData<II_SRL , [InstrStage<1, [ALU]>]>, - InstrItinData<II_ROTR , [InstrStage<1, [ALU]>]>, - InstrItinData<II_SLLV , [InstrStage<1, [ALU]>]>, - InstrItinData<II_SRAV , [InstrStage<1, [ALU]>]>, - InstrItinData<II_SRLV , [InstrStage<1, [ALU]>]>, - InstrItinData<II_ROTRV , [InstrStage<1, [ALU]>]>, - InstrItinData<II_CLO , [InstrStage<1, [ALU]>]>, - InstrItinData<II_CLZ , [InstrStage<1, [ALU]>]>, - InstrItinData<II_DADDIU , [InstrStage<1, [ALU]>]>, - InstrItinData<II_DADDU , [InstrStage<1, [ALU]>]>, - InstrItinData<II_DADDI , [InstrStage<1, [ALU]>]>, - InstrItinData<II_DADD , [InstrStage<1, [ALU]>]>, - InstrItinData<II_DALIGN , [InstrStage<1, [ALU]>]>, - InstrItinData<II_DAHI , [InstrStage<1, [ALU]>]>, - InstrItinData<II_DATI , [InstrStage<1, [ALU]>]>, - InstrItinData<II_DAUI , [InstrStage<1, [ALU]>]>, - InstrItinData<II_DBITSWAP , [InstrStage<1, [ALU]>]>, - InstrItinData<II_DCLO , [InstrStage<1, [ALU]>]>, - InstrItinData<II_DCLZ , [InstrStage<1, [ALU]>]>, - InstrItinData<II_DMOD , [InstrStage<17, [IMULDIV]>]>, - InstrItinData<II_DMODU , [InstrStage<17, [IMULDIV]>]>, - InstrItinData<II_DMT , [InstrStage<2, [ALU]>]>, - InstrItinData<II_DSLL , [InstrStage<1, [ALU]>]>, - InstrItinData<II_DSLL32 , [InstrStage<1, [ALU]>]>, - InstrItinData<II_DSRL , [InstrStage<1, [ALU]>]>, - InstrItinData<II_DSRL32 , [InstrStage<1, [ALU]>]>, - InstrItinData<II_DSRA , [InstrStage<1, [ALU]>]>, - InstrItinData<II_DSRA32 , [InstrStage<1, [ALU]>]>, - InstrItinData<II_DSLLV , [InstrStage<1, [ALU]>]>, - InstrItinData<II_DSRLV , [InstrStage<1, [ALU]>]>, - InstrItinData<II_DSRAV , [InstrStage<1, [ALU]>]>, - InstrItinData<II_DSUBU , [InstrStage<1, [ALU]>]>, - InstrItinData<II_DSUB , [InstrStage<1, [ALU]>]>, - InstrItinData<II_DROTR , [InstrStage<1, [ALU]>]>, - InstrItinData<II_DROTR32 , [InstrStage<1, [ALU]>]>, - InstrItinData<II_DROTRV , [InstrStage<1, [ALU]>]>, - InstrItinData<II_DSBH , [InstrStage<1, [ALU]>]>, - InstrItinData<II_DSHD , [InstrStage<1, [ALU]>]>, - InstrItinData<II_DCLO , [InstrStage<1, [ALU]>]>, - InstrItinData<II_DCLZ , [InstrStage<1, [ALU]>]>, - InstrItinData<II_DVPE , [InstrStage<2, [ALU]>]>, - InstrItinData<II_EMT , [InstrStage<2, [ALU]>]>, - InstrItinData<II_EVPE , [InstrStage<2, [ALU]>]>, - InstrItinData<II_EXT , [InstrStage<1, [ALU]>]>, - InstrItinData<II_FORK , [InstrStage<1, [ALU]>]>, - InstrItinData<II_INS , [InstrStage<1, [ALU]>]>, - InstrItinData<II_LUI , [InstrStage<1, [ALU]>]>, - InstrItinData<II_MOVE , [InstrStage<1, [ALU]>]>, - InstrItinData<II_MOVF , [InstrStage<1, [ALU]>]>, - InstrItinData<II_MOVN , [InstrStage<1, [ALU]>]>, - InstrItinData<II_MOVN_S , [InstrStage<1, [ALU]>]>, - InstrItinData<II_MOVN_D , [InstrStage<1, [ALU]>]>, - InstrItinData<II_MOVT , [InstrStage<1, [ALU]>]>, - InstrItinData<II_MOVZ , [InstrStage<1, [ALU]>]>, - InstrItinData<II_NOR , [InstrStage<1, [ALU]>]>, - InstrItinData<II_NOT , [InstrStage<1, [ALU]>]>, - InstrItinData<II_OR , [InstrStage<1, [ALU]>]>, - InstrItinData<II_POP , [InstrStage<1, [ALU]>]>, - InstrItinData<II_RDHWR , [InstrStage<1, [ALU]>]>, - InstrItinData<II_SUB , [InstrStage<1, [ALU]>]>, - InstrItinData<II_SUBU , [InstrStage<1, [ALU]>]>, - InstrItinData<II_XOR , [InstrStage<1, [ALU]>]>, - InstrItinData<II_ANDI , [InstrStage<1, [ALU]>]>, - InstrItinData<II_ORI , [InstrStage<1, [ALU]>]>, - InstrItinData<II_XORI , [InstrStage<1, [ALU]>]>, - InstrItinData<II_LB , [InstrStage<3, [ALU]>]>, - InstrItinData<II_LBE , [InstrStage<3, [ALU]>]>, - InstrItinData<II_LBU , [InstrStage<3, [ALU]>]>, - InstrItinData<II_LBUE , [InstrStage<3, [ALU]>]>, - InstrItinData<II_LH , [InstrStage<3, [ALU]>]>, - InstrItinData<II_LHU , [InstrStage<3, [ALU]>]>, - InstrItinData<II_LHUE , [InstrStage<3, [ALU]>]>, - InstrItinData<II_LW , [InstrStage<3, [ALU]>]>, - InstrItinData<II_LWM , [InstrStage<3, [ALU]>]>, - InstrItinData<II_LWP , [InstrStage<3, [ALU]>]>, - InstrItinData<II_LWPC , [InstrStage<3, [ALU]>]>, - InstrItinData<II_LWL , [InstrStage<3, [ALU]>]>, - InstrItinData<II_LWLE , [InstrStage<3, [ALU]>]>, - InstrItinData<II_LWR , [InstrStage<3, [ALU]>]>, - InstrItinData<II_LWRE , [InstrStage<3, [ALU]>]>, - InstrItinData<II_LWUPC , [InstrStage<3, [ALU]>]>, - InstrItinData<II_LD , [InstrStage<3, [ALU]>]>, - InstrItinData<II_LDL , [InstrStage<3, [ALU]>]>, - InstrItinData<II_LDR , [InstrStage<3, [ALU]>]>, - InstrItinData<II_LDPC , [InstrStage<3, [ALU]>]>, - InstrItinData<II_LI , [InstrStage<1, [ALU]>]>, - InstrItinData<II_LL , [InstrStage<3, [ALU]>]>, - InstrItinData<II_LLD , [InstrStage<3, [ALU]>]>, - InstrItinData<II_RESTORE , [InstrStage<3, [ALU]>]>, - InstrItinData<II_SB , [InstrStage<1, [ALU]>]>, - InstrItinData<II_SH , [InstrStage<1, [ALU]>]>, - InstrItinData<II_SHE , [InstrStage<1, [ALU]>]>, - InstrItinData<II_SW , [InstrStage<1, [ALU]>]>, - InstrItinData<II_SWM , [InstrStage<1, [ALU]>]>, - InstrItinData<II_SWL , [InstrStage<1, [ALU]>]>, - InstrItinData<II_SWR , [InstrStage<1, [ALU]>]>, - InstrItinData<II_SWP , [InstrStage<1, [ALU]>]>, - InstrItinData<II_SDL , [InstrStage<1, [ALU]>]>, - InstrItinData<II_SDR , [InstrStage<1, [ALU]>]>, - InstrItinData<II_SD , [InstrStage<1, [ALU]>]>, - InstrItinData<II_SC , [InstrStage<1, [ALU]>]>, - InstrItinData<II_SCD , [InstrStage<1, [ALU]>]>, - InstrItinData<II_SAVE , [InstrStage<1, [ALU]>]>, - InstrItinData<II_SELCCZ_S , [InstrStage<1, [ALU]>]>, - InstrItinData<II_SELCCZ_D , [InstrStage<1, [ALU]>]>, - InstrItinData<II_SEQ_SNE , [InstrStage<1, [ALU]>]>, - InstrItinData<II_SEQI_SNEI , [InstrStage<1, [ALU]>]>, - InstrItinData<II_SLTI_SLTIU , [InstrStage<1, [ALU]>]>, - InstrItinData<II_SLT_SLTU , [InstrStage<1, [ALU]>]>, - InstrItinData<II_B , [InstrStage<1, [ALU]>]>, - InstrItinData<II_BALC , [InstrStage<1, [ALU]>]>, - InstrItinData<II_BBIT , [InstrStage<1, [ALU]>]>, - InstrItinData<II_BC , [InstrStage<1, [ALU]>]>, - InstrItinData<II_BC1F , [InstrStage<1, [ALU]>]>, - InstrItinData<II_BC1FL , [InstrStage<1, [ALU]>]>, - InstrItinData<II_BC1T , [InstrStage<1, [ALU]>]>, - InstrItinData<II_BC1TL , [InstrStage<1, [ALU]>]>, - InstrItinData<II_BC1CCZ , [InstrStage<1, [ALU]>]>, - InstrItinData<II_BC2CCZ , [InstrStage<1, [ALU]>]>, - InstrItinData<II_BCC , [InstrStage<1, [ALU]>]>, - InstrItinData<II_BCCC , [InstrStage<1, [ALU]>]>, - InstrItinData<II_BCCZ , [InstrStage<1, [ALU]>]>, - InstrItinData<II_BCCZAL , [InstrStage<1, [ALU]>]>, - InstrItinData<II_BCCZALS , [InstrStage<1, [ALU]>]>, - InstrItinData<II_BCCZC , [InstrStage<1, [ALU]>]>, - InstrItinData<II_CLASS_D , [InstrStage<1, [ALU]>]>, - InstrItinData<II_CLASS_S , [InstrStage<1, [ALU]>]>, - InstrItinData<II_IndirectBranchPseudo, [InstrStage<1, [ALU]>]>, - InstrItinData<II_J , [InstrStage<1, [ALU]>]>, - InstrItinData<II_JAL , [InstrStage<1, [ALU]>]>, - InstrItinData<II_JALR , [InstrStage<1, [ALU]>]>, - InstrItinData<II_JALR_HB , [InstrStage<1, [ALU]>]>, - InstrItinData<II_JALRC , [InstrStage<1, [ALU]>]>, - InstrItinData<II_JALRS , [InstrStage<1, [ALU]>]>, - InstrItinData<II_JALS , [InstrStage<1, [ALU]>]>, - InstrItinData<II_JIC , [InstrStage<1, [ALU]>]>, - InstrItinData<II_JIALC , [InstrStage<1, [ALU]>]>, - InstrItinData<II_JR , [InstrStage<1, [ALU]>]>, - InstrItinData<II_JR_HB , [InstrStage<1, [ALU]>]>, - InstrItinData<II_JRADDIUSP , [InstrStage<1, [ALU]>]>, - InstrItinData<II_JRC , [InstrStage<1, [ALU]>]>, - InstrItinData<II_ReturnPseudo , [InstrStage<1, [ALU]>]>, - InstrItinData<IIPseudo , [InstrStage<1, [ALU]>]>, - InstrItinData<II_DMUH , [InstrStage<17, [IMULDIV]>]>, - InstrItinData<II_DMUHU , [InstrStage<17, [IMULDIV]>]>, - InstrItinData<II_ERET , [InstrStage<1, [ALU]>]>, - InstrItinData<II_DERET , [InstrStage<1, [ALU]>]>, - InstrItinData<II_ERETNC , [InstrStage<1, [ALU]>]>, - InstrItinData<II_EHB , [InstrStage<1, [ALU]>]>, - InstrItinData<II_SDBBP , [InstrStage<1, [ALU]>]>, - InstrItinData<II_SIGRIE , [InstrStage<1, [ALU]>]>, - InstrItinData<II_SSNOP , [InstrStage<1, [ALU]>]>, - InstrItinData<II_SYSCALL , [InstrStage<1, [ALU]>]>, - InstrItinData<II_PAUSE , [InstrStage<1, [ALU]>]>, - InstrItinData<II_WAIT , [InstrStage<1, [ALU]>]>, - InstrItinData<II_EI , [InstrStage<1, [ALU]>]>, - InstrItinData<II_DI , [InstrStage<1, [ALU]>]>, - InstrItinData<II_TEQ , [InstrStage<1, [ALU]>]>, - InstrItinData<II_TEQI , [InstrStage<1, [ALU]>]>, - InstrItinData<II_TGE , [InstrStage<1, [ALU]>]>, - InstrItinData<II_TGEI , [InstrStage<1, [ALU]>]>, - InstrItinData<II_TGEIU , [InstrStage<1, [ALU]>]>, - InstrItinData<II_TGEU , [InstrStage<1, [ALU]>]>, - InstrItinData<II_TNE , [InstrStage<1, [ALU]>]>, - InstrItinData<II_TNEI , [InstrStage<1, [ALU]>]>, - InstrItinData<II_TLT , [InstrStage<1, [ALU]>]>, - InstrItinData<II_TLTI , [InstrStage<1, [ALU]>]>, - InstrItinData<II_TLTU , [InstrStage<1, [ALU]>]>, - InstrItinData<II_TTLTIU , [InstrStage<1, [ALU]>]>, - InstrItinData<II_TLBP , [InstrStage<1, [ALU]>]>, - InstrItinData<II_TLBR , [InstrStage<1, [ALU]>]>, - InstrItinData<II_TLBWI , [InstrStage<1, [ALU]>]>, - InstrItinData<II_TLBWR , [InstrStage<1, [ALU]>]>, - InstrItinData<II_TRAP , [InstrStage<1, [ALU]>]>, - InstrItinData<II_BREAK , [InstrStage<1, [ALU]>]>, - InstrItinData<II_SYNC , [InstrStage<1, [ALU]>]>, - InstrItinData<II_SYNCI , [InstrStage<1, [ALU]>]>, - InstrItinData<II_DMUL , [InstrStage<17, [IMULDIV]>]>, - InstrItinData<II_DMULT , [InstrStage<17, [IMULDIV]>]>, - InstrItinData<II_DMULTU , [InstrStage<17, [IMULDIV]>]>, - InstrItinData<II_DMULU , [InstrStage<17, [IMULDIV]>]>, - InstrItinData<II_MADD , [InstrStage<17, [IMULDIV]>]>, - InstrItinData<II_MADDU , [InstrStage<17, [IMULDIV]>]>, - InstrItinData<II_MFHI_MFLO , [InstrStage<1, [IMULDIV]>]>, - InstrItinData<II_MAX_D , [InstrStage<4, [ALU]>]>, - InstrItinData<II_MAX_S , [InstrStage<4, [ALU]>]>, - InstrItinData<II_MAXA_D , [InstrStage<4, [ALU]>]>, - InstrItinData<II_MAXA_S , [InstrStage<4, [ALU]>]>, - InstrItinData<II_MIN_S , [InstrStage<4, [ALU]>]>, - InstrItinData<II_MIN_D , [InstrStage<4, [ALU]>]>, - InstrItinData<II_MINA_S , [InstrStage<4, [ALU]>]>, - InstrItinData<II_MINA_D , [InstrStage<4, [ALU]>]>, - InstrItinData<II_MOD , [InstrStage<38, [IMULDIV]>]>, - InstrItinData<II_MODU , [InstrStage<38, [IMULDIV]>]>, - InstrItinData<II_MSUB , [InstrStage<17, [IMULDIV]>]>, - InstrItinData<II_MSUBU , [InstrStage<17, [IMULDIV]>]>, - InstrItinData<II_MTHI_MTLO , [InstrStage<1, [IMULDIV]>]>, - InstrItinData<II_MUH , [InstrStage<17, [IMULDIV]>]>, - InstrItinData<II_MUHU , [InstrStage<17, [IMULDIV]>]>, - InstrItinData<II_MUL , [InstrStage<17, [IMULDIV]>]>, - InstrItinData<II_MULT , [InstrStage<17, [IMULDIV]>]>, - InstrItinData<II_MULTU , [InstrStage<17, [IMULDIV]>]>, - InstrItinData<II_MULU , [InstrStage<17, [IMULDIV]>]>, - InstrItinData<II_MSUB , [InstrStage<17, [IMULDIV]>]>, - InstrItinData<II_MSUBU , [InstrStage<17, [IMULDIV]>]>, - InstrItinData<II_DIV , [InstrStage<38, [IMULDIV]>]>, - InstrItinData<II_DIVU , [InstrStage<38, [IMULDIV]>]>, - InstrItinData<II_DDIV , [InstrStage<38, [IMULDIV]>]>, - InstrItinData<II_DDIVU , [InstrStage<38, [IMULDIV]>]>, - InstrItinData<II_CEIL , [InstrStage<1, [ALU]>]>, - InstrItinData<II_CVT , [InstrStage<1, [ALU]>]>, - InstrItinData<II_ABS , [InstrStage<1, [ALU]>]>, - InstrItinData<II_FLOOR , [InstrStage<1, [ALU]>]>, - InstrItinData<II_NEG , [InstrStage<1, [ALU]>]>, - InstrItinData<II_ROUND , [InstrStage<1, [ALU]>]>, - InstrItinData<II_TRUNC , [InstrStage<1, [ALU]>]>, - InstrItinData<II_MOV_D , [InstrStage<2, [ALU]>]>, - InstrItinData<II_MOV_S , [InstrStage<2, [ALU]>]>, - InstrItinData<II_CFC1 , [InstrStage<2, [ALU]>]>, - InstrItinData<II_CTC1 , [InstrStage<2, [ALU]>]>, - InstrItinData<II_CFC2 , [InstrStage<2, [ALU]>]>, - InstrItinData<II_CTC2 , [InstrStage<2, [ALU]>]>, - InstrItinData<II_MOVF_D , [InstrStage<2, [ALU]>]>, - InstrItinData<II_MOVF_S , [InstrStage<2, [ALU]>]>, - InstrItinData<II_MOVT_D , [InstrStage<2, [ALU]>]>, - InstrItinData<II_MOVT_S , [InstrStage<2, [ALU]>]>, - InstrItinData<II_MOVZ_D , [InstrStage<2, [ALU]>]>, - InstrItinData<II_MOVZ_S , [InstrStage<2, [ALU]>]>, - InstrItinData<II_C_CC_S , [InstrStage<3, [ALU]>]>, - InstrItinData<II_C_CC_D , [InstrStage<3, [ALU]>]>, - InstrItinData<II_CMP_CC_S , [InstrStage<3, [ALU]>]>, - InstrItinData<II_CMP_CC_D , [InstrStage<3, [ALU]>]>, - InstrItinData<II_ADD_D , [InstrStage<4, [ALU]>]>, - InstrItinData<II_ADD_S , [InstrStage<4, [ALU]>]>, - InstrItinData<II_SUB_D , [InstrStage<4, [ALU]>]>, - InstrItinData<II_SUB_S , [InstrStage<4, [ALU]>]>, - InstrItinData<II_MUL_S , [InstrStage<7, [ALU]>]>, - InstrItinData<II_MADD_S , [InstrStage<7, [ALU]>]>, - InstrItinData<II_MADDF_S , [InstrStage<7, [ALU]>]>, - InstrItinData<II_MSUB_S , [InstrStage<7, [ALU]>]>, - InstrItinData<II_MSUBF_S , [InstrStage<7, [ALU]>]>, - InstrItinData<II_NMADD_S , [InstrStage<7, [ALU]>]>, - InstrItinData<II_NMSUB_S , [InstrStage<7, [ALU]>]>, - InstrItinData<II_MUL_D , [InstrStage<8, [ALU]>]>, - InstrItinData<II_MADD_D , [InstrStage<8, [ALU]>]>, - InstrItinData<II_MADDF_D , [InstrStage<8, [ALU]>]>, - InstrItinData<II_MSUB_D , [InstrStage<8, [ALU]>]>, - InstrItinData<II_MSUBF_D , [InstrStage<8, [ALU]>]>, - InstrItinData<II_NMADD_D , [InstrStage<8, [ALU]>]>, - InstrItinData<II_NMSUB_D , [InstrStage<8, [ALU]>]>, - InstrItinData<II_DIV_S , [InstrStage<23, [ALU]>]>, - InstrItinData<II_DIV_D , [InstrStage<36, [ALU]>]>, - InstrItinData<II_RECIP_D , [InstrStage<25, [ALU]>]>, - InstrItinData<II_RECIP_S , [InstrStage<13, [ALU]>]>, - InstrItinData<II_RSQRT_D , [InstrStage<29, [ALU]>]>, - InstrItinData<II_RSQRT_S , [InstrStage<14, [ALU]>]>, - InstrItinData<II_RINT_D , [InstrStage<1, [ALU]>]>, - InstrItinData<II_RINT_S , [InstrStage<1, [ALU]>]>, - InstrItinData<II_SQRT_S , [InstrStage<54, [ALU]>]>, - InstrItinData<II_SQRT_D , [InstrStage<12, [ALU]>]>, - InstrItinData<II_SEL_D , [InstrStage<1, [ALU]>]>, - InstrItinData<II_SEL_S , [InstrStage<1, [ALU]>]>, - InstrItinData<II_WSBH , [InstrStage<1, [ALU]>]>, - InstrItinData<II_LSA , [InstrStage<1, [ALU]>]>, - InstrItinData<II_DLSA , [InstrStage<1, [ALU]>]>, - InstrItinData<II_LDC1 , [InstrStage<3, [ALU]>]>, - InstrItinData<II_LDC2 , [InstrStage<3, [ALU]>]>, - InstrItinData<II_LDC3 , [InstrStage<3, [ALU]>]>, - InstrItinData<II_LWC1 , [InstrStage<3, [ALU]>]>, - InstrItinData<II_LWC2 , [InstrStage<3, [ALU]>]>, - InstrItinData<II_LWC3 , [InstrStage<3, [ALU]>]>, - InstrItinData<II_LDXC1 , [InstrStage<3, [ALU]>]>, - InstrItinData<II_LWXC1 , [InstrStage<3, [ALU]>]>, - InstrItinData<II_LUXC1 , [InstrStage<3, [ALU]>]>, - InstrItinData<II_LWXS , [InstrStage<3, [ALU]>]>, - InstrItinData<II_SDC1 , [InstrStage<1, [ALU]>]>, - InstrItinData<II_SDC2 , [InstrStage<1, [ALU]>]>, - InstrItinData<II_SDC3 , [InstrStage<1, [ALU]>]>, - InstrItinData<II_SWC1 , [InstrStage<1, [ALU]>]>, - InstrItinData<II_SWC2 , [InstrStage<1, [ALU]>]>, - InstrItinData<II_SWC3 , [InstrStage<1, [ALU]>]>, - InstrItinData<II_SDXC1 , [InstrStage<1, [ALU]>]>, - InstrItinData<II_SWXC1 , [InstrStage<1, [ALU]>]>, - InstrItinData<II_SUXC1 , [InstrStage<1, [ALU]>]>, - InstrItinData<II_DMFC0 , [InstrStage<2, [ALU]>]>, - InstrItinData<II_DMFC1 , [InstrStage<2, [ALU]>]>, - InstrItinData<II_DMFC2 , [InstrStage<2, [ALU]>]>, - InstrItinData<II_DMTC0 , [InstrStage<2, [ALU]>]>, - InstrItinData<II_DMTC1 , [InstrStage<2, [ALU]>]>, - InstrItinData<II_DMTC2 , [InstrStage<2, [ALU]>]>, - InstrItinData<II_MFC0 , [InstrStage<2, [ALU]>]>, - InstrItinData<II_MFHC0 , [InstrStage<2, [ALU]>]>, - InstrItinData<II_MFC1 , [InstrStage<2, [ALU]>]>, - InstrItinData<II_MFC2 , [InstrStage<2, [ALU]>]>, - InstrItinData<II_MFTR , [InstrStage<2, [ALU]>]>, - InstrItinData<II_MTC0 , [InstrStage<2, [ALU]>]>, - InstrItinData<II_MTHC0 , [InstrStage<2, [ALU]>]>, - InstrItinData<II_MTC1 , [InstrStage<2, [ALU]>]>, - InstrItinData<II_MTC2 , [InstrStage<2, [ALU]>]>, - InstrItinData<II_MFHC1 , [InstrStage<2, [ALU]>]>, - InstrItinData<II_MTHC1 , [InstrStage<2, [ALU]>]>, - InstrItinData<II_MTTR , [InstrStage<2, [ALU]>]>, - InstrItinData<II_CACHE , [InstrStage<1, [ALU]>]>, - InstrItinData<II_PREF , [InstrStage<1, [ALU]>]>, - InstrItinData<II_CACHEE , [InstrStage<1, [ALU]>]>, - InstrItinData<II_PREFE , [InstrStage<1, [ALU]>]>, - InstrItinData<II_TLBINV , [InstrStage<1, [ALU]>]>, - InstrItinData<II_TLBINVF , [InstrStage<1, [ALU]>]>, - InstrItinData<II_LLE , [InstrStage<3, [ALU]>]>, - InstrItinData<II_SCE , [InstrStage<1, [ALU]>]>, - InstrItinData<II_WRPGPR , [InstrStage<1, [ALU]>]>, - InstrItinData<II_RDPGPR , [InstrStage<1, [ALU]>]>, - InstrItinData<II_DVP , [InstrStage<1, [ALU]>]>, - InstrItinData<II_EVP , [InstrStage<1, [ALU]>]>, - InstrItinData<II_YIELD , [InstrStage<5, [ALU]>]>, - InstrItinData<II_CRC32B , [InstrStage<1, [ALU]>]>, - InstrItinData<II_CRC32H , [InstrStage<1, [ALU]>]>, - InstrItinData<II_CRC32W , [InstrStage<1, [ALU]>]>, - InstrItinData<II_CRC32D , [InstrStage<1, [ALU]>]>, - InstrItinData<II_CRC32CB , [InstrStage<1, [ALU]>]>, - InstrItinData<II_CRC32CH , [InstrStage<1, [ALU]>]>, - InstrItinData<II_CRC32CW , [InstrStage<1, [ALU]>]>, - InstrItinData<II_CRC32CD , [InstrStage<1, [ALU]>]>, - InstrItinData<II_MFGC0 , [InstrStage<2, [ALU]>]>, - InstrItinData<II_MTGC0 , [InstrStage<2, [ALU]>]>, - InstrItinData<II_MFHGC0 , [InstrStage<2, [ALU]>]>, - InstrItinData<II_MTHGC0 , [InstrStage<2, [ALU]>]>, - InstrItinData<II_HYPCALL , [InstrStage<2, [ALU]>]>, - InstrItinData<II_TLBGINV , [InstrStage<2, [ALU]>]>, - InstrItinData<II_TLBGINVF , [InstrStage<2, [ALU]>]>, - InstrItinData<II_TLBGP , [InstrStage<2, [ALU]>]>, - InstrItinData<II_TLBGR , [InstrStage<2, [ALU]>]>, - InstrItinData<II_TLBWI , [InstrStage<2, [ALU]>]>, - InstrItinData<II_TLBWR , [InstrStage<2, [ALU]>]>, - InstrItinData<II_DMFGC0 , [InstrStage<2, [ALU]>]>, - InstrItinData<II_DMTGC0 , [InstrStage<2, [ALU]>]>, - InstrItinData<II_GINVI , [InstrStage<1, [ALU]>]>, - InstrItinData<II_GINVT , [InstrStage<1, [ALU]>]> -]>; diff --git a/contrib/llvm/lib/Target/Mips/MipsScheduleGeneric.td b/contrib/llvm/lib/Target/Mips/MipsScheduleGeneric.td deleted file mode 100644 index 08c6d3e79023..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsScheduleGeneric.td +++ /dev/null @@ -1,1619 +0,0 @@ -//=- MipsScheduleGeneric.td - Generic Scheduling Definitions -*- tablegen -*-=// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file describes the interAptiv processor in a manner of speaking. It -// describes a hypothetical version of the in-order MIPS32R2 interAptiv with all -// branches of the MIPS ISAs, ASEs and ISA variants. The itinerary lists are -// broken down into per ISA lists, so that this file can be used to rapidly -// develop new schedule models. -// -//===----------------------------------------------------------------------===// -def MipsGenericModel : SchedMachineModel { - int IssueWidth = 1; - int MicroOpBufferSize = 0; - - // These figures assume an L1 hit. - int LoadLatency = 2; - int MispredictPenalty = 4; - - int HighLatency = 37; - list<Predicate> UnsupportedFeatures = []; - - let CompleteModel = 1; - let PostRAScheduler = 1; - - // FIXME: Remove when all errors have been fixed. - let FullInstRWOverlapCheck = 1; -} - -let SchedModel = MipsGenericModel in { - -// ALU Pipeline -// ============ - -def GenericALU : ProcResource<1> { let BufferSize = 1; } -def GenericIssueALU : ProcResource<1> { let Super = GenericALU; } - -def GenericWriteALU : SchedWriteRes<[GenericIssueALU]>; - -// add, addi, addiu, addu, and, andi, clo, clz, ext, ins, lui, nor, or, ori, -// rotr, rotrv, seb, seh, sll, sllv, slt, slti, sltiu, sltu, sra, srav, srl, -// srlv, ssnop, sub, subu, wsbh, xor, xori -def : InstRW<[GenericWriteALU], (instrs ADD, ADDi, ADDiu, ADDu, AND, ANDi, - CLO, CLZ, EXT, INS, LEA_ADDiu, LUi, NOP, - NOR, OR, ORi, ROTR, ROTRV, SEB, SEH, SLL, - SLLV, SLT, SLTi, SLTiu, SLTu, SRA, SRAV, SRL, - SRLV, SSNOP, SUB, SUBu, WSBH, XOR, XORi)>; - -def : InstRW<[GenericWriteALU], (instrs COPY)>; - -// MIPSR6 -// ====== - -// addiupc, align, aluipc, aui, auipc, bitswap, clo, clz, lsa, seleqz, selnez -def : InstRW<[GenericWriteALU], (instrs ADDIUPC, ALIGN, ALUIPC, AUI, - AUIPC, BITSWAP, CLO_R6, CLZ_R6, LSA_R6, - SELEQZ, SELNEZ)>; - -// MIPS16e -// ======= - -def : InstRW<[GenericWriteALU], (instrs AddiuRxImmX16, AddiuRxRxImm16, - AddiuRxRxImmX16, AddiuRxRyOffMemX16, - AddiuRxPcImmX16, AddiuSpImm16, AddiuSpImmX16, - AdduRxRyRz16, AndRxRxRy16, CmpRxRy16, - CmpiRxImm16, CmpiRxImmX16, LiRxImm16, - LiRxImmX16, LiRxImmAlignX16, Move32R16, - MoveR3216, Mfhi16, Mflo16, NegRxRy16, - NotRxRy16, OrRxRxRy16, SebRx16, SehRx16, - SllX16, SllvRxRy16, SltiRxImm16, - SltiRxImmX16, SltiCCRxImmX16, - SltiuRxImm16, SltiuRxImmX16, SltiuCCRxImmX16, - SltRxRy16, SltCCRxRy16, SltuRxRy16, - SltuRxRyRz16, SltuCCRxRy16, SravRxRy16, - SraX16, SrlvRxRy16, SrlX16, SubuRxRyRz16, - XorRxRxRy16)>; - -def : InstRW<[GenericWriteALU], (instrs Constant32, LwConstant32, - GotPrologue16, CONSTPOOL_ENTRY)>; - -// microMIPS -// ========= - -def : InstRW<[GenericWriteALU], (instrs ADDIUPC_MM, ADDIUR1SP_MM, ADDIUR2_MM, - ADDIUS5_MM, ADDIUSP_MM, ADDU16_MM, ADD_MM, - ADDi_MM, ADDiu_MM, ADDu_MM, AND16_MM, - ANDI16_MM, AND_MM, ANDi_MM, CLO_MM, CLZ_MM, - EXT_MM, INS_MM, LEA_ADDiu_MM, LI16_MM, - LUi_MM, MOVE16_MM, MOVEP_MM, NOR_MM, - NOT16_MM, OR16_MM, OR_MM, ORi_MM, ROTRV_MM, - ROTR_MM, SEB_MM, SEH_MM, SLL16_MM, SLLV_MM, - SLL_MM, SLT_MM, SLTi_MM, SLTiu_MM, SLTu_MM, - SRAV_MM, SRA_MM, SRL16_MM, SRLV_MM, SRL_MM, - SSNOP_MM, SUBU16_MM, SUB_MM, SUBu_MM, - WSBH_MM, XOR16_MM, XOR_MM, XORi_MM)>; - -// microMIPS32r6 -// ============= - -def : InstRW<[GenericWriteALU], (instrs ADDIUPC_MMR6, ADDIU_MMR6, ADDU16_MMR6, - ADDU_MMR6, ADD_MMR6, ALIGN_MMR6, ALUIPC_MMR6, - AND16_MMR6, ANDI16_MMR6, ANDI_MMR6, AND_MMR6, - AUIPC_MMR6, AUI_MMR6, BITSWAP_MMR6, CLO_MMR6, - CLZ_MMR6, EXT_MMR6, INS_MMR6, LI16_MMR6, - LSA_MMR6, LUI_MMR6, MOVE16_MMR6, NOR_MMR6, - NOT16_MMR6, OR16_MMR6, ORI_MMR6, OR_MMR6, - SELEQZ_MMR6, SELNEZ_MMR6, SLL16_MMR6, - SLL_MMR6, SRL16_MMR6, SSNOP_MMR6, SUBU16_MMR6, - SUBU_MMR6, SUB_MMR6, WSBH_MMR6, XOR16_MMR6, - XORI_MMR6, XOR_MMR6)>; - -// MIPS64 -// ====== - -def : InstRW<[GenericWriteALU], (instrs AND64, ANDi64, DEXT64_32, DSLL64_32, - ORi64, SEB64, SEH64, SLL64_32, SLL64_64, - SLT64, SLTi64, SLTiu64, SLTu64, XOR64, - XORi64)>; - -def : InstRW<[GenericWriteALU], (instrs DADD, DADDi, DADDiu, DADDu, DCLO, - DCLZ, DEXT, DEXTM, DEXTU, DINS, DINSM, DINSU, - DROTR, DROTR32, DROTRV, DSBH, DSHD, DSLL, - DSLL32, DSLLV, DSRA, DSRA32, DSRAV, DSRL, - DSRL32, DSRLV, DSUB, DSUBu, LEA_ADDiu64, - LUi64, NOR64, OR64)>; - -// MIPS64R6 -// ======== - -def : InstRW<[GenericWriteALU], (instrs DALIGN, DAHI, DATI, DAUI, DCLO_R6, - DCLZ_R6, DBITSWAP, DLSA, DLSA_R6, SELEQZ64, - SELNEZ64)>; - - -def GenericMDU : ProcResource<1> { let BufferSize = 1; } -def GenericIssueMDU : ProcResource<1> { let Super = GenericALU; } -def GenericIssueDIV : ProcResource<1> { let Super = GenericMDU; } -def GenericWriteHILO : SchedWriteRes<[GenericIssueMDU]>; -def GenericWriteALULong : SchedWriteRes<[GenericIssueALU]> { let Latency = 5; } -def GenericWriteMove : SchedWriteRes<[GenericIssueALU]> { let Latency = 2; } -def GenericWriteMul : SchedWriteRes<[GenericIssueMDU]> { let Latency = 4; } - -def : InstRW<[GenericWriteHILO], (instrs MADD, MADDU, MSUB, MSUBU)>; - -def : InstRW<[GenericWriteHILO], (instrs PseudoMADD_MM, PseudoMADDU_MM, - PseudoMSUB_MM, PseudoMSUBU_MM, - PseudoMULT_MM, PseudoMULTu_MM)>; - -def : InstRW<[GenericWriteHILO], (instrs PseudoMADD, PseudoMADDU, PseudoMSUB, - PseudoMSUBU, PseudoMULT, PseudoMULTu)>; - -def GenericWriteMDUtoGPR : SchedWriteRes<[GenericIssueMDU]> { - let Latency = 5; -} - -def GenericWriteDIV : SchedWriteRes<[GenericIssueDIV]> { - // Estimated worst case - let Latency = 33; - let ResourceCycles = [33]; -} -def GenericWriteDIVU : SchedWriteRes<[GenericIssueDIV]> { - // Estimated worst case - let Latency = 31; - let ResourceCycles = [31]; -} - -// mul -def : InstRW<[GenericWriteMDUtoGPR], (instrs MUL)>; - -// mult, multu -def : InstRW<[GenericWriteMul], (instrs MULT, MULTu)>; - -// div, sdiv -def : InstRW<[GenericWriteDIV], (instrs PseudoSDIV, SDIV)>; - -def : InstRW<[GenericWriteDIVU], (instrs PseudoUDIV, UDIV)>; - -// mfhi, mflo, movn, mthi, mtlo, rdwhr -def : InstRW<[GenericWriteALULong], (instrs MFHI, MFLO, PseudoMFHI, - PseudoMFLO)>; - -def : InstRW<[GenericWriteALULong], (instrs PseudoMFHI_MM, PseudoMFLO_MM)>; - -def : InstRW<[GenericWriteMove], (instrs MTHI, MTLO, RDHWR, PseudoMTLOHI)>; -def : InstRW<[GenericWriteMove], (instrs PseudoMTLOHI_MM)>; - -def : InstRW<[GenericWriteALU], (instrs MOVN_I_I, MOVZ_I_I)>; - -// MIPSR6 -// ====== - -// muh, muhu, mulu, mul -def : InstRW<[GenericWriteMul], (instrs MUH, MUHU, MULU, MUL_R6)>; - -// divu, udiv -def : InstRW<[GenericWriteDIV], (instrs MOD, MODU, DIV, DIVU)>; - - -// MIPS16e -// ======= - -def : InstRW<[GenericWriteHILO], (instrs MultRxRy16, MultuRxRy16, - MultRxRyRz16, MultuRxRyRz16)>; - -def : InstRW<[GenericWriteDIV], (instrs DivRxRy16)>; - -def : InstRW<[GenericWriteDIVU], (instrs DivuRxRy16)>; - -// microMIPS -// ========= - -def : InstRW<[GenericWriteMul], (instrs MULT_MM, MULTu_MM, MADD_MM, MADDU_MM, - MSUB_MM, MSUBU_MM)>; - -def : InstRW<[GenericWriteALULong], (instrs MUL_MM)>; - -def : InstRW<[GenericWriteDIV], (instrs SDIV_MM, SDIV_MM_Pseudo)>; - -def : InstRW<[GenericWriteDIVU], (instrs UDIV_MM, UDIV_MM_Pseudo)>; - -def : InstRW<[GenericWriteMove], (instrs MFHI16_MM, MFLO16_MM, MOVF_I_MM, - MOVT_I_MM, MFHI_MM, MFLO_MM, MTHI_MM, - MTLO_MM)>; - -def : InstRW<[GenericWriteMove], (instrs RDHWR_MM)>; - -// microMIPS32r6 -// ============= - -def : InstRW<[GenericWriteMul], (instrs MUHU_MMR6, MUH_MMR6, MULU_MMR6, - MUL_MMR6)>; - -def : InstRW<[GenericWriteDIV], (instrs MODU_MMR6, MOD_MMR6, DIVU_MMR6, - DIV_MMR6)>; - -def : InstRW<[GenericWriteMove], (instrs RDHWR_MMR6)>; - -// MIPS64 -// ====== - -def : InstRW<[GenericWriteHILO], (instrs DMULU, DMULT, DMULTu, PseudoDMULT, - PseudoDMULTu)>; - -def : InstRW<[GenericWriteDIV], (instrs DSDIV, PseudoDSDIV)>; - -def : InstRW<[GenericWriteDIVU], (instrs DUDIV, PseudoDUDIV)>; - -def : InstRW<[GenericWriteALULong], (instrs MFHI64, MFLO64, PseudoMFHI64, - PseudoMFLO64, PseudoMTLOHI64)>; - -def : InstRW<[GenericWriteMove], (instrs MTHI64, MTLO64, RDHWR64)>; - -// mov[zn] -def : InstRW<[GenericWriteALU], (instrs MOVN_I_I64, MOVN_I64_I, MOVN_I64_I64, - MOVZ_I_I64, MOVZ_I64_I, MOVZ_I64_I64)>; - - -// MIPS64R6 -// ======== - -def : InstRW<[GenericWriteMDUtoGPR], (instrs DMUH, DMUHU, DMUL_R6)>; - -def : InstRW<[GenericWriteDIV], (instrs DDIV, DMOD)>; - -def : InstRW<[GenericWriteDIVU], (instrs DDIVU, DMODU)>; - -// CTISTD Pipeline -// --------------- - -def GenericIssueCTISTD : ProcResource<1> { let Super = GenericALU; } - -def GenericLDST : ProcResource<1> { let BufferSize = 1; } -def GenericIssueLDST : ProcResource<1> { let Super = GenericLDST; } - -def GenericWriteJump : SchedWriteRes<[GenericIssueCTISTD]>; -def GenericWriteJumpAndLink : SchedWriteRes<[GenericIssueCTISTD]> { - let Latency = 2; -} - -// b, beq, beql, bg[et]z, bl[et]z, bne, bnel, j, syscall, jal, bltzal, jalx, -// jalr, jr.hb, jr, jalr.hb, jarlc, jialc -def : InstRW<[GenericWriteJump], (instrs B, BAL, BAL_BR, BEQ, BNE, BGTZ, BGEZ, - BLEZ, BLTZ, BLTZAL, J, JALX, JR, JR_HB, ERET, - ERet, ERETNC, DERET)>; - -def : InstRW<[GenericWriteJump], (instrs BEQL, BNEL, BGEZL, BGTZL, BLEZL, - BLTZL)>; - -def : InstRW<[GenericWriteJump], (instrs TAILCALL, TAILCALLREG, - TAILCALLREGHB, PseudoIndirectBranch, - PseudoIndirectHazardBranch, PseudoReturn, - RetRA)>; - -def : InstRW<[GenericWriteJumpAndLink], (instrs BGEZAL, JAL, JALR, JALR_HB, - JALRHBPseudo, JALRPseudo)>; - -def : InstRW<[GenericWriteJumpAndLink], (instrs BGEZALL, BLTZALL)>; - -def GenericWriteTrap : SchedWriteRes<[GenericIssueCTISTD]>; - -def : InstRW<[GenericWriteTrap], (instrs BREAK, SYSCALL, TEQ, TEQI, - TGE, TGEI, TGEIU, TGEU, TNE, - TNEI, TLT, TLTI, TLTU, TTLTIU, - TRAP, SDBBP)>; - -// MIPSR6 -// ====== - -def : InstRW<[GenericWriteJumpAndLink], (instrs BALC, BEQZALC, BGEZALC, - BGTZALC, BLEZALC, BLTZALC, - BNEZALC, - JIALC)>; - -def : InstRW<[GenericWriteJump], (instrs BC, BC2EQZ, BC2NEZ, BEQC, BEQZC, BGEC, - BGEUC, BGEZC, BGTZC, BLEZC, BLTC, BLTUC, - BLTZC, BNEC, BNEZC, BNVC, BOVC, JIC, JR_HB_R6, - SIGRIE, PseudoIndirectBranchR6, - PseudoIndrectHazardBranchR6)>; - -def : InstRW<[GenericWriteJump], (instrs TAILCALLR6REG, TAILCALLHBR6REG)>; - -def : InstRW<[GenericWriteTrap], (instrs SDBBP_R6)>; - -// MIPS16e -// ======= - -def : InstRW<[GenericWriteJump], (instrs Bimm16, BimmX16, BeqzRxImm16, - BeqzRxImmX16, BnezRxImm16, BnezRxImmX16, - Bteqz16, BteqzX16, BteqzT8CmpX16, - BteqzT8CmpiX16, BteqzT8SltX16, - BteqzT8SltuX16, BteqzT8SltiX16, - BteqzT8SltiuX16, Btnez16, BtnezX16, - BtnezT8CmpX16, BtnezT8CmpiX16, - BtnezT8SltX16, BtnezT8SltuX16, - BtnezT8SltiX16, BtnezT8SltiuX16, JrRa16, - JrcRa16, JrcRx16, RetRA16)>; - -def : InstRW<[GenericWriteJumpAndLink], (instrs Jal16, JalB16, JumpLinkReg16)>; - -def : InstRW<[GenericWriteTrap], (instrs Break16)>; - -def : InstRW<[GenericWriteALULong], (instrs SelBeqZ, SelTBteqZCmp, - SelTBteqZCmpi, SelTBteqZSlt, - SelTBteqZSlti, SelTBteqZSltu, - SelTBteqZSltiu, SelBneZ, SelTBtneZCmp, - SelTBtneZCmpi, SelTBtneZSlt, - SelTBtneZSlti, SelTBtneZSltu, - SelTBtneZSltiu)>; - -// microMIPS -// ========= - -def : InstRW<[GenericWriteJump], (instrs B16_MM, BAL_BR_MM, BC1F_MM, BC1T_MM, - BEQZ16_MM, BEQZC_MM, BEQ_MM, BGEZ_MM, - BGTZ_MM, BLEZ_MM, BLTZ_MM, BNEZ16_MM, - BNEZC_MM, BNE_MM, B_MM, DERET_MM, ERET_MM, - JR16_MM, JR_MM, J_MM, B_MM_Pseudo)>; - -def : InstRW<[GenericWriteJumpAndLink], (instrs BGEZALS_MM, BGEZAL_MM, - BLTZALS_MM, BLTZAL_MM, JALR16_MM, - JALRS16_MM, JALRS_MM, JALR_MM, - JALS_MM, JALX_MM, JAL_MM)>; - -def : InstRW<[GenericWriteJump], (instrs TAILCALLREG_MM, TAILCALL_MM, - PseudoIndirectBranch_MM)>; - -def : InstRW<[GenericWriteTrap], (instrs BREAK16_MM, BREAK_MM, SDBBP16_MM, - SDBBP_MM, SYSCALL_MM, TEQI_MM, TEQ_MM, - TGEIU_MM, TGEI_MM, TGEU_MM, TGE_MM, TLTIU_MM, - TLTI_MM, TLTU_MM, TLT_MM, TNEI_MM, TNE_MM, - TRAP_MM)>; - -// microMIPS32r6 -// ============= - -def : InstRW<[GenericWriteJump], (instrs BC16_MMR6, BC1EQZC_MMR6, BC1NEZC_MMR6, - BC2EQZC_MMR6, BC2NEZC_MMR6, BC_MMR6, - BEQC_MMR6, BEQZC16_MMR6, BEQZC_MMR6, - BGEC_MMR6, BGEUC_MMR6, BGEZC_MMR6, - BGTZC_MMR6, BLEZC_MMR6, BLTC_MMR6, - BLTUC_MMR6, BLTZC_MMR6, BNEC_MMR6, - BNEZC16_MMR6, BNEZC_MMR6, BNVC_MMR6, - BOVC_MMR6, DERET_MMR6, ERETNC_MMR6, JAL_MMR6, - ERET_MMR6, JIC_MMR6, JRADDIUSP, JRC16_MM, - JRC16_MMR6, JRCADDIUSP_MMR6, SIGRIE_MMR6, - B_MMR6_Pseudo, PseudoIndirectBranch_MMR6)>; - -def : InstRW<[GenericWriteJumpAndLink], (instrs BALC_MMR6, BEQZALC_MMR6, - BGEZALC_MMR6, BGTZALC_MMR6, - BLEZALC_MMR6, BLTZALC_MMR6, - BNEZALC_MMR6, JALRC16_MMR6, - JALRC_HB_MMR6, JALRC_MMR6, - JIALC_MMR6)>; - -def : InstRW<[GenericWriteJump], (instrs TAILCALLREG_MMR6, TAILCALL_MMR6)>; - -def : InstRW<[GenericWriteTrap], (instrs BREAK16_MMR6, BREAK_MMR6, SDBBP_MMR6, - SDBBP16_MMR6)>; - -// MIPS64 -// ====== - -def : InstRW<[GenericWriteJump], (instrs BEQ64, BGEZ64, BGTZ64, BLEZ64, - BLTZ64, BNE64, JR64)>; - -def : InstRW<[GenericWriteJumpAndLink], (instrs JALR64, JALR64Pseudo, - JALRHB64Pseudo, JALR_HB64)>; - -def : InstRW<[GenericWriteJump], (instrs JR_HB64, TAILCALLREG64, - TAILCALLREGHB64, PseudoReturn64)>; - -// MIPS64R6 -// ======== - -def : InstRW<[GenericWriteJump], (instrs BEQC64, BEQZC64, BGEC64, BGEUC64, - BGEZC64, BGTZC64, BLEZC64, BLTC64, BLTUC64, - BLTZC64, BNEC64, BNEZC64, JIC64, - PseudoIndirectBranch64, - PseudoIndirectHazardBranch64)>; - -def : InstRW<[GenericWriteJumpAndLink], (instrs JIALC64)>; - -def : InstRW<[GenericWriteJump], (instrs JR_HB64_R6, TAILCALL64R6REG, - TAILCALLHB64R6REG, PseudoIndirectBranch64R6, - PseudoIndrectHazardBranch64R6)>; - -// COP0 Pipeline -// ============= - -def GenericCOP0 : ProcResource<1> { let BufferSize = 1; } - -def GenericIssueCOP0 : ProcResource<1> { let Super = GenericCOP0; } -def GenericWriteCOP0TLB : SchedWriteRes<[GenericIssueCOP0]> { let Latency = 4; } -def GenericWriteCOP0 : SchedWriteRes<[GenericIssueCOP0]> { let Latency = 3; } -def GenericReadCOP0 : SchedWriteRes<[GenericIssueCOP0]> { let Latency = 2; } -def GenericReadWritePGPR : SchedWriteRes<[GenericIssueCOP0]>; -def GenericReadWriteCOP0Long : SchedWriteRes<[GenericIssueCOP0]> { - let Latency = 5; -} -def GenericWriteCOP0Short : SchedWriteRes<[GenericIssueCOP0]>; - -def : InstRW<[GenericWriteCOP0TLB], (instrs TLBP, TLBR, TLBWI, TLBWR)>; -def : InstRW<[GenericWriteCOP0TLB], (instrs TLBINV, TLBINVF)>; - -def : InstRW<[GenericReadCOP0], (instrs MFC0)>; -def : InstRW<[GenericWriteCOP0], (instrs MTC0)>; - -def : InstRW<[GenericWriteCOP0], (instrs EVP, DVP)>; - -def : InstRW<[GenericWriteCOP0], (instrs DI, EI)>; - -def : InstRW<[GenericWriteCOP0], (instrs EHB, PAUSE, WAIT)>; - -// microMIPS -// ========= - -def : InstRW<[GenericWriteCOP0TLB], (instrs TLBP_MM, TLBR_MM, TLBWI_MM, - TLBWR_MM)>; - -def : InstRW<[GenericWriteCOP0], (instrs DI_MM, EI_MM)>; - -def : InstRW<[GenericWriteCOP0], (instrs EHB_MM, PAUSE_MM, WAIT_MM)>; - - -// microMIPS32R6 -// ============= - -def : InstRW<[GenericWriteCOP0], (instrs RDPGPR_MMR6, WRPGPR_MMR6)>; - -def : InstRW<[GenericWriteCOP0TLB], (instrs TLBINV_MMR6, TLBINVF_MMR6)>; - -def : InstRW<[GenericReadCOP0], (instrs MFHC0_MMR6, MFC0_MMR6, MFHC2_MMR6, - MFC2_MMR6)>; - -def : InstRW<[GenericWriteCOP0], (instrs MTHC0_MMR6, MTC0_MMR6, MTHC2_MMR6, - MTC2_MMR6)>; - -def : InstRW<[GenericWriteCOP0], (instrs EVP_MMR6, DVP_MMR6)>; - -def : InstRW<[GenericWriteCOP0], (instrs DI_MMR6, EI_MMR6)>; - -def : InstRW<[GenericWriteCOP0], (instrs EHB_MMR6, PAUSE_MMR6, WAIT_MMR6)>; - -// MIPS64 -// ====== - -def : InstRW<[GenericReadCOP0], (instrs DMFC0)>; - -def : InstRW<[GenericWriteCOP0], (instrs DMTC0)>; - - -def GenericCOP2 : ProcResource<1> { let BufferSize = 1; } -def GenericWriteCOPOther : SchedWriteRes<[GenericCOP2]>; - -def : InstRW<[GenericWriteCOPOther], (instrs MFC2, MTC2)>; - -def : InstRW<[GenericWriteCOPOther], (instrs DMFC2, DMTC2)>; - -// microMIPS32R6 -// ============= - -// The latency and repeat rate of these instructions are implementation -// dependant. -def : InstRW<[GenericWriteMove], (instrs CFC2_MM, CTC2_MM)>; - - -// MIPS MT ASE - hasMT -// ==================== - -def : InstRW<[GenericWriteMove], (instrs DMT, DVPE, EMT, EVPE, MFTR, - MTTR)>; - -def : InstRW<[GenericReadWriteCOP0Long], (instrs YIELD)>; - -def : InstRW<[GenericWriteCOP0Short], (instrs FORK)>; - -// MIPS Virtualization ASE -// ======================= - -def : InstRW<[GenericWriteCOP0Short], (instrs HYPCALL, TLBGINV, TLBGINVF, TLBGP, - TLBGR, TLBGWI, TLBGWR, MFGC0, MFHGC0, - MTGC0, MTHGC0)>; - -// MIPS64 Virtualization ASE -// ========================= - -def : InstRW<[GenericWriteCOP0Short], (instrs DMFGC0, DMTGC0)>; - -// microMIPS virtualization ASE -// ============================ - -def : InstRW<[GenericWriteCOP0Short], (instrs HYPCALL_MM, TLBGINVF_MM, - TLBGINV_MM, TLBGP_MM, TLBGR_MM, - TLBGWI_MM, TLBGWR_MM, MFGC0_MM, - MFHGC0_MM, MTGC0_MM, MTHGC0_MM)>; - -// LDST Pipeline -// ------------- - -def GenericWriteLoad : SchedWriteRes<[GenericIssueLDST]> { - let Latency = 2; -} - -def GenericWritePref : SchedWriteRes<[GenericIssueLDST]>; -def GenericWriteSync : SchedWriteRes<[GenericIssueLDST]>; -def GenericWriteCache : SchedWriteRes<[GenericIssueLDST]> { let Latency = 5; } - -def GenericWriteStore : SchedWriteRes<[GenericIssueLDST]>; -def GenericWriteStoreSC : SchedWriteRes<[GenericIssueLDST]> { let Latency = 2; } - -def GenericWriteGPRFromBypass : SchedWriteRes<[GenericIssueLDST]> { - let Latency = 2; -} - -def GenericWriteStoreFromOtherUnits : SchedWriteRes<[GenericIssueLDST]>; -def GenericWriteLoadToOtherUnits : SchedWriteRes<[GenericIssueLDST]> { - let Latency = 0; -} - -// l[bhw], l[bh]u, ll -def : InstRW<[GenericWriteLoad], (instrs LB, LBu, LH, LHu, LW, LL, - LWC2, LWC3, LDC2, LDC3)>; - -// lw[lr] -def : InstRW<[GenericWriteLoad], (instrs LWL, LWR)>; - -// s[bhw], sc, s[dw]c[23] -def : InstRW<[GenericWriteStore], (instrs SB, SH, SW, SWC2, SWC3, - SDC2, SDC3)>; - -// PreMIPSR6 sw[lr] -def : InstRW<[GenericWriteStore], (instrs SWL, SWR)>; - -def : InstRW<[GenericWriteStoreSC], (instrs SC, SC_MMR6)>; - -// pref -def : InstRW<[GenericWritePref], (instrs PREF)>; -// cache -def : InstRW<[GenericWriteCache], (instrs CACHE)>; - -// sync -def : InstRW<[GenericWriteSync], (instrs SYNC, SYNCI)>; - -// MIPSR6 -// ====== - -def : InstRW<[GenericWriteLoad], (instrs LDC2_R6, LL_R6, LWC2_R6, LWPC)>; - -def : InstRW<[GenericWriteStore], (instrs SWC2_R6, SDC2_R6)>; - -def : InstRW<[GenericWriteStoreSC], (instrs SC_R6)>; - -def : InstRW<[GenericWritePref], (instrs PREF_R6)>; - -def : InstRW<[GenericWriteCache], (instrs CACHE_R6)>; - -def : InstRW<[GenericWriteSync], (instrs GINVI, GINVT)>; - -// MIPS32 EVA -// ========== - -def : InstRW<[GenericWriteLoad], (instrs LBE, LBuE, LHE, LHuE, LWE, - LLE)>; - -def : InstRW<[GenericWriteStore], (instrs SBE, SHE, SWE, SCE)>; - -def : InstRW<[GenericWriteLoad], (instrs LWLE, LWRE)>; - -def : InstRW<[GenericWriteStore], (instrs SWLE, SWRE)>; - -def : InstRW<[GenericWritePref], (instrs PREFE)>; - -def : InstRW<[GenericWriteCache], (instrs CACHEE)>; - -// microMIPS EVA ASE - InMicroMipsMode, hasEVA -// =========================================== - -def : InstRW<[GenericWriteLoad], (instrs LBE_MM, LBuE_MM, LHE_MM, LHuE_MM, - LWE_MM, LWLE_MM, LWRE_MM, LLE_MM)>; - -def : InstRW<[GenericWriteStore], (instrs SBE_MM, SB_MM, SHE_MM, SWE_MM, - SWLE_MM, SWRE_MM, SCE_MM)>; - -def : InstRW<[GenericWritePref], (instrs PREFE_MM)>; -def : InstRW<[GenericWriteCache], (instrs CACHEE_MM)>; - - -// MIPS16e -// ======= - -def : InstRW<[GenericWriteLoad], (instrs Restore16, RestoreX16, - LbRxRyOffMemX16, - LbuRxRyOffMemX16, LhRxRyOffMemX16, - LhuRxRyOffMemX16, LwRxRyOffMemX16, - LwRxSpImmX16, LwRxPcTcp16, LwRxPcTcpX16)>; - -def : InstRW<[GenericWriteStore], (instrs Save16, SaveX16, SbRxRyOffMemX16, - ShRxRyOffMemX16, SwRxRyOffMemX16, - SwRxSpImmX16)>; - -// microMIPS -// ========= - -def : InstRW<[GenericWriteLoad], (instrs LBU16_MM, LB_MM, LBu_MM, LHU16_MM, - LH_MM, LHu_MM, LL_MM, LW16_MM, LWGP_MM, - LWL_MM, LWM16_MM, LWM32_MM, LWP_MM, LWR_MM, - LWSP_MM, LWU_MM, LWXS_MM, LW_MM)>; - -def : InstRW<[GenericWriteStore], (instrs SB16_MM, SC_MM, SH16_MM, SH_MM, - SW16_MM, SWL_MM, SWM16_MM, SWM32_MM, SWM_MM, - SWP_MM, SWR_MM, SWSP_MM, SW_MM)>; - - -def : InstRW<[GenericWritePref], (instrs PREF_MM, PREFX_MM)>; - -def : InstRW<[GenericWriteCache], (instrs CACHE_MM)>; - -def : InstRW<[GenericWriteSync], (instrs SYNC_MM, SYNCI_MM)>; -def : InstRW<[GenericWriteSync], (instrs GINVI_MMR6, GINVT_MMR6)>; - -// microMIPS32r6 -// ============= - -def : InstRW<[GenericWriteLoad], (instrs LBU_MMR6, LB_MMR6, LDC2_MMR6, LL_MMR6, - LWM16_MMR6, LWC2_MMR6, LWPC_MMR6, LW_MMR6)>; - -def : InstRW<[GenericWriteStore], (instrs SB16_MMR6, SB_MMR6, SDC2_MMR6, - SH16_MMR6, SH_MMR6, SW16_MMR6, SWC2_MMR6, - SWM16_MMR6, SWSP_MMR6, SW_MMR6)>; - -def : InstRW<[GenericWriteSync], (instrs SYNC_MMR6, SYNCI_MMR6)>; - -def : InstRW<[GenericWritePref], (instrs PREF_MMR6)>; - -def : InstRW<[GenericWriteCache], (instrs CACHE_MMR6)>; - -// MIPS64 -// ====== - -def : InstRW<[GenericWriteLoad], (instrs LD, LL64, LLD, LWu, LB64, LBu64, - LH64, LHu64, LW64)>; - -// l[dw][lr] -def : InstRW<[GenericWriteLoad], (instrs LWL64, LWR64, LDL, LDR)>; - -def : InstRW<[GenericWriteStore], (instrs SD, SC64, SCD, SB64, SH64, SW64, - SWL64, SWR64)>; - -def : InstRW<[GenericWriteStore], (instrs SDL, SDR)>; - -// MIPS64R6 -// ======== - -def : InstRW<[GenericWriteLoad], (instrs LWUPC, LDPC)>; - -def : InstRW<[GenericWriteLoad], (instrs LLD_R6, LL64_R6)>; - -def : InstRW<[GenericWriteStoreSC], (instrs SC64_R6, SCD_R6)>; - -// MIPSR6 CRC ASE - hasCRC -// ======================= - -def : InstRW<[GenericWriteALU], (instrs CRC32B, CRC32H, CRC32W, CRC32CB, - CRC32CH, CRC32CW)>; - -// MIPS64R6 CRC ASE - hasCRC -// ------------------------- - -def : InstRW<[GenericWriteALU], (instrs CRC32D, CRC32CD)>; - - -// Cavium Networks MIPS (cnMIPS) - Octeon, HasCnMips -// ================================================= - -def : InstRW<[GenericWriteALU], (instrs BADDu, BBIT0, BBIT032, BBIT1, BBIT132, - CINS, CINS32, CINS64_32, CINS_i32, - DMFC2_OCTEON, DMTC2_OCTEON, DPOP, EXTS, - EXTS32, MTM0, MTM1, MTM2, MTP0, MTP1, MTP2, - POP, SEQ, SEQi, SNE, SNEi, - V3MULU, VMM0, VMULU)>; - -def : InstRW<[GenericWriteMDUtoGPR], (instrs DMUL)>; - -// Cavium Networks MIPS (cnMIPSP) - Octeon+, HasCnMipsP -// ================================================= - -def : InstRW<[GenericWriteALU], (instrs SAA, SAAD)>; - -// FPU Pipelines -// ============= - -def GenericFPQ : ProcResource<1> { let BufferSize = 1; } -def GenericIssueFPUS : ProcResource<1> { let Super = GenericFPQ; } -def GenericIssueFPUL : ProcResource<1> { let Super = GenericFPQ; } -def GenericIssueFPULoad : ProcResource<1> { let Super = GenericFPQ; } -def GenericIssueFPUStore : ProcResource<1> { let Super = GenericFPQ; } -def GenericIssueFPUMove : ProcResource<1> { let Super = GenericFPQ; } -def GenericFPUDivSqrt : ProcResource<1> { let Super = GenericFPQ; } - -// The floating point compare of the 24k series including interAptiv has a -// listed latency of 1-2. Using the higher latency here. - -def GenericWriteFPUCmp : SchedWriteRes<[GenericIssueFPUS]> { let Latency = 2; } -def GenericWriteFPUS : SchedWriteRes<[GenericIssueFPUS]> { let Latency = 4; } -def GenericWriteFPUL : SchedWriteRes<[GenericIssueFPUL]> { let Latency = 5; } -def GenericWriteFPUStore : SchedWriteRes<[GenericIssueFPUStore]> { let - Latency = 1; -} -def GenericWriteFPULoad : SchedWriteRes<[GenericIssueFPULoad]> { - let Latency = 2; -} -def GenericWriteFPUMoveFP : SchedWriteRes<[GenericIssueFPUMove]> { - let Latency = 4; -} -def GenericWriteFPUMoveGPRFPU : SchedWriteRes<[GenericIssueFPUMove]> { - let Latency = 2; -} -def GenericWriteFPUDivS : SchedWriteRes<[GenericFPUDivSqrt]> { - let Latency = 17; - let ResourceCycles = [ 14 ]; -} -def GenericWriteFPUDivD : SchedWriteRes<[GenericFPUDivSqrt]> { - let Latency = 32; - let ResourceCycles = [ 29 ]; -} -def GenericWriteFPURcpS : SchedWriteRes<[GenericFPUDivSqrt]> { - let Latency = 13; - let ResourceCycles = [ 10 ]; -} -def GenericWriteFPURcpD : SchedWriteRes<[GenericFPUDivSqrt]> { - let Latency = 25; - let ResourceCycles = [ 21 ]; -} -def GenericWriteFPURsqrtS : SchedWriteRes<[GenericFPUDivSqrt]> { - let Latency = 17; - let ResourceCycles = [ 14 ]; -} -def GenericWriteFPURsqrtD : SchedWriteRes<[GenericFPUDivSqrt]> { - let Latency = 32; - let ResourceCycles = [ 29 ]; -} -def GenericWriteFPUSqrtS : SchedWriteRes<[GenericFPUDivSqrt]> { - let Latency = 17; - let ResourceCycles = [ 14 ]; -} -def GenericWriteFPUSqrtD : SchedWriteRes<[GenericFPUDivSqrt]> { - let Latency = 29; - let ResourceCycles = [ 29 ]; -} - -// Floating point compare and branch -// --------------------------------- -// -// c.<cc>.[ds], bc1[tf], bc1[tf]l -def : InstRW<[GenericWriteFPUCmp], (instrs FCMP_D32, FCMP_D64, FCMP_S32, BC1F, - BC1T, BC1FL, BC1TL)>; - -def : InstRW<[GenericWriteFPUCmp], (instregex "C_[A-Z]+_(S|D32|D64)$")>; - -// Short Pipe -// ---------- -// -// abs.[ds], abs.ps, add.[ds], neg.[ds], neg.ps, madd.s, msub.s, nmadd,s -// nmsub.s, sub.[ds], mul.s - -def : InstRW<[GenericWriteFPUS], (instrs FABS_S, FABS_D32, FABS_D64, FADD_D32, - FADD_D64, FADD_S, MADD_S, MSUB_S, FMUL_S, - FNEG_S, FNEG_D32, FNEG_D64, NMADD_S, NMSUB_S, - FSUB_S, FSUB_D32, FSUB_D64)>; - -// Long Pipe -// ---------- -// -// nmadd.d, nmsub.d, mul.[ds], mul.ps, ceil.[wl].[sd], cvt.d.[sw], cvt.s.[dw], -// cvt.w.[sd], cvt.[sw].ps, trunc.w.[ds], trunc.w.ps, floor.[ds], -// round.[lw].[ds], floor.[lw].ds - -// madd.d, msub.dm mul.d, mul.ps, nmadd.d, nmsub.d, ceil.[wl].[sd], cvt.d.[sw], -// cvt.s.[dw], cvt.w.[sd], cvt.[sw].ps, round.[lw].[ds], floor.[lw].ds, -// trunc.w.[ds], trunc.w.ps, -def : InstRW<[GenericWriteFPUL], (instrs CEIL_L_D64, CEIL_L_S, CEIL_W_D32, - CEIL_W_D64, CEIL_W_S, CVT_D32_S, CVT_D32_W, - CVT_D64_L, CVT_D64_S, CVT_D64_W, CVT_L_D64, - CVT_L_S, CVT_S_D32, CVT_S_D64, CVT_S_L, - CVT_S_W, CVT_W_D32, CVT_W_D64, CVT_W_S, - CVT_PS_S64, CVT_S_PL64, CVT_S_PU64, - FLOOR_L_D64, FLOOR_L_S, FLOOR_W_D32, - FLOOR_W_D64, FLOOR_W_S, FMUL_D32, FMUL_D64, - MADD_D32, MADD_D64, MSUB_D32, MSUB_D64, - NMADD_D32, NMADD_D64, NMSUB_D32, NMSUB_D64, - PLL_PS64, PLU_PS64, - ROUND_L_D64, ROUND_L_S, ROUND_W_D32, - ROUND_W_D64, ROUND_W_S, TRUNC_L_D64, - TRUNC_L_S, TRUNC_W_D32, TRUNC_W_D64, - TRUNC_W_S, PseudoTRUNC_W_D, - PseudoTRUNC_W_D32, PseudoTRUNC_W_S)>; - -// Pseudo convert instruction -def : InstRW<[GenericWriteFPUL], (instrs PseudoCVT_D32_W, PseudoCVT_D64_L, - PseudoCVT_D64_W, PseudoCVT_S_L, - PseudoCVT_S_W)>; - -// div.[ds], div.ps -def : InstRW<[GenericWriteFPUDivS], (instrs FDIV_S)>; -def : InstRW<[GenericWriteFPUDivD], (instrs FDIV_D32, FDIV_D64)>; - -// sqrt.[ds], sqrt.ps -def : InstRW<[GenericWriteFPUSqrtS], (instrs FSQRT_S)>; -def : InstRW<[GenericWriteFPUSqrtD], (instrs FSQRT_D32, FSQRT_D64)>; - -// rsqrt.[ds], recip.[ds] -def : InstRW<[GenericWriteFPURcpS], (instrs RECIP_S, RSQRT_S)>; -def : InstRW<[GenericWriteFPURcpD], (instrs RECIP_D32, RECIP_D64, - RSQRT_D32, RSQRT_D64)>; - - -// Load Pipe -// --------- - -// ctc1, mtc1, mthc1, cfc1, mfc1, mfhc1 -def : InstRW<[GenericWriteFPUMoveGPRFPU], (instrs BuildPairF64, - BuildPairF64_64, ExtractElementF64, - ExtractElementF64_64, CFC1, CTC1, - MFC1, MFC1_D64, MFHC1_D32, - MFHC1_D64, MTC1, MTC1_D64, - MTHC1_D32, MTHC1_D64)>; - -// swc1, swxc1 -def : InstRW<[GenericWriteFPUStore], (instrs SDC1, SDC164, SDXC1, SDXC164, - SUXC1, SUXC164, SWC1, SWXC1)>; - -def : InstRW<[GenericWriteFPUMoveFP], (instrs FMOV_D32, FMOV_D64, FMOV_S)>; - - -// movn.[ds], movz.[ds] -def : InstRW<[GenericWriteFPUMoveFP], (instrs MOVF_I, MOVF_D32, MOVF_D64, - MOVF_S, MOVT_I, MOVT_D32, MOVT_D64, - MOVT_S, MOVN_I_D32, MOVN_I_D64, - MOVN_I_S, MOVZ_I_D32, MOVZ_I_D64, - MOVZ_I_S)>; - -def : InstRW<[GenericWriteFPUMoveFP], (instrs MOVT_I64, MOVF_I64, MOVZ_I64_S, - MOVN_I64_D64, MOVN_I64_S, - MOVZ_I64_D64)>; - -// l[dw]x?c1 -def : InstRW<[GenericWriteFPULoad], (instrs LDC1, LDC164, LDXC1, LDXC164, - LUXC1, LUXC164, LWC1, LWXC1)>; - -// MIPSR6 -// ====== - -// sel(eq|ne).[ds], max.[ds], maxa.[ds], min.[ds], mina.[ds], class.[ds] -def : InstRW<[GenericWriteFPUS], (instrs SELEQZ_S, SELNEZ_S, SELEQZ_D, SELNEZ_D, - MAX_S, MAX_D, MAXA_S, MAXA_D, MIN_S, MIN_D, - MINA_S, MINA_D, CLASS_S, CLASS_D)>; - -def : InstRW<[GenericWriteFPUL], (instrs RINT_S, RINT_D)>; - -def : InstRW<[GenericWriteFPUCmp], (instrs BC1EQZ, BC1NEZ, SEL_D, SEL_S)>; - -def : InstRW<[GenericWriteFPUS], (instrs MADDF_S, MSUBF_S, MADDF_D, MSUBF_D)>; - - -// microMIPS -// ========= - -def : InstRW<[GenericWriteFPUMoveFP], (instrs MOVF_D32_MM, MOVF_S_MM, - MOVN_I_D32_MM, MOVN_I_S_MM, - MOVT_D32_MM, MOVT_S_MM, MOVZ_I_D32_MM, - MOVZ_I_S_MM)>; - - -// cvt.?.?, ceil.?, floor.?, round.?, trunc.? (n)madd.? (n)msub.? -def : InstRW<[GenericWriteFPUL], (instrs CVT_D32_S_MM, CVT_D32_W_MM, - CVT_D64_S_MM, CVT_D64_W_MM, CVT_L_D64_MM, - CVT_L_S_MM, CVT_S_D32_MM, CVT_S_D64_MM, - CVT_S_W_MM, CVT_W_D32_MM, CVT_W_D64_MM, - CVT_W_S_MM, CEIL_W_MM, CEIL_W_S_MM, - FLOOR_W_MM, FLOOR_W_S_MM, NMADD_S_MM, - NMADD_D32_MM, NMSUB_S_MM, NMSUB_D32_MM, - MADD_S_MM, MADD_D32_MM, ROUND_W_MM, - ROUND_W_S_MM, TRUNC_W_MM, TRUNC_W_S_MM)>; - -def : InstRW<[GenericWriteFPUCmp], (instregex "^C_[A-Z]_(S|D32|D64)_MM$")>; -def : InstRW<[GenericWriteFPUCmp], (instregex "^C_[A-Z][A-Z]_(S|D32|D64)_MM$")>; -def : InstRW<[GenericWriteFPUCmp], (instregex "^C_[A-Z][A-Z][A-Z]_(S|D32|D64)_MM$")>; -def : InstRW<[GenericWriteFPUCmp], (instregex "^C_NGLE_(S|D32|D64)_MM$")>; -def : InstRW<[GenericWriteFPUCmp], (instrs FCMP_S32_MM, FCMP_D32_MM)>; - -def : InstRW<[GenericWriteFPUS], (instrs MFC1_MM, MFHC1_D32_MM, MFHC1_D64_MM, - MTC1_MM, MTC1_D64_MM, - MTHC1_D32_MM, MTHC1_D64_MM)>; - -def : InstRW<[GenericWriteFPUS], (instrs FABS_D32_MM, FABS_D64_MM, FABS_S_MM, - FNEG_D32_MM, FNEG_D64_MM, FNEG_S_MM, - FADD_D32_MM, FADD_D64_MM, FADD_S_MM, - FMOV_D32_MM, FMOV_D64_MM, FMOV_S_MM, - FMUL_D32_MM, FMUL_D64_MM, FMUL_S_MM, - FSUB_D32_MM, FSUB_D64_MM, FSUB_S_MM, - MSUB_S_MM, MSUB_D32_MM)>; - -def : InstRW<[GenericWriteFPUDivS], (instrs FDIV_S_MM)>; -def : InstRW<[GenericWriteFPUDivD], (instrs FDIV_D32_MM, FDIV_D64_MM)>; - -def : InstRW<[GenericWriteFPUSqrtS], (instrs FSQRT_S_MM)>; -def : InstRW<[GenericWriteFPUSqrtD], (instrs FSQRT_D32_MM, FSQRT_D64_MM)>; - -def : InstRW<[GenericWriteFPURcpS], (instrs RECIP_S_MM, RSQRT_S_MM)>; -def : InstRW<[GenericWriteFPURcpD], (instrs RECIP_D32_MM, RECIP_D64_MM, - RSQRT_D32_MM, RSQRT_D64_MM)>; - -def : InstRW<[GenericWriteFPUStore], (instrs SDC1_MM, SWC1_MM, SUXC1_MM, - SWXC1_MM)>; - -def : InstRW<[GenericWriteFPUMoveGPRFPU], (instrs CFC1_MM, CTC1_MM)>; - -def : InstRW<[GenericWriteFPULoad], (instrs LDC1_MM, LUXC1_MM, LWC1_MM, - LWXC1_MM)>; - -// microMIPS32r6 -// ============= - -def : InstRW<[GenericWriteFPUS], (instrs FNEG_S_MMR6)>; - -def : InstRW<[GenericWriteFPUCmp], (instregex "CMP_[A-Z][A-Z]_(S|D)_MMR6")>; -def : InstRW<[GenericWriteFPUCmp], - (instregex "CMP_[A-Z][A-Z][A-Z]_(S|D)_MMR6")>; -def : InstRW<[GenericWriteFPUCmp], - (instregex "CMP_[A-Z][A-Z][A-Z][A-Z]_(S|D)_MMR6")>; - -def : InstRW<[GenericWriteFPUL], - (instregex "CVT_(L|D|S|W)_(L|D|S|L|W)_MMR6")>; - -def : InstRW<[GenericWriteFPUL], - (instregex "TRUNC_(L|W)_(D|S)_MMR6")>; - -def : InstRW<[GenericWriteFPUL], - (instregex "ROUND_(L|W)_(D|S)_MMR6")>; - -def : InstRW<[GenericWriteFPUL], - (instregex "FLOOR_(L|W)_(D|S)_MMR6")>; - -def : InstRW<[GenericWriteFPUL], - (instregex "CEIL_(L|W)_(S|D)_MMR6")>; - -def : InstRW<[GenericWriteFPUS], - (instrs MFC1_MMR6, MTC1_MMR6, CLASS_S_MMR6, CLASS_D_MMR6, - FADD_S_MMR6)>; - -def : InstRW<[GenericWriteFPUS], (instregex "M(IN|AX)_(S|D)_MMR6")>; - -def : InstRW<[GenericWriteFPUS], (instregex "M(IN|AX)A_(S|D)_MMR6")>; - -def : InstRW<[GenericWriteFPUS], (instregex "SEL(EQ|NE)Z_(S|D)_MMR6")>; - -def : InstRW<[GenericWriteFPUS], (instregex "SEL_(S|D)_MMR6")>; - -def : InstRW<[GenericWriteFPUL], (instrs RINT_S_MMR6, RINT_D_MMR6)>; - -def : InstRW<[GenericWriteFPUS], (instregex "M(ADD|SUB)F_(S|D)_MMR6")>; - -def : InstRW<[GenericWriteFPUS], (instrs FMOV_S_MMR6, FMUL_S_MMR6, - FSUB_S_MMR6, FMOV_D_MMR6)>; - -def : InstRW<[GenericWriteFPUL], (instrs FDIV_S_MMR6)>; - -def : InstRW<[GenericWriteFPUStore], (instrs SDC1_D64_MMR6)>; - -def : InstRW<[GenericWriteFPULoad], (instrs LDC1_D64_MMR6)>; - -// MIPS64 -// ====== - -def : InstRW<[GenericWriteFPUMoveGPRFPU], (instrs DMFC1, DMTC1)>; - -// MIPS DSP ASE, HasDSP -// ==================== - -def : InstRW<[GenericWriteStore], (instrs SWDSP)>; - -def : InstRW<[GenericWriteLoad], (instrs LWDSP)>; - -def : InstRW<[GenericWriteMove], (instrs PseudoMTLOHI_DSP)>; - -def GenericDSP : ProcResource<1> { let BufferSize = 1; } -def GenericDSPShort : SchedWriteRes<[GenericDSP]> { let Latency = 2; } -def GenericDSPLong : SchedWriteRes<[GenericDSP]> { let Latency = 6; } -def GenericDSPBypass : SchedWriteRes<[GenericDSP]> { let Latency = 1; } -def GenericDSPMTHILO : SchedWriteRes<[GenericDSP]> { let Latency = 5; } -def GenericDSPLoad : SchedWriteRes<[GenericDSP]> { let Latency = 4; } -def GenericDSPMTHLIP : SchedWriteRes<[GenericDSP]> { let Latency = 5; } - -def : InstRW<[GenericDSPLong], (instregex "^EXTRV_RS_W$")>; -def : InstRW<[GenericDSPLong], (instregex "^EXTRV_R_W$")>; -def : InstRW<[GenericDSPLong], (instregex "^EXTRV_S_H$")>; -def : InstRW<[GenericDSPLong], (instregex "^EXTRV_W$")>; -def : InstRW<[GenericDSPLong], (instregex "^EXTR_RS_W$")>; -def : InstRW<[GenericDSPLong], (instregex "^EXTR_R_W$")>; -def : InstRW<[GenericDSPLong], (instregex "^EXTR_S_H$")>; -def : InstRW<[GenericDSPLong], (instregex "^EXTR_W$")>; -def : InstRW<[GenericDSPLong], (instregex "^INSV$")>; - -def : InstRW<[GenericDSPMTHLIP], (instregex "^MTHLIP$")>; -def : InstRW<[GenericDSPMTHILO], (instregex "^MTHI_DSP$")>; -def : InstRW<[GenericDSPMTHILO], (instregex "^MTLO_DSP$")>; - -def : InstRW<[GenericDSPShort], (instregex "^ABSQ_S_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^ABSQ_S_W$")>; -def : InstRW<[GenericDSPShort], (instregex "^ADDQ_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^ADDQ_S_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^ADDQ_S_W$")>; -def : InstRW<[GenericDSPShort], (instregex "^ADDSC$")>; -def : InstRW<[GenericDSPShort], (instregex "^ADDU_QB$")>; -def : InstRW<[GenericDSPShort], (instregex "^ADDU_S_QB$")>; -def : InstRW<[GenericDSPShort], (instregex "^ADDWC$")>; -def : InstRW<[GenericDSPShort], (instregex "^BITREV$")>; -def : InstRW<[GenericDSPShort], (instregex "^BPOSGE32$")>; -def : InstRW<[GenericDSPShort], (instregex "^CMPGU_EQ_QB$")>; -def : InstRW<[GenericDSPShort], (instregex "^CMPGU_LE_QB$")>; -def : InstRW<[GenericDSPShort], (instregex "^CMPGU_LT_QB$")>; -def : InstRW<[GenericDSPShort], (instregex "^CMPU_EQ_QB$")>; -def : InstRW<[GenericDSPShort], (instregex "^CMPU_LE_QB$")>; -def : InstRW<[GenericDSPShort], (instregex "^CMPU_LT_QB$")>; -def : InstRW<[GenericDSPShort], (instregex "^CMP_EQ_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^CMP_LE_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^CMP_LT_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^DPAQ_SA_L_W$")>; -def : InstRW<[GenericDSPShort], (instregex "^DPAQ_S_W_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^DPAU_H_QBL$")>; -def : InstRW<[GenericDSPShort], (instregex "^DPAU_H_QBR$")>; -def : InstRW<[GenericDSPShort], (instregex "^DPSQ_SA_L_W$")>; -def : InstRW<[GenericDSPShort], (instregex "^DPSQ_S_W_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^DPSU_H_QBL$")>; -def : InstRW<[GenericDSPShort], (instregex "^DPSU_H_QBR$")>; -def : InstRW<[GenericDSPShort], (instregex "^EXTPDPV$")>; -def : InstRW<[GenericDSPShort], (instregex "^EXTPDP$")>; -def : InstRW<[GenericDSPShort], (instregex "^EXTPV$")>; -def : InstRW<[GenericDSPShort], (instregex "^EXTP$")>; -def : InstRW<[GenericDSPShort], (instregex "^LBUX$")>; -def : InstRW<[GenericDSPShort], (instregex "^LHX$")>; -def : InstRW<[GenericDSPShort], (instregex "^LWX$")>; -def : InstRW<[GenericDSPShort], (instregex "^MADDU_DSP$")>; -def : InstRW<[GenericDSPShort], (instregex "^MADD_DSP$")>; -def : InstRW<[GenericDSPShort], (instregex "^MAQ_SA_W_PHL$")>; -def : InstRW<[GenericDSPShort], (instregex "^MAQ_SA_W_PHR$")>; -def : InstRW<[GenericDSPShort], (instregex "^MAQ_S_W_PHL$")>; -def : InstRW<[GenericDSPShort], (instregex "^MAQ_S_W_PHR$")>; -def : InstRW<[GenericDSPShort], (instregex "^MFHI_DSP$")>; -def : InstRW<[GenericDSPShort], (instregex "^MFLO_DSP$")>; -def : InstRW<[GenericDSPShort], (instregex "^MODSUB$")>; -def : InstRW<[GenericDSPShort], (instregex "^MSUBU_DSP$")>; -def : InstRW<[GenericDSPShort], (instregex "^MSUB_DSP$")>; -def : InstRW<[GenericDSPShort], (instregex "^MULEQ_S_W_PHL$")>; -def : InstRW<[GenericDSPShort], (instregex "^MULEQ_S_W_PHR$")>; -def : InstRW<[GenericDSPShort], (instregex "^MULEU_S_PH_QBL$")>; -def : InstRW<[GenericDSPShort], (instregex "^MULEU_S_PH_QBR$")>; -def : InstRW<[GenericDSPShort], (instregex "^MULQ_RS_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^MULSAQ_S_W_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^MULTU_DSP$")>; -def : InstRW<[GenericDSPShort], (instregex "^MULT_DSP$")>; -def : InstRW<[GenericDSPShort], (instregex "^PACKRL_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^PICK_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^PICK_QB$")>; -def : InstRW<[GenericDSPShort], (instregex "^PRECEQU_PH_QBLA$")>; -def : InstRW<[GenericDSPShort], (instregex "^PRECEQU_PH_QBL$")>; -def : InstRW<[GenericDSPShort], (instregex "^PRECEQU_PH_QBRA$")>; -def : InstRW<[GenericDSPShort], (instregex "^PRECEQU_PH_QBR$")>; -def : InstRW<[GenericDSPShort], (instregex "^PRECEQ_W_PHL$")>; -def : InstRW<[GenericDSPShort], (instregex "^PRECEQ_W_PHR$")>; -def : InstRW<[GenericDSPShort], (instregex "^PRECEU_PH_QBLA$")>; -def : InstRW<[GenericDSPShort], (instregex "^PRECEU_PH_QBL$")>; -def : InstRW<[GenericDSPShort], (instregex "^PRECEU_PH_QBRA$")>; -def : InstRW<[GenericDSPShort], (instregex "^PRECEU_PH_QBR$")>; -def : InstRW<[GenericDSPShort], (instregex "^PRECRQU_S_QB_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^PRECRQ_PH_W$")>; -def : InstRW<[GenericDSPShort], (instregex "^PRECRQ_QB_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^PRECRQ_RS_PH_W$")>; -def : InstRW<[GenericDSPShort], (instregex "^RADDU_W_QB$")>; -def : InstRW<[GenericDSPShort], (instregex "^RDDSP$")>; -def : InstRW<[GenericDSPShort], (instregex "^REPLV_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^REPLV_QB$")>; -def : InstRW<[GenericDSPShort], (instregex "^REPL_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^REPL_QB$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHILOV$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHILO$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHLLV_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHLLV_QB$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHLLV_S_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHLLV_S_W$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHLL_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHLL_QB$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHLL_S_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHLL_S_W$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHRAV_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHRAV_R_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHRAV_R_W$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHRA_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHRA_R_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHRA_R_W$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHRLV_QB$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHRL_QB$")>; -def : InstRW<[GenericDSPShort], (instregex "^SUBQ_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^SUBQ_S_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^SUBQ_S_W$")>; -def : InstRW<[GenericDSPShort], (instregex "^SUBU_QB$")>; -def : InstRW<[GenericDSPShort], (instregex "^SUBU_S_QB$")>; -def : InstRW<[GenericDSPShort], (instregex "^WRDSP$")>; - -def : InstRW<[GenericDSPShort], - (instregex "^Pseudo(CMP|CMPU)_(EQ|LE|LT)_(PH|QB)$")>; -def : InstRW<[GenericDSPShort], - (instregex "^PseudoPICK_(PH|QB)$")>; - -// MIPS DSP R2 - hasDSP, HasDSPR2, InMicroMips -// =========================================== - -def : InstRW<[GenericDSPShort], (instregex "^ABSQ_S_QB$")>; -def : InstRW<[GenericDSPShort], (instregex "^ADDQH_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^ADDQH_R_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^ADDQH_R_W$")>; -def : InstRW<[GenericDSPShort], (instregex "^ADDQH_W$")>; -def : InstRW<[GenericDSPShort], (instregex "^ADDUH_QB$")>; -def : InstRW<[GenericDSPShort], (instregex "^ADDUH_R_QB$")>; -def : InstRW<[GenericDSPShort], (instregex "^ADDU_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^ADDU_S_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^APPEND$")>; -def : InstRW<[GenericDSPShort], (instregex "^BALIGN$")>; -def : InstRW<[GenericDSPShort], (instregex "^CMPGDU_EQ_QB$")>; -def : InstRW<[GenericDSPShort], (instregex "^CMPGDU_LE_QB$")>; -def : InstRW<[GenericDSPShort], (instregex "^CMPGDU_LT_QB$")>; -def : InstRW<[GenericDSPShort], (instregex "^DPA_W_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^DPAQX_SA_W_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^DPAQX_S_W_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^DPAX_W_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^DPS_W_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^DPSQX_S_W_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^DPSQX_SA_W_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^DPSX_W_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^MUL_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^MUL_S_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^MULQ_RS_W$")>; -def : InstRW<[GenericDSPShort], (instregex "^MULQ_S_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^MULQ_S_W$")>; -def : InstRW<[GenericDSPShort], (instregex "^MULSA_W_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^PRECR_QB_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^PRECR_SRA_PH_W$")>; -def : InstRW<[GenericDSPShort], (instregex "^PRECR_SRA_R_PH_W$")>; -def : InstRW<[GenericDSPShort], (instregex "^PREPEND$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHRA_QB$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHRA_R_QB$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHRAV_QB$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHRAV_R_QB$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHRL_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHRLV_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^SUBQH_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^SUBQH_R_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^SUBQH_W$")>; -def : InstRW<[GenericDSPShort], (instregex "^SUBQH_R_W$")>; -def : InstRW<[GenericDSPShort], (instregex "^SUBU_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^SUBU_S_PH$")>; -def : InstRW<[GenericDSPShort], (instregex "^SUBUH_QB$")>; -def : InstRW<[GenericDSPShort], (instregex "^SUBUH_R_QB$")>; - -// microMIPS DSP R1 - HasDSP, InMicroMips -// ====================================== - -def : InstRW<[GenericWriteLoad], (instrs LWDSP_MM)>; - -def : InstRW<[GenericWriteStore], (instrs SWDSP_MM)>; - -def : InstRW<[GenericDSPShort], (instregex "^ABSQ_S_PH_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^ABSQ_S_W_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^ADDQ_PH_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^ADDQ_S_PH_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^ADDQ_S_W_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^ADDSC_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^ADDU_QB_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^ADDU_S_QB_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^ADDWC_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^BITREV_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^BPOSGE32_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^CMPGU_EQ_QB_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^CMPGU_LE_QB_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^CMPGU_LT_QB_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^CMPU_EQ_QB_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^CMPU_LE_QB_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^CMPU_LT_QB_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^CMP_EQ_PH_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^CMP_LE_PH_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^CMP_LT_PH_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^DPAQ_SA_L_W_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^DPAQ_S_W_PH_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^DPAU_H_QBL_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^DPAU_H_QBR_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^DPSQ_SA_L_W_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^DPSQ_S_W_PH_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^DPSU_H_QBL_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^DPSU_H_QBR_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^EXTPDPV_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^EXTPDP_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^EXTPV_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^EXTP_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^EXTRV_RS_W_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^EXTRV_R_W_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^EXTRV_S_H_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^EXTRV_W_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^EXTR_RS_W_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^EXTR_R_W_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^EXTR_S_H_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^EXTR_W_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^INSV_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^LBUX_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^LHX_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^LWX_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^MADDU_DSP_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^MADD_DSP_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^MAQ_SA_W_PHL_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^MAQ_SA_W_PHR_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^MAQ_S_W_PHL_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^MAQ_S_W_PHR_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^MFHI_DSP_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^MFLO_DSP_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^MODSUB_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^MOVEP_MMR6$")>; -def : InstRW<[GenericDSPShort], (instregex "^MOVN_I_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^MOVZ_I_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^MSUBU_DSP_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^MSUB_DSP_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^MTHI_DSP_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^MTHLIP_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^MTLO_DSP_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^MULEQ_S_W_PHL_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^MULEQ_S_W_PHR_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^MULEU_S_PH_QBL_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^MULEU_S_PH_QBR_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^MULQ_RS_PH_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^MULSAQ_S_W_PH_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^MULTU_DSP_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^MULT_DSP_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^PACKRL_PH_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^PICK_PH_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^PICK_QB_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^PRECEQU_PH_QBLA_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^PRECEQU_PH_QBL_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^PRECEQU_PH_QBRA_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^PRECEQU_PH_QBR_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^PRECEQ_W_PHL_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^PRECEQ_W_PHR_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^PRECEU_PH_QBLA_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^PRECEU_PH_QBL_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^PRECEU_PH_QBRA_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^PRECEU_PH_QBR_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^PRECRQU_S_QB_PH_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^PRECRQ_PH_W_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^PRECRQ_QB_PH_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^PRECRQ_RS_PH_W_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^RADDU_W_QB_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^RDDSP_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^REPLV_PH_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^REPLV_QB_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^REPL_PH_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^REPL_QB_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHILOV_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHILO_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHLLV_PH_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHLLV_QB_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHLLV_S_PH_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHLLV_S_W_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHLL_PH_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHLL_QB_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHLL_S_PH_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHLL_S_W_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHRAV_PH_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHRAV_R_PH_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHRAV_R_W_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHRA_PH_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHRA_R_PH_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHRA_R_W_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHRLV_QB_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHRL_QB_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^SUBQ_PH_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^SUBQ_S_PH_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^SUBQ_S_W_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^SUBU_QB_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^SUBU_S_QB_MM$")>; -def : InstRW<[GenericDSPShort], (instregex "^WRDSP_MM$")>; - - -// microMIPS DSP R2 - hasDSP, HasDSPR2, InMicroMips -// ================================================ - -def : InstRW<[GenericDSPShort], (instregex "^ABSQ_S_QB_MMR2$")>; -def : InstRW<[GenericDSPShort], (instregex "^ADDQH_PH_MMR2$")>; -def : InstRW<[GenericDSPShort], (instregex "^ADDQH_R_PH_MMR2$")>; -def : InstRW<[GenericDSPShort], (instregex "^ADDQH_R_W_MMR2$")>; -def : InstRW<[GenericDSPShort], (instregex "^ADDQH_W_MMR2$")>; -def : InstRW<[GenericDSPShort], (instregex "^ADDUH_QB_MMR2$")>; -def : InstRW<[GenericDSPShort], (instregex "^ADDUH_R_QB_MMR2$")>; -def : InstRW<[GenericDSPShort], (instregex "^ADDU_PH_MMR2$")>; -def : InstRW<[GenericDSPShort], (instregex "^ADDU_S_PH_MMR2$")>; -def : InstRW<[GenericDSPShort], (instregex "^APPEND_MMR2$")>; -def : InstRW<[GenericDSPShort], (instregex "^BALIGN_MMR2$")>; -def : InstRW<[GenericDSPShort], (instregex "^CMPGDU_EQ_QB_MMR2$")>; -def : InstRW<[GenericDSPShort], (instregex "^CMPGDU_LE_QB_MMR2$")>; -def : InstRW<[GenericDSPShort], (instregex "^CMPGDU_LT_QB_MMR2$")>; -def : InstRW<[GenericDSPShort], (instregex "^DPA_W_PH_MMR2$")>; -def : InstRW<[GenericDSPShort], (instregex "^DPAQX_SA_W_PH_MMR2$")>; -def : InstRW<[GenericDSPShort], (instregex "^DPAQX_S_W_PH_MMR2$")>; -def : InstRW<[GenericDSPShort], (instregex "^DPAX_W_PH_MMR2$")>; -def : InstRW<[GenericDSPShort], (instregex "^DPS_W_PH_MMR2$")>; -def : InstRW<[GenericDSPShort], (instregex "^DPSQX_S_W_PH_MMR2$")>; -def : InstRW<[GenericDSPShort], (instregex "^DPSQX_SA_W_PH_MMR2$")>; -def : InstRW<[GenericDSPShort], (instregex "^DPSX_W_PH_MMR2$")>; -def : InstRW<[GenericDSPShort], (instregex "^MUL_PH_MMR2$")>; -def : InstRW<[GenericDSPShort], (instregex "^MUL_S_PH_MMR2$")>; -def : InstRW<[GenericDSPShort], (instregex "^MULQ_RS_W_MMR2$")>; -def : InstRW<[GenericDSPShort], (instregex "^MULQ_S_PH_MMR2$")>; -def : InstRW<[GenericDSPShort], (instregex "^MULQ_S_W_MMR2$")>; -def : InstRW<[GenericDSPShort], (instregex "^MULSA_W_PH_MMR2$")>; -def : InstRW<[GenericDSPShort], (instregex "^PRECR_QB_PH_MMR2$")>; -def : InstRW<[GenericDSPShort], (instregex "^PRECR_SRA_PH_W_MMR2$")>; -def : InstRW<[GenericDSPShort], (instregex "^PRECR_SRA_R_PH_W_MMR2$")>; -def : InstRW<[GenericDSPShort], (instregex "^PREPEND_MMR2$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHRA_QB_MMR2$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHRA_R_QB_MMR2$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHRAV_QB_MMR2$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHRAV_R_QB_MMR2$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHRL_PH_MMR2$")>; -def : InstRW<[GenericDSPShort], (instregex "^SHRLV_PH_MMR2$")>; -def : InstRW<[GenericDSPShort], (instregex "^SUBQH_PH_MMR2$")>; -def : InstRW<[GenericDSPShort], (instregex "^SUBQH_R_PH_MMR2$")>; -def : InstRW<[GenericDSPShort], (instregex "^SUBQH_W_MMR2$")>; -def : InstRW<[GenericDSPShort], (instregex "^SUBQH_R_W_MMR2$")>; -def : InstRW<[GenericDSPShort], (instregex "^SUBU_PH_MMR2$")>; -def : InstRW<[GenericDSPShort], (instregex "^SUBU_S_PH_MMR2$")>; -def : InstRW<[GenericDSPShort], (instregex "^SUBUH_QB_MMR2$")>; -def : InstRW<[GenericDSPShort], (instregex "^SUBUH_R_QB_MMR2$")>; - -// microMIPS DSP R3 - hasDSP, hasDSPR2, hasDSPR3, InMicroMips -// ========================================================== - -def : InstRW<[GenericDSPShort], (instregex "^BPOSGE32C_MMR3$")>; - -// MIPS MSA ASE - hasMSA -// ===================== - -def GenericWriteMSAShortLogic : SchedWriteRes<[GenericIssueFPUS]>; -def GenericWriteMSAShortInt : SchedWriteRes<[GenericIssueFPUS]> { -let Latency = 2; -} -def GenericWriteMoveOtherUnitsToFPU : SchedWriteRes<[GenericIssueFPUS]>; -def GenericWriteMSAOther3 : SchedWriteRes<[GenericIssueFPUS]> { -let Latency = 3; -} -def GenericWriteMSALongInt : SchedWriteRes<[GenericIssueFPUS]> { -let Latency = 5; -} -def GenericWriteFPUDivI : SchedWriteRes<[GenericFPQ]> { - let Latency = 33; - let ResourceCycles = [ 33 ]; -} - -// FPUS is also used in moves from floating point and MSA registers to general -// purpose registers. -def GenericWriteMoveFPUSToOtherUnits : SchedWriteRes<[GenericIssueFPUS]> { - let Latency = 0; -} - -// FPUL is also used in moves from floating point and MSA registers to general -// purpose registers. -def GenericWriteMoveFPULToOtherUnits : SchedWriteRes<[GenericIssueFPUL]>; - - -// adds_a.[bhwd], adds_[asu].[bhwd], addvi?.[bhwd], asub_[us].[bhwd], -// aver?_[us].[bhwd] -def : InstRW<[GenericWriteMSAShortInt], (instregex "^ADD_A_[BHWD]$")>; -def : InstRW<[GenericWriteMSAShortInt], (instregex "^ADDS_[ASU]_[BHWD]$")>; - -// TODO: ADDVI_[BHW] might be 1 cycle latency rather than 2. Need to confirm it. -// add.[bhwd], addvi.[bhwd], asub_[us].[bhwd], ave.[bhwd], aver.[bhwd] -def : InstRW<[GenericWriteMSAShortInt], (instregex "^ADDVI?_[BHWD]$")>; -def : InstRW<[GenericWriteMSAShortInt], (instregex "^ASUB_[US].[BHWD]$")>; -def : InstRW<[GenericWriteMSAShortInt], (instregex "^AVER?_[US].[BHWD]$")>; - -// and.v, andi.b, move.v, ldi.[bhwd], xor.v, nor.v, xori.b, nori.b, lsa -def : InstRW<[GenericWriteMSAShortLogic], (instregex "^MOVE_V$")>; -def : InstRW<[GenericWriteMSAShortLogic], (instregex "^LDI_[BHWD]$")>; -def : InstRW<[GenericWriteMSAShortLogic], (instrs LSA)>; -def : InstRW<[GenericWriteMSAShortLogic], (instregex "^(AND|OR|[XN]OR)_V$")>; -def : InstRW<[GenericWriteMSAShortLogic], (instregex "^(AND|OR|[XN]OR)I_B$")>; -def : InstRW<[GenericWriteMSAShortLogic], - (instregex "^(AND|OR|[XN]OR)_V_[DHW]_PSEUDO$")>; - -// vshf.[bhwd], binsl.[bhwd], binsr.[bhwd], insert.[bhwd], sld?.[bhwd], -// bset.[bhwd], bclr.[bhwd], bneg.[bhwd], bsel_v, bseli_b -def : InstRW<[GenericWriteMSAShortInt], (instregex "^VSHF_[BHWD]$")>; -def : InstRW<[GenericWriteMSAShortInt], (instregex "^(BINSL|BINSLI)_[BHWD]$")>; -def : InstRW<[GenericWriteMSAShortInt], (instregex "^(BINSR|BINSRI)_[BHWD]$")>; -def : InstRW<[GenericWriteMSAShortInt], (instregex "^INSERT_[BHWD]$")>; -def : InstRW<[GenericWriteMSAShortInt], (instregex "^(SLD|SLDI)_[BHWD]$")>; -def : InstRW<[GenericWriteMSAShortInt], (instregex "^(BSET|BSETI)_[BHWD]$")>; -def : InstRW<[GenericWriteMSAShortInt], (instregex "^(BCLR|BCLRI)_[BHWD]$")>; -def : InstRW<[GenericWriteMSAShortInt], (instregex "^(BNEG|BNEGI)_[BHWD]$")>; -def : InstRW<[GenericWriteMSAShortInt], (instregex "^(BSEL_V|BSELI_B)$")>; -def : InstRW<[GenericWriteMSAShortInt], (instregex "^BMN*Z.*$")>; -def : InstRW<[GenericWriteMSAShortInt], - (instregex "^BSEL_(H|W|D|FW|FD)_PSEUDO$")>; - -// pcnt.[bhwd], sat_s.[bhwd], sat_u.[bhwd] -def : InstRW<[GenericWriteMSAOther3], (instregex "^PCNT_[BHWD]$")>; -def : InstRW<[GenericWriteMSAOther3], (instregex "^SAT_(S|U)_[BHWD]$")>; - -// bnz.[bhwdv], cfcmsa, ctcmsa -def : InstRW<[GenericWriteMSAShortLogic], (instregex "^(BNZ|BZ)_[BHWDV]$")>; -def : InstRW<[GenericWriteMSAShortLogic], (instregex "^C(F|T)CMSA$")>; - -// shf.[bhw], fill[bhwd], splat?.[bhwd] -def : InstRW<[GenericWriteMSAShortInt], (instregex "^SHF_[BHW]$")>; -def : InstRW<[GenericWriteMSAShortInt], (instregex "^FILL_[BHWD]$")>; -def : InstRW<[GenericWriteMSAShortInt], (instregex "^(SPLAT|SPLATI)_[BHWD]$")>; - -// fexp2_w, fexp2_d -def : InstRW<[GenericWriteFPUS], (instregex "^FEXP2_(W|D)$")>; - -// compare, converts, round to int, floating point truncate. -def : InstRW<[GenericWriteFPUS], (instregex "^(CLT|CLTI)_(S|U)_[BHWD]$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^(CLE|CLEI)_(S|U)_[BHWD]$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^(CEQ|CEQI)_[BHWD]$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^CMP_UN_(S|D)$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^CMP_UEQ_(S|D)$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^CMP_EQ_(S|D)$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^CMP_LT_(S|D)$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^CMP_ULT_(S|D)$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^CMP_LE_(S|D)$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^CMP_ULE_(S|D)$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^CMP_F_(D|S)$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^CMP_SAF_(D|S)$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^CMP_SEQ_(D|S)$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^CMP_SLE_(D|S)$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^CMP_SLT_(D|S)$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^CMP_SUEQ_(D|S)$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^CMP_SULE_(D|S)$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^CMP_SULT_(D|S)$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^CMP_SUN_(D|S)$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^FS(AF|EQ|LT|LE|NE|OR)_(W|D)$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^FSUEQ_(W|D)$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^FSULE_(W|D)$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^FSULT_(W|D)$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^FSUNE_(W|D)$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^FSUN_(W|D)$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^FCAF_(W|D)$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^FCEQ_(W|D)$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^FCLE_(W|D)$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^FCLT_(W|D)$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^FCNE_(W|D)$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^FCOR_(W|D)$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^FCUEQ_(W|D)$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^FCULE_(W|D)$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^FCULT_(W|D)$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^FCUNE_(W|D)$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^FCUN_(W|D)$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^FABS_(W|D)$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^FFINT_(U|S)_(W|D)$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^FFQL_(W|D)$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^FFQR_(W|D)$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^FTINT_(U|S)_(W|D)$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^FRINT_(W|D)$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^FTQ_(H|W)$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^FTRUNC_(U|S)_(W|D)$")>; - -// fexdo.[hw], fexupl.[wd], fexupr.[wd] -def : InstRW<[GenericWriteFPUS], (instregex "^FEXDO_(H|W)$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^FEXUPL_(W|D)$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^FEXUPR_(W|D)$")>; - -// fclass.[wd], fmax.[wd], fmax_a.[wd], fmin.[wd], fmin_a.[wd], flog2.[wd] -def : InstRW<[GenericWriteFPUS], (instregex "^FCLASS_(W|D)$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^FMAX_A_(W|D)$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^FMAX_(W|D)$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^FMIN_A_(W|D)$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^FMIN_(W|D)$")>; -def : InstRW<[GenericWriteFPUS], (instregex "^FLOG2_(W|D)$")>; - -// interleave right/left, interleave even/odd, insert -def : InstRW<[GenericWriteMSAShortLogic], (instregex "^(ILVR|ILVL)_[BHWD]$")>; -def : InstRW<[GenericWriteMSAShortLogic], (instregex "^(ILVEV|ILVOD)_[BHWD]$")>; - -// subs_?.[bhwd], subsus_?.[bhwd], subsuu_?.[bhwd], subvi.[bhwd], subv.[bhwd], -def : InstRW<[GenericWriteMSAShortInt], (instregex "^SUBS_(S|U)_[BHWD]$")>; -def : InstRW<[GenericWriteMSAShortInt], (instregex "^SUBSUS_(S|U)_[BHWD]$")>; -def : InstRW<[GenericWriteMSAShortInt], (instregex "^SUBSUU_(S|U)_[BHWD]$")>; -def : InstRW<[GenericWriteMSAShortInt], (instregex "^SUBVI_[BHWD]$")>; -def : InstRW<[GenericWriteMSAShortInt], (instregex "^SUBV_[BHWD]$")>; - -// mod_[su].[bhwd], div_[su].[bhwd] -def : InstRW<[GenericWriteFPUDivI], (instregex "^MOD_(S|U)_[BHWD]$")>; -def : InstRW<[GenericWriteFPUDivI], (instregex "^DIV_(S|U)_[BHWD]$")>; - -// hadd_[su].[bhwd], hsub_[su].[bhwd], max_[sua].[bhwd], min_[sua].[bhwd], -// maxi_[su].[bhwd], mini_[su].[bhwd], sra?.[bhwd], srar?.[bhwd], srlr.[bhwd], -// sll?.[bhwd], pckev.[bhwd], pckod.[bhwd], nloc.[bhwd], nlzc.[bhwd], -// insve.[bhwd] -def : InstRW<[GenericWriteMSAShortLogic], (instregex "^HADD_(S|U)_[BHWD]$")>; -def : InstRW<[GenericWriteMSAShortLogic], (instregex "^HSUB_(S|U)_[BHWD]$")>; -def : InstRW<[GenericWriteMSAShortLogic], (instregex "^(MAX|MIN)_S_[BHWD]$")>; -def : InstRW<[GenericWriteMSAShortLogic], (instregex "^(MAX|MIN)_U_[BHWD]$")>; -def : InstRW<[GenericWriteMSAShortLogic], (instregex "^(MAX|MIN)_A_[BHWD]$")>; -def : InstRW<[GenericWriteMSAShortLogic], - (instregex "^(MAXI|MINI)_(S|U)_[BHWD]$")>; -def : InstRW<[GenericWriteMSAShortLogic], (instregex "^(SRA|SRAI)_[BHWD]$")>; -def : InstRW<[GenericWriteMSAShortLogic], (instregex "^(SRL|SRLI)_[BHWD]$")>; -def : InstRW<[GenericWriteMSAShortLogic], (instregex "^(SRAR|SRARI)_[BHWD]$")>; -def : InstRW<[GenericWriteMSAShortLogic], (instregex "^(SRLR|SRLRI)_[BHWD]$")>; -def : InstRW<[GenericWriteMSAShortLogic], (instregex "^(SLL|SLLI)_[BHWD]$")>; -def : InstRW<[GenericWriteMSAShortLogic], (instregex "^(PCKEV|PCKOD)_[BHWD]$")>; -def : InstRW<[GenericWriteMSAShortLogic], (instregex "^(NLOC|NLZC)_[BHWD]$")>; -def : InstRW<[GenericWriteMSAShortLogic], (instregex "^INSVE_[BHWD]$")>; -def : InstRW<[GenericWriteMSAShortLogic], (instregex "^INSERT_F(D|W)_PSEUDO$")>; -def : InstRW<[GenericWriteMSAShortLogic], (instregex "^FILL_F(D|W)_PSEUDO$")>; - -// dpadd_?.[bhwd], dpsub_?.[bhwd], dotp_?.[bhwd], msubv.[bhwd], maddv.[bhwd] -// mulv.[bhwd]. -def : InstRW<[GenericWriteMSALongInt], (instregex "^DPADD_(S|U)_[HWD]$")>; -def : InstRW<[GenericWriteMSALongInt], (instregex "^DPSUB_(S|U)_[HWD]$")>; -def : InstRW<[GenericWriteMSALongInt], (instregex "^DOTP_(S|U)_[HWD]$")>; -def : InstRW<[GenericWriteMSALongInt], (instregex "^MSUBV_[BHWD]$")>; -def : InstRW<[GenericWriteMSALongInt], (instregex "^MADDV_[BHWD]$")>; -def : InstRW<[GenericWriteMSALongInt], (instregex "^MULV_[BHWD]$")>; - -// madd?.q.[hw], msub?.q.[hw], mul?.q.[hw] -def : InstRW<[GenericWriteMSALongInt], (instregex "^MADDR_Q_[HW]$")>; -def : InstRW<[GenericWriteMSALongInt], (instregex "^MADD_Q_[HW]$")>; -def : InstRW<[GenericWriteMSALongInt], (instregex "^MSUBR_Q_[HW]$")>; -def : InstRW<[GenericWriteMSALongInt], (instregex "^MSUB_Q_[HW]$")>; -def : InstRW<[GenericWriteMSALongInt], (instregex "^MULR_Q_[HW]$")>; -def : InstRW<[GenericWriteMSALongInt], (instregex "^MUL_Q_[HW]$")>; - -// fadd.[dw], fmadd.[dw], fmul.[dw], frcp.[dw], frsqrt.[dw], fsqrt.[dw] -// fsub.[dw], fdiv.[dw] -def : InstRW<[GenericWriteFPUL], (instregex "^FADD_[DW]$")>; -def : InstRW<[GenericWriteFPUL], (instregex "^FMADD_[DW]$")>; -def : InstRW<[GenericWriteFPUL], (instregex "^FMSUB_[DW]$")>; -def : InstRW<[GenericWriteFPUL], (instregex "^FMUL_[DW]$")>; -def : InstRW<[GenericWriteFPUL], (instregex "^FRCP_[DW]$")>; -def : InstRW<[GenericWriteFPUL], (instregex "^FRSQRT_[DW]$")>; -def : InstRW<[GenericWriteFPUL], (instregex "^FSQRT_[DW]$")>; -def : InstRW<[GenericWriteFPUL], (instregex "^FSUB_[DW]$")>; -def : InstRW<[GenericWriteFPUL], (instregex "^FDIV_[DW]$")>; - -// copy.[su]_[bhwd] -def : InstRW<[GenericWriteFPUMoveGPRFPU], (instregex "^COPY_U_[BHW]$")>; -def : InstRW<[GenericWriteFPUMoveGPRFPU], (instregex "^COPY_S_[BHWD]$")>; - -def : InstRW<[GenericWriteFPUStore], (instregex "^ST_[BHWD]$")>; -def : InstRW<[GenericWriteFPUStore], (instrs ST_F16)>; -def : InstRW<[GenericWriteFPULoad], (instregex "^LD_[BHWD]$")>; -def : InstRW<[GenericWriteFPULoad], (instrs LD_F16)>; - -// Atomic instructions - -// FIXME: Define `WriteAtomic` in the MipsSchedule.td and -// attach it to the Atomic2OpsPostRA, AtomicCmpSwapPostRA, ... -// classes. Then just define resources for the `WriteAtomic` in each -// machine models. -def GenericAtomic : ProcResource<1> { let BufferSize = 1; } -def GenericWriteAtomic : SchedWriteRes<[GenericAtomic]> { let Latency = 2; } - -def : InstRW<[GenericWriteAtomic], - (instregex "^ATOMIC_SWAP_I(8|16|32|64)_POSTRA$")>; -def : InstRW<[GenericWriteAtomic], - (instregex "^ATOMIC_CMP_SWAP_I(8|16|32|64)_POSTRA$")>; -def : InstRW<[GenericWriteAtomic], - (instregex "^ATOMIC_LOAD_(ADD|SUB|AND|OR|XOR|NAND)_I(8|16|32|64)_POSTRA$")>; -} diff --git a/contrib/llvm/lib/Target/Mips/MipsScheduleP5600.td b/contrib/llvm/lib/Target/Mips/MipsScheduleP5600.td deleted file mode 100644 index f68adc3496ab..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsScheduleP5600.td +++ /dev/null @@ -1,636 +0,0 @@ -//==- MipsScheduleP5600.td - P5600 Scheduling Definitions --*- tablegen -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -def MipsP5600Model : SchedMachineModel { - int IssueWidth = 2; // 2x dispatched per cycle - int MicroOpBufferSize = 48; // min(48, 48, 64) - int LoadLatency = 4; - int MispredictPenalty = 8; // TODO: Estimated - - let CompleteModel = 1; - let FullInstRWOverlapCheck = 1; - - list<Predicate> UnsupportedFeatures = [HasMips3, HasMips32r6, HasMips64, - HasMips64r2, HasMips64r5, HasMips64r6, - IsGP64bit, IsPTR64bit, - InMicroMips, InMips16Mode, - HasCnMips, HasCnMipsP, - HasDSP, HasDSPR2, HasMT, HasCRC]; -} - -let SchedModel = MipsP5600Model in { - -// ALQ Pipelines -// ============= - -def P5600ALQ : ProcResource<1> { let BufferSize = 16; } -def P5600IssueALU : ProcResource<1> { let Super = P5600ALQ; } - -// ALU Pipeline -// ------------ - -def P5600WriteALU : SchedWriteRes<[P5600IssueALU]>; - -// and, lui, nor, or, slti, sltiu, sub, subu, xor -def : InstRW<[P5600WriteALU], (instrs AND, LUi, NOR, OR, SLTi, SLTiu, SUB, - SUBu, XOR)>; - -// AGQ Pipelines -// ============= - -def P5600AGQ : ProcResource<3> { let BufferSize = 16; } -def P5600IssueAL2 : ProcResource<1> { let Super = P5600AGQ; } -def P5600IssueCTISTD : ProcResource<1> { let Super = P5600AGQ; } -def P5600IssueLDST : ProcResource<1> { let Super = P5600AGQ; } - -def P5600AL2Div : ProcResource<1>; -// Pseudo-resource used to block CTISTD when handling multi-pipeline splits. -def P5600CTISTD : ProcResource<1>; - -// CTISTD Pipeline -// --------------- - -def P5600WriteJump : SchedWriteRes<[P5600IssueCTISTD, P5600CTISTD]>; -def P5600WriteJumpAndLink : SchedWriteRes<[P5600IssueCTISTD, P5600CTISTD]> { - let Latency = 2; -} - -def P5600Nop : SchedWriteRes<[P5600IssueCTISTD]> { - let Latency = 0; -} - -def : InstRW<[P5600Nop], (instrs SSNOP, NOP)>; - -// b, beq, beql, bg[et]z, bl[et]z, bne, bnel, j, syscall, jal, bltzal, -// jalr, jr.hb, jr -def : InstRW<[P5600WriteJump], (instrs B, BAL, BAL_BR, BEQ, BEQL, BGEZ, BGEZAL, - BGEZALL, BGEZL, BGTZ, BGTZL, BLEZ, BLEZL, BLTZ, - BLTZAL, BLTZALL, BLTZL, BNE, BNEL, BREAK, - DERET, ERET, ERet, ERETNC, J, JR, JR_HB, - PseudoIndirectBranch, - PseudoIndirectHazardBranch, PseudoReturn, - SDBBP, SYSCALL, RetRA, TAILCALL, TAILCALLREG, - TAILCALLREGHB, TEQ, TEQI, TGE, TGEI, TGEIU, - TGEU, TLT, TLTI, TLTU, TNE, TNEI, TRAP, - TTLTIU, WAIT, PAUSE)>; - -def : InstRW<[P5600WriteJumpAndLink], (instrs JAL, JALR, JALRHBPseudo, - JALRPseudo, JALR_HB)>; - -def : InstRW<[P5600WriteJumpAndLink], (instrs JALX)> { - let Unsupported = 1; -} - -def P5600COP0 : SchedWriteRes<[P5600IssueCTISTD, P5600CTISTD]>; - -def : InstRW<[P5600COP0], (instrs TLBINV, TLBINVF, TLBP, TLBR, TLBWI, TLBWR, - MFC0, MTC0)>; - -def P5600COP2 : SchedWriteRes<[P5600IssueCTISTD, P5600CTISTD]>; - -def : InstRW<[P5600COP2], (instrs MFC2, MTC2)> { - let Unsupported = 1; -} - -// MIPS Virtualization ASE -// ======================= -def : InstRW<[P5600COP0], (instrs HYPCALL, MFGC0, MFHGC0, MTGC0, MTHGC0, - TLBGINV, TLBGINVF, TLBGP, TLBGR, TLBGWI, TLBGWR)>; - -// LDST Pipeline -// ------------- - -def P5600WriteLoad : SchedWriteRes<[P5600IssueLDST]> { - let Latency = 4; -} - -def P5600WriteLoadShifted : SchedWriteRes<[P5600IssueLDST, P5600CTISTD]> { - let Latency = 4; -} - -def P5600WriteCache : SchedWriteRes<[P5600IssueLDST]>; - -def P5600WriteStore : SchedWriteRes<[P5600IssueLDST, P5600CTISTD]> { - // FIXME: This is a bit pessimistic. P5600CTISTD is only used during cycle 2 - // not during 0, 1, and 2. - let ResourceCycles = [ 1, 3 ]; -} - -def P5600WriteGPRFromBypass : SchedWriteRes<[P5600IssueLDST]> { - let Latency = 2; -} - -def P5600WriteStoreFromOtherUnits : SchedWriteRes<[P5600IssueLDST]>; -def P5600WriteLoadToOtherUnits : SchedWriteRes<[P5600IssueLDST]> { - let Latency = 0; -} - -// l[bhw], l[bh]u, ll -def : InstRW<[P5600WriteLoad], (instrs LB, LBu, LH, LHu, LW, LL, LWC2, LWC3, - LDC2, LDC3, LBE, LBuE, LHE, LHuE, LWE, LLE, - LWPC)>; - -// lw[lr] -def : InstRW<[P5600WriteLoadShifted], (instrs LWL, LWR, LWLE, LWRE)>; - -// s[bhw], sw[lr] -def : InstRW<[P5600WriteStore], (instrs SB, SH, SW, SWC2, SWC3, SDC2, SDC3, SC, - SBE, SHE, SWE, SCE, SWL, SWR, SWLE, SWRE)>; - -// pref, cache, sync, synci -def : InstRW<[P5600WriteCache], (instrs PREF, PREFE, CACHE, CACHEE, SYNC, - SYNCI)>; - -// LDST is also used in moves from general purpose registers to floating point -// and MSA. -def P5600WriteMoveGPRToOtherUnits : SchedWriteRes<[P5600IssueLDST]> { - let Latency = 0; -} - -// AL2 Pipeline -// ------------ - -def P5600WriteAL2 : SchedWriteRes<[P5600IssueAL2]>; -def P5600WriteAL2BitExt : SchedWriteRes<[P5600IssueAL2]> { let Latency = 2; } -def P5600WriteAL2ShadowMov : SchedWriteRes<[P5600IssueAL2]> { let Latency = 2; } -def P5600WriteAL2CondMov : SchedWriteRes<[P5600IssueAL2, P5600CTISTD]> { - let Latency = 2; -} -def P5600WriteAL2Div : SchedWriteRes<[P5600IssueAL2, P5600AL2Div]> { - // Estimated worst case - let Latency = 34; - let ResourceCycles = [1, 34]; -} -def P5600WriteAL2DivU : SchedWriteRes<[P5600IssueAL2, P5600AL2Div]> { - // Estimated worst case - let Latency = 34; - let ResourceCycles = [1, 34]; -} -def P5600WriteAL2Mul : SchedWriteRes<[P5600IssueAL2]> { let Latency = 3; } -def P5600WriteAL2Mult: SchedWriteRes<[P5600IssueAL2]> { let Latency = 5; } -def P5600WriteAL2MAdd: SchedWriteRes<[P5600IssueAL2, P5600CTISTD]> { - let Latency = 5; -} - -// clo, clz, di, ei, mfhi, mflo -def : InstRW<[P5600WriteAL2], (instrs CLO, CLZ, DI, EI, MFHI, MFLO, - PseudoMFHI, PseudoMFLO)>; - -// ehb, rdhwr, rdpgpr, wrpgpr, wsbh -def : InstRW<[P5600WriteAL2ShadowMov], (instrs EHB, RDHWR, WSBH)>; - -// mov[nz] -def : InstRW<[P5600WriteAL2CondMov], (instrs MOVN_I_I, MOVZ_I_I)>; - -// divu? -def : InstRW<[P5600WriteAL2Div], (instrs DIV, PseudoSDIV, SDIV)>; -def : InstRW<[P5600WriteAL2DivU], (instrs DIVU, PseudoUDIV, UDIV)>; - -// mul -def : InstRW<[P5600WriteAL2Mul], (instrs MUL)>; -// multu?, multu? -def : InstRW<[P5600WriteAL2Mult], (instrs MULT, MULTu, PseudoMULT, - PseudoMULTu)>; -// maddu?, msubu?, mthi, mtlo -def : InstRW<[P5600WriteAL2MAdd], (instrs MADD, MADDU, MSUB, MSUBU, - MTHI, MTLO, PseudoMADD, PseudoMADDU, - PseudoMSUB, PseudoMSUBU, PseudoMTLOHI)>; - -// ext, ins -def : InstRW<[P5600WriteAL2BitExt], (instrs EXT, INS)>; - -// Either ALU or AL2 Pipelines -// --------------------------- -// -// Some instructions can choose between ALU and AL2, but once dispatched to -// ALQ or AGQ respectively they are committed to that path. -// The decision is based on the outcome of the most recent selection when the -// choice was last available. For now, we assume ALU is always chosen. - -def P5600WriteEitherALU : SchedWriteVariant< - // FIXME: Implement selection predicate - [SchedVar<SchedPredicate<[{1}]>, [P5600WriteALU]>, - SchedVar<SchedPredicate<[{0}]>, [P5600WriteAL2]> - ]>; - -// add, addi, addiu, addu, andi, ori, rotr, se[bh], sllv?, sr[al]v?, slt, sltu, -// xori -def : InstRW<[P5600WriteEitherALU], (instrs ADD, ADDi, ADDiu, ANDi, ORi, ROTR, - SEB, SEH, SLT, SLTu, SLL, SRA, SRL, XORi, - ADDu, SLLV, SRAV, SRLV, LSA, COPY)>; - -// FPU Pipelines -// ============= - -def P5600FPQ : ProcResource<3> { let BufferSize = 16; } -def P5600IssueFPUS : ProcResource<1> { let Super = P5600FPQ; } -def P5600IssueFPUL : ProcResource<1> { let Super = P5600FPQ; } -def P5600IssueFPULoad : ProcResource<1> { let Super = P5600FPQ; } - -def P5600FPUDivSqrt : ProcResource<2>; - -def P5600WriteFPUS : SchedWriteRes<[P5600IssueFPUS]>; -def P5600WriteFPUL : SchedWriteRes<[P5600IssueFPUL]> { let Latency = 4; } -def P5600WriteFPUL_MADDSUB : SchedWriteRes<[P5600IssueFPUL]> { let Latency = 6; } -def P5600WriteFPUDivI : SchedWriteRes<[P5600IssueFPUL, P5600FPUDivSqrt]> { - // Best/Common/Worst case = 7 / 23 / 27 - let Latency = 23; // Using common case - let ResourceCycles = [ 1, 23 ]; -} -def P5600WriteFPUDivS : SchedWriteRes<[P5600IssueFPUL, P5600FPUDivSqrt]> { - // Best/Common/Worst case = 7 / 23 / 27 - let Latency = 23; // Using common case - let ResourceCycles = [ 1, 23 ]; -} -def P5600WriteFPUDivD : SchedWriteRes<[P5600IssueFPUL, P5600FPUDivSqrt]> { - // Best/Common/Worst case = 7 / 31 / 35 - let Latency = 31; // Using common case - let ResourceCycles = [ 1, 31 ]; -} -def P5600WriteFPURcpS : SchedWriteRes<[P5600IssueFPUL, P5600FPUDivSqrt]> { - // Best/Common/Worst case = 7 / 19 / 23 - let Latency = 19; // Using common case - let ResourceCycles = [ 1, 19 ]; -} -def P5600WriteFPURcpD : SchedWriteRes<[P5600IssueFPUL, P5600FPUDivSqrt]> { - // Best/Common/Worst case = 7 / 27 / 31 - let Latency = 27; // Using common case - let ResourceCycles = [ 1, 27 ]; -} -def P5600WriteFPURsqrtS : SchedWriteRes<[P5600IssueFPUL, P5600FPUDivSqrt]> { - // Best/Common/Worst case = 7 / 27 / 27 - let Latency = 27; // Using common case - let ResourceCycles = [ 1, 27 ]; -} -def P5600WriteFPURsqrtD : SchedWriteRes<[P5600IssueFPUL, P5600FPUDivSqrt]> { - // Best/Common/Worst case = 7 / 27 / 31 - let Latency = 27; // Using common case - let ResourceCycles = [ 1, 27 ]; -} -def P5600WriteFPUSqrtS : SchedWriteRes<[P5600IssueFPUL, P5600FPUDivSqrt]> { - // Best/Common/Worst case = 7 / 27 / 31 - let Latency = 27; // Using common case - let ResourceCycles = [ 1, 27 ]; -} -def P5600WriteFPUSqrtD : SchedWriteRes<[P5600IssueFPUL, P5600FPUDivSqrt]> { - // Best/Common/Worst case = 7 / 35 / 39 - let Latency = 35; // Using common case - let ResourceCycles = [ 1, 35 ]; -} -def P5600WriteMSAShortLogic : SchedWriteRes<[P5600IssueFPUS]>; -def P5600WriteMSAShortInt : SchedWriteRes<[P5600IssueFPUS]> { let Latency = 2; } -def P5600WriteMoveOtherUnitsToFPU : SchedWriteRes<[P5600IssueFPUS]>; -def P5600WriteMSAOther3 : SchedWriteRes<[P5600IssueFPUS]> { let Latency = 3; } -def P5600WriteMSALongInt : SchedWriteRes<[P5600IssueFPUS]> { let Latency = 5; } - -// vshf.[bhwd], binsl.[bhwd], binsr.[bhwd], insert.[bhwd], sld?.[bhwd], -// bset.[bhwd], bclr.[bhwd], bneg.[bhwd], bsel_v, bseli_b -def : InstRW<[P5600WriteMSAShortInt], (instregex "^VSHF_[BHWD]$")>; -def : InstRW<[P5600WriteMSAShortInt], (instregex "^(BINSL|BINSLI)_[BHWD]$")>; -def : InstRW<[P5600WriteMSAShortInt], (instregex "^(BINSR|BINSRI)_[BHWD]$")>; -def : InstRW<[P5600WriteMSAShortInt], (instregex "^INSERT_[BHWD]$")>; -def : InstRW<[P5600WriteMSAShortInt], (instregex "^(SLD|SLDI)_[BHWD]$")>; -def : InstRW<[P5600WriteMSAShortInt], (instregex "^(BSET|BSETI)_[BHWD]$")>; -def : InstRW<[P5600WriteMSAShortInt], (instregex "^(BCLR|BCLRI)_[BHWD]$")>; -def : InstRW<[P5600WriteMSAShortInt], (instregex "^(BNEG|BNEGI)_[BHWD]$")>; -def : InstRW<[P5600WriteMSAShortInt], (instregex "^(BSEL_V|BSELI_B)$")>; -def : InstRW<[P5600WriteMSAShortInt], (instregex "^BMN*Z.*$")>; -def : InstRW<[P5600WriteMSAShortInt], - (instregex "^BSEL_(H|W|D|FW|FD)_PSEUDO$")>; - -// pcnt.[bhwd], sat_s.[bhwd], sat_u.bhwd] -def : InstRW<[P5600WriteMSAOther3], (instregex "^PCNT_[BHWD]$")>; -def : InstRW<[P5600WriteMSAOther3], (instregex "^SAT_(S|U)_[BHWD]$")>; - -// bnz.[bhwdv], cfcmsa, ctcmsa -def : InstRW<[P5600WriteMSAShortLogic], (instregex "^(BNZ|BZ)_[BHWDV]$")>; -def : InstRW<[P5600WriteMSAShortLogic], (instregex "^C(F|T)CMSA$")>; - -// FPUS is also used in moves from floating point and MSA registers to general -// purpose registers. -def P5600WriteMoveFPUSToOtherUnits : SchedWriteRes<[P5600IssueFPUS]> { - let Latency = 0; -} - -// FPUL is also used in moves from floating point and MSA registers to general -// purpose registers. -def P5600WriteMoveFPULToOtherUnits : SchedWriteRes<[P5600IssueFPUL]>; - -// Short Pipe -// ---------- -// -// abs.[ds], abs.ps, bc1[tf]l?, mov[tf].[ds], mov[tf], mov.[ds], [cm][ft]c1, -// m[ft]hc1, neg.[ds], neg.ps, nor.v, nori.b, or.v, ori.b, xor.v, xori.b, -// sdxc1, sdc1, st.[bhwd], swc1, swxc1 -def : InstRW<[P5600WriteFPUS], (instrs FABS_S, FABS_D32, FABS_D64, MOVF_D32, - MOVF_D64, MOVF_S, MOVT_D32, MOVT_D64, - MOVT_S, FMOV_D32, FMOV_D64, FMOV_S, FNEG_S, - FNEG_D32, FNEG_D64)>; - -// adds_a.[bhwd], adds_[asu].[bhwd], addvi?.[bhwd], asub_[us].[bhwd], -// aver?_[us].[bhwd], shf.[bhw], fill[bhwd], splat?.[bhwd] -def : InstRW<[P5600WriteMSAShortInt], (instregex "^ADD_A_[BHWD]$")>; -def : InstRW<[P5600WriteMSAShortInt], (instregex "^ADDS_[ASU]_[BHWD]$")>; -// TODO: ADDVI_[BHW] might be 1 cycle latency rather than 2. Need to confirm it. -def : InstRW<[P5600WriteMSAShortInt], (instregex "^ADDVI?_[BHWD]$")>; -def : InstRW<[P5600WriteMSAShortInt], (instregex "^ASUB_[US].[BHWD]$")>; -def : InstRW<[P5600WriteMSAShortInt], (instregex "^AVER?_[US].[BHWD]$")>; -def : InstRW<[P5600WriteMSAShortInt], (instregex "^SHF_[BHW]$")>; -def : InstRW<[P5600WriteMSAShortInt], (instregex "^FILL_[BHWD]$")>; -def : InstRW<[P5600WriteMSAShortInt], (instregex "^(SPLAT|SPLATI)_[BHWD]$")>; - -// and.v, andi.b, move.v, ldi.[bhwd] -def : InstRW<[P5600WriteMSAShortLogic], (instregex "^MOVE_V$")>; -def : InstRW<[P5600WriteMSAShortLogic], (instregex "^LDI_[BHWD]$")>; -def : InstRW<[P5600WriteMSAShortLogic], (instregex "^(AND|OR|[XN]OR)_V$")>; -def : InstRW<[P5600WriteMSAShortLogic], (instregex "^(AND|OR|[XN]OR)I_B$")>; -def : InstRW<[P5600WriteMSAShortLogic], - (instregex "^(AND|OR|[XN]OR)_V_[DHW]_PSEUDO$")>; -def : InstRW<[P5600WriteMSAShortLogic], (instregex "^FILL_F(D|W)_PSEUDO$")>; -def : InstRW<[P5600WriteMSAShortLogic], (instregex "^INSERT_F(D|W)_PSEUDO$")>; - -// fexp2_w, fexp2_d -def : InstRW<[P5600WriteFPUS], (instregex "^FEXP2_(W|D)$")>; - -// compare, converts, round to int, floating point truncate. -def : InstRW<[P5600WriteFPUS], (instregex "^(CLT|CLTI)_(S|U)_[BHWD]$")>; -def : InstRW<[P5600WriteFPUS], (instregex "^(CLE|CLEI)_(S|U)_[BHWD]$")>; -def : InstRW<[P5600WriteFPUS], (instregex "^(CEQ|CEQI)_[BHWD]$")>; -def : InstRW<[P5600WriteFPUS], (instregex "^CMP_UN_(S|D)$")>; -def : InstRW<[P5600WriteFPUS], (instregex "^CMP_UEQ_(S|D)$")>; -def : InstRW<[P5600WriteFPUS], (instregex "^CMP_EQ_(S|D)$")>; -def : InstRW<[P5600WriteFPUS], (instregex "^CMP_LT_(S|D)$")>; -def : InstRW<[P5600WriteFPUS], (instregex "^CMP_ULT_(S|D)$")>; -def : InstRW<[P5600WriteFPUS], (instregex "^CMP_LE_(S|D)$")>; -def : InstRW<[P5600WriteFPUS], (instregex "^CMP_ULE_(S|D)$")>; -def : InstRW<[P5600WriteFPUS], (instregex "^FS(AF|EQ|LT|LE|NE|OR)_(W|D)$")>; -def : InstRW<[P5600WriteFPUS], (instregex "^FSUEQ_(W|D)$")>; -def : InstRW<[P5600WriteFPUS], (instregex "^FSULE_(W|D)$")>; -def : InstRW<[P5600WriteFPUS], (instregex "^FSULT_(W|D)$")>; -def : InstRW<[P5600WriteFPUS], (instregex "^FSUNE_(W|D)$")>; -def : InstRW<[P5600WriteFPUS], (instregex "^FSUN_(W|D)$")>; -def : InstRW<[P5600WriteFPUS], (instregex "^FCAF_(W|D)$")>; -def : InstRW<[P5600WriteFPUS], (instregex "^FCEQ_(W|D)$")>; -def : InstRW<[P5600WriteFPUS], (instregex "^FCLE_(W|D)$")>; -def : InstRW<[P5600WriteFPUS], (instregex "^FCLT_(W|D)$")>; -def : InstRW<[P5600WriteFPUS], (instregex "^FCNE_(W|D)$")>; -def : InstRW<[P5600WriteFPUS], (instregex "^FCOR_(W|D)$")>; -def : InstRW<[P5600WriteFPUS], (instregex "^FCUEQ_(W|D)$")>; -def : InstRW<[P5600WriteFPUS], (instregex "^FCULE_(W|D)$")>; -def : InstRW<[P5600WriteFPUS], (instregex "^FCULT_(W|D)$")>; -def : InstRW<[P5600WriteFPUS], (instregex "^FCUNE_(W|D)$")>; -def : InstRW<[P5600WriteFPUS], (instregex "^FCUN_(W|D)$")>; -def : InstRW<[P5600WriteFPUS], (instregex "^FABS_(W|D)$")>; -def : InstRW<[P5600WriteFPUS], (instregex "^FFINT_(U|S)_(W|D)$")>; -def : InstRW<[P5600WriteFPUS], (instregex "^FFQL_(W|D)$")>; -def : InstRW<[P5600WriteFPUS], (instregex "^FFQR_(W|D)$")>; -def : InstRW<[P5600WriteFPUS], (instregex "^FTINT_(U|S)_(W|D)$")>; -def : InstRW<[P5600WriteFPUS], (instregex "^FRINT_(W|D)$")>; -def : InstRW<[P5600WriteFPUS], (instregex "^FTQ_(H|W)$")>; -def : InstRW<[P5600WriteFPUS], (instregex "^FTRUNC_(U|S)_(W|D)$")>; - -// fexdo.[hw], fexupl.[wd], fexupr.[wd] -def : InstRW<[P5600WriteFPUS], (instregex "^FEXDO_(H|W)$")>; -def : InstRW<[P5600WriteFPUS], (instregex "^FEXUPL_(W|D)$")>; -def : InstRW<[P5600WriteFPUS], (instregex "^FEXUPR_(W|D)$")>; - -// fclass.[wd], fmax.[wd], fmax_a.[wd], fmin.[wd], fmin_a.[wd], flog2.[wd] -def : InstRW<[P5600WriteFPUS], (instregex "^FCLASS_(W|D)$")>; -def : InstRW<[P5600WriteFPUS], (instregex "^FMAX_A_(W|D)$")>; -def : InstRW<[P5600WriteFPUS], (instregex "^FMAX_(W|D)$")>; -def : InstRW<[P5600WriteFPUS], (instregex "^FMIN_A_(W|D)$")>; -def : InstRW<[P5600WriteFPUS], (instregex "^FMIN_(W|D)$")>; -def : InstRW<[P5600WriteFPUS], (instregex "^FLOG2_(W|D)$")>; - -// interleave right/left, interleave even/odd, insert -def : InstRW<[P5600WriteMSAShortLogic], (instregex "^(ILVR|ILVL)_[BHWD]$")>; -def : InstRW<[P5600WriteMSAShortLogic], (instregex "^(ILVEV|ILVOD)_[BHWD]$")>; -def : InstRW<[P5600WriteMSAShortLogic], (instregex "^INSVE_[BHWD]$")>; - -// subs_?.[bhwd], subsus_?.[bhwd], subsuu_?.[bhwd], subvi.[bhwd], subv.[bhwd], -def : InstRW<[P5600WriteMSAShortInt], (instregex "^SUBS_(S|U)_[BHWD]$")>; -def : InstRW<[P5600WriteMSAShortInt], (instregex "^SUBSUS_(S|U)_[BHWD]$")>; -def : InstRW<[P5600WriteMSAShortInt], (instregex "^SUBSUU_(S|U)_[BHWD]$")>; -def : InstRW<[P5600WriteMSAShortInt], (instregex "^SUBVI_[BHWD]$")>; -def : InstRW<[P5600WriteMSAShortInt], (instregex "^SUBV_[BHWD]$")>; - -// mod_[su].[bhwd], div_[su].[bhwd] -def : InstRW<[P5600WriteFPUDivI], (instregex "^MOD_(S|U)_[BHWD]$")>; -def : InstRW<[P5600WriteFPUDivI], (instregex "^DIV_(S|U)_[BHWD]$")>; - -// hadd_[su].[bhwd], hsub_[su].[bhwd], max_[sua].[bhwd], min_[sua].[bhwd], -// maxi_[su].[bhwd], mini_[su].[bhwd], sra?.[bhwd], srar?.[bhwd], srlr.[bhwd], -// sll?.[bhwd], pckev.[bhwd], pckod.[bhwd], nloc.[bhwd], nlzc.[bhwd], -// insve.[bhwd] -def : InstRW<[P5600WriteMSAShortLogic], (instregex "^HADD_(S|U)_[BHWD]$")>; -def : InstRW<[P5600WriteMSAShortLogic], (instregex "^HSUB_(S|U)_[BHWD]$")>; -def : InstRW<[P5600WriteMSAShortLogic], (instregex "^(MAX|MIN)_S_[BHWD]$")>; -def : InstRW<[P5600WriteMSAShortLogic], (instregex "^(MAX|MIN)_U_[BHWD]$")>; -def : InstRW<[P5600WriteMSAShortLogic], (instregex "^(MAX|MIN)_A_[BHWD]$")>; -def : InstRW<[P5600WriteMSAShortLogic], (instregex "^(MAXI|MINI)_(S|U)_[BHWD]$")>; -def : InstRW<[P5600WriteMSAShortLogic], (instregex "^(SRA|SRAI)_[BHWD]$")>; -def : InstRW<[P5600WriteMSAShortLogic], (instregex "^(SRL|SRLI)_[BHWD]$")>; -def : InstRW<[P5600WriteMSAShortLogic], (instregex "^(SRAR|SRARI)_[BHWD]$")>; -def : InstRW<[P5600WriteMSAShortLogic], (instregex "^(SRLR|SRLRI)_[BHWD]$")>; -def : InstRW<[P5600WriteMSAShortLogic], (instregex "^(SLL|SLLI)_[BHWD]$")>; -def : InstRW<[P5600WriteMSAShortLogic], (instregex "^(PCKEV|PCKOD)_[BHWD]$")>; -def : InstRW<[P5600WriteMSAShortLogic], (instregex "^(NLOC|NLZC)_[BHWD]$")>; - -// Long Pipe -// ---------- -// -// add.[ds], add.ps, cvt.d.[sw], cvt.s.[dw], cvt.w.[sd], cvt.[sw].ps, -// cvt.ps.[sw], cvt.s.(pl|pu), c.<cc>.[ds], c.<cc>.ps, mul.[ds], mul.ps, -// pl[lu].ps, sub.[ds], sub.ps, trunc.w.[ds], trunc.w.ps -def : InstRW<[P5600WriteFPUL], - (instrs FADD_D32, FADD_D64, FADD_S, FMUL_D32, FMUL_D64, FMUL_S, - FSUB_D32, FSUB_D64, FSUB_S)>; -def : InstRW<[P5600WriteFPUL], (instregex "^TRUNC_(L|W)_(S|D32|D64)$")>; -def : InstRW<[P5600WriteFPUL], - (instregex "^CVT_(S|D32|D64|L|W)_(S|D32|D64|L|W)$")>; -def : InstRW<[P5600WriteFPUL], (instrs CVT_PS_S64, CVT_S_PL64, CVT_S_PU64)>; -def : InstRW<[P5600WriteFPUL], (instregex "^C_[A-Z]+_(S|D32|D64)$")>; -def : InstRW<[P5600WriteFPUL], (instregex "^FCMP_(S32|D32|D64)$")>; -def : InstRW<[P5600WriteFPUL], (instregex "^PseudoCVT_(S|D32|D64)_(L|W)$")>; -def : InstRW<[P5600WriteFPUL], (instrs PLL_PS64, PLU_PS64)>; - -// div.[ds], div.ps -def : InstRW<[P5600WriteFPUDivS], (instrs FDIV_S)>; -def : InstRW<[P5600WriteFPUDivD], (instrs FDIV_D32, FDIV_D64)>; - -// sqrt.[ds], sqrt.ps -def : InstRW<[P5600WriteFPUSqrtS], (instrs FSQRT_S)>; -def : InstRW<[P5600WriteFPUSqrtD], (instrs FSQRT_D32, FSQRT_D64)>; - -// frcp.[wd], frsqrt.[wd] -def : InstRW<[P5600WriteFPURsqrtD], (instregex "^FRCP_(W|D)$")>; -def : InstRW<[P5600WriteFPURsqrtD], (instregex "^FRSQRT_(W|D)$")>; - -def : InstRW<[P5600WriteFPURsqrtD], (instrs RECIP_D32, RECIP_D64, RSQRT_D32, - RSQRT_D64)>; -def : InstRW<[P5600WriteFPURsqrtS], (instrs RECIP_S, RSQRT_S)>; - -// fmadd.[wd], fmsubb.[wd], fdiv.[wd], fsqrt.[wd], fmul.[wd], fadd.[wd], -// fsub.[wd] -def : InstRW<[P5600WriteFPUL_MADDSUB], (instregex "^FMADD_(W|D)$")>; -def : InstRW<[P5600WriteFPUL_MADDSUB], (instregex "^FMSUB_(W|D)$")>; -def : InstRW<[P5600WriteFPUDivS], (instregex "^FDIV_W$")>; -def : InstRW<[P5600WriteFPUDivD], (instregex "^FDIV_D$")>; -def : InstRW<[P5600WriteFPUSqrtS], (instregex "^FSQRT_W$")>; -def : InstRW<[P5600WriteFPUSqrtD], (instregex "^FSQRT_D$")>; -def : InstRW<[P5600WriteFPUL], (instregex "^FMUL_(W|D)$")>; -def : InstRW<[P5600WriteFPUL], (instregex "^FADD_(W|D)$")>; -def : InstRW<[P5600WriteFPUL], (instregex "^FSUB_(W|D)$")>; - -// dpadd_?.[bhwd], dpsub_?.[bhwd], dotp_?.[bhwd], msubv.[bhwd], maddv.[bhwd] -// mulv.[bhwd]. -def : InstRW<[P5600WriteMSALongInt], (instregex "^DPADD_(S|U)_[HWD]$")>; -def : InstRW<[P5600WriteMSALongInt], (instregex "^DPSUB_(S|U)_[HWD]$")>; -def : InstRW<[P5600WriteMSALongInt], (instregex "^DOTP_(S|U)_[HWD]$")>; -def : InstRW<[P5600WriteMSALongInt], (instregex "^MSUBV_[BHWD]$")>; -def : InstRW<[P5600WriteMSALongInt], (instregex "^MADDV_[BHWD]$")>; -def : InstRW<[P5600WriteMSALongInt], (instregex "^MULV_[BHWD]$")>; - -def : InstRW<[P5600WriteMSALongInt], (instregex "^MADDR_Q_[HW]$")>; -def : InstRW<[P5600WriteMSALongInt], (instregex "^MADD_Q_[HW]$")>; -def : InstRW<[P5600WriteMSALongInt], (instregex "^MSUBR_Q_[HW]$")>; -def : InstRW<[P5600WriteMSALongInt], (instregex "^MSUB_Q_[HW]$")>; -def : InstRW<[P5600WriteMSALongInt], (instregex "^MULR_Q_[HW]$")>; -def : InstRW<[P5600WriteMSALongInt], (instregex "^MUL_Q_[HW]$")>; - -// madd.[ds], msub.[ds], nmadd.[ds], nmsub.[ds], -// Operand 0 is read on cycle 5. All other operands are read on operand 0. -def : InstRW<[SchedReadAdvance<5>, P5600WriteFPUL_MADDSUB], - (instrs MADD_D32, MADD_D64, MADD_S, MSUB_D32, MSUB_D64, MSUB_S, - NMADD_D32, NMADD_D64, NMADD_S, NMSUB_D32, NMSUB_D64, NMSUB_S)>; - -// madd.ps, msub.ps, nmadd.ps, nmsub.ps -// Operand 0 and 1 are read on cycle 5. All others are read on operand 0. -// (none of these instructions exist in the backend yet) - -// Load Pipe -// --------- -// -// This is typically used in conjunction with the load pipeline under the AGQ -// All the instructions are in the 'Tricky Instructions' section. - -def P5600WriteLoadOtherUnitsToFPU : SchedWriteRes<[P5600IssueFPULoad]> { - let Latency = 4; -} - -// Tricky Instructions -// =================== -// -// These instructions are split across multiple uops (in different pipelines) -// that must cooperate to complete the operation - -// FIXME: This isn't quite right since the implementation of WriteSequence -// current aggregates the resources and ignores the exact cycle they are -// used. -def P5600WriteMoveGPRToFPU : WriteSequence<[P5600WriteMoveGPRToOtherUnits, - P5600WriteMoveOtherUnitsToFPU]>; - -// FIXME: This isn't quite right since the implementation of WriteSequence -// current aggregates the resources and ignores the exact cycle they are -// used. -def P5600WriteMoveFPUToGPR : WriteSequence<[P5600WriteMoveFPUSToOtherUnits, - P5600WriteGPRFromBypass]>; - -// FIXME: This isn't quite right since the implementation of WriteSequence -// current aggregates the resources and ignores the exact cycle they are -// used. -def P5600WriteStoreFPUS : WriteSequence<[P5600WriteMoveFPUSToOtherUnits, - P5600WriteStoreFromOtherUnits]>; - -// FIXME: This isn't quite right since the implementation of WriteSequence -// current aggregates the resources and ignores the exact cycle they are -// used. -def P5600WriteStoreFPUL : WriteSequence<[P5600WriteMoveFPULToOtherUnits, - P5600WriteStoreFromOtherUnits]>; - -// FIXME: This isn't quite right since the implementation of WriteSequence -// current aggregates the resources and ignores the exact cycle they are -// used. -def P5600WriteLoadFPU : WriteSequence<[P5600WriteLoadToOtherUnits, - P5600WriteLoadOtherUnitsToFPU]>; - -// ctc1, mtc1, mthc1 -def : InstRW<[P5600WriteMoveGPRToFPU], (instrs CTC1, MTC1, MTC1_D64, MTHC1_D32, - MTHC1_D64, BuildPairF64, - BuildPairF64_64)>; - -// copy.[su]_[bhwd] -def : InstRW<[P5600WriteMoveFPUToGPR], (instregex "^COPY_U_[BHW]$")>; -def : InstRW<[P5600WriteMoveFPUToGPR], (instregex "^COPY_S_[BHWD]$")>; - -// bc1[ft], cfc1, mfc1, mfhc1, movf, movt -def : InstRW<[P5600WriteMoveFPUToGPR], (instrs BC1F, BC1FL, BC1T, BC1TL, CFC1, - MFC1, MFC1_D64, MFHC1_D32, MFHC1_D64, - MOVF_I, MOVT_I, ExtractElementF64, - ExtractElementF64_64)>; - -// swc1, swxc1, st.[bhwd] -def : InstRW<[P5600WriteStoreFPUS], (instrs SDC1, SDC164, SDXC1, SDXC164, - SWC1, SWXC1, SUXC1, SUXC164)>; -def : InstRW<[P5600WriteStoreFPUS], (instregex "^ST_[BHWD]$")>; -def : InstRW<[P5600WriteStoreFPUS], (instrs ST_F16)>; - -// movn.[ds], movz.[ds] -def : InstRW<[P5600WriteStoreFPUL], (instrs MOVN_I_D32, MOVN_I_D64, MOVN_I_S, - MOVZ_I_D32, MOVZ_I_D64, MOVZ_I_S)>; - -// l[dw]x?c1, ld.[bhwd] -def : InstRW<[P5600WriteLoadFPU], (instrs LDC1, LDC164, LDXC1, LDXC164, - LWC1, LWXC1, LUXC1, LUXC164)>; -def : InstRW<[P5600WriteLoadFPU], (instregex "LD_[BHWD]")>; -def : InstRW<[P5600WriteLoadFPU], (instrs LD_F16)>; - -// Unsupported Instructions -// ======================== -// -// The following instruction classes are never valid on P5600. -// II_DADDIU, II_DADDU, II_DMFC1, II_DMTC1, II_DMULT, II_DMULTU, II_DROTR, -// II_DROTR32, II_DROTRV, II_DDIV, II_DSLL, II_DSLL32, II_DSLLV, II_DSRA, -// II_DSRA32, II_DSRAV, II_DSRL, II_DSRL32, II_DSRLV, II_DSUBU, II_DDIVU, -// II_JALRC, II_LD, II_LD[LR], II_RESTORE, II_SAVE, II_SD, II_SDC1, II_SD[LR] -// -// The following instructions are never valid on P5600. -// addq.ph, repl.ph, repl.qb, subq.ph, subu_s.qb -// -// Guesswork -// ========= -// -// This section is largely temporary guesswork. - -// ceil.[lw].[ds], floor.[lw].[ds] -// Reason behind guess: trunc.[lw].ds and the various cvt's are in FPUL -def : InstRW<[P5600WriteFPUL], (instregex "^CEIL_(L|W)_(S|D32|D64)$")>; -def : InstRW<[P5600WriteFPUL], (instregex "^FLOOR_(L|W)_(S|D32|D64)$")>; -def : InstRW<[P5600WriteFPUL], (instregex "^ROUND_(L|W)_(S|D32|D64)$")>; - -// rotrv -// Reason behind guess: rotr is in the same category and the two register forms -// generally follow the immediate forms in this category -def : InstRW<[P5600WriteEitherALU], (instrs ROTRV)>; - -// Atomic instructions - -// FIXME: Define `WriteAtomic` in the MipsSchedule.td and -// attach it to the Atomic2OpsPostRA, AtomicCmpSwapPostRA, ... -// classes. Then just define resources for the `WriteAtomic` in each -// machine models. -def P5600Atomic : ProcResource<1> { let BufferSize = 1; } -def P5600WriteAtomic : SchedWriteRes<[P5600Atomic]> { let Latency = 2; } - -def : InstRW<[P5600WriteAtomic], - (instregex "^ATOMIC_SWAP_I(8|16|32|64)_POSTRA$")>; -def : InstRW<[P5600WriteAtomic], - (instregex "^ATOMIC_CMP_SWAP_I(8|16|32|64)_POSTRA$")>; -def : InstRW<[P5600WriteAtomic], - (instregex "^ATOMIC_LOAD_(ADD|SUB|AND|OR|XOR|NAND)_I(8|16|32|64)_POSTRA$")>; -} diff --git a/contrib/llvm/lib/Target/Mips/MipsSubtarget.cpp b/contrib/llvm/lib/Target/Mips/MipsSubtarget.cpp deleted file mode 100644 index d021b3d021b1..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsSubtarget.cpp +++ /dev/null @@ -1,291 +0,0 @@ -//===-- MipsSubtarget.cpp - Mips Subtarget Information --------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements the Mips specific subclass of TargetSubtargetInfo. -// -//===----------------------------------------------------------------------===// - -#include "MipsSubtarget.h" -#include "Mips.h" -#include "MipsMachineFunction.h" -#include "MipsRegisterInfo.h" -#include "MipsTargetMachine.h" -#include "MipsCallLowering.h" -#include "MipsLegalizerInfo.h" -#include "MipsRegisterBankInfo.h" -#include "llvm/IR/Attributes.h" -#include "llvm/IR/Function.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/TargetRegistry.h" -#include "llvm/Support/raw_ostream.h" - -using namespace llvm; - -#define DEBUG_TYPE "mips-subtarget" - -#define GET_SUBTARGETINFO_TARGET_DESC -#define GET_SUBTARGETINFO_CTOR -#include "MipsGenSubtargetInfo.inc" - -// FIXME: Maybe this should be on by default when Mips16 is specified -// -static cl::opt<bool> - Mixed16_32("mips-mixed-16-32", cl::init(false), - cl::desc("Allow for a mixture of Mips16 " - "and Mips32 code in a single output file"), - cl::Hidden); - -static cl::opt<bool> Mips_Os16("mips-os16", cl::init(false), - cl::desc("Compile all functions that don't use " - "floating point as Mips 16"), - cl::Hidden); - -static cl::opt<bool> Mips16HardFloat("mips16-hard-float", cl::NotHidden, - cl::desc("Enable mips16 hard float."), - cl::init(false)); - -static cl::opt<bool> - Mips16ConstantIslands("mips16-constant-islands", cl::NotHidden, - cl::desc("Enable mips16 constant islands."), - cl::init(true)); - -static cl::opt<bool> - GPOpt("mgpopt", cl::Hidden, - cl::desc("Enable gp-relative addressing of mips small data items")); - -bool MipsSubtarget::DspWarningPrinted = false; -bool MipsSubtarget::MSAWarningPrinted = false; -bool MipsSubtarget::VirtWarningPrinted = false; -bool MipsSubtarget::CRCWarningPrinted = false; -bool MipsSubtarget::GINVWarningPrinted = false; - -void MipsSubtarget::anchor() {} - -MipsSubtarget::MipsSubtarget(const Triple &TT, StringRef CPU, StringRef FS, - bool little, const MipsTargetMachine &TM, - unsigned StackAlignOverride) - : MipsGenSubtargetInfo(TT, CPU, FS), MipsArchVersion(MipsDefault), - IsLittle(little), IsSoftFloat(false), IsSingleFloat(false), IsFPXX(false), - NoABICalls(false), Abs2008(false), IsFP64bit(false), UseOddSPReg(true), - IsNaN2008bit(false), IsGP64bit(false), HasVFPU(false), HasCnMips(false), - HasMips3_32(false), HasMips3_32r2(false), HasMips4_32(false), - HasMips4_32r2(false), HasMips5_32r2(false), InMips16Mode(false), - InMips16HardFloat(Mips16HardFloat), InMicroMipsMode(false), HasDSP(false), - HasDSPR2(false), HasDSPR3(false), AllowMixed16_32(Mixed16_32 | Mips_Os16), - Os16(Mips_Os16), HasMSA(false), UseTCCInDIV(false), HasSym32(false), - HasEVA(false), DisableMadd4(false), HasMT(false), HasCRC(false), - HasVirt(false), HasGINV(false), UseIndirectJumpsHazard(false), - StackAlignOverride(StackAlignOverride), - TM(TM), TargetTriple(TT), TSInfo(), - InstrInfo( - MipsInstrInfo::create(initializeSubtargetDependencies(CPU, FS, TM))), - FrameLowering(MipsFrameLowering::create(*this)), - TLInfo(MipsTargetLowering::create(TM, *this)) { - - if (MipsArchVersion == MipsDefault) - MipsArchVersion = Mips32; - - // Don't even attempt to generate code for MIPS-I and MIPS-V. They have not - // been tested and currently exist for the integrated assembler only. - if (MipsArchVersion == Mips1) - report_fatal_error("Code generation for MIPS-I is not implemented", false); - if (MipsArchVersion == Mips5) - report_fatal_error("Code generation for MIPS-V is not implemented", false); - - // Check if Architecture and ABI are compatible. - assert(((!isGP64bit() && isABI_O32()) || - (isGP64bit() && (isABI_N32() || isABI_N64()))) && - "Invalid Arch & ABI pair."); - - if (hasMSA() && !isFP64bit()) - report_fatal_error("MSA requires a 64-bit FPU register file (FR=1 mode). " - "See -mattr=+fp64.", - false); - - if (isFP64bit() && !hasMips64() && hasMips32() && !hasMips32r2()) - report_fatal_error( - "FPU with 64-bit registers is not available on MIPS32 pre revision 2. " - "Use -mcpu=mips32r2 or greater."); - - if (!isABI_O32() && !useOddSPReg()) - report_fatal_error("-mattr=+nooddspreg requires the O32 ABI.", false); - - if (IsFPXX && (isABI_N32() || isABI_N64())) - report_fatal_error("FPXX is not permitted for the N32/N64 ABI's.", false); - - if (hasMips64r6() && InMicroMipsMode) - report_fatal_error("microMIPS64R6 is not supported", false); - - if (!isABI_O32() && InMicroMipsMode) - report_fatal_error("microMIPS64 is not supported.", false); - - if (UseIndirectJumpsHazard) { - if (InMicroMipsMode) - report_fatal_error( - "cannot combine indirect jumps with hazard barriers and microMIPS"); - if (!hasMips32r2()) - report_fatal_error( - "indirect jumps with hazard barriers requires MIPS32R2 or later"); - } - if (inAbs2008Mode() && hasMips32() && !hasMips32r2()) { - report_fatal_error("IEEE 754-2008 abs.fmt is not supported for the given " - "architecture.", - false); - } - - if (hasMips32r6()) { - StringRef ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6"; - - assert(isFP64bit()); - assert(isNaN2008()); - assert(inAbs2008Mode()); - if (hasDSP()) - report_fatal_error(ISA + " is not compatible with the DSP ASE", false); - } - - if (NoABICalls && TM.isPositionIndependent()) - report_fatal_error("position-independent code requires '-mabicalls'"); - - if (isABI_N64() && !TM.isPositionIndependent() && !hasSym32()) - NoABICalls = true; - - // Set UseSmallSection. - UseSmallSection = GPOpt; - if (!NoABICalls && GPOpt) { - errs() << "warning: cannot use small-data accesses for '-mabicalls'" - << "\n"; - UseSmallSection = false; - } - - if (hasDSPR2() && !DspWarningPrinted) { - if (hasMips64() && !hasMips64r2()) { - errs() << "warning: the 'dspr2' ASE requires MIPS64 revision 2 or " - << "greater\n"; - DspWarningPrinted = true; - } else if (hasMips32() && !hasMips32r2()) { - errs() << "warning: the 'dspr2' ASE requires MIPS32 revision 2 or " - << "greater\n"; - DspWarningPrinted = true; - } - } else if (hasDSP() && !DspWarningPrinted) { - if (hasMips64() && !hasMips64r2()) { - errs() << "warning: the 'dsp' ASE requires MIPS64 revision 2 or " - << "greater\n"; - DspWarningPrinted = true; - } else if (hasMips32() && !hasMips32r2()) { - errs() << "warning: the 'dsp' ASE requires MIPS32 revision 2 or " - << "greater\n"; - DspWarningPrinted = true; - } - } - - StringRef ArchName = hasMips64() ? "MIPS64" : "MIPS32"; - - if (!hasMips32r5() && hasMSA() && !MSAWarningPrinted) { - errs() << "warning: the 'msa' ASE requires " << ArchName - << " revision 5 or greater\n"; - MSAWarningPrinted = true; - } - if (!hasMips32r5() && hasVirt() && !VirtWarningPrinted) { - errs() << "warning: the 'virt' ASE requires " << ArchName - << " revision 5 or greater\n"; - VirtWarningPrinted = true; - } - if (!hasMips32r6() && hasCRC() && !CRCWarningPrinted) { - errs() << "warning: the 'crc' ASE requires " << ArchName - << " revision 6 or greater\n"; - CRCWarningPrinted = true; - } - if (!hasMips32r6() && hasGINV() && !GINVWarningPrinted) { - errs() << "warning: the 'ginv' ASE requires " << ArchName - << " revision 6 or greater\n"; - GINVWarningPrinted = true; - } - - CallLoweringInfo.reset(new MipsCallLowering(*getTargetLowering())); - Legalizer.reset(new MipsLegalizerInfo(*this)); - - auto *RBI = new MipsRegisterBankInfo(*getRegisterInfo()); - RegBankInfo.reset(RBI); - InstSelector.reset(createMipsInstructionSelector( - *static_cast<const MipsTargetMachine *>(&TM), *this, *RBI)); -} - -bool MipsSubtarget::isPositionIndependent() const { - return TM.isPositionIndependent(); -} - -/// This overrides the PostRAScheduler bit in the SchedModel for any CPU. -bool MipsSubtarget::enablePostRAScheduler() const { return true; } - -void MipsSubtarget::getCriticalPathRCs(RegClassVector &CriticalPathRCs) const { - CriticalPathRCs.clear(); - CriticalPathRCs.push_back(isGP64bit() ? &Mips::GPR64RegClass - : &Mips::GPR32RegClass); -} - -CodeGenOpt::Level MipsSubtarget::getOptLevelToEnablePostRAScheduler() const { - return CodeGenOpt::Aggressive; -} - -MipsSubtarget & -MipsSubtarget::initializeSubtargetDependencies(StringRef CPU, StringRef FS, - const TargetMachine &TM) { - std::string CPUName = MIPS_MC::selectMipsCPU(TM.getTargetTriple(), CPU); - - // Parse features string. - ParseSubtargetFeatures(CPUName, FS); - // Initialize scheduling itinerary for the specified CPU. - InstrItins = getInstrItineraryForCPU(CPUName); - - if (InMips16Mode && !IsSoftFloat) - InMips16HardFloat = true; - - if (StackAlignOverride) - stackAlignment = StackAlignOverride; - else if (isABI_N32() || isABI_N64()) - stackAlignment = 16; - else { - assert(isABI_O32() && "Unknown ABI for stack alignment!"); - stackAlignment = 8; - } - - return *this; -} - -bool MipsSubtarget::useConstantIslands() { - LLVM_DEBUG(dbgs() << "use constant islands " << Mips16ConstantIslands - << "\n"); - return Mips16ConstantIslands; -} - -Reloc::Model MipsSubtarget::getRelocationModel() const { - return TM.getRelocationModel(); -} - -bool MipsSubtarget::isABI_N64() const { return getABI().IsN64(); } -bool MipsSubtarget::isABI_N32() const { return getABI().IsN32(); } -bool MipsSubtarget::isABI_O32() const { return getABI().IsO32(); } -const MipsABIInfo &MipsSubtarget::getABI() const { return TM.getABI(); } - -const CallLowering *MipsSubtarget::getCallLowering() const { - return CallLoweringInfo.get(); -} - -const LegalizerInfo *MipsSubtarget::getLegalizerInfo() const { - return Legalizer.get(); -} - -const RegisterBankInfo *MipsSubtarget::getRegBankInfo() const { - return RegBankInfo.get(); -} - -const InstructionSelector *MipsSubtarget::getInstructionSelector() const { - return InstSelector.get(); -} diff --git a/contrib/llvm/lib/Target/Mips/MipsSubtarget.h b/contrib/llvm/lib/Target/Mips/MipsSubtarget.h deleted file mode 100644 index 0758dcb5a658..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsSubtarget.h +++ /dev/null @@ -1,402 +0,0 @@ -//===-- MipsSubtarget.h - Define Subtarget for the Mips ---------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file declares the Mips specific subclass of TargetSubtargetInfo. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_MIPS_MIPSSUBTARGET_H -#define LLVM_LIB_TARGET_MIPS_MIPSSUBTARGET_H - -#include "MCTargetDesc/MipsABIInfo.h" -#include "MipsFrameLowering.h" -#include "MipsISelLowering.h" -#include "MipsInstrInfo.h" -#include "llvm/CodeGen/SelectionDAGTargetInfo.h" -#include "llvm/CodeGen/TargetSubtargetInfo.h" -#include "llvm/CodeGen/GlobalISel/CallLowering.h" -#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h" -#include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h" -#include "llvm/CodeGen/GlobalISel/InstructionSelector.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/MC/MCInstrItineraries.h" -#include "llvm/Support/ErrorHandling.h" -#include <string> - -#define GET_SUBTARGETINFO_HEADER -#include "MipsGenSubtargetInfo.inc" - -namespace llvm { -class StringRef; - -class MipsTargetMachine; - -class MipsSubtarget : public MipsGenSubtargetInfo { - virtual void anchor(); - - enum MipsArchEnum { - MipsDefault, - Mips1, Mips2, Mips32, Mips32r2, Mips32r3, Mips32r5, Mips32r6, Mips32Max, - Mips3, Mips4, Mips5, Mips64, Mips64r2, Mips64r3, Mips64r5, Mips64r6 - }; - - enum class CPU { P5600 }; - - // Used to avoid printing dsp warnings multiple times. - static bool DspWarningPrinted; - - // Used to avoid printing msa warnings multiple times. - static bool MSAWarningPrinted; - - // Used to avoid printing crc warnings multiple times. - static bool CRCWarningPrinted; - - // Used to avoid printing ginv warnings multiple times. - static bool GINVWarningPrinted; - - // Used to avoid printing virt warnings multiple times. - static bool VirtWarningPrinted; - - // Mips architecture version - MipsArchEnum MipsArchVersion; - - // Processor implementation (unused but required to exist by - // tablegen-erated code). - CPU ProcImpl; - - // IsLittle - The target is Little Endian - bool IsLittle; - - // IsSoftFloat - The target does not support any floating point instructions. - bool IsSoftFloat; - - // IsSingleFloat - The target only supports single precision float - // point operations. This enable the target to use all 32 32-bit - // floating point registers instead of only using even ones. - bool IsSingleFloat; - - // IsFPXX - MIPS O32 modeless ABI. - bool IsFPXX; - - // NoABICalls - Disable SVR4-style position-independent code. - bool NoABICalls; - - // Abs2008 - Use IEEE 754-2008 abs.fmt instruction. - bool Abs2008; - - // IsFP64bit - The target processor has 64-bit floating point registers. - bool IsFP64bit; - - /// Are odd single-precision registers permitted? - /// This corresponds to -modd-spreg and -mno-odd-spreg - bool UseOddSPReg; - - // IsNan2008 - IEEE 754-2008 NaN encoding. - bool IsNaN2008bit; - - // IsGP64bit - General-purpose registers are 64 bits wide - bool IsGP64bit; - - // IsPTR64bit - Pointers are 64 bit wide - bool IsPTR64bit; - - // HasVFPU - Processor has a vector floating point unit. - bool HasVFPU; - - // CPU supports cnMIPS (Cavium Networks Octeon CPU). - bool HasCnMips; - - // CPU supports cnMIPSP (Cavium Networks Octeon+ CPU). - bool HasCnMipsP; - - // isLinux - Target system is Linux. Is false we consider ELFOS for now. - bool IsLinux; - - // UseSmallSection - Small section is used. - bool UseSmallSection; - - /// Features related to the presence of specific instructions. - - // HasMips3_32 - The subset of MIPS-III instructions added to MIPS32 - bool HasMips3_32; - - // HasMips3_32r2 - The subset of MIPS-III instructions added to MIPS32r2 - bool HasMips3_32r2; - - // HasMips4_32 - Has the subset of MIPS-IV present in MIPS32 - bool HasMips4_32; - - // HasMips4_32r2 - Has the subset of MIPS-IV present in MIPS32r2 - bool HasMips4_32r2; - - // HasMips5_32r2 - Has the subset of MIPS-V present in MIPS32r2 - bool HasMips5_32r2; - - // InMips16 -- can process Mips16 instructions - bool InMips16Mode; - - // Mips16 hard float - bool InMips16HardFloat; - - // InMicroMips -- can process MicroMips instructions - bool InMicroMipsMode; - - // HasDSP, HasDSPR2, HasDSPR3 -- supports DSP ASE. - bool HasDSP, HasDSPR2, HasDSPR3; - - // Allow mixed Mips16 and Mips32 in one source file - bool AllowMixed16_32; - - // Optimize for space by compiling all functions as Mips 16 unless - // it needs floating point. Functions needing floating point are - // compiled as Mips32 - bool Os16; - - // HasMSA -- supports MSA ASE. - bool HasMSA; - - // UseTCCInDIV -- Enables the use of trapping in the assembler. - bool UseTCCInDIV; - - // Sym32 -- On Mips64 symbols are 32 bits. - bool HasSym32; - - // HasEVA -- supports EVA ASE. - bool HasEVA; - - // nomadd4 - disables generation of 4-operand madd.s, madd.d and - // related instructions. - bool DisableMadd4; - - // HasMT -- support MT ASE. - bool HasMT; - - // HasCRC -- supports R6 CRC ASE - bool HasCRC; - - // HasVirt -- supports Virtualization ASE - bool HasVirt; - - // HasGINV -- supports R6 Global INValidate ASE - bool HasGINV; - - // Use hazard variants of the jump register instructions for indirect - // function calls and jump tables. - bool UseIndirectJumpsHazard; - - // Disable use of the `jal` instruction. - bool UseLongCalls = false; - - /// The minimum alignment known to hold of the stack frame on - /// entry to the function and which must be maintained by every function. - unsigned stackAlignment; - - /// The overridden stack alignment. - unsigned StackAlignOverride; - - InstrItineraryData InstrItins; - - // We can override the determination of whether we are in mips16 mode - // as from the command line - enum {NoOverride, Mips16Override, NoMips16Override} OverrideMode; - - const MipsTargetMachine &TM; - - Triple TargetTriple; - - const SelectionDAGTargetInfo TSInfo; - std::unique_ptr<const MipsInstrInfo> InstrInfo; - std::unique_ptr<const MipsFrameLowering> FrameLowering; - std::unique_ptr<const MipsTargetLowering> TLInfo; - -public: - bool isPositionIndependent() const; - /// This overrides the PostRAScheduler bit in the SchedModel for each CPU. - bool enablePostRAScheduler() const override; - void getCriticalPathRCs(RegClassVector &CriticalPathRCs) const override; - CodeGenOpt::Level getOptLevelToEnablePostRAScheduler() const override; - - bool isABI_N64() const; - bool isABI_N32() const; - bool isABI_O32() const; - const MipsABIInfo &getABI() const; - bool isABI_FPXX() const { return isABI_O32() && IsFPXX; } - - /// This constructor initializes the data members to match that - /// of the specified triple. - MipsSubtarget(const Triple &TT, StringRef CPU, StringRef FS, bool little, - const MipsTargetMachine &TM, unsigned StackAlignOverride); - - /// ParseSubtargetFeatures - Parses features string setting specified - /// subtarget options. Definition of function is auto generated by tblgen. - void ParseSubtargetFeatures(StringRef CPU, StringRef FS); - - bool hasMips1() const { return MipsArchVersion >= Mips1; } - bool hasMips2() const { return MipsArchVersion >= Mips2; } - bool hasMips3() const { return MipsArchVersion >= Mips3; } - bool hasMips4() const { return MipsArchVersion >= Mips4; } - bool hasMips5() const { return MipsArchVersion >= Mips5; } - bool hasMips4_32() const { return HasMips4_32; } - bool hasMips4_32r2() const { return HasMips4_32r2; } - bool hasMips32() const { - return (MipsArchVersion >= Mips32 && MipsArchVersion < Mips32Max) || - hasMips64(); - } - bool hasMips32r2() const { - return (MipsArchVersion >= Mips32r2 && MipsArchVersion < Mips32Max) || - hasMips64r2(); - } - bool hasMips32r3() const { - return (MipsArchVersion >= Mips32r3 && MipsArchVersion < Mips32Max) || - hasMips64r2(); - } - bool hasMips32r5() const { - return (MipsArchVersion >= Mips32r5 && MipsArchVersion < Mips32Max) || - hasMips64r5(); - } - bool hasMips32r6() const { - return (MipsArchVersion >= Mips32r6 && MipsArchVersion < Mips32Max) || - hasMips64r6(); - } - bool hasMips64() const { return MipsArchVersion >= Mips64; } - bool hasMips64r2() const { return MipsArchVersion >= Mips64r2; } - bool hasMips64r3() const { return MipsArchVersion >= Mips64r3; } - bool hasMips64r5() const { return MipsArchVersion >= Mips64r5; } - bool hasMips64r6() const { return MipsArchVersion >= Mips64r6; } - - bool hasCnMips() const { return HasCnMips; } - bool hasCnMipsP() const { return HasCnMipsP; } - - bool isLittle() const { return IsLittle; } - bool isABICalls() const { return !NoABICalls; } - bool isFPXX() const { return IsFPXX; } - bool isFP64bit() const { return IsFP64bit; } - bool useOddSPReg() const { return UseOddSPReg; } - bool noOddSPReg() const { return !UseOddSPReg; } - bool isNaN2008() const { return IsNaN2008bit; } - bool inAbs2008Mode() const { return Abs2008; } - bool isGP64bit() const { return IsGP64bit; } - bool isGP32bit() const { return !IsGP64bit; } - unsigned getGPRSizeInBytes() const { return isGP64bit() ? 8 : 4; } - bool isPTR64bit() const { return IsPTR64bit; } - bool isPTR32bit() const { return !IsPTR64bit; } - bool hasSym32() const { - return (HasSym32 && isABI_N64()) || isABI_N32() || isABI_O32(); - } - bool isSingleFloat() const { return IsSingleFloat; } - bool isTargetELF() const { return TargetTriple.isOSBinFormatELF(); } - bool hasVFPU() const { return HasVFPU; } - bool inMips16Mode() const { return InMips16Mode; } - bool inMips16ModeDefault() const { - return InMips16Mode; - } - // Hard float for mips16 means essentially to compile as soft float - // but to use a runtime library for soft float that is written with - // native mips32 floating point instructions (those runtime routines - // run in mips32 hard float mode). - bool inMips16HardFloat() const { - return inMips16Mode() && InMips16HardFloat; - } - bool inMicroMipsMode() const { return InMicroMipsMode && !InMips16Mode; } - bool inMicroMips32r6Mode() const { - return inMicroMipsMode() && hasMips32r6(); - } - bool hasDSP() const { return HasDSP; } - bool hasDSPR2() const { return HasDSPR2; } - bool hasDSPR3() const { return HasDSPR3; } - bool hasMSA() const { return HasMSA; } - bool disableMadd4() const { return DisableMadd4; } - bool hasEVA() const { return HasEVA; } - bool hasMT() const { return HasMT; } - bool hasCRC() const { return HasCRC; } - bool hasVirt() const { return HasVirt; } - bool hasGINV() const { return HasGINV; } - bool useIndirectJumpsHazard() const { - return UseIndirectJumpsHazard && hasMips32r2(); - } - bool useSmallSection() const { return UseSmallSection; } - - bool hasStandardEncoding() const { return !InMips16Mode && !InMicroMipsMode; } - - bool useSoftFloat() const { return IsSoftFloat; } - - bool useLongCalls() const { return UseLongCalls; } - - bool enableLongBranchPass() const { - return hasStandardEncoding() || inMicroMipsMode() || allowMixed16_32(); - } - - /// Features related to the presence of specific instructions. - bool hasExtractInsert() const { return !inMips16Mode() && hasMips32r2(); } - bool hasMTHC1() const { return hasMips32r2(); } - - bool allowMixed16_32() const { return inMips16ModeDefault() | - AllowMixed16_32; } - - bool os16() const { return Os16; } - - bool isTargetNaCl() const { return TargetTriple.isOSNaCl(); } - - bool isXRaySupported() const override { return true; } - - // for now constant islands are on for the whole compilation unit but we only - // really use them if in addition we are in mips16 mode - static bool useConstantIslands(); - - unsigned getStackAlignment() const { return stackAlignment; } - - // Grab relocation model - Reloc::Model getRelocationModel() const; - - MipsSubtarget &initializeSubtargetDependencies(StringRef CPU, StringRef FS, - const TargetMachine &TM); - - /// Does the system support unaligned memory access. - /// - /// MIPS32r6/MIPS64r6 require full unaligned access support but does not - /// specify which component of the system provides it. Hardware, software, and - /// hybrid implementations are all valid. - bool systemSupportsUnalignedAccess() const { return hasMips32r6(); } - - // Set helper classes - void setHelperClassesMips16(); - void setHelperClassesMipsSE(); - - const SelectionDAGTargetInfo *getSelectionDAGInfo() const override { - return &TSInfo; - } - const MipsInstrInfo *getInstrInfo() const override { return InstrInfo.get(); } - const TargetFrameLowering *getFrameLowering() const override { - return FrameLowering.get(); - } - const MipsRegisterInfo *getRegisterInfo() const override { - return &InstrInfo->getRegisterInfo(); - } - const MipsTargetLowering *getTargetLowering() const override { - return TLInfo.get(); - } - const InstrItineraryData *getInstrItineraryData() const override { - return &InstrItins; - } - -protected: - // GlobalISel related APIs. - std::unique_ptr<CallLowering> CallLoweringInfo; - std::unique_ptr<LegalizerInfo> Legalizer; - std::unique_ptr<RegisterBankInfo> RegBankInfo; - std::unique_ptr<InstructionSelector> InstSelector; - -public: - const CallLowering *getCallLowering() const override; - const LegalizerInfo *getLegalizerInfo() const override; - const RegisterBankInfo *getRegBankInfo() const override; - const InstructionSelector *getInstructionSelector() const override; -}; -} // End llvm namespace - -#endif diff --git a/contrib/llvm/lib/Target/Mips/MipsTargetMachine.cpp b/contrib/llvm/lib/Target/Mips/MipsTargetMachine.cpp deleted file mode 100644 index c878abb042e4..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsTargetMachine.cpp +++ /dev/null @@ -1,339 +0,0 @@ -//===-- MipsTargetMachine.cpp - Define TargetMachine for Mips -------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Implements the info about Mips target spec. -// -//===----------------------------------------------------------------------===// - -#include "MipsTargetMachine.h" -#include "MCTargetDesc/MipsABIInfo.h" -#include "MCTargetDesc/MipsMCTargetDesc.h" -#include "Mips.h" -#include "Mips16ISelDAGToDAG.h" -#include "MipsSEISelDAGToDAG.h" -#include "MipsSubtarget.h" -#include "MipsTargetObjectFile.h" -#include "TargetInfo/MipsTargetInfo.h" -#include "llvm/ADT/Optional.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Analysis/TargetTransformInfo.h" -#include "llvm/CodeGen/GlobalISel/IRTranslator.h" -#include "llvm/CodeGen/GlobalISel/Legalizer.h" -#include "llvm/CodeGen/GlobalISel/RegBankSelect.h" -#include "llvm/CodeGen/GlobalISel/InstructionSelect.h" -#include "llvm/CodeGen/BasicTTIImpl.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/Passes.h" -#include "llvm/CodeGen/TargetPassConfig.h" -#include "llvm/IR/Attributes.h" -#include "llvm/IR/Function.h" -#include "llvm/Support/CodeGen.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/TargetRegistry.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetOptions.h" -#include <string> - -using namespace llvm; - -#define DEBUG_TYPE "mips" - -extern "C" void LLVMInitializeMipsTarget() { - // Register the target. - RegisterTargetMachine<MipsebTargetMachine> X(getTheMipsTarget()); - RegisterTargetMachine<MipselTargetMachine> Y(getTheMipselTarget()); - RegisterTargetMachine<MipsebTargetMachine> A(getTheMips64Target()); - RegisterTargetMachine<MipselTargetMachine> B(getTheMips64elTarget()); - - PassRegistry *PR = PassRegistry::getPassRegistry(); - initializeGlobalISel(*PR); - initializeMipsDelaySlotFillerPass(*PR); - initializeMipsBranchExpansionPass(*PR); - initializeMicroMipsSizeReducePass(*PR); - initializeMipsPreLegalizerCombinerPass(*PR); -} - -static std::string computeDataLayout(const Triple &TT, StringRef CPU, - const TargetOptions &Options, - bool isLittle) { - std::string Ret; - MipsABIInfo ABI = MipsABIInfo::computeTargetABI(TT, CPU, Options.MCOptions); - - // There are both little and big endian mips. - if (isLittle) - Ret += "e"; - else - Ret += "E"; - - if (ABI.IsO32()) - Ret += "-m:m"; - else - Ret += "-m:e"; - - // Pointers are 32 bit on some ABIs. - if (!ABI.IsN64()) - Ret += "-p:32:32"; - - // 8 and 16 bit integers only need to have natural alignment, but try to - // align them to 32 bits. 64 bit integers have natural alignment. - Ret += "-i8:8:32-i16:16:32-i64:64"; - - // 32 bit registers are always available and the stack is at least 64 bit - // aligned. On N64 64 bit registers are also available and the stack is - // 128 bit aligned. - if (ABI.IsN64() || ABI.IsN32()) - Ret += "-n32:64-S128"; - else - Ret += "-n32-S64"; - - return Ret; -} - -static Reloc::Model getEffectiveRelocModel(bool JIT, - Optional<Reloc::Model> RM) { - if (!RM.hasValue() || JIT) - return Reloc::Static; - return *RM; -} - -// On function prologue, the stack is created by decrementing -// its pointer. Once decremented, all references are done with positive -// offset from the stack/frame pointer, using StackGrowsUp enables -// an easier handling. -// Using CodeModel::Large enables different CALL behavior. -MipsTargetMachine::MipsTargetMachine(const Target &T, const Triple &TT, - StringRef CPU, StringRef FS, - const TargetOptions &Options, - Optional<Reloc::Model> RM, - Optional<CodeModel::Model> CM, - CodeGenOpt::Level OL, bool JIT, - bool isLittle) - : LLVMTargetMachine(T, computeDataLayout(TT, CPU, Options, isLittle), TT, - CPU, FS, Options, getEffectiveRelocModel(JIT, RM), - getEffectiveCodeModel(CM, CodeModel::Small), OL), - isLittle(isLittle), TLOF(llvm::make_unique<MipsTargetObjectFile>()), - ABI(MipsABIInfo::computeTargetABI(TT, CPU, Options.MCOptions)), - Subtarget(nullptr), DefaultSubtarget(TT, CPU, FS, isLittle, *this, - Options.StackAlignmentOverride), - NoMips16Subtarget(TT, CPU, FS.empty() ? "-mips16" : FS.str() + ",-mips16", - isLittle, *this, Options.StackAlignmentOverride), - Mips16Subtarget(TT, CPU, FS.empty() ? "+mips16" : FS.str() + ",+mips16", - isLittle, *this, Options.StackAlignmentOverride) { - Subtarget = &DefaultSubtarget; - initAsmInfo(); -} - -MipsTargetMachine::~MipsTargetMachine() = default; - -void MipsebTargetMachine::anchor() {} - -MipsebTargetMachine::MipsebTargetMachine(const Target &T, const Triple &TT, - StringRef CPU, StringRef FS, - const TargetOptions &Options, - Optional<Reloc::Model> RM, - Optional<CodeModel::Model> CM, - CodeGenOpt::Level OL, bool JIT) - : MipsTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, JIT, false) {} - -void MipselTargetMachine::anchor() {} - -MipselTargetMachine::MipselTargetMachine(const Target &T, const Triple &TT, - StringRef CPU, StringRef FS, - const TargetOptions &Options, - Optional<Reloc::Model> RM, - Optional<CodeModel::Model> CM, - CodeGenOpt::Level OL, bool JIT) - : MipsTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, JIT, true) {} - -const MipsSubtarget * -MipsTargetMachine::getSubtargetImpl(const Function &F) const { - Attribute CPUAttr = F.getFnAttribute("target-cpu"); - Attribute FSAttr = F.getFnAttribute("target-features"); - - std::string CPU = !CPUAttr.hasAttribute(Attribute::None) - ? CPUAttr.getValueAsString().str() - : TargetCPU; - std::string FS = !FSAttr.hasAttribute(Attribute::None) - ? FSAttr.getValueAsString().str() - : TargetFS; - bool hasMips16Attr = - !F.getFnAttribute("mips16").hasAttribute(Attribute::None); - bool hasNoMips16Attr = - !F.getFnAttribute("nomips16").hasAttribute(Attribute::None); - - bool HasMicroMipsAttr = - !F.getFnAttribute("micromips").hasAttribute(Attribute::None); - bool HasNoMicroMipsAttr = - !F.getFnAttribute("nomicromips").hasAttribute(Attribute::None); - - // FIXME: This is related to the code below to reset the target options, - // we need to know whether or not the soft float flag is set on the - // function, so we can enable it as a subtarget feature. - bool softFloat = - F.hasFnAttribute("use-soft-float") && - F.getFnAttribute("use-soft-float").getValueAsString() == "true"; - - if (hasMips16Attr) - FS += FS.empty() ? "+mips16" : ",+mips16"; - else if (hasNoMips16Attr) - FS += FS.empty() ? "-mips16" : ",-mips16"; - if (HasMicroMipsAttr) - FS += FS.empty() ? "+micromips" : ",+micromips"; - else if (HasNoMicroMipsAttr) - FS += FS.empty() ? "-micromips" : ",-micromips"; - if (softFloat) - FS += FS.empty() ? "+soft-float" : ",+soft-float"; - - auto &I = SubtargetMap[CPU + FS]; - if (!I) { - // This needs to be done before we create a new subtarget since any - // creation will depend on the TM and the code generation flags on the - // function that reside in TargetOptions. - resetTargetOptions(F); - I = llvm::make_unique<MipsSubtarget>(TargetTriple, CPU, FS, isLittle, *this, - Options.StackAlignmentOverride); - } - return I.get(); -} - -void MipsTargetMachine::resetSubtarget(MachineFunction *MF) { - LLVM_DEBUG(dbgs() << "resetSubtarget\n"); - - Subtarget = &MF->getSubtarget<MipsSubtarget>(); -} - -namespace { - -/// Mips Code Generator Pass Configuration Options. -class MipsPassConfig : public TargetPassConfig { -public: - MipsPassConfig(MipsTargetMachine &TM, PassManagerBase &PM) - : TargetPassConfig(TM, PM) { - // The current implementation of long branch pass requires a scratch - // register ($at) to be available before branch instructions. Tail merging - // can break this requirement, so disable it when long branch pass is - // enabled. - EnableTailMerge = !getMipsSubtarget().enableLongBranchPass(); - } - - MipsTargetMachine &getMipsTargetMachine() const { - return getTM<MipsTargetMachine>(); - } - - const MipsSubtarget &getMipsSubtarget() const { - return *getMipsTargetMachine().getSubtargetImpl(); - } - - void addIRPasses() override; - bool addInstSelector() override; - void addPreEmitPass() override; - void addPreRegAlloc() override; - bool addIRTranslator() override; - void addPreLegalizeMachineIR() override; - bool addLegalizeMachineIR() override; - bool addRegBankSelect() override; - bool addGlobalInstructionSelect() override; - - std::unique_ptr<CSEConfigBase> getCSEConfig() const override; -}; - -} // end anonymous namespace - -TargetPassConfig *MipsTargetMachine::createPassConfig(PassManagerBase &PM) { - return new MipsPassConfig(*this, PM); -} - -std::unique_ptr<CSEConfigBase> MipsPassConfig::getCSEConfig() const { - return getStandardCSEConfigForOpt(TM->getOptLevel()); -} - -void MipsPassConfig::addIRPasses() { - TargetPassConfig::addIRPasses(); - addPass(createAtomicExpandPass()); - if (getMipsSubtarget().os16()) - addPass(createMipsOs16Pass()); - if (getMipsSubtarget().inMips16HardFloat()) - addPass(createMips16HardFloatPass()); -} -// Install an instruction selector pass using -// the ISelDag to gen Mips code. -bool MipsPassConfig::addInstSelector() { - addPass(createMipsModuleISelDagPass()); - addPass(createMips16ISelDag(getMipsTargetMachine(), getOptLevel())); - addPass(createMipsSEISelDag(getMipsTargetMachine(), getOptLevel())); - return false; -} - -void MipsPassConfig::addPreRegAlloc() { - addPass(createMipsOptimizePICCallPass()); -} - -TargetTransformInfo -MipsTargetMachine::getTargetTransformInfo(const Function &F) { - if (Subtarget->allowMixed16_32()) { - LLVM_DEBUG(errs() << "No Target Transform Info Pass Added\n"); - // FIXME: This is no longer necessary as the TTI returned is per-function. - return TargetTransformInfo(F.getParent()->getDataLayout()); - } - - LLVM_DEBUG(errs() << "Target Transform Info Pass Added\n"); - return TargetTransformInfo(BasicTTIImpl(this, F)); -} - -// Implemented by targets that want to run passes immediately before -// machine code is emitted. return true if -print-machineinstrs should -// print out the code after the passes. -void MipsPassConfig::addPreEmitPass() { - // Expand pseudo instructions that are sensitive to register allocation. - addPass(createMipsExpandPseudoPass()); - - // The microMIPS size reduction pass performs instruction reselection for - // instructions which can be remapped to a 16 bit instruction. - addPass(createMicroMipsSizeReducePass()); - - // The delay slot filler pass can potientially create forbidden slot hazards - // for MIPSR6 and therefore it should go before MipsBranchExpansion pass. - addPass(createMipsDelaySlotFillerPass()); - - // This pass expands branches and takes care about the forbidden slot hazards. - // Expanding branches may potentially create forbidden slot hazards for - // MIPSR6, and fixing such hazard may potentially break a branch by extending - // its offset out of range. That's why this pass combine these two tasks, and - // runs them alternately until one of them finishes without any changes. Only - // then we can be sure that all branches are expanded properly and no hazards - // exists. - // Any new pass should go before this pass. - addPass(createMipsBranchExpansion()); - - addPass(createMipsConstantIslandPass()); -} - -bool MipsPassConfig::addIRTranslator() { - addPass(new IRTranslator()); - return false; -} - -void MipsPassConfig::addPreLegalizeMachineIR() { - addPass(createMipsPreLegalizeCombiner()); -} - -bool MipsPassConfig::addLegalizeMachineIR() { - addPass(new Legalizer()); - return false; -} - -bool MipsPassConfig::addRegBankSelect() { - addPass(new RegBankSelect()); - return false; -} - -bool MipsPassConfig::addGlobalInstructionSelect() { - addPass(new InstructionSelect()); - return false; -} diff --git a/contrib/llvm/lib/Target/Mips/MipsTargetMachine.h b/contrib/llvm/lib/Target/Mips/MipsTargetMachine.h deleted file mode 100644 index 25300504a02d..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsTargetMachine.h +++ /dev/null @@ -1,96 +0,0 @@ -//===- MipsTargetMachine.h - Define TargetMachine for Mips ------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file declares the Mips specific subclass of TargetMachine. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_MIPS_MIPSTARGETMACHINE_H -#define LLVM_LIB_TARGET_MIPS_MIPSTARGETMACHINE_H - -#include "MCTargetDesc/MipsABIInfo.h" -#include "MipsSubtarget.h" -#include "llvm/ADT/Optional.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/CodeGen.h" -#include "llvm/Target/TargetMachine.h" -#include <memory> - -namespace llvm { - -class MipsTargetMachine : public LLVMTargetMachine { - bool isLittle; - std::unique_ptr<TargetLoweringObjectFile> TLOF; - // Selected ABI - MipsABIInfo ABI; - const MipsSubtarget *Subtarget; - MipsSubtarget DefaultSubtarget; - MipsSubtarget NoMips16Subtarget; - MipsSubtarget Mips16Subtarget; - - mutable StringMap<std::unique_ptr<MipsSubtarget>> SubtargetMap; - -public: - MipsTargetMachine(const Target &T, const Triple &TT, StringRef CPU, - StringRef FS, const TargetOptions &Options, - Optional<Reloc::Model> RM, Optional<CodeModel::Model> CM, - CodeGenOpt::Level OL, bool JIT, bool isLittle); - ~MipsTargetMachine() override; - - TargetTransformInfo getTargetTransformInfo(const Function &F) override; - - const MipsSubtarget *getSubtargetImpl() const { - if (Subtarget) - return Subtarget; - return &DefaultSubtarget; - } - - const MipsSubtarget *getSubtargetImpl(const Function &F) const override; - - /// Reset the subtarget for the Mips target. - void resetSubtarget(MachineFunction *MF); - - // Pass Pipeline Configuration - TargetPassConfig *createPassConfig(PassManagerBase &PM) override; - - TargetLoweringObjectFile *getObjFileLowering() const override { - return TLOF.get(); - } - - bool isLittleEndian() const { return isLittle; } - const MipsABIInfo &getABI() const { return ABI; } -}; - -/// Mips32/64 big endian target machine. -/// -class MipsebTargetMachine : public MipsTargetMachine { - virtual void anchor(); - -public: - MipsebTargetMachine(const Target &T, const Triple &TT, StringRef CPU, - StringRef FS, const TargetOptions &Options, - Optional<Reloc::Model> RM, Optional<CodeModel::Model> CM, - CodeGenOpt::Level OL, bool JIT); -}; - -/// Mips32/64 little endian target machine. -/// -class MipselTargetMachine : public MipsTargetMachine { - virtual void anchor(); - -public: - MipselTargetMachine(const Target &T, const Triple &TT, StringRef CPU, - StringRef FS, const TargetOptions &Options, - Optional<Reloc::Model> RM, Optional<CodeModel::Model> CM, - CodeGenOpt::Level OL, bool JIT); -}; - -} // end namespace llvm - -#endif // LLVM_LIB_TARGET_MIPS_MIPSTARGETMACHINE_H diff --git a/contrib/llvm/lib/Target/Mips/MipsTargetObjectFile.cpp b/contrib/llvm/lib/Target/Mips/MipsTargetObjectFile.cpp deleted file mode 100644 index 0852b5a18c68..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsTargetObjectFile.cpp +++ /dev/null @@ -1,195 +0,0 @@ -//===-- MipsTargetObjectFile.cpp - Mips Object Files ----------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "MipsTargetObjectFile.h" -#include "MipsSubtarget.h" -#include "MipsTargetMachine.h" -#include "MCTargetDesc/MipsMCExpr.h" -#include "llvm/BinaryFormat/ELF.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/GlobalVariable.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCSectionELF.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Target/TargetMachine.h" -using namespace llvm; - -static cl::opt<unsigned> -SSThreshold("mips-ssection-threshold", cl::Hidden, - cl::desc("Small data and bss section threshold size (default=8)"), - cl::init(8)); - -static cl::opt<bool> -LocalSData("mlocal-sdata", cl::Hidden, - cl::desc("MIPS: Use gp_rel for object-local data."), - cl::init(true)); - -static cl::opt<bool> -ExternSData("mextern-sdata", cl::Hidden, - cl::desc("MIPS: Use gp_rel for data that is not defined by the " - "current object."), - cl::init(true)); - -static cl::opt<bool> -EmbeddedData("membedded-data", cl::Hidden, - cl::desc("MIPS: Try to allocate variables in the following" - " sections if possible: .rodata, .sdata, .data ."), - cl::init(false)); - -void MipsTargetObjectFile::Initialize(MCContext &Ctx, const TargetMachine &TM){ - TargetLoweringObjectFileELF::Initialize(Ctx, TM); - InitializeELF(TM.Options.UseInitArray); - - SmallDataSection = getContext().getELFSection( - ".sdata", ELF::SHT_PROGBITS, - ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL); - - SmallBSSSection = getContext().getELFSection(".sbss", ELF::SHT_NOBITS, - ELF::SHF_WRITE | ELF::SHF_ALLOC | - ELF::SHF_MIPS_GPREL); - this->TM = &static_cast<const MipsTargetMachine &>(TM); -} - -// A address must be loaded from a small section if its size is less than the -// small section size threshold. Data in this section must be addressed using -// gp_rel operator. -static bool IsInSmallSection(uint64_t Size) { - // gcc has traditionally not treated zero-sized objects as small data, so this - // is effectively part of the ABI. - return Size > 0 && Size <= SSThreshold; -} - -/// Return true if this global address should be placed into small data/bss -/// section. -bool MipsTargetObjectFile::IsGlobalInSmallSection( - const GlobalObject *GO, const TargetMachine &TM) const { - // We first check the case where global is a declaration, because finding - // section kind using getKindForGlobal() is only allowed for global - // definitions. - if (GO->isDeclaration() || GO->hasAvailableExternallyLinkage()) - return IsGlobalInSmallSectionImpl(GO, TM); - - return IsGlobalInSmallSection(GO, TM, getKindForGlobal(GO, TM)); -} - -/// Return true if this global address should be placed into small data/bss -/// section. -bool MipsTargetObjectFile:: -IsGlobalInSmallSection(const GlobalObject *GO, const TargetMachine &TM, - SectionKind Kind) const { - return IsGlobalInSmallSectionImpl(GO, TM) && - (Kind.isData() || Kind.isBSS() || Kind.isCommon() || - Kind.isReadOnly()); -} - -/// Return true if this global address should be placed into small data/bss -/// section. This method does all the work, except for checking the section -/// kind. -bool MipsTargetObjectFile:: -IsGlobalInSmallSectionImpl(const GlobalObject *GO, - const TargetMachine &TM) const { - const MipsSubtarget &Subtarget = - *static_cast<const MipsTargetMachine &>(TM).getSubtargetImpl(); - - // Return if small section is not available. - if (!Subtarget.useSmallSection()) - return false; - - // Only global variables, not functions. - const GlobalVariable *GVA = dyn_cast<GlobalVariable>(GO); - if (!GVA) - return false; - - // If the variable has an explicit section, it is placed in that section but - // it's addressing mode may change. - if (GVA->hasSection()) { - StringRef Section = GVA->getSection(); - - // Explicitly placing any variable in the small data section overrides - // the global -G value. - if (Section == ".sdata" || Section == ".sbss") - return true; - - // Otherwise reject accessing it through the gp pointer. There are some - // historic cases which GCC doesn't appear to respect any more. These - // are .lit4, .lit8 and .srdata. For the moment reject these as well. - return false; - } - - // Enforce -mlocal-sdata. - if (!LocalSData && GVA->hasLocalLinkage()) - return false; - - // Enforce -mextern-sdata. - if (!ExternSData && ((GVA->hasExternalLinkage() && GVA->isDeclaration()) || - GVA->hasCommonLinkage())) - return false; - - // Enforce -membedded-data. - if (EmbeddedData && GVA->isConstant()) - return false; - - Type *Ty = GVA->getValueType(); - - // It is possible that the type of the global is unsized, i.e. a declaration - // of a extern struct. In this case don't presume it is in the small data - // section. This happens e.g. when building the FreeBSD kernel. - if (!Ty->isSized()) - return false; - - return IsInSmallSection( - GVA->getParent()->getDataLayout().getTypeAllocSize(Ty)); -} - -MCSection *MipsTargetObjectFile::SelectSectionForGlobal( - const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const { - // TODO: Could also support "weak" symbols as well with ".gnu.linkonce.s.*" - // sections? - - // Handle Small Section classification here. - if (Kind.isBSS() && IsGlobalInSmallSection(GO, TM, Kind)) - return SmallBSSSection; - if (Kind.isData() && IsGlobalInSmallSection(GO, TM, Kind)) - return SmallDataSection; - if (Kind.isReadOnly() && IsGlobalInSmallSection(GO, TM, Kind)) - return SmallDataSection; - - // Otherwise, we work the same as ELF. - return TargetLoweringObjectFileELF::SelectSectionForGlobal(GO, Kind, TM); -} - -/// Return true if this constant should be placed into small data section. -bool MipsTargetObjectFile::IsConstantInSmallSection( - const DataLayout &DL, const Constant *CN, const TargetMachine &TM) const { - return (static_cast<const MipsTargetMachine &>(TM) - .getSubtargetImpl() - ->useSmallSection() && - LocalSData && IsInSmallSection(DL.getTypeAllocSize(CN->getType()))); -} - -/// Return true if this constant should be placed into small data section. -MCSection *MipsTargetObjectFile::getSectionForConstant(const DataLayout &DL, - SectionKind Kind, - const Constant *C, - unsigned &Align) const { - if (IsConstantInSmallSection(DL, C, *TM)) - return SmallDataSection; - - // Otherwise, we work the same as ELF. - return TargetLoweringObjectFileELF::getSectionForConstant(DL, Kind, C, Align); -} - -const MCExpr * -MipsTargetObjectFile::getDebugThreadLocalSymbol(const MCSymbol *Sym) const { - const MCExpr *Expr = - MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); - Expr = MCBinaryExpr::createAdd( - Expr, MCConstantExpr::create(0x8000, getContext()), getContext()); - return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL, Expr, getContext()); -} diff --git a/contrib/llvm/lib/Target/Mips/MipsTargetObjectFile.h b/contrib/llvm/lib/Target/Mips/MipsTargetObjectFile.h deleted file mode 100644 index bdf485f83260..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsTargetObjectFile.h +++ /dev/null @@ -1,49 +0,0 @@ -//===-- llvm/Target/MipsTargetObjectFile.h - Mips Object Info ---*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_MIPS_MIPSTARGETOBJECTFILE_H -#define LLVM_LIB_TARGET_MIPS_MIPSTARGETOBJECTFILE_H - -#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" - -namespace llvm { -class MipsTargetMachine; - class MipsTargetObjectFile : public TargetLoweringObjectFileELF { - MCSection *SmallDataSection; - MCSection *SmallBSSSection; - const MipsTargetMachine *TM; - - bool IsGlobalInSmallSection(const GlobalObject *GO, const TargetMachine &TM, - SectionKind Kind) const; - bool IsGlobalInSmallSectionImpl(const GlobalObject *GO, - const TargetMachine &TM) const; - public: - - void Initialize(MCContext &Ctx, const TargetMachine &TM) override; - - /// Return true if this global address should be placed into small data/bss - /// section. - bool IsGlobalInSmallSection(const GlobalObject *GO, - const TargetMachine &TM) const; - - MCSection *SelectSectionForGlobal(const GlobalObject *GO, SectionKind Kind, - const TargetMachine &TM) const override; - - /// Return true if this constant should be placed into small data section. - bool IsConstantInSmallSection(const DataLayout &DL, const Constant *CN, - const TargetMachine &TM) const; - - MCSection *getSectionForConstant(const DataLayout &DL, SectionKind Kind, - const Constant *C, - unsigned &Align) const override; - /// Describe a TLS variable address within debug info. - const MCExpr *getDebugThreadLocalSymbol(const MCSymbol *Sym) const override; - }; -} // end namespace llvm - -#endif diff --git a/contrib/llvm/lib/Target/Mips/MipsTargetStreamer.h b/contrib/llvm/lib/Target/Mips/MipsTargetStreamer.h deleted file mode 100644 index 1fa8ebadd643..000000000000 --- a/contrib/llvm/lib/Target/Mips/MipsTargetStreamer.h +++ /dev/null @@ -1,362 +0,0 @@ -//===-- MipsTargetStreamer.h - Mips Target Streamer ------------*- C++ -*--===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_MIPS_MIPSTARGETSTREAMER_H -#define LLVM_LIB_TARGET_MIPS_MIPSTARGETSTREAMER_H - -#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" - -namespace llvm { - -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(); - - virtual void emitDirectiveSetReorder(); - virtual void emitDirectiveSetNoReorder(); - virtual void emitDirectiveSetMacro(); - 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(); - virtual void emitDirectiveEnd(StringRef Name); - - virtual void emitDirectiveEnt(const MCSymbol &Symbol); - virtual void emitDirectiveAbiCalls(); - virtual void emitDirectiveNaN2008(); - virtual void emitDirectiveNaNLegacy(); - virtual void emitDirectiveOptionPic0(); - virtual void emitDirectiveOptionPic2(); - virtual void emitDirectiveInsn(); - virtual void emitFrame(unsigned StackReg, unsigned StackSize, - unsigned ReturnReg); - virtual void emitMask(unsigned CPUBitmask, int CPUTopSavedRegOff); - virtual void emitFMask(unsigned FPUBitmask, int FPUTopSavedRegOff); - - virtual void emitDirectiveSetArch(StringRef Arch); - virtual void emitDirectiveSetMips0(); - virtual void emitDirectiveSetMips1(); - virtual void emitDirectiveSetMips2(); - virtual void emitDirectiveSetMips3(); - virtual void emitDirectiveSetMips4(); - virtual void emitDirectiveSetMips5(); - virtual void emitDirectiveSetMips32(); - virtual void emitDirectiveSetMips32R2(); - virtual void emitDirectiveSetMips32R3(); - virtual void emitDirectiveSetMips32R5(); - virtual void emitDirectiveSetMips32R6(); - virtual void emitDirectiveSetMips64(); - virtual void emitDirectiveSetMips64R2(); - virtual void emitDirectiveSetMips64R3(); - virtual void emitDirectiveSetMips64R5(); - virtual void emitDirectiveSetMips64R6(); - virtual void emitDirectiveSetDsp(); - virtual void emitDirectiveSetDspr2(); - virtual void emitDirectiveSetNoDsp(); - virtual void emitDirectiveSetPop(); - virtual void emitDirectiveSetPush(); - virtual void emitDirectiveSetSoftFloat(); - virtual void emitDirectiveSetHardFloat(); - - // PIC support - virtual void emitDirectiveCpLoad(unsigned RegNo); - virtual void emitDirectiveCpLocal(unsigned RegNo); - virtual bool emitDirectiveCpRestore(int Offset, - function_ref<unsigned()> GetATReg, - SMLoc IDLoc, const MCSubtargetInfo *STI); - virtual void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset, - const MCSymbol &Sym, bool IsReg); - virtual void emitDirectiveCpreturn(unsigned SaveLocation, - bool SaveLocationIsRegister); - - // FP abiflags directives - virtual void emitDirectiveModuleFP(); - 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; } - bool isModuleDirectiveAllowed() { return ModuleDirectiveAllowed; } - - // This method enables template classes to set internal abi flags - // structure values. - template <class PredicateLibrary> - void updateABIInfo(const PredicateLibrary &P) { - ABI = P.getABI(); - ABIFlagsSection.setAllFromPredicates(P); - } - - MipsABIFlagsSection &getABIFlagsSection() { return ABIFlagsSection; } - const MipsABIInfo &getABI() const { - assert(ABI.hasValue() && "ABI hasn't been set!"); - return *ABI; - } - -protected: - llvm::Optional<MipsABIInfo> ABI; - MipsABIFlagsSection ABIFlagsSection; - - bool GPRInfoSet; - unsigned GPRBitMask; - int GPROffset; - - bool FPRInfoSet; - unsigned FPRBitMask; - int FPROffset; - - bool FrameInfoSet; - int FrameOffset; - unsigned FrameReg; - unsigned GPReg; - unsigned ReturnReg; - -private: - bool ModuleDirectiveAllowed; -}; - -// This part is for ascii assembly output -class MipsTargetAsmStreamer : public MipsTargetStreamer { - formatted_raw_ostream &OS; - -public: - MipsTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS); - void emitDirectiveSetMicroMips() override; - void emitDirectiveSetNoMicroMips() override; - void emitDirectiveSetMips16() override; - void emitDirectiveSetNoMips16() override; - - void emitDirectiveSetReorder() override; - void emitDirectiveSetNoReorder() override; - void emitDirectiveSetMacro() override; - 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; - void emitDirectiveEnd(StringRef Name) override; - - void emitDirectiveEnt(const MCSymbol &Symbol) override; - void emitDirectiveAbiCalls() override; - void emitDirectiveNaN2008() override; - void emitDirectiveNaNLegacy() override; - void emitDirectiveOptionPic0() override; - void emitDirectiveOptionPic2() override; - void emitDirectiveInsn() override; - void emitFrame(unsigned StackReg, unsigned StackSize, - unsigned ReturnReg) override; - void emitMask(unsigned CPUBitmask, int CPUTopSavedRegOff) override; - void emitFMask(unsigned FPUBitmask, int FPUTopSavedRegOff) override; - - void emitDirectiveSetArch(StringRef Arch) override; - void emitDirectiveSetMips0() override; - void emitDirectiveSetMips1() override; - void emitDirectiveSetMips2() override; - void emitDirectiveSetMips3() override; - void emitDirectiveSetMips4() override; - void emitDirectiveSetMips5() override; - void emitDirectiveSetMips32() override; - void emitDirectiveSetMips32R2() override; - void emitDirectiveSetMips32R3() override; - void emitDirectiveSetMips32R5() override; - void emitDirectiveSetMips32R6() override; - void emitDirectiveSetMips64() override; - void emitDirectiveSetMips64R2() override; - void emitDirectiveSetMips64R3() override; - void emitDirectiveSetMips64R5() override; - void emitDirectiveSetMips64R6() override; - void emitDirectiveSetDsp() override; - void emitDirectiveSetDspr2() override; - void emitDirectiveSetNoDsp() override; - void emitDirectiveSetPop() override; - void emitDirectiveSetPush() override; - void emitDirectiveSetSoftFloat() override; - void emitDirectiveSetHardFloat() override; - - // PIC support - void emitDirectiveCpLoad(unsigned RegNo) override; - void emitDirectiveCpLocal(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 emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset, - const MCSymbol &Sym, bool IsReg) override; - void emitDirectiveCpreturn(unsigned SaveLocation, - bool SaveLocationIsRegister) override; - - // FP abiflags directives - void emitDirectiveModuleFP() override; - 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; -}; - -// This part is for ELF object output -class MipsTargetELFStreamer : public MipsTargetStreamer { - bool MicroMipsEnabled; - const MCSubtargetInfo &STI; - bool Pic; - -public: - bool isMicroMipsEnabled() const { return MicroMipsEnabled; } - 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; - void emitDirectiveEnd(StringRef Name) override; - - void emitDirectiveEnt(const MCSymbol &Symbol) override; - void emitDirectiveAbiCalls() override; - void emitDirectiveNaN2008() override; - void emitDirectiveNaNLegacy() override; - void emitDirectiveOptionPic0() override; - void emitDirectiveOptionPic2() override; - void emitDirectiveInsn() override; - void emitFrame(unsigned StackReg, unsigned StackSize, - unsigned ReturnReg) override; - void emitMask(unsigned CPUBitmask, int CPUTopSavedRegOff) override; - void emitFMask(unsigned FPUBitmask, int FPUTopSavedRegOff) override; - - // PIC support - void emitDirectiveCpLoad(unsigned RegNo) override; - void emitDirectiveCpLocal(unsigned RegNo) override; - bool emitDirectiveCpRestore(int Offset, function_ref<unsigned()> GetATReg, - SMLoc IDLoc, const MCSubtargetInfo *STI) override; - void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset, - const MCSymbol &Sym, bool IsReg) override; - void emitDirectiveCpreturn(unsigned SaveLocation, - bool SaveLocationIsRegister) override; - - void emitMipsAbiFlags(); -}; -} -#endif diff --git a/contrib/llvm/lib/Target/Mips/Relocation.txt b/contrib/llvm/lib/Target/Mips/Relocation.txt deleted file mode 100644 index 2f98e16886a1..000000000000 --- a/contrib/llvm/lib/Target/Mips/Relocation.txt +++ /dev/null @@ -1,92 +0,0 @@ -MIPS Relocation Principles - -In LLVM, there are several elements of the llvm::ISD::NodeType enum -that deal with addresses and/or relocations. These are defined in -include/llvm/Target/TargetSelectionDAG.td, namely: - GlobalAddress, GlobalTLSAddress, JumpTable, ConstantPool, - ExternalSymbol, BlockAddress -The MIPS backend uses several principles to handle these. - -1. Code for lowering addresses references to machine dependent code is -factored into common code for generating different address forms and -is called by the relocation model specific lowering function, using -templated functions. For example: - - // lib/Target/Mips/MipsISelLowering.cpp - SDValue MipsTargetLowering:: - lowerJumpTable(SDValue Op, SelectionDAG &DAG) const - -calls - - template <class NodeTy> // lib/Target/Mips/MipsISelLowering.h - SDValue getAddrLocal(NodeTy *N, const SDLoc &DL, EVT Ty, - SelectionDAG &DAG, bool IsN32OrN64) const - -which calls the overloaded function: - - // lib/Target/Mips/MipsISelLowering.h - SDValue getTargetNode(JumpTableSDNode *N, EVT Ty, SelectionDAG &DAG, - unsigned Flag) const; - -2. Generic address nodes are lowered to some combination of target -independent and machine specific SDNodes (for example: -MipsISD::{Highest, Higher, Hi, Lo}) depending upon relocation model, -ABI, and compilation options. - -The choice of specific instructions that are to be used is delegated -to ISel which in turn relies on TableGen patterns to choose subtarget -specific instructions. For example, in getAddrLocal, the pseudo-code -generated is: - - (add (load (wrapper $gp, %got(sym)), %lo(sym)) - -where "%lo" represents an instance of an SDNode with opcode -"MipsISD::Lo", "wrapper" indicates one with opcode "MipsISD::Wrapper", -and "%got" the global table pointer "getGlobalReg(...)". The "add" is -"ISD::ADD", not a target dependent one. - -3. A TableGen multiclass pattern "MipsHiLoRelocs" is used to define a -template pattern parameterized over the load upper immediate -instruction, add operation, the zero register, and register class. -Here the instantiation of MipsHiLoRelocs in MipsInstrInfo.td is used -to MIPS32 to compute addresses for the static relocation model. - - // lib/Target/Mips/MipsInstrInfo.td - multiclass MipsHiLoRelocs<Instruction Lui, Instruction Addiu, - Register ZeroReg, RegisterOperand GPROpnd> { - def : MipsPat<(MipsHi tglobaladdr:$in), (Lui tglobaladdr:$in)>; - ... - def : MipsPat<(MipsLo tglobaladdr:$in), (Addiu ZeroReg, tglobaladdr:$in)>; - ... - def : MipsPat<(add GPROpnd:$hi, (MipsLo tglobaladdr:$lo)), - (Addiu GPROpnd:$hi, tglobaladdr:$lo)>; - ... - } - defm : MipsHiLoRelocs<LUi, ADDiu, ZERO, GPR32Opnd>; - - // lib/Target/Mips/Mips64InstrInfo.td - defm : MipsHiLoRelocs<LUi64, DADDiu, ZERO_64, GPR64Opnd>, SYM_32; - -The instantiation in Mips64InstrInfo.td is used for MIPS64 in ILP32 -mode, as guarded by the predicate "SYM_32" and also for a submode of -LP64 where symbols are assumed to be 32 bits wide. - -More details on how multiclasses in TableGen work can be found in the -section "Multiclass definitions and instances" in the document -"TableGen Language Introduction" - -4. Instruction definitions are multiply defined to cover the different -register classes. In some cases, such as LW/LW64, this also accounts -for the difference in the results of instruction execution. On MIPS32, -"lw" loads a 32 bit value from memory. On MIPS64, "lw" loads a 32 bit -value from memory and sign extends the value to 64 bits. - - // lib/Target/Mips/MipsInstrInfo.td - def LUi : MMRel, LoadUpper<"lui", GPR32Opnd, uimm16_relaxed>, LUI_FM; - // lib/Target/Mips/Mips64InstrInfo.td - def LUi64 : LoadUpper<"lui", GPR64Opnd, uimm16_64_relaxed>, LUI_FM; - -defines two names "LUi" and "LUi64" with two different register -classes, but with the same encoding---"LUI_FM". These instructions load a -16-bit immediate into bits 31-16 and clear the lower 15 bits. On MIPS64, -the result is sign-extended to 64 bits. diff --git a/contrib/llvm/lib/Target/Mips/TargetInfo/MipsTargetInfo.cpp b/contrib/llvm/lib/Target/Mips/TargetInfo/MipsTargetInfo.cpp deleted file mode 100644 index 0082ca34cdbd..000000000000 --- a/contrib/llvm/lib/Target/Mips/TargetInfo/MipsTargetInfo.cpp +++ /dev/null @@ -1,47 +0,0 @@ -//===-- MipsTargetInfo.cpp - Mips Target Implementation -------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "TargetInfo/MipsTargetInfo.h" -#include "llvm/Support/TargetRegistry.h" -using namespace llvm; - -Target &llvm::getTheMipsTarget() { - static Target TheMipsTarget; - return TheMipsTarget; -} -Target &llvm::getTheMipselTarget() { - static Target TheMipselTarget; - return TheMipselTarget; -} -Target &llvm::getTheMips64Target() { - static Target TheMips64Target; - return TheMips64Target; -} -Target &llvm::getTheMips64elTarget() { - static Target TheMips64elTarget; - return TheMips64elTarget; -} - -extern "C" void LLVMInitializeMipsTargetInfo() { - RegisterTarget<Triple::mips, - /*HasJIT=*/true> - X(getTheMipsTarget(), "mips", "MIPS (32-bit big endian)", "Mips"); - - RegisterTarget<Triple::mipsel, - /*HasJIT=*/true> - Y(getTheMipselTarget(), "mipsel", "MIPS (32-bit little endian)", "Mips"); - - RegisterTarget<Triple::mips64, - /*HasJIT=*/true> - A(getTheMips64Target(), "mips64", "MIPS (64-bit big endian)", "Mips"); - - RegisterTarget<Triple::mips64el, - /*HasJIT=*/true> - B(getTheMips64elTarget(), "mips64el", "MIPS (64-bit little endian)", - "Mips"); -} diff --git a/contrib/llvm/lib/Target/Mips/TargetInfo/MipsTargetInfo.h b/contrib/llvm/lib/Target/Mips/TargetInfo/MipsTargetInfo.h deleted file mode 100644 index d91a2719108d..000000000000 --- a/contrib/llvm/lib/Target/Mips/TargetInfo/MipsTargetInfo.h +++ /dev/null @@ -1,23 +0,0 @@ -//===-- MipsTargetInfo.h - Mips Target Implementation -----------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_MIPS_TARGETINFO_MIPSTARGETINFO_H -#define LLVM_LIB_TARGET_MIPS_TARGETINFO_MIPSTARGETINFO_H - -namespace llvm { - -class Target; - -Target &getTheMipsTarget(); -Target &getTheMipselTarget(); -Target &getTheMips64Target(); -Target &getTheMips64elTarget(); - -} // namespace llvm - -#endif // LLVM_LIB_TARGET_MIPS_TARGETINFO_MIPSTARGETINFO_H |