aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm/lib/Target/Mips
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2019-12-20 19:53:05 +0000
committerDimitry Andric <dim@FreeBSD.org>2019-12-20 19:53:05 +0000
commit0b57cec536236d46e3dba9bd041533462f33dbb7 (patch)
tree56229dbdbbf76d18580f72f789003db17246c8d9 /contrib/llvm/lib/Target/Mips
parent718ef55ec7785aae63f98f8ca05dc07ed399c16d (diff)
downloadsrc-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')
-rw-r--r--contrib/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp8530
-rw-r--r--contrib/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp2621
-rw-r--r--contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.cpp74
-rw-r--r--contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h208
-rw-r--r--contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp127
-rw-r--r--contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h81
-rw-r--r--contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp591
-rw-r--r--contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h98
-rw-r--r--contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h136
-rw-r--r--contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp695
-rw-r--r--contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp121
-rw-r--r--contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h82
-rw-r--r--contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h233
-rw-r--r--contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.cpp287
-rw-r--r--contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsInstPrinter.h112
-rw-r--r--contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp52
-rw-r--r--contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h30
-rw-r--r--contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp1139
-rw-r--r--contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h275
-rw-r--r--contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp302
-rw-r--r--contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.h93
-rw-r--r--contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCNaCl.h31
-rw-r--r--contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp208
-rw-r--r--contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h67
-rw-r--r--contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp278
-rw-r--r--contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsOptionRecord.cpp100
-rw-r--r--contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp1313
-rw-r--r--contrib/llvm/lib/Target/Mips/MSA.txt83
-rw-r--r--contrib/llvm/lib/Target/Mips/MicroMips32r6InstrFormats.td1030
-rw-r--r--contrib/llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td1837
-rw-r--r--contrib/llvm/lib/Target/Mips/MicroMipsDSPInstrFormats.td301
-rw-r--r--contrib/llvm/lib/Target/Mips/MicroMipsDSPInstrInfo.td608
-rw-r--r--contrib/llvm/lib/Target/Mips/MicroMipsInstrFPU.td447
-rw-r--r--contrib/llvm/lib/Target/Mips/MicroMipsInstrFormats.td1114
-rw-r--r--contrib/llvm/lib/Target/Mips/MicroMipsInstrInfo.td1453
-rw-r--r--contrib/llvm/lib/Target/Mips/MicroMipsSizeReduction.cpp797
-rw-r--r--contrib/llvm/lib/Target/Mips/Mips.h52
-rw-r--r--contrib/llvm/lib/Target/Mips/Mips.td264
-rw-r--r--contrib/llvm/lib/Target/Mips/Mips16FrameLowering.cpp180
-rw-r--r--contrib/llvm/lib/Target/Mips/Mips16FrameLowering.h46
-rw-r--r--contrib/llvm/lib/Target/Mips/Mips16HardFloat.cpp536
-rw-r--r--contrib/llvm/lib/Target/Mips/Mips16HardFloatInfo.cpp49
-rw-r--r--contrib/llvm/lib/Target/Mips/Mips16HardFloatInfo.h49
-rw-r--r--contrib/llvm/lib/Target/Mips/Mips16ISelDAGToDAG.cpp225
-rw-r--r--contrib/llvm/lib/Target/Mips/Mips16ISelDAGToDAG.h54
-rw-r--r--contrib/llvm/lib/Target/Mips/Mips16ISelLowering.cpp790
-rw-r--r--contrib/llvm/lib/Target/Mips/Mips16ISelLowering.h82
-rw-r--r--contrib/llvm/lib/Target/Mips/Mips16InstrFormats.td639
-rw-r--r--contrib/llvm/lib/Target/Mips/Mips16InstrInfo.cpp495
-rw-r--r--contrib/llvm/lib/Target/Mips/Mips16InstrInfo.h131
-rw-r--r--contrib/llvm/lib/Target/Mips/Mips16InstrInfo.td1910
-rw-r--r--contrib/llvm/lib/Target/Mips/Mips16RegisterInfo.cpp147
-rw-r--r--contrib/llvm/lib/Target/Mips/Mips16RegisterInfo.h47
-rw-r--r--contrib/llvm/lib/Target/Mips/Mips32r6InstrFormats.td613
-rw-r--r--contrib/llvm/lib/Target/Mips/Mips32r6InstrInfo.td1139
-rw-r--r--contrib/llvm/lib/Target/Mips/Mips64InstrInfo.td1205
-rw-r--r--contrib/llvm/lib/Target/Mips/Mips64r6InstrInfo.td339
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsAnalyzeImmediate.cpp157
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsAnalyzeImmediate.h66
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsAsmPrinter.cpp1304
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsAsmPrinter.h165
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsBranchExpansion.cpp863
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsCCState.cpp175
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsCCState.h166
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsCallLowering.cpp668
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsCallLowering.h93
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsCallingConv.td411
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsCondMov.td309
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsConstantIslandPass.cpp1687
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsDSPInstrFormats.td368
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsDSPInstrInfo.td1473
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp930
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsEVAInstrFormats.td83
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsEVAInstrInfo.td213
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsExpandPseudo.cpp701
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsFastISel.cpp2153
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsFrameLowering.cpp151
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsFrameLowering.h57
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp274
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsISelDAGToDAG.h145
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsISelLowering.cpp4589
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsISelLowering.h730
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsInstrFPU.td970
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsInstrFormats.td998
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsInstrInfo.cpp842
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsInstrInfo.h187
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsInstrInfo.td3383
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsInstructionSelector.cpp671
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsLegalizerInfo.cpp155
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsLegalizerInfo.h33
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsMCInstLower.cpp330
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsMCInstLower.h53
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsMSAInstrFormats.td455
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsMSAInstrInfo.td4057
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsMTInstrFormats.td97
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsMTInstrInfo.td207
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsMachineFunction.cpp201
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsMachineFunction.h130
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsModuleISelDAGToDAG.cpp56
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsOptimizePICCall.cpp322
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsOptionRecord.h82
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsOs16.cpp159
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsPreLegalizerCombiner.cpp102
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsRegisterBankInfo.cpp677
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsRegisterBankInfo.h167
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsRegisterBanks.td14
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsRegisterInfo.cpp326
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsRegisterInfo.h85
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsRegisterInfo.td758
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsSEFrameLowering.cpp920
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsSEFrameLowering.h52
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp1297
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.h142
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsSEISelLowering.cpp3864
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsSEISelLowering.h143
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsSEInstrInfo.cpp906
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsSEInstrInfo.h127
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsSERegisterInfo.cpp260
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsSERegisterInfo.h40
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsSchedule.td737
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsScheduleGeneric.td1619
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsScheduleP5600.td636
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsSubtarget.cpp291
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsSubtarget.h402
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsTargetMachine.cpp339
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsTargetMachine.h96
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsTargetObjectFile.cpp195
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsTargetObjectFile.h49
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsTargetStreamer.h362
-rw-r--r--contrib/llvm/lib/Target/Mips/Relocation.txt92
-rw-r--r--contrib/llvm/lib/Target/Mips/TargetInfo/MipsTargetInfo.cpp47
-rw-r--r--contrib/llvm/lib/Target/Mips/TargetInfo/MipsTargetInfo.h23
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