From 0b57cec536236d46e3dba9bd041533462f33dbb7 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Fri, 20 Dec 2019 19:53:05 +0000 Subject: 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. --- .../lib/Target/Sparc/AsmParser/SparcAsmParser.cpp | 1346 -------- contrib/llvm/lib/Target/Sparc/DelaySlotFiller.cpp | 511 --- .../Sparc/Disassembler/SparcDisassembler.cpp | 662 ---- contrib/llvm/lib/Target/Sparc/LeonFeatures.td | 63 - contrib/llvm/lib/Target/Sparc/LeonPasses.cpp | 157 - contrib/llvm/lib/Target/Sparc/LeonPasses.h | 87 - .../Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp | 331 -- .../Sparc/MCTargetDesc/SparcELFObjectWriter.cpp | 139 - .../Target/Sparc/MCTargetDesc/SparcFixupKinds.h | 102 - .../Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp | 219 -- .../Target/Sparc/MCTargetDesc/SparcInstPrinter.h | 56 - .../Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp | 72 - .../lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.h | 39 - .../Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp | 233 -- .../lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp | 236 -- .../lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h | 113 - .../Sparc/MCTargetDesc/SparcMCTargetDesc.cpp | 125 - .../Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h | 59 - .../Sparc/MCTargetDesc/SparcTargetStreamer.cpp | 45 - .../Sparc/MCTargetDesc/SparcTargetStreamer.h | 47 - contrib/llvm/lib/Target/Sparc/Sparc.h | 166 - contrib/llvm/lib/Target/Sparc/Sparc.td | 183 -- contrib/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp | 446 --- contrib/llvm/lib/Target/Sparc/SparcCallingConv.td | 143 - .../llvm/lib/Target/Sparc/SparcFrameLowering.cpp | 385 --- contrib/llvm/lib/Target/Sparc/SparcFrameLowering.h | 67 - .../llvm/lib/Target/Sparc/SparcISelDAGToDAG.cpp | 401 --- .../llvm/lib/Target/Sparc/SparcISelLowering.cpp | 3417 -------------------- contrib/llvm/lib/Target/Sparc/SparcISelLowering.h | 216 -- contrib/llvm/lib/Target/Sparc/SparcInstr64Bit.td | 540 ---- contrib/llvm/lib/Target/Sparc/SparcInstrAliases.td | 523 --- contrib/llvm/lib/Target/Sparc/SparcInstrFormats.td | 368 --- contrib/llvm/lib/Target/Sparc/SparcInstrInfo.cpp | 509 --- contrib/llvm/lib/Target/Sparc/SparcInstrInfo.h | 107 - contrib/llvm/lib/Target/Sparc/SparcInstrInfo.td | 1712 ---------- contrib/llvm/lib/Target/Sparc/SparcInstrVIS.td | 262 -- contrib/llvm/lib/Target/Sparc/SparcMCInstLower.cpp | 107 - .../lib/Target/Sparc/SparcMachineFunctionInfo.cpp | 13 - .../lib/Target/Sparc/SparcMachineFunctionInfo.h | 55 - .../llvm/lib/Target/Sparc/SparcRegisterInfo.cpp | 240 -- contrib/llvm/lib/Target/Sparc/SparcRegisterInfo.h | 49 - contrib/llvm/lib/Target/Sparc/SparcRegisterInfo.td | 378 --- contrib/llvm/lib/Target/Sparc/SparcSchedule.td | 123 - contrib/llvm/lib/Target/Sparc/SparcSubtarget.cpp | 102 - contrib/llvm/lib/Target/Sparc/SparcSubtarget.h | 125 - .../llvm/lib/Target/Sparc/SparcTargetMachine.cpp | 218 -- contrib/llvm/lib/Target/Sparc/SparcTargetMachine.h | 78 - .../lib/Target/Sparc/SparcTargetObjectFile.cpp | 47 - .../llvm/lib/Target/Sparc/SparcTargetObjectFile.h | 36 - .../Target/Sparc/TargetInfo/SparcTargetInfo.cpp | 33 - .../lib/Target/Sparc/TargetInfo/SparcTargetInfo.h | 22 - 51 files changed, 15713 deletions(-) delete mode 100644 contrib/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp delete mode 100644 contrib/llvm/lib/Target/Sparc/DelaySlotFiller.cpp delete mode 100644 contrib/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp delete mode 100755 contrib/llvm/lib/Target/Sparc/LeonFeatures.td delete mode 100755 contrib/llvm/lib/Target/Sparc/LeonPasses.cpp delete mode 100755 contrib/llvm/lib/Target/Sparc/LeonPasses.h delete mode 100644 contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp delete mode 100644 contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp delete mode 100644 contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h delete mode 100644 contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp delete mode 100644 contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.h delete mode 100644 contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp delete mode 100644 contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.h delete mode 100644 contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp delete mode 100644 contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp delete mode 100644 contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h delete mode 100644 contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp delete mode 100644 contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h delete mode 100644 contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.cpp delete mode 100644 contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.h delete mode 100644 contrib/llvm/lib/Target/Sparc/Sparc.h delete mode 100644 contrib/llvm/lib/Target/Sparc/Sparc.td delete mode 100644 contrib/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp delete mode 100644 contrib/llvm/lib/Target/Sparc/SparcCallingConv.td delete mode 100644 contrib/llvm/lib/Target/Sparc/SparcFrameLowering.cpp delete mode 100644 contrib/llvm/lib/Target/Sparc/SparcFrameLowering.h delete mode 100644 contrib/llvm/lib/Target/Sparc/SparcISelDAGToDAG.cpp delete mode 100644 contrib/llvm/lib/Target/Sparc/SparcISelLowering.cpp delete mode 100644 contrib/llvm/lib/Target/Sparc/SparcISelLowering.h delete mode 100644 contrib/llvm/lib/Target/Sparc/SparcInstr64Bit.td delete mode 100644 contrib/llvm/lib/Target/Sparc/SparcInstrAliases.td delete mode 100644 contrib/llvm/lib/Target/Sparc/SparcInstrFormats.td delete mode 100644 contrib/llvm/lib/Target/Sparc/SparcInstrInfo.cpp delete mode 100644 contrib/llvm/lib/Target/Sparc/SparcInstrInfo.h delete mode 100644 contrib/llvm/lib/Target/Sparc/SparcInstrInfo.td delete mode 100644 contrib/llvm/lib/Target/Sparc/SparcInstrVIS.td delete mode 100644 contrib/llvm/lib/Target/Sparc/SparcMCInstLower.cpp delete mode 100644 contrib/llvm/lib/Target/Sparc/SparcMachineFunctionInfo.cpp delete mode 100644 contrib/llvm/lib/Target/Sparc/SparcMachineFunctionInfo.h delete mode 100644 contrib/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp delete mode 100644 contrib/llvm/lib/Target/Sparc/SparcRegisterInfo.h delete mode 100644 contrib/llvm/lib/Target/Sparc/SparcRegisterInfo.td delete mode 100755 contrib/llvm/lib/Target/Sparc/SparcSchedule.td delete mode 100644 contrib/llvm/lib/Target/Sparc/SparcSubtarget.cpp delete mode 100644 contrib/llvm/lib/Target/Sparc/SparcSubtarget.h delete mode 100644 contrib/llvm/lib/Target/Sparc/SparcTargetMachine.cpp delete mode 100644 contrib/llvm/lib/Target/Sparc/SparcTargetMachine.h delete mode 100644 contrib/llvm/lib/Target/Sparc/SparcTargetObjectFile.cpp delete mode 100644 contrib/llvm/lib/Target/Sparc/SparcTargetObjectFile.h delete mode 100644 contrib/llvm/lib/Target/Sparc/TargetInfo/SparcTargetInfo.cpp delete mode 100644 contrib/llvm/lib/Target/Sparc/TargetInfo/SparcTargetInfo.h (limited to 'contrib/llvm/lib/Target/Sparc') diff --git a/contrib/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp b/contrib/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp deleted file mode 100644 index 15453ae59a4f..000000000000 --- a/contrib/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +++ /dev/null @@ -1,1346 +0,0 @@ -//===-- SparcAsmParser.cpp - Parse Sparc 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/SparcMCExpr.h" -#include "MCTargetDesc/SparcMCTargetDesc.h" -#include "TargetInfo/SparcTargetInfo.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Triple.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCInst.h" -#include "llvm/MC/MCObjectFileInfo.h" -#include "llvm/MC/MCParser/MCAsmLexer.h" -#include "llvm/MC/MCParser/MCAsmParser.h" -#include "llvm/MC/MCParser/MCParsedAsmOperand.h" -#include "llvm/MC/MCParser/MCTargetAsmParser.h" -#include "llvm/MC/MCRegisterInfo.h" -#include "llvm/MC/MCStreamer.h" -#include "llvm/MC/MCSubtargetInfo.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/SMLoc.h" -#include "llvm/Support/TargetRegistry.h" -#include "llvm/Support/raw_ostream.h" -#include -#include -#include -#include - -using namespace llvm; - -// The generated AsmMatcher SparcGenAsmMatcher uses "Sparc" as the target -// namespace. But SPARC backend uses "SP" as its namespace. -namespace llvm { -namespace Sparc { - - using namespace SP; - -} // end namespace Sparc -} // end namespace llvm - -namespace { - -class SparcOperand; - -class SparcAsmParser : public MCTargetAsmParser { - MCAsmParser &Parser; - - /// @name Auto-generated Match Functions - /// { - -#define GET_ASSEMBLER_HEADER -#include "SparcGenAsmMatcher.inc" - - /// } - - // public interface of the MCTargetAsmParser. - bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, - OperandVector &Operands, MCStreamer &Out, - uint64_t &ErrorInfo, - bool MatchingInlineAsm) override; - bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; - bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, - SMLoc NameLoc, OperandVector &Operands) override; - bool ParseDirective(AsmToken DirectiveID) override; - - unsigned validateTargetOperandClass(MCParsedAsmOperand &Op, - unsigned Kind) override; - - // Custom parse functions for Sparc specific operands. - OperandMatchResultTy parseMEMOperand(OperandVector &Operands); - - OperandMatchResultTy parseMembarTag(OperandVector &Operands); - - OperandMatchResultTy parseOperand(OperandVector &Operands, StringRef Name); - - OperandMatchResultTy - parseSparcAsmOperand(std::unique_ptr &Operand, - bool isCall = false); - - OperandMatchResultTy parseBranchModifiers(OperandVector &Operands); - - // Helper function for dealing with %lo / %hi in PIC mode. - const SparcMCExpr *adjustPICRelocation(SparcMCExpr::VariantKind VK, - const MCExpr *subExpr); - - // returns true if Tok is matched to a register and returns register in RegNo. - bool matchRegisterName(const AsmToken &Tok, unsigned &RegNo, - unsigned &RegKind); - - bool matchSparcAsmModifiers(const MCExpr *&EVal, SMLoc &EndLoc); - - bool is64Bit() const { - return getSTI().getTargetTriple().getArch() == Triple::sparcv9; - } - - bool expandSET(MCInst &Inst, SMLoc IDLoc, - SmallVectorImpl &Instructions); - -public: - SparcAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser, - const MCInstrInfo &MII, - const MCTargetOptions &Options) - : MCTargetAsmParser(Options, sti, MII), Parser(parser) { - Parser.addAliasForDirective(".half", ".2byte"); - Parser.addAliasForDirective(".uahalf", ".2byte"); - Parser.addAliasForDirective(".word", ".4byte"); - Parser.addAliasForDirective(".uaword", ".4byte"); - Parser.addAliasForDirective(".nword", is64Bit() ? ".8byte" : ".4byte"); - if (is64Bit()) - Parser.addAliasForDirective(".xword", ".8byte"); - - // Initialize the set of available features. - setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits())); - } -}; - -} // end anonymous namespace - - static const MCPhysReg IntRegs[32] = { - Sparc::G0, Sparc::G1, Sparc::G2, Sparc::G3, - Sparc::G4, Sparc::G5, Sparc::G6, Sparc::G7, - Sparc::O0, Sparc::O1, Sparc::O2, Sparc::O3, - Sparc::O4, Sparc::O5, Sparc::O6, Sparc::O7, - Sparc::L0, Sparc::L1, Sparc::L2, Sparc::L3, - Sparc::L4, Sparc::L5, Sparc::L6, Sparc::L7, - Sparc::I0, Sparc::I1, Sparc::I2, Sparc::I3, - Sparc::I4, Sparc::I5, Sparc::I6, Sparc::I7 }; - - static const MCPhysReg FloatRegs[32] = { - Sparc::F0, Sparc::F1, Sparc::F2, Sparc::F3, - Sparc::F4, Sparc::F5, Sparc::F6, Sparc::F7, - Sparc::F8, Sparc::F9, Sparc::F10, Sparc::F11, - Sparc::F12, Sparc::F13, Sparc::F14, Sparc::F15, - Sparc::F16, Sparc::F17, Sparc::F18, Sparc::F19, - Sparc::F20, Sparc::F21, Sparc::F22, Sparc::F23, - Sparc::F24, Sparc::F25, Sparc::F26, Sparc::F27, - Sparc::F28, Sparc::F29, Sparc::F30, Sparc::F31 }; - - static const MCPhysReg DoubleRegs[32] = { - Sparc::D0, Sparc::D1, Sparc::D2, Sparc::D3, - Sparc::D4, Sparc::D5, Sparc::D6, Sparc::D7, - Sparc::D8, Sparc::D9, Sparc::D10, Sparc::D11, - Sparc::D12, Sparc::D13, Sparc::D14, Sparc::D15, - Sparc::D16, Sparc::D17, Sparc::D18, Sparc::D19, - Sparc::D20, Sparc::D21, Sparc::D22, Sparc::D23, - Sparc::D24, Sparc::D25, Sparc::D26, Sparc::D27, - Sparc::D28, Sparc::D29, Sparc::D30, Sparc::D31 }; - - static const MCPhysReg QuadFPRegs[32] = { - Sparc::Q0, Sparc::Q1, Sparc::Q2, Sparc::Q3, - Sparc::Q4, Sparc::Q5, Sparc::Q6, Sparc::Q7, - Sparc::Q8, Sparc::Q9, Sparc::Q10, Sparc::Q11, - Sparc::Q12, Sparc::Q13, Sparc::Q14, Sparc::Q15 }; - - static const MCPhysReg ASRRegs[32] = { - SP::Y, SP::ASR1, SP::ASR2, SP::ASR3, - SP::ASR4, SP::ASR5, SP::ASR6, SP::ASR7, - SP::ASR8, SP::ASR9, SP::ASR10, SP::ASR11, - SP::ASR12, SP::ASR13, SP::ASR14, SP::ASR15, - SP::ASR16, SP::ASR17, SP::ASR18, SP::ASR19, - SP::ASR20, SP::ASR21, SP::ASR22, SP::ASR23, - SP::ASR24, SP::ASR25, SP::ASR26, SP::ASR27, - SP::ASR28, SP::ASR29, SP::ASR30, SP::ASR31}; - - static const MCPhysReg IntPairRegs[] = { - Sparc::G0_G1, Sparc::G2_G3, Sparc::G4_G5, Sparc::G6_G7, - Sparc::O0_O1, Sparc::O2_O3, Sparc::O4_O5, Sparc::O6_O7, - Sparc::L0_L1, Sparc::L2_L3, Sparc::L4_L5, Sparc::L6_L7, - Sparc::I0_I1, Sparc::I2_I3, Sparc::I4_I5, Sparc::I6_I7}; - - static const MCPhysReg CoprocRegs[32] = { - Sparc::C0, Sparc::C1, Sparc::C2, Sparc::C3, - Sparc::C4, Sparc::C5, Sparc::C6, Sparc::C7, - Sparc::C8, Sparc::C9, Sparc::C10, Sparc::C11, - Sparc::C12, Sparc::C13, Sparc::C14, Sparc::C15, - Sparc::C16, Sparc::C17, Sparc::C18, Sparc::C19, - Sparc::C20, Sparc::C21, Sparc::C22, Sparc::C23, - Sparc::C24, Sparc::C25, Sparc::C26, Sparc::C27, - Sparc::C28, Sparc::C29, Sparc::C30, Sparc::C31 }; - - static const MCPhysReg CoprocPairRegs[] = { - Sparc::C0_C1, Sparc::C2_C3, Sparc::C4_C5, Sparc::C6_C7, - Sparc::C8_C9, Sparc::C10_C11, Sparc::C12_C13, Sparc::C14_C15, - Sparc::C16_C17, Sparc::C18_C19, Sparc::C20_C21, Sparc::C22_C23, - Sparc::C24_C25, Sparc::C26_C27, Sparc::C28_C29, Sparc::C30_C31}; - -namespace { - -/// SparcOperand - Instances of this class represent a parsed Sparc machine -/// instruction. -class SparcOperand : public MCParsedAsmOperand { -public: - enum RegisterKind { - rk_None, - rk_IntReg, - rk_IntPairReg, - rk_FloatReg, - rk_DoubleReg, - rk_QuadReg, - rk_CoprocReg, - rk_CoprocPairReg, - rk_Special, - }; - -private: - enum KindTy { - k_Token, - k_Register, - k_Immediate, - k_MemoryReg, - k_MemoryImm - } Kind; - - SMLoc StartLoc, EndLoc; - - struct Token { - const char *Data; - unsigned Length; - }; - - struct RegOp { - unsigned RegNum; - RegisterKind Kind; - }; - - struct ImmOp { - const MCExpr *Val; - }; - - struct MemOp { - unsigned Base; - unsigned OffsetReg; - const MCExpr *Off; - }; - - union { - struct Token Tok; - struct RegOp Reg; - struct ImmOp Imm; - struct MemOp Mem; - }; - -public: - SparcOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {} - - bool isToken() const override { return Kind == k_Token; } - bool isReg() const override { return Kind == k_Register; } - bool isImm() const override { return Kind == k_Immediate; } - bool isMem() const override { return isMEMrr() || isMEMri(); } - bool isMEMrr() const { return Kind == k_MemoryReg; } - bool isMEMri() const { return Kind == k_MemoryImm; } - bool isMembarTag() const { return Kind == k_Immediate; } - - bool isIntReg() const { - return (Kind == k_Register && Reg.Kind == rk_IntReg); - } - - bool isFloatReg() const { - return (Kind == k_Register && Reg.Kind == rk_FloatReg); - } - - bool isFloatOrDoubleReg() const { - return (Kind == k_Register && (Reg.Kind == rk_FloatReg - || Reg.Kind == rk_DoubleReg)); - } - - bool isCoprocReg() const { - return (Kind == k_Register && Reg.Kind == rk_CoprocReg); - } - - StringRef getToken() const { - assert(Kind == k_Token && "Invalid access!"); - return StringRef(Tok.Data, Tok.Length); - } - - unsigned getReg() const override { - assert((Kind == k_Register) && "Invalid access!"); - return Reg.RegNum; - } - - const MCExpr *getImm() const { - assert((Kind == k_Immediate) && "Invalid access!"); - return Imm.Val; - } - - unsigned getMemBase() const { - assert((Kind == k_MemoryReg || Kind == k_MemoryImm) && "Invalid access!"); - return Mem.Base; - } - - unsigned getMemOffsetReg() const { - assert((Kind == k_MemoryReg) && "Invalid access!"); - return Mem.OffsetReg; - } - - const MCExpr *getMemOff() const { - assert((Kind == k_MemoryImm) && "Invalid access!"); - return Mem.Off; - } - - /// 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_Token: OS << "Token: " << getToken() << "\n"; break; - case k_Register: OS << "Reg: #" << getReg() << "\n"; break; - case k_Immediate: OS << "Imm: " << getImm() << "\n"; break; - case k_MemoryReg: OS << "Mem: " << getMemBase() << "+" - << getMemOffsetReg() << "\n"; break; - case k_MemoryImm: assert(getMemOff() != nullptr); - OS << "Mem: " << getMemBase() - << "+" << *getMemOff() - << "\n"; break; - } - } - - void addRegOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::createReg(getReg())); - } - - void addImmOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - const MCExpr *Expr = getImm(); - addExpr(Inst, Expr); - } - - 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(Expr)) - Inst.addOperand(MCOperand::createImm(CE->getValue())); - else - Inst.addOperand(MCOperand::createExpr(Expr)); - } - - void addMEMrrOperands(MCInst &Inst, unsigned N) const { - assert(N == 2 && "Invalid number of operands!"); - - Inst.addOperand(MCOperand::createReg(getMemBase())); - - assert(getMemOffsetReg() != 0 && "Invalid offset"); - Inst.addOperand(MCOperand::createReg(getMemOffsetReg())); - } - - void addMEMriOperands(MCInst &Inst, unsigned N) const { - assert(N == 2 && "Invalid number of operands!"); - - Inst.addOperand(MCOperand::createReg(getMemBase())); - - const MCExpr *Expr = getMemOff(); - addExpr(Inst, Expr); - } - - void addMembarTagOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - const MCExpr *Expr = getImm(); - addExpr(Inst, Expr); - } - - static std::unique_ptr CreateToken(StringRef Str, SMLoc S) { - auto Op = make_unique(k_Token); - Op->Tok.Data = Str.data(); - Op->Tok.Length = Str.size(); - Op->StartLoc = S; - Op->EndLoc = S; - return Op; - } - - static std::unique_ptr CreateReg(unsigned RegNum, unsigned Kind, - SMLoc S, SMLoc E) { - auto Op = make_unique(k_Register); - Op->Reg.RegNum = RegNum; - Op->Reg.Kind = (SparcOperand::RegisterKind)Kind; - Op->StartLoc = S; - Op->EndLoc = E; - return Op; - } - - static std::unique_ptr CreateImm(const MCExpr *Val, SMLoc S, - SMLoc E) { - auto Op = make_unique(k_Immediate); - Op->Imm.Val = Val; - Op->StartLoc = S; - Op->EndLoc = E; - return Op; - } - - static bool MorphToIntPairReg(SparcOperand &Op) { - unsigned Reg = Op.getReg(); - assert(Op.Reg.Kind == rk_IntReg); - unsigned regIdx = 32; - if (Reg >= Sparc::G0 && Reg <= Sparc::G7) - regIdx = Reg - Sparc::G0; - else if (Reg >= Sparc::O0 && Reg <= Sparc::O7) - regIdx = Reg - Sparc::O0 + 8; - else if (Reg >= Sparc::L0 && Reg <= Sparc::L7) - regIdx = Reg - Sparc::L0 + 16; - else if (Reg >= Sparc::I0 && Reg <= Sparc::I7) - regIdx = Reg - Sparc::I0 + 24; - if (regIdx % 2 || regIdx > 31) - return false; - Op.Reg.RegNum = IntPairRegs[regIdx / 2]; - Op.Reg.Kind = rk_IntPairReg; - return true; - } - - static bool MorphToDoubleReg(SparcOperand &Op) { - unsigned Reg = Op.getReg(); - assert(Op.Reg.Kind == rk_FloatReg); - unsigned regIdx = Reg - Sparc::F0; - if (regIdx % 2 || regIdx > 31) - return false; - Op.Reg.RegNum = DoubleRegs[regIdx / 2]; - Op.Reg.Kind = rk_DoubleReg; - return true; - } - - static bool MorphToQuadReg(SparcOperand &Op) { - unsigned Reg = Op.getReg(); - unsigned regIdx = 0; - switch (Op.Reg.Kind) { - default: llvm_unreachable("Unexpected register kind!"); - case rk_FloatReg: - regIdx = Reg - Sparc::F0; - if (regIdx % 4 || regIdx > 31) - return false; - Reg = QuadFPRegs[regIdx / 4]; - break; - case rk_DoubleReg: - regIdx = Reg - Sparc::D0; - if (regIdx % 2 || regIdx > 31) - return false; - Reg = QuadFPRegs[regIdx / 2]; - break; - } - Op.Reg.RegNum = Reg; - Op.Reg.Kind = rk_QuadReg; - return true; - } - - static bool MorphToCoprocPairReg(SparcOperand &Op) { - unsigned Reg = Op.getReg(); - assert(Op.Reg.Kind == rk_CoprocReg); - unsigned regIdx = 32; - if (Reg >= Sparc::C0 && Reg <= Sparc::C31) - regIdx = Reg - Sparc::C0; - if (regIdx % 2 || regIdx > 31) - return false; - Op.Reg.RegNum = CoprocPairRegs[regIdx / 2]; - Op.Reg.Kind = rk_CoprocPairReg; - return true; - } - - static std::unique_ptr - MorphToMEMrr(unsigned Base, std::unique_ptr Op) { - unsigned offsetReg = Op->getReg(); - Op->Kind = k_MemoryReg; - Op->Mem.Base = Base; - Op->Mem.OffsetReg = offsetReg; - Op->Mem.Off = nullptr; - return Op; - } - - static std::unique_ptr - CreateMEMr(unsigned Base, SMLoc S, SMLoc E) { - auto Op = make_unique(k_MemoryReg); - Op->Mem.Base = Base; - Op->Mem.OffsetReg = Sparc::G0; // always 0 - Op->Mem.Off = nullptr; - Op->StartLoc = S; - Op->EndLoc = E; - return Op; - } - - static std::unique_ptr - MorphToMEMri(unsigned Base, std::unique_ptr Op) { - const MCExpr *Imm = Op->getImm(); - Op->Kind = k_MemoryImm; - Op->Mem.Base = Base; - Op->Mem.OffsetReg = 0; - Op->Mem.Off = Imm; - return Op; - } -}; - -} // end anonymous namespace - -bool SparcAsmParser::expandSET(MCInst &Inst, SMLoc IDLoc, - SmallVectorImpl &Instructions) { - MCOperand MCRegOp = Inst.getOperand(0); - MCOperand MCValOp = Inst.getOperand(1); - assert(MCRegOp.isReg()); - assert(MCValOp.isImm() || MCValOp.isExpr()); - - // the imm operand can be either an expression or an immediate. - bool IsImm = Inst.getOperand(1).isImm(); - int64_t RawImmValue = IsImm ? MCValOp.getImm() : 0; - - // Allow either a signed or unsigned 32-bit immediate. - if (RawImmValue < -2147483648LL || RawImmValue > 4294967295LL) { - return Error(IDLoc, - "set: argument must be between -2147483648 and 4294967295"); - } - - // If the value was expressed as a large unsigned number, that's ok. - // We want to see if it "looks like" a small signed number. - int32_t ImmValue = RawImmValue; - // For 'set' you can't use 'or' with a negative operand on V9 because - // that would splat the sign bit across the upper half of the destination - // register, whereas 'set' is defined to zero the high 32 bits. - bool IsEffectivelyImm13 = - IsImm && ((is64Bit() ? 0 : -4096) <= ImmValue && ImmValue < 4096); - const MCExpr *ValExpr; - if (IsImm) - ValExpr = MCConstantExpr::create(ImmValue, getContext()); - else - ValExpr = MCValOp.getExpr(); - - MCOperand PrevReg = MCOperand::createReg(Sparc::G0); - - // If not just a signed imm13 value, then either we use a 'sethi' with a - // following 'or', or a 'sethi' by itself if there are no more 1 bits. - // In either case, start with the 'sethi'. - if (!IsEffectivelyImm13) { - MCInst TmpInst; - const MCExpr *Expr = adjustPICRelocation(SparcMCExpr::VK_Sparc_HI, ValExpr); - TmpInst.setLoc(IDLoc); - TmpInst.setOpcode(SP::SETHIi); - TmpInst.addOperand(MCRegOp); - TmpInst.addOperand(MCOperand::createExpr(Expr)); - Instructions.push_back(TmpInst); - PrevReg = MCRegOp; - } - - // The low bits require touching in 3 cases: - // * A non-immediate value will always require both instructions. - // * An effectively imm13 value needs only an 'or' instruction. - // * Otherwise, an immediate that is not effectively imm13 requires the - // 'or' only if bits remain after clearing the 22 bits that 'sethi' set. - // If the low bits are known zeros, there's nothing to do. - // In the second case, and only in that case, must we NOT clear - // bits of the immediate value via the %lo() assembler function. - // Note also, the 'or' instruction doesn't mind a large value in the case - // where the operand to 'set' was 0xFFFFFzzz - it does exactly what you mean. - if (!IsImm || IsEffectivelyImm13 || (ImmValue & 0x3ff)) { - MCInst TmpInst; - const MCExpr *Expr; - if (IsEffectivelyImm13) - Expr = ValExpr; - else - Expr = adjustPICRelocation(SparcMCExpr::VK_Sparc_LO, ValExpr); - TmpInst.setLoc(IDLoc); - TmpInst.setOpcode(SP::ORri); - TmpInst.addOperand(MCRegOp); - TmpInst.addOperand(PrevReg); - TmpInst.addOperand(MCOperand::createExpr(Expr)); - Instructions.push_back(TmpInst); - } - return false; -} - -bool SparcAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, - OperandVector &Operands, - MCStreamer &Out, - uint64_t &ErrorInfo, - bool MatchingInlineAsm) { - MCInst Inst; - SmallVector Instructions; - unsigned MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo, - MatchingInlineAsm); - switch (MatchResult) { - case Match_Success: { - switch (Inst.getOpcode()) { - default: - Inst.setLoc(IDLoc); - Instructions.push_back(Inst); - break; - case SP::SET: - if (expandSET(Inst, IDLoc, Instructions)) - return true; - break; - } - - for (const MCInst &I : Instructions) { - Out.EmitInstruction(I, getSTI()); - } - return false; - } - - case Match_MissingFeature: - return Error(IDLoc, - "instruction requires a CPU feature not currently enabled"); - - case Match_InvalidOperand: { - SMLoc ErrorLoc = IDLoc; - if (ErrorInfo != ~0ULL) { - if (ErrorInfo >= Operands.size()) - return Error(IDLoc, "too few operands for instruction"); - - ErrorLoc = ((SparcOperand &)*Operands[ErrorInfo]).getStartLoc(); - if (ErrorLoc == SMLoc()) - ErrorLoc = IDLoc; - } - - return Error(ErrorLoc, "invalid operand for instruction"); - } - case Match_MnemonicFail: - return Error(IDLoc, "invalid instruction mnemonic"); - } - llvm_unreachable("Implement any new match types added!"); -} - -bool SparcAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, - SMLoc &EndLoc) { - const AsmToken &Tok = Parser.getTok(); - StartLoc = Tok.getLoc(); - EndLoc = Tok.getEndLoc(); - RegNo = 0; - if (getLexer().getKind() != AsmToken::Percent) - return false; - Parser.Lex(); - unsigned regKind = SparcOperand::rk_None; - if (matchRegisterName(Tok, RegNo, regKind)) { - Parser.Lex(); - return false; - } - - return Error(StartLoc, "invalid register name"); -} - -static void applyMnemonicAliases(StringRef &Mnemonic, - const FeatureBitset &Features, - unsigned VariantID); - -bool SparcAsmParser::ParseInstruction(ParseInstructionInfo &Info, - StringRef Name, SMLoc NameLoc, - OperandVector &Operands) { - - // First operand in MCInst is instruction mnemonic. - Operands.push_back(SparcOperand::CreateToken(Name, NameLoc)); - - // apply mnemonic aliases, if any, so that we can parse operands correctly. - applyMnemonicAliases(Name, getAvailableFeatures(), 0); - - if (getLexer().isNot(AsmToken::EndOfStatement)) { - // Read the first operand. - if (getLexer().is(AsmToken::Comma)) { - if (parseBranchModifiers(Operands) != MatchOperand_Success) { - SMLoc Loc = getLexer().getLoc(); - return Error(Loc, "unexpected token"); - } - } - if (parseOperand(Operands, Name) != MatchOperand_Success) { - SMLoc Loc = getLexer().getLoc(); - return Error(Loc, "unexpected token"); - } - - while (getLexer().is(AsmToken::Comma) || getLexer().is(AsmToken::Plus)) { - if (getLexer().is(AsmToken::Plus)) { - // Plus tokens are significant in software_traps (p83, sparcv8.pdf). We must capture them. - Operands.push_back(SparcOperand::CreateToken("+", Parser.getTok().getLoc())); - } - Parser.Lex(); // Eat the comma or plus. - // Parse and remember the operand. - if (parseOperand(Operands, Name) != MatchOperand_Success) { - SMLoc Loc = getLexer().getLoc(); - return Error(Loc, "unexpected token"); - } - } - } - if (getLexer().isNot(AsmToken::EndOfStatement)) { - SMLoc Loc = getLexer().getLoc(); - return Error(Loc, "unexpected token"); - } - Parser.Lex(); // Consume the EndOfStatement. - return false; -} - -bool SparcAsmParser:: -ParseDirective(AsmToken DirectiveID) -{ - StringRef IDVal = DirectiveID.getString(); - - if (IDVal == ".register") { - // For now, ignore .register directive. - Parser.eatToEndOfStatement(); - return false; - } - if (IDVal == ".proc") { - // For compatibility, ignore this directive. - // (It's supposed to be an "optimization" in the Sun assembler) - Parser.eatToEndOfStatement(); - return false; - } - - // Let the MC layer to handle other directives. - return true; -} - -OperandMatchResultTy -SparcAsmParser::parseMEMOperand(OperandVector &Operands) { - SMLoc S, E; - unsigned BaseReg = 0; - - if (ParseRegister(BaseReg, S, E)) { - return MatchOperand_NoMatch; - } - - switch (getLexer().getKind()) { - default: return MatchOperand_NoMatch; - - case AsmToken::Comma: - case AsmToken::RBrac: - case AsmToken::EndOfStatement: - Operands.push_back(SparcOperand::CreateMEMr(BaseReg, S, E)); - return MatchOperand_Success; - - case AsmToken:: Plus: - Parser.Lex(); // Eat the '+' - break; - case AsmToken::Minus: - break; - } - - std::unique_ptr Offset; - OperandMatchResultTy ResTy = parseSparcAsmOperand(Offset); - if (ResTy != MatchOperand_Success || !Offset) - return MatchOperand_NoMatch; - - Operands.push_back( - Offset->isImm() ? SparcOperand::MorphToMEMri(BaseReg, std::move(Offset)) - : SparcOperand::MorphToMEMrr(BaseReg, std::move(Offset))); - - return MatchOperand_Success; -} - -OperandMatchResultTy SparcAsmParser::parseMembarTag(OperandVector &Operands) { - SMLoc S = Parser.getTok().getLoc(); - const MCExpr *EVal; - int64_t ImmVal = 0; - - std::unique_ptr Mask; - if (parseSparcAsmOperand(Mask) == MatchOperand_Success) { - if (!Mask->isImm() || !Mask->getImm()->evaluateAsAbsolute(ImmVal) || - ImmVal < 0 || ImmVal > 127) { - Error(S, "invalid membar mask number"); - return MatchOperand_ParseFail; - } - } - - while (getLexer().getKind() == AsmToken::Hash) { - SMLoc TagStart = getLexer().getLoc(); - Parser.Lex(); // Eat the '#'. - unsigned MaskVal = StringSwitch(Parser.getTok().getString()) - .Case("LoadLoad", 0x1) - .Case("StoreLoad", 0x2) - .Case("LoadStore", 0x4) - .Case("StoreStore", 0x8) - .Case("Lookaside", 0x10) - .Case("MemIssue", 0x20) - .Case("Sync", 0x40) - .Default(0); - - Parser.Lex(); // Eat the identifier token. - - if (!MaskVal) { - Error(TagStart, "unknown membar tag"); - return MatchOperand_ParseFail; - } - - ImmVal |= MaskVal; - - if (getLexer().getKind() == AsmToken::Pipe) - Parser.Lex(); // Eat the '|'. - } - - EVal = MCConstantExpr::create(ImmVal, getContext()); - SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); - Operands.push_back(SparcOperand::CreateImm(EVal, S, E)); - return MatchOperand_Success; -} - -OperandMatchResultTy -SparcAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { - - OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic); - - // 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_Success || ResTy == MatchOperand_ParseFail) - return ResTy; - - if (getLexer().is(AsmToken::LBrac)) { - // Memory operand - Operands.push_back(SparcOperand::CreateToken("[", - Parser.getTok().getLoc())); - Parser.Lex(); // Eat the [ - - if (Mnemonic == "cas" || Mnemonic == "casx" || Mnemonic == "casa") { - SMLoc S = Parser.getTok().getLoc(); - if (getLexer().getKind() != AsmToken::Percent) - return MatchOperand_NoMatch; - Parser.Lex(); // eat % - - unsigned RegNo, RegKind; - if (!matchRegisterName(Parser.getTok(), RegNo, RegKind)) - return MatchOperand_NoMatch; - - Parser.Lex(); // Eat the identifier token. - SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer()-1); - Operands.push_back(SparcOperand::CreateReg(RegNo, RegKind, S, E)); - ResTy = MatchOperand_Success; - } else { - ResTy = parseMEMOperand(Operands); - } - - if (ResTy != MatchOperand_Success) - return ResTy; - - if (!getLexer().is(AsmToken::RBrac)) - return MatchOperand_ParseFail; - - Operands.push_back(SparcOperand::CreateToken("]", - Parser.getTok().getLoc())); - Parser.Lex(); // Eat the ] - - // Parse an optional address-space identifier after the address. - if (getLexer().is(AsmToken::Integer)) { - std::unique_ptr Op; - ResTy = parseSparcAsmOperand(Op, false); - if (ResTy != MatchOperand_Success || !Op) - return MatchOperand_ParseFail; - Operands.push_back(std::move(Op)); - } - return MatchOperand_Success; - } - - std::unique_ptr Op; - - ResTy = parseSparcAsmOperand(Op, (Mnemonic == "call")); - if (ResTy != MatchOperand_Success || !Op) - return MatchOperand_ParseFail; - - // Push the parsed operand into the list of operands - Operands.push_back(std::move(Op)); - - return MatchOperand_Success; -} - -OperandMatchResultTy -SparcAsmParser::parseSparcAsmOperand(std::unique_ptr &Op, - bool isCall) { - SMLoc S = Parser.getTok().getLoc(); - SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); - const MCExpr *EVal; - - Op = nullptr; - switch (getLexer().getKind()) { - default: break; - - case AsmToken::Percent: - Parser.Lex(); // Eat the '%'. - unsigned RegNo; - unsigned RegKind; - if (matchRegisterName(Parser.getTok(), RegNo, RegKind)) { - StringRef name = Parser.getTok().getString(); - Parser.Lex(); // Eat the identifier token. - E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); - switch (RegNo) { - default: - Op = SparcOperand::CreateReg(RegNo, RegKind, S, E); - break; - case Sparc::PSR: - Op = SparcOperand::CreateToken("%psr", S); - break; - case Sparc::FSR: - Op = SparcOperand::CreateToken("%fsr", S); - break; - case Sparc::FQ: - Op = SparcOperand::CreateToken("%fq", S); - break; - case Sparc::CPSR: - Op = SparcOperand::CreateToken("%csr", S); - break; - case Sparc::CPQ: - Op = SparcOperand::CreateToken("%cq", S); - break; - case Sparc::WIM: - Op = SparcOperand::CreateToken("%wim", S); - break; - case Sparc::TBR: - Op = SparcOperand::CreateToken("%tbr", S); - break; - case Sparc::ICC: - if (name == "xcc") - Op = SparcOperand::CreateToken("%xcc", S); - else - Op = SparcOperand::CreateToken("%icc", S); - break; - } - break; - } - if (matchSparcAsmModifiers(EVal, E)) { - E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); - Op = SparcOperand::CreateImm(EVal, S, E); - } - break; - - case AsmToken::Minus: - case AsmToken::Integer: - case AsmToken::LParen: - case AsmToken::Dot: - if (!getParser().parseExpression(EVal, E)) - Op = SparcOperand::CreateImm(EVal, S, E); - break; - - case AsmToken::Identifier: { - StringRef Identifier; - if (!getParser().parseIdentifier(Identifier)) { - E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); - MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier); - - const MCExpr *Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, - getContext()); - SparcMCExpr::VariantKind Kind = SparcMCExpr::VK_Sparc_13; - - if (getContext().getObjectFileInfo()->isPositionIndependent()) { - if (isCall) - Kind = SparcMCExpr::VK_Sparc_WPLT30; - else - Kind = SparcMCExpr::VK_Sparc_GOT13; - } - - Res = SparcMCExpr::create(Kind, Res, getContext()); - - Op = SparcOperand::CreateImm(Res, S, E); - } - break; - } - } - return (Op) ? MatchOperand_Success : MatchOperand_ParseFail; -} - -OperandMatchResultTy -SparcAsmParser::parseBranchModifiers(OperandVector &Operands) { - // parse (,a|,pn|,pt)+ - - while (getLexer().is(AsmToken::Comma)) { - Parser.Lex(); // Eat the comma - - if (!getLexer().is(AsmToken::Identifier)) - return MatchOperand_ParseFail; - StringRef modName = Parser.getTok().getString(); - if (modName == "a" || modName == "pn" || modName == "pt") { - Operands.push_back(SparcOperand::CreateToken(modName, - Parser.getTok().getLoc())); - Parser.Lex(); // eat the identifier. - } - } - return MatchOperand_Success; -} - -bool SparcAsmParser::matchRegisterName(const AsmToken &Tok, unsigned &RegNo, - unsigned &RegKind) { - int64_t intVal = 0; - RegNo = 0; - RegKind = SparcOperand::rk_None; - if (Tok.is(AsmToken::Identifier)) { - StringRef name = Tok.getString(); - - // %fp - if (name.equals("fp")) { - RegNo = Sparc::I6; - RegKind = SparcOperand::rk_IntReg; - return true; - } - // %sp - if (name.equals("sp")) { - RegNo = Sparc::O6; - RegKind = SparcOperand::rk_IntReg; - return true; - } - - if (name.equals("y")) { - RegNo = Sparc::Y; - RegKind = SparcOperand::rk_Special; - return true; - } - - if (name.substr(0, 3).equals_lower("asr") - && !name.substr(3).getAsInteger(10, intVal) - && intVal > 0 && intVal < 32) { - RegNo = ASRRegs[intVal]; - RegKind = SparcOperand::rk_Special; - return true; - } - - // %fprs is an alias of %asr6. - if (name.equals("fprs")) { - RegNo = ASRRegs[6]; - RegKind = SparcOperand::rk_Special; - return true; - } - - if (name.equals("icc")) { - RegNo = Sparc::ICC; - RegKind = SparcOperand::rk_Special; - return true; - } - - if (name.equals("psr")) { - RegNo = Sparc::PSR; - RegKind = SparcOperand::rk_Special; - return true; - } - - if (name.equals("fsr")) { - RegNo = Sparc::FSR; - RegKind = SparcOperand::rk_Special; - return true; - } - - if (name.equals("fq")) { - RegNo = Sparc::FQ; - RegKind = SparcOperand::rk_Special; - return true; - } - - if (name.equals("csr")) { - RegNo = Sparc::CPSR; - RegKind = SparcOperand::rk_Special; - return true; - } - - if (name.equals("cq")) { - RegNo = Sparc::CPQ; - RegKind = SparcOperand::rk_Special; - return true; - } - - if (name.equals("wim")) { - RegNo = Sparc::WIM; - RegKind = SparcOperand::rk_Special; - return true; - } - - if (name.equals("tbr")) { - RegNo = Sparc::TBR; - RegKind = SparcOperand::rk_Special; - return true; - } - - if (name.equals("xcc")) { - // FIXME:: check 64bit. - RegNo = Sparc::ICC; - RegKind = SparcOperand::rk_Special; - return true; - } - - // %fcc0 - %fcc3 - if (name.substr(0, 3).equals_lower("fcc") - && !name.substr(3).getAsInteger(10, intVal) - && intVal < 4) { - // FIXME: check 64bit and handle %fcc1 - %fcc3 - RegNo = Sparc::FCC0 + intVal; - RegKind = SparcOperand::rk_Special; - return true; - } - - // %g0 - %g7 - if (name.substr(0, 1).equals_lower("g") - && !name.substr(1).getAsInteger(10, intVal) - && intVal < 8) { - RegNo = IntRegs[intVal]; - RegKind = SparcOperand::rk_IntReg; - return true; - } - // %o0 - %o7 - if (name.substr(0, 1).equals_lower("o") - && !name.substr(1).getAsInteger(10, intVal) - && intVal < 8) { - RegNo = IntRegs[8 + intVal]; - RegKind = SparcOperand::rk_IntReg; - return true; - } - if (name.substr(0, 1).equals_lower("l") - && !name.substr(1).getAsInteger(10, intVal) - && intVal < 8) { - RegNo = IntRegs[16 + intVal]; - RegKind = SparcOperand::rk_IntReg; - return true; - } - if (name.substr(0, 1).equals_lower("i") - && !name.substr(1).getAsInteger(10, intVal) - && intVal < 8) { - RegNo = IntRegs[24 + intVal]; - RegKind = SparcOperand::rk_IntReg; - return true; - } - // %f0 - %f31 - if (name.substr(0, 1).equals_lower("f") - && !name.substr(1, 2).getAsInteger(10, intVal) && intVal < 32) { - RegNo = FloatRegs[intVal]; - RegKind = SparcOperand::rk_FloatReg; - return true; - } - // %f32 - %f62 - if (name.substr(0, 1).equals_lower("f") - && !name.substr(1, 2).getAsInteger(10, intVal) - && intVal >= 32 && intVal <= 62 && (intVal % 2 == 0)) { - // FIXME: Check V9 - RegNo = DoubleRegs[intVal/2]; - RegKind = SparcOperand::rk_DoubleReg; - return true; - } - - // %r0 - %r31 - if (name.substr(0, 1).equals_lower("r") - && !name.substr(1, 2).getAsInteger(10, intVal) && intVal < 31) { - RegNo = IntRegs[intVal]; - RegKind = SparcOperand::rk_IntReg; - return true; - } - - // %c0 - %c31 - if (name.substr(0, 1).equals_lower("c") - && !name.substr(1).getAsInteger(10, intVal) - && intVal < 32) { - RegNo = CoprocRegs[intVal]; - RegKind = SparcOperand::rk_CoprocReg; - return true; - } - - if (name.equals("tpc")) { - RegNo = Sparc::TPC; - RegKind = SparcOperand::rk_Special; - return true; - } - if (name.equals("tnpc")) { - RegNo = Sparc::TNPC; - RegKind = SparcOperand::rk_Special; - return true; - } - if (name.equals("tstate")) { - RegNo = Sparc::TSTATE; - RegKind = SparcOperand::rk_Special; - return true; - } - if (name.equals("tt")) { - RegNo = Sparc::TT; - RegKind = SparcOperand::rk_Special; - return true; - } - if (name.equals("tick")) { - RegNo = Sparc::TICK; - RegKind = SparcOperand::rk_Special; - return true; - } - if (name.equals("tba")) { - RegNo = Sparc::TBA; - RegKind = SparcOperand::rk_Special; - return true; - } - if (name.equals("pstate")) { - RegNo = Sparc::PSTATE; - RegKind = SparcOperand::rk_Special; - return true; - } - if (name.equals("tl")) { - RegNo = Sparc::TL; - RegKind = SparcOperand::rk_Special; - return true; - } - if (name.equals("pil")) { - RegNo = Sparc::PIL; - RegKind = SparcOperand::rk_Special; - return true; - } - if (name.equals("cwp")) { - RegNo = Sparc::CWP; - RegKind = SparcOperand::rk_Special; - return true; - } - if (name.equals("cansave")) { - RegNo = Sparc::CANSAVE; - RegKind = SparcOperand::rk_Special; - return true; - } - if (name.equals("canrestore")) { - RegNo = Sparc::CANRESTORE; - RegKind = SparcOperand::rk_Special; - return true; - } - if (name.equals("cleanwin")) { - RegNo = Sparc::CLEANWIN; - RegKind = SparcOperand::rk_Special; - return true; - } - if (name.equals("otherwin")) { - RegNo = Sparc::OTHERWIN; - RegKind = SparcOperand::rk_Special; - return true; - } - if (name.equals("wstate")) { - RegNo = Sparc::WSTATE; - RegKind = SparcOperand::rk_Special; - return true; - } - } - return false; -} - -// Determine if an expression contains a reference to the symbol -// "_GLOBAL_OFFSET_TABLE_". -static bool hasGOTReference(const MCExpr *Expr) { - switch (Expr->getKind()) { - case MCExpr::Target: - if (const SparcMCExpr *SE = dyn_cast(Expr)) - return hasGOTReference(SE->getSubExpr()); - break; - - case MCExpr::Constant: - break; - - case MCExpr::Binary: { - const MCBinaryExpr *BE = cast(Expr); - return hasGOTReference(BE->getLHS()) || hasGOTReference(BE->getRHS()); - } - - case MCExpr::SymbolRef: { - const MCSymbolRefExpr &SymRef = *cast(Expr); - return (SymRef.getSymbol().getName() == "_GLOBAL_OFFSET_TABLE_"); - } - - case MCExpr::Unary: - return hasGOTReference(cast(Expr)->getSubExpr()); - } - return false; -} - -const SparcMCExpr * -SparcAsmParser::adjustPICRelocation(SparcMCExpr::VariantKind VK, - const MCExpr *subExpr) { - // When in PIC mode, "%lo(...)" and "%hi(...)" behave differently. - // If the expression refers contains _GLOBAL_OFFSETE_TABLE, it is - // actually a %pc10 or %pc22 relocation. Otherwise, they are interpreted - // as %got10 or %got22 relocation. - - if (getContext().getObjectFileInfo()->isPositionIndependent()) { - switch(VK) { - default: break; - case SparcMCExpr::VK_Sparc_LO: - VK = (hasGOTReference(subExpr) ? SparcMCExpr::VK_Sparc_PC10 - : SparcMCExpr::VK_Sparc_GOT10); - break; - case SparcMCExpr::VK_Sparc_HI: - VK = (hasGOTReference(subExpr) ? SparcMCExpr::VK_Sparc_PC22 - : SparcMCExpr::VK_Sparc_GOT22); - break; - } - } - - return SparcMCExpr::create(VK, subExpr, getContext()); -} - -bool SparcAsmParser::matchSparcAsmModifiers(const MCExpr *&EVal, - SMLoc &EndLoc) { - AsmToken Tok = Parser.getTok(); - if (!Tok.is(AsmToken::Identifier)) - return false; - - StringRef name = Tok.getString(); - - SparcMCExpr::VariantKind VK = SparcMCExpr::parseVariantKind(name); - - if (VK == SparcMCExpr::VK_Sparc_None) - return false; - - Parser.Lex(); // Eat the identifier. - if (Parser.getTok().getKind() != AsmToken::LParen) - return false; - - Parser.Lex(); // Eat the LParen token. - const MCExpr *subExpr; - if (Parser.parseParenExpression(subExpr, EndLoc)) - return false; - - EVal = adjustPICRelocation(VK, subExpr); - return true; -} - -extern "C" void LLVMInitializeSparcAsmParser() { - RegisterMCAsmParser A(getTheSparcTarget()); - RegisterMCAsmParser B(getTheSparcV9Target()); - RegisterMCAsmParser C(getTheSparcelTarget()); -} - -#define GET_REGISTER_MATCHER -#define GET_MATCHER_IMPLEMENTATION -#include "SparcGenAsmMatcher.inc" - -unsigned SparcAsmParser::validateTargetOperandClass(MCParsedAsmOperand &GOp, - unsigned Kind) { - SparcOperand &Op = (SparcOperand &)GOp; - if (Op.isFloatOrDoubleReg()) { - switch (Kind) { - default: break; - case MCK_DFPRegs: - if (!Op.isFloatReg() || SparcOperand::MorphToDoubleReg(Op)) - return MCTargetAsmParser::Match_Success; - break; - case MCK_QFPRegs: - if (SparcOperand::MorphToQuadReg(Op)) - return MCTargetAsmParser::Match_Success; - break; - } - } - if (Op.isIntReg() && Kind == MCK_IntPair) { - if (SparcOperand::MorphToIntPairReg(Op)) - return MCTargetAsmParser::Match_Success; - } - if (Op.isCoprocReg() && Kind == MCK_CoprocPair) { - if (SparcOperand::MorphToCoprocPairReg(Op)) - return MCTargetAsmParser::Match_Success; - } - return Match_InvalidOperand; -} diff --git a/contrib/llvm/lib/Target/Sparc/DelaySlotFiller.cpp b/contrib/llvm/lib/Target/Sparc/DelaySlotFiller.cpp deleted file mode 100644 index f1ca8e18c228..000000000000 --- a/contrib/llvm/lib/Target/Sparc/DelaySlotFiller.cpp +++ /dev/null @@ -1,511 +0,0 @@ -//===-- DelaySlotFiller.cpp - SPARC 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 -// -//===----------------------------------------------------------------------===// -// -// This is a simple local pass that attempts to fill delay slots with useful -// instructions. If no instructions can be moved into the delay slot, then a -// NOP is placed. -//===----------------------------------------------------------------------===// - -#include "Sparc.h" -#include "SparcSubtarget.h" -#include "llvm/ADT/SmallSet.h" -#include "llvm/ADT/Statistic.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/TargetInstrInfo.h" -#include "llvm/CodeGen/TargetRegisterInfo.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Target/TargetMachine.h" - -using namespace llvm; - -#define DEBUG_TYPE "delay-slot-filler" - -STATISTIC(FilledSlots, "Number of delay slots filled"); - -static cl::opt DisableDelaySlotFiller( - "disable-sparc-delay-filler", - cl::init(false), - cl::desc("Disable the Sparc delay slot filler."), - cl::Hidden); - -namespace { - struct Filler : public MachineFunctionPass { - const SparcSubtarget *Subtarget; - - static char ID; - Filler() : MachineFunctionPass(ID) {} - - StringRef getPassName() const override { return "SPARC Delay Slot Filler"; } - - bool runOnMachineBasicBlock(MachineBasicBlock &MBB); - bool runOnMachineFunction(MachineFunction &F) override { - bool Changed = false; - Subtarget = &F.getSubtarget(); - - // This pass invalidates liveness information when it reorders - // instructions to fill delay slot. - F.getRegInfo().invalidateLiveness(); - - for (MachineFunction::iterator FI = F.begin(), FE = F.end(); - FI != FE; ++FI) - Changed |= runOnMachineBasicBlock(*FI); - return Changed; - } - - MachineFunctionProperties getRequiredProperties() const override { - return MachineFunctionProperties().set( - MachineFunctionProperties::Property::NoVRegs); - } - - void insertCallDefsUses(MachineBasicBlock::iterator MI, - SmallSet& RegDefs, - SmallSet& RegUses); - - void insertDefsUses(MachineBasicBlock::iterator MI, - SmallSet& RegDefs, - SmallSet& RegUses); - - bool IsRegInSet(SmallSet& RegSet, - unsigned Reg); - - bool delayHasHazard(MachineBasicBlock::iterator candidate, - bool &sawLoad, bool &sawStore, - SmallSet &RegDefs, - SmallSet &RegUses); - - MachineBasicBlock::iterator - findDelayInstr(MachineBasicBlock &MBB, MachineBasicBlock::iterator slot); - - bool needsUnimp(MachineBasicBlock::iterator I, unsigned &StructSize); - - bool tryCombineRestoreWithPrevInst(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI); - - }; - char Filler::ID = 0; -} // end of anonymous namespace - -/// createSparcDelaySlotFillerPass - Returns a pass that fills in delay -/// slots in Sparc MachineFunctions -/// -FunctionPass *llvm::createSparcDelaySlotFillerPass() { - return new Filler; -} - - -/// runOnMachineBasicBlock - Fill in delay slots for the given basic block. -/// We assume there is only one delay slot per delayed instruction. -/// -bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) { - bool Changed = false; - Subtarget = &MBB.getParent()->getSubtarget(); - const TargetInstrInfo *TII = Subtarget->getInstrInfo(); - - for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ) { - MachineBasicBlock::iterator MI = I; - ++I; - - // If MI is restore, try combining it with previous inst. - if (!DisableDelaySlotFiller && - (MI->getOpcode() == SP::RESTORErr - || MI->getOpcode() == SP::RESTOREri)) { - Changed |= tryCombineRestoreWithPrevInst(MBB, MI); - continue; - } - - // TODO: If we ever want to support v7, this needs to be extended - // to cover all floating point operations. - if (!Subtarget->isV9() && - (MI->getOpcode() == SP::FCMPS || MI->getOpcode() == SP::FCMPD - || MI->getOpcode() == SP::FCMPQ)) { - BuildMI(MBB, I, MI->getDebugLoc(), TII->get(SP::NOP)); - Changed = true; - continue; - } - - // If MI has no delay slot, skip. - if (!MI->hasDelaySlot()) - continue; - - MachineBasicBlock::iterator D = MBB.end(); - - if (!DisableDelaySlotFiller) - D = findDelayInstr(MBB, MI); - - ++FilledSlots; - Changed = true; - - if (D == MBB.end()) - BuildMI(MBB, I, MI->getDebugLoc(), TII->get(SP::NOP)); - else - MBB.splice(I, &MBB, D); - - unsigned structSize = 0; - if (needsUnimp(MI, structSize)) { - MachineBasicBlock::iterator J = MI; - ++J; // skip the delay filler. - assert (J != MBB.end() && "MI needs a delay instruction."); - BuildMI(MBB, ++J, MI->getDebugLoc(), - TII->get(SP::UNIMP)).addImm(structSize); - // Bundle the delay filler and unimp with the instruction. - MIBundleBuilder(MBB, MachineBasicBlock::iterator(MI), J); - } else { - MIBundleBuilder(MBB, MachineBasicBlock::iterator(MI), I); - } - } - return Changed; -} - -MachineBasicBlock::iterator -Filler::findDelayInstr(MachineBasicBlock &MBB, - MachineBasicBlock::iterator slot) -{ - SmallSet RegDefs; - SmallSet RegUses; - bool sawLoad = false; - bool sawStore = false; - - if (slot == MBB.begin()) - return MBB.end(); - - if (slot->getOpcode() == SP::RET || slot->getOpcode() == SP::TLS_CALL) - return MBB.end(); - - if (slot->getOpcode() == SP::RETL) { - MachineBasicBlock::iterator J = slot; - --J; - - if (J->getOpcode() == SP::RESTORErr - || J->getOpcode() == SP::RESTOREri) { - // change retl to ret. - slot->setDesc(Subtarget->getInstrInfo()->get(SP::RET)); - return J; - } - } - - // Call's delay filler can def some of call's uses. - if (slot->isCall()) - insertCallDefsUses(slot, RegDefs, RegUses); - else - insertDefsUses(slot, RegDefs, RegUses); - - bool done = false; - - MachineBasicBlock::iterator I = slot; - - while (!done) { - done = (I == MBB.begin()); - - if (!done) - --I; - - // skip debug instruction - if (I->isDebugInstr()) - continue; - - if (I->hasUnmodeledSideEffects() || I->isInlineAsm() || I->isPosition() || - I->hasDelaySlot() || I->isBundledWithSucc()) - break; - - if (delayHasHazard(I, sawLoad, sawStore, RegDefs, RegUses)) { - insertDefsUses(I, RegDefs, RegUses); - continue; - } - - return I; - } - return MBB.end(); -} - -bool Filler::delayHasHazard(MachineBasicBlock::iterator candidate, - bool &sawLoad, - bool &sawStore, - SmallSet &RegDefs, - SmallSet &RegUses) -{ - - if (candidate->isImplicitDef() || candidate->isKill()) - return true; - - if (candidate->mayLoad()) { - sawLoad = true; - if (sawStore) - return true; - } - - if (candidate->mayStore()) { - if (sawStore) - return true; - sawStore = true; - if (sawLoad) - return true; - } - - for (unsigned i = 0, e = candidate->getNumOperands(); i!= e; ++i) { - const MachineOperand &MO = candidate->getOperand(i); - if (!MO.isReg()) - continue; // skip - - unsigned Reg = MO.getReg(); - - if (MO.isDef()) { - // check whether Reg is defined or used before delay slot. - if (IsRegInSet(RegDefs, Reg) || IsRegInSet(RegUses, Reg)) - return true; - } - if (MO.isUse()) { - // check whether Reg is defined before delay slot. - if (IsRegInSet(RegDefs, Reg)) - return true; - } - } - - unsigned Opcode = candidate->getOpcode(); - // LD and LDD may have NOPs inserted afterwards in the case of some LEON - // processors, so we can't use the delay slot if this feature is switched-on. - if (Subtarget->insertNOPLoad() - && - Opcode >= SP::LDDArr && Opcode <= SP::LDrr) - return true; - - // Same as above for FDIV and FSQRT on some LEON processors. - if (Subtarget->fixAllFDIVSQRT() - && - Opcode >= SP::FDIVD && Opcode <= SP::FSQRTD) - return true; - - - return false; -} - - -void Filler::insertCallDefsUses(MachineBasicBlock::iterator MI, - SmallSet& RegDefs, - SmallSet& RegUses) -{ - // Call defines o7, which is visible to the instruction in delay slot. - RegDefs.insert(SP::O7); - - switch(MI->getOpcode()) { - default: llvm_unreachable("Unknown opcode."); - case SP::CALL: break; - case SP::CALLrr: - case SP::CALLri: - assert(MI->getNumOperands() >= 2); - const MachineOperand &Reg = MI->getOperand(0); - assert(Reg.isReg() && "CALL first operand is not a register."); - assert(Reg.isUse() && "CALL first operand is not a use."); - RegUses.insert(Reg.getReg()); - - const MachineOperand &Operand1 = MI->getOperand(1); - if (Operand1.isImm() || Operand1.isGlobal()) - break; - assert(Operand1.isReg() && "CALLrr second operand is not a register."); - assert(Operand1.isUse() && "CALLrr second operand is not a use."); - RegUses.insert(Operand1.getReg()); - break; - } -} - -// Insert Defs and Uses of MI into the sets RegDefs and RegUses. -void Filler::insertDefsUses(MachineBasicBlock::iterator MI, - SmallSet& RegDefs, - SmallSet& RegUses) -{ - for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { - const MachineOperand &MO = MI->getOperand(i); - if (!MO.isReg()) - continue; - - unsigned Reg = MO.getReg(); - if (Reg == 0) - continue; - if (MO.isDef()) - RegDefs.insert(Reg); - if (MO.isUse()) { - // Implicit register uses of retl are return values and - // retl does not use them. - if (MO.isImplicit() && MI->getOpcode() == SP::RETL) - continue; - RegUses.insert(Reg); - } - } -} - -// returns true if the Reg or its alias is in the RegSet. -bool Filler::IsRegInSet(SmallSet& RegSet, unsigned Reg) -{ - // Check Reg and all aliased Registers. - for (MCRegAliasIterator AI(Reg, Subtarget->getRegisterInfo(), true); - AI.isValid(); ++AI) - if (RegSet.count(*AI)) - return true; - return false; -} - -bool Filler::needsUnimp(MachineBasicBlock::iterator I, unsigned &StructSize) -{ - if (!I->isCall()) - return false; - - unsigned structSizeOpNum = 0; - switch (I->getOpcode()) { - default: llvm_unreachable("Unknown call opcode."); - case SP::CALL: structSizeOpNum = 1; break; - case SP::CALLrr: - case SP::CALLri: structSizeOpNum = 2; break; - case SP::TLS_CALL: return false; - } - - const MachineOperand &MO = I->getOperand(structSizeOpNum); - if (!MO.isImm()) - return false; - StructSize = MO.getImm(); - return true; -} - -static bool combineRestoreADD(MachineBasicBlock::iterator RestoreMI, - MachineBasicBlock::iterator AddMI, - const TargetInstrInfo *TII) -{ - // Before: add , , %i[0-7] - // restore %g0, %g0, %i[0-7] - // - // After : restore , , %o[0-7] - - unsigned reg = AddMI->getOperand(0).getReg(); - if (reg < SP::I0 || reg > SP::I7) - return false; - - // Erase RESTORE. - RestoreMI->eraseFromParent(); - - // Change ADD to RESTORE. - AddMI->setDesc(TII->get((AddMI->getOpcode() == SP::ADDrr) - ? SP::RESTORErr - : SP::RESTOREri)); - - // Map the destination register. - AddMI->getOperand(0).setReg(reg - SP::I0 + SP::O0); - - return true; -} - -static bool combineRestoreOR(MachineBasicBlock::iterator RestoreMI, - MachineBasicBlock::iterator OrMI, - const TargetInstrInfo *TII) -{ - // Before: or , , %i[0-7] - // restore %g0, %g0, %i[0-7] - // and or is zero, - // - // After : restore , , %o[0-7] - - unsigned reg = OrMI->getOperand(0).getReg(); - if (reg < SP::I0 || reg > SP::I7) - return false; - - // check whether it is a copy. - if (OrMI->getOpcode() == SP::ORrr - && OrMI->getOperand(1).getReg() != SP::G0 - && OrMI->getOperand(2).getReg() != SP::G0) - return false; - - if (OrMI->getOpcode() == SP::ORri - && OrMI->getOperand(1).getReg() != SP::G0 - && (!OrMI->getOperand(2).isImm() || OrMI->getOperand(2).getImm() != 0)) - return false; - - // Erase RESTORE. - RestoreMI->eraseFromParent(); - - // Change OR to RESTORE. - OrMI->setDesc(TII->get((OrMI->getOpcode() == SP::ORrr) - ? SP::RESTORErr - : SP::RESTOREri)); - - // Map the destination register. - OrMI->getOperand(0).setReg(reg - SP::I0 + SP::O0); - - return true; -} - -static bool combineRestoreSETHIi(MachineBasicBlock::iterator RestoreMI, - MachineBasicBlock::iterator SetHiMI, - const TargetInstrInfo *TII) -{ - // Before: sethi imm3, %i[0-7] - // restore %g0, %g0, %g0 - // - // After : restore %g0, (imm3<<10), %o[0-7] - - unsigned reg = SetHiMI->getOperand(0).getReg(); - if (reg < SP::I0 || reg > SP::I7) - return false; - - if (!SetHiMI->getOperand(1).isImm()) - return false; - - int64_t imm = SetHiMI->getOperand(1).getImm(); - - // Is it a 3 bit immediate? - if (!isInt<3>(imm)) - return false; - - // Make it a 13 bit immediate. - imm = (imm << 10) & 0x1FFF; - - assert(RestoreMI->getOpcode() == SP::RESTORErr); - - RestoreMI->setDesc(TII->get(SP::RESTOREri)); - - RestoreMI->getOperand(0).setReg(reg - SP::I0 + SP::O0); - RestoreMI->getOperand(1).setReg(SP::G0); - RestoreMI->getOperand(2).ChangeToImmediate(imm); - - - // Erase the original SETHI. - SetHiMI->eraseFromParent(); - - return true; -} - -bool Filler::tryCombineRestoreWithPrevInst(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI) -{ - // No previous instruction. - if (MBBI == MBB.begin()) - return false; - - // assert that MBBI is a "restore %g0, %g0, %g0". - assert(MBBI->getOpcode() == SP::RESTORErr - && MBBI->getOperand(0).getReg() == SP::G0 - && MBBI->getOperand(1).getReg() == SP::G0 - && MBBI->getOperand(2).getReg() == SP::G0); - - MachineBasicBlock::iterator PrevInst = std::prev(MBBI); - - // It cannot be combined with a bundled instruction. - if (PrevInst->isBundledWithSucc()) - return false; - - const TargetInstrInfo *TII = Subtarget->getInstrInfo(); - - switch (PrevInst->getOpcode()) { - default: break; - case SP::ADDrr: - case SP::ADDri: return combineRestoreADD(MBBI, PrevInst, TII); break; - case SP::ORrr: - case SP::ORri: return combineRestoreOR(MBBI, PrevInst, TII); break; - case SP::SETHIi: return combineRestoreSETHIi(MBBI, PrevInst, TII); break; - } - // It cannot combine with the previous instruction. - return false; -} diff --git a/contrib/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp b/contrib/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp deleted file mode 100644 index bee331874e96..000000000000 --- a/contrib/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp +++ /dev/null @@ -1,662 +0,0 @@ -//===- SparcDisassembler.cpp - Disassembler for Sparc -----------*- 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 is part of the Sparc Disassembler. -// -//===----------------------------------------------------------------------===// - -#include "MCTargetDesc/SparcMCTargetDesc.h" -#include "TargetInfo/SparcTargetInfo.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCDisassembler/MCDisassembler.h" -#include "llvm/MC/MCFixedLenDisassembler.h" -#include "llvm/MC/MCInst.h" -#include "llvm/Support/TargetRegistry.h" - -using namespace llvm; - -#define DEBUG_TYPE "sparc-disassembler" - -typedef MCDisassembler::DecodeStatus DecodeStatus; - -namespace { - -/// A disassembler class for Sparc. -class SparcDisassembler : public MCDisassembler { -public: - SparcDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx) - : MCDisassembler(STI, Ctx) {} - virtual ~SparcDisassembler() {} - - DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size, - ArrayRef Bytes, uint64_t Address, - raw_ostream &VStream, - raw_ostream &CStream) const override; -}; -} - -static MCDisassembler *createSparcDisassembler(const Target &T, - const MCSubtargetInfo &STI, - MCContext &Ctx) { - return new SparcDisassembler(STI, Ctx); -} - - -extern "C" void LLVMInitializeSparcDisassembler() { - // Register the disassembler. - TargetRegistry::RegisterMCDisassembler(getTheSparcTarget(), - createSparcDisassembler); - TargetRegistry::RegisterMCDisassembler(getTheSparcV9Target(), - createSparcDisassembler); - TargetRegistry::RegisterMCDisassembler(getTheSparcelTarget(), - createSparcDisassembler); -} - -static const unsigned IntRegDecoderTable[] = { - SP::G0, SP::G1, SP::G2, SP::G3, - SP::G4, SP::G5, SP::G6, SP::G7, - SP::O0, SP::O1, SP::O2, SP::O3, - SP::O4, SP::O5, SP::O6, SP::O7, - SP::L0, SP::L1, SP::L2, SP::L3, - SP::L4, SP::L5, SP::L6, SP::L7, - SP::I0, SP::I1, SP::I2, SP::I3, - SP::I4, SP::I5, SP::I6, SP::I7 }; - -static const unsigned FPRegDecoderTable[] = { - SP::F0, SP::F1, SP::F2, SP::F3, - SP::F4, SP::F5, SP::F6, SP::F7, - SP::F8, SP::F9, SP::F10, SP::F11, - SP::F12, SP::F13, SP::F14, SP::F15, - SP::F16, SP::F17, SP::F18, SP::F19, - SP::F20, SP::F21, SP::F22, SP::F23, - SP::F24, SP::F25, SP::F26, SP::F27, - SP::F28, SP::F29, SP::F30, SP::F31 }; - -static const unsigned DFPRegDecoderTable[] = { - SP::D0, SP::D16, SP::D1, SP::D17, - SP::D2, SP::D18, SP::D3, SP::D19, - SP::D4, SP::D20, SP::D5, SP::D21, - SP::D6, SP::D22, SP::D7, SP::D23, - SP::D8, SP::D24, SP::D9, SP::D25, - SP::D10, SP::D26, SP::D11, SP::D27, - SP::D12, SP::D28, SP::D13, SP::D29, - SP::D14, SP::D30, SP::D15, SP::D31 }; - -static const unsigned QFPRegDecoderTable[] = { - SP::Q0, SP::Q8, ~0U, ~0U, - SP::Q1, SP::Q9, ~0U, ~0U, - SP::Q2, SP::Q10, ~0U, ~0U, - SP::Q3, SP::Q11, ~0U, ~0U, - SP::Q4, SP::Q12, ~0U, ~0U, - SP::Q5, SP::Q13, ~0U, ~0U, - SP::Q6, SP::Q14, ~0U, ~0U, - SP::Q7, SP::Q15, ~0U, ~0U } ; - -static const unsigned FCCRegDecoderTable[] = { - SP::FCC0, SP::FCC1, SP::FCC2, SP::FCC3 }; - -static const unsigned ASRRegDecoderTable[] = { - SP::Y, SP::ASR1, SP::ASR2, SP::ASR3, - SP::ASR4, SP::ASR5, SP::ASR6, SP::ASR7, - SP::ASR8, SP::ASR9, SP::ASR10, SP::ASR11, - SP::ASR12, SP::ASR13, SP::ASR14, SP::ASR15, - SP::ASR16, SP::ASR17, SP::ASR18, SP::ASR19, - SP::ASR20, SP::ASR21, SP::ASR22, SP::ASR23, - SP::ASR24, SP::ASR25, SP::ASR26, SP::ASR27, - SP::ASR28, SP::ASR29, SP::ASR30, SP::ASR31}; - -static const unsigned PRRegDecoderTable[] = { - SP::TPC, SP::TNPC, SP::TSTATE, SP::TT, SP::TICK, SP::TBA, SP::PSTATE, - SP::TL, SP::PIL, SP::CWP, SP::CANSAVE, SP::CANRESTORE, SP::CLEANWIN, - SP::OTHERWIN, SP::WSTATE -}; - -static const uint16_t IntPairDecoderTable[] = { - SP::G0_G1, SP::G2_G3, SP::G4_G5, SP::G6_G7, - SP::O0_O1, SP::O2_O3, SP::O4_O5, SP::O6_O7, - SP::L0_L1, SP::L2_L3, SP::L4_L5, SP::L6_L7, - SP::I0_I1, SP::I2_I3, SP::I4_I5, SP::I6_I7, -}; - -static const unsigned CPRegDecoderTable[] = { - SP::C0, SP::C1, SP::C2, SP::C3, - SP::C4, SP::C5, SP::C6, SP::C7, - SP::C8, SP::C9, SP::C10, SP::C11, - SP::C12, SP::C13, SP::C14, SP::C15, - SP::C16, SP::C17, SP::C18, SP::C19, - SP::C20, SP::C21, SP::C22, SP::C23, - SP::C24, SP::C25, SP::C26, SP::C27, - SP::C28, SP::C29, SP::C30, SP::C31 -}; - - -static const uint16_t CPPairDecoderTable[] = { - SP::C0_C1, SP::C2_C3, SP::C4_C5, SP::C6_C7, - SP::C8_C9, SP::C10_C11, SP::C12_C13, SP::C14_C15, - SP::C16_C17, SP::C18_C19, SP::C20_C21, SP::C22_C23, - SP::C24_C25, SP::C26_C27, SP::C28_C29, SP::C30_C31 -}; - -static DecodeStatus DecodeIntRegsRegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder) { - if (RegNo > 31) - return MCDisassembler::Fail; - unsigned Reg = IntRegDecoderTable[RegNo]; - Inst.addOperand(MCOperand::createReg(Reg)); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeI64RegsRegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder) { - if (RegNo > 31) - return MCDisassembler::Fail; - unsigned Reg = IntRegDecoderTable[RegNo]; - Inst.addOperand(MCOperand::createReg(Reg)); - return MCDisassembler::Success; -} - - -static DecodeStatus DecodeFPRegsRegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder) { - if (RegNo > 31) - return MCDisassembler::Fail; - unsigned Reg = FPRegDecoderTable[RegNo]; - Inst.addOperand(MCOperand::createReg(Reg)); - return MCDisassembler::Success; -} - - -static DecodeStatus DecodeDFPRegsRegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder) { - if (RegNo > 31) - return MCDisassembler::Fail; - unsigned Reg = DFPRegDecoderTable[RegNo]; - Inst.addOperand(MCOperand::createReg(Reg)); - return MCDisassembler::Success; -} - - -static DecodeStatus DecodeQFPRegsRegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder) { - if (RegNo > 31) - return MCDisassembler::Fail; - - unsigned Reg = QFPRegDecoderTable[RegNo]; - if (Reg == ~0U) - return MCDisassembler::Fail; - Inst.addOperand(MCOperand::createReg(Reg)); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeCPRegsRegisterClass(MCInst &Inst, - unsigned RegNo, - uint64_t Address, - const void *Decoder) { - if (RegNo > 31) - return MCDisassembler::Fail; - unsigned Reg = CPRegDecoderTable[RegNo]; - Inst.addOperand(MCOperand::createReg(Reg)); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeFCCRegsRegisterClass(MCInst &Inst, unsigned RegNo, - uint64_t Address, - const void *Decoder) { - if (RegNo > 3) - return MCDisassembler::Fail; - Inst.addOperand(MCOperand::createReg(FCCRegDecoderTable[RegNo])); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeASRRegsRegisterClass(MCInst &Inst, unsigned RegNo, - uint64_t Address, - const void *Decoder) { - if (RegNo > 31) - return MCDisassembler::Fail; - Inst.addOperand(MCOperand::createReg(ASRRegDecoderTable[RegNo])); - return MCDisassembler::Success; -} - -static DecodeStatus DecodePRRegsRegisterClass(MCInst &Inst, unsigned RegNo, - uint64_t Address, - const void *Decoder) { - if (RegNo >= array_lengthof(PRRegDecoderTable)) - return MCDisassembler::Fail; - Inst.addOperand(MCOperand::createReg(PRRegDecoderTable[RegNo])); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeIntPairRegisterClass(MCInst &Inst, unsigned RegNo, - uint64_t Address, const void *Decoder) { - DecodeStatus S = MCDisassembler::Success; - - if (RegNo > 31) - return MCDisassembler::Fail; - - if ((RegNo & 1)) - S = MCDisassembler::SoftFail; - - unsigned RegisterPair = IntPairDecoderTable[RegNo/2]; - Inst.addOperand(MCOperand::createReg(RegisterPair)); - return S; -} - -static DecodeStatus DecodeCPPairRegisterClass(MCInst &Inst, unsigned RegNo, - uint64_t Address, const void *Decoder) { - if (RegNo > 31) - return MCDisassembler::Fail; - - unsigned RegisterPair = CPPairDecoderTable[RegNo/2]; - Inst.addOperand(MCOperand::createReg(RegisterPair)); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeLoadInt(MCInst &Inst, unsigned insn, uint64_t Address, - const void *Decoder); -static DecodeStatus DecodeLoadIntPair(MCInst &Inst, unsigned insn, uint64_t Address, - const void *Decoder); -static DecodeStatus DecodeLoadFP(MCInst &Inst, unsigned insn, uint64_t Address, - const void *Decoder); -static DecodeStatus DecodeLoadDFP(MCInst &Inst, unsigned insn, uint64_t Address, - const void *Decoder); -static DecodeStatus DecodeLoadQFP(MCInst &Inst, unsigned insn, uint64_t Address, - const void *Decoder); -static DecodeStatus DecodeLoadCP(MCInst &Inst, unsigned insn, uint64_t Address, - const void *Decoder); -static DecodeStatus DecodeLoadCPPair(MCInst &Inst, unsigned insn, uint64_t Address, - const void *Decoder); -static DecodeStatus DecodeStoreInt(MCInst &Inst, unsigned insn, - uint64_t Address, const void *Decoder); -static DecodeStatus DecodeStoreIntPair(MCInst &Inst, unsigned insn, - uint64_t Address, const void *Decoder); -static DecodeStatus DecodeStoreFP(MCInst &Inst, unsigned insn, - uint64_t Address, const void *Decoder); -static DecodeStatus DecodeStoreDFP(MCInst &Inst, unsigned insn, - uint64_t Address, const void *Decoder); -static DecodeStatus DecodeStoreQFP(MCInst &Inst, unsigned insn, - uint64_t Address, const void *Decoder); -static DecodeStatus DecodeStoreCP(MCInst &Inst, unsigned insn, - uint64_t Address, const void *Decoder); -static DecodeStatus DecodeStoreCPPair(MCInst &Inst, unsigned insn, - uint64_t Address, const void *Decoder); -static DecodeStatus DecodeCall(MCInst &Inst, unsigned insn, - uint64_t Address, const void *Decoder); -static DecodeStatus DecodeSIMM13(MCInst &Inst, unsigned insn, - uint64_t Address, const void *Decoder); -static DecodeStatus DecodeJMPL(MCInst &Inst, unsigned insn, uint64_t Address, - const void *Decoder); -static DecodeStatus DecodeReturn(MCInst &MI, unsigned insn, uint64_t Address, - const void *Decoder); -static DecodeStatus DecodeSWAP(MCInst &Inst, unsigned insn, uint64_t Address, - const void *Decoder); -static DecodeStatus DecodeTRAP(MCInst &Inst, unsigned insn, uint64_t Address, - const void *Decoder); - -#include "SparcGenDisassemblerTables.inc" - -/// Read four bytes from the ArrayRef and return 32 bit word. -static DecodeStatus readInstruction32(ArrayRef Bytes, uint64_t Address, - uint64_t &Size, uint32_t &Insn, - bool IsLittleEndian) { - // We want to read exactly 4 Bytes of data. - if (Bytes.size() < 4) { - Size = 0; - return MCDisassembler::Fail; - } - - Insn = IsLittleEndian - ? (Bytes[0] << 0) | (Bytes[1] << 8) | (Bytes[2] << 16) | - (Bytes[3] << 24) - : (Bytes[3] << 0) | (Bytes[2] << 8) | (Bytes[1] << 16) | - (Bytes[0] << 24); - - return MCDisassembler::Success; -} - -DecodeStatus SparcDisassembler::getInstruction(MCInst &Instr, uint64_t &Size, - ArrayRef Bytes, - uint64_t Address, - raw_ostream &VStream, - raw_ostream &CStream) const { - uint32_t Insn; - bool isLittleEndian = getContext().getAsmInfo()->isLittleEndian(); - DecodeStatus Result = - readInstruction32(Bytes, Address, Size, Insn, isLittleEndian); - if (Result == MCDisassembler::Fail) - return MCDisassembler::Fail; - - // Calling the auto-generated decoder function. - - if (STI.getFeatureBits()[Sparc::FeatureV9]) - { - Result = decodeInstruction(DecoderTableSparcV932, Instr, Insn, Address, this, STI); - } - else - { - Result = decodeInstruction(DecoderTableSparcV832, Instr, Insn, Address, this, STI); - } - if (Result != MCDisassembler::Fail) - return Result; - - Result = - decodeInstruction(DecoderTableSparc32, Instr, Insn, Address, this, STI); - - if (Result != MCDisassembler::Fail) { - Size = 4; - return Result; - } - - return MCDisassembler::Fail; -} - - -typedef DecodeStatus (*DecodeFunc)(MCInst &MI, unsigned insn, uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeMem(MCInst &MI, unsigned insn, uint64_t Address, - const void *Decoder, - bool isLoad, DecodeFunc DecodeRD) { - unsigned rd = fieldFromInstruction(insn, 25, 5); - unsigned rs1 = fieldFromInstruction(insn, 14, 5); - bool isImm = fieldFromInstruction(insn, 13, 1); - bool hasAsi = fieldFromInstruction(insn, 23, 1); // (in op3 field) - unsigned asi = fieldFromInstruction(insn, 5, 8); - unsigned rs2 = 0; - unsigned simm13 = 0; - if (isImm) - simm13 = SignExtend32<13>(fieldFromInstruction(insn, 0, 13)); - else - rs2 = fieldFromInstruction(insn, 0, 5); - - DecodeStatus status; - if (isLoad) { - status = DecodeRD(MI, rd, Address, Decoder); - if (status != MCDisassembler::Success) - return status; - } - - // Decode rs1. - status = DecodeIntRegsRegisterClass(MI, rs1, Address, Decoder); - if (status != MCDisassembler::Success) - return status; - - // Decode imm|rs2. - if (isImm) - MI.addOperand(MCOperand::createImm(simm13)); - else { - status = DecodeIntRegsRegisterClass(MI, rs2, Address, Decoder); - if (status != MCDisassembler::Success) - return status; - } - - if (hasAsi) - MI.addOperand(MCOperand::createImm(asi)); - - if (!isLoad) { - status = DecodeRD(MI, rd, Address, Decoder); - if (status != MCDisassembler::Success) - return status; - } - return MCDisassembler::Success; -} - -static DecodeStatus DecodeLoadInt(MCInst &Inst, unsigned insn, uint64_t Address, - const void *Decoder) { - return DecodeMem(Inst, insn, Address, Decoder, true, - DecodeIntRegsRegisterClass); -} - -static DecodeStatus DecodeLoadIntPair(MCInst &Inst, unsigned insn, uint64_t Address, - const void *Decoder) { - return DecodeMem(Inst, insn, Address, Decoder, true, - DecodeIntPairRegisterClass); -} - -static DecodeStatus DecodeLoadFP(MCInst &Inst, unsigned insn, uint64_t Address, - const void *Decoder) { - return DecodeMem(Inst, insn, Address, Decoder, true, - DecodeFPRegsRegisterClass); -} - -static DecodeStatus DecodeLoadDFP(MCInst &Inst, unsigned insn, uint64_t Address, - const void *Decoder) { - return DecodeMem(Inst, insn, Address, Decoder, true, - DecodeDFPRegsRegisterClass); -} - -static DecodeStatus DecodeLoadQFP(MCInst &Inst, unsigned insn, uint64_t Address, - const void *Decoder) { - return DecodeMem(Inst, insn, Address, Decoder, true, - DecodeQFPRegsRegisterClass); -} - -static DecodeStatus DecodeLoadCP(MCInst &Inst, unsigned insn, uint64_t Address, - const void *Decoder) { - return DecodeMem(Inst, insn, Address, Decoder, true, - DecodeCPRegsRegisterClass); -} - -static DecodeStatus DecodeLoadCPPair(MCInst &Inst, unsigned insn, uint64_t Address, - const void *Decoder) { - return DecodeMem(Inst, insn, Address, Decoder, true, - DecodeCPPairRegisterClass); -} - -static DecodeStatus DecodeStoreInt(MCInst &Inst, unsigned insn, - uint64_t Address, const void *Decoder) { - return DecodeMem(Inst, insn, Address, Decoder, false, - DecodeIntRegsRegisterClass); -} - -static DecodeStatus DecodeStoreIntPair(MCInst &Inst, unsigned insn, - uint64_t Address, const void *Decoder) { - return DecodeMem(Inst, insn, Address, Decoder, false, - DecodeIntPairRegisterClass); -} - -static DecodeStatus DecodeStoreFP(MCInst &Inst, unsigned insn, uint64_t Address, - const void *Decoder) { - return DecodeMem(Inst, insn, Address, Decoder, false, - DecodeFPRegsRegisterClass); -} - -static DecodeStatus DecodeStoreDFP(MCInst &Inst, unsigned insn, - uint64_t Address, const void *Decoder) { - return DecodeMem(Inst, insn, Address, Decoder, false, - DecodeDFPRegsRegisterClass); -} - -static DecodeStatus DecodeStoreQFP(MCInst &Inst, unsigned insn, - uint64_t Address, const void *Decoder) { - return DecodeMem(Inst, insn, Address, Decoder, false, - DecodeQFPRegsRegisterClass); -} - -static DecodeStatus DecodeStoreCP(MCInst &Inst, unsigned insn, - uint64_t Address, const void *Decoder) { - return DecodeMem(Inst, insn, Address, Decoder, false, - DecodeCPRegsRegisterClass); -} - -static DecodeStatus DecodeStoreCPPair(MCInst &Inst, unsigned insn, - uint64_t Address, const void *Decoder) { - return DecodeMem(Inst, insn, Address, Decoder, false, - DecodeCPPairRegisterClass); -} - -static bool tryAddingSymbolicOperand(int64_t Value, bool isBranch, - uint64_t Address, uint64_t Offset, - uint64_t Width, MCInst &MI, - const void *Decoder) { - const MCDisassembler *Dis = static_cast(Decoder); - return Dis->tryAddingSymbolicOperand(MI, Value, Address, isBranch, - Offset, Width); -} - -static DecodeStatus DecodeCall(MCInst &MI, unsigned insn, - uint64_t Address, const void *Decoder) { - unsigned tgt = fieldFromInstruction(insn, 0, 30); - tgt <<= 2; - if (!tryAddingSymbolicOperand(tgt+Address, false, Address, - 0, 30, MI, Decoder)) - MI.addOperand(MCOperand::createImm(tgt)); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeSIMM13(MCInst &MI, unsigned insn, - uint64_t Address, const void *Decoder) { - unsigned tgt = SignExtend32<13>(fieldFromInstruction(insn, 0, 13)); - MI.addOperand(MCOperand::createImm(tgt)); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeJMPL(MCInst &MI, unsigned insn, uint64_t Address, - const void *Decoder) { - - unsigned rd = fieldFromInstruction(insn, 25, 5); - unsigned rs1 = fieldFromInstruction(insn, 14, 5); - unsigned isImm = fieldFromInstruction(insn, 13, 1); - unsigned rs2 = 0; - unsigned simm13 = 0; - if (isImm) - simm13 = SignExtend32<13>(fieldFromInstruction(insn, 0, 13)); - else - rs2 = fieldFromInstruction(insn, 0, 5); - - // Decode RD. - DecodeStatus status = DecodeIntRegsRegisterClass(MI, rd, Address, Decoder); - if (status != MCDisassembler::Success) - return status; - - // Decode RS1. - status = DecodeIntRegsRegisterClass(MI, rs1, Address, Decoder); - if (status != MCDisassembler::Success) - return status; - - // Decode RS1 | SIMM13. - if (isImm) - MI.addOperand(MCOperand::createImm(simm13)); - else { - status = DecodeIntRegsRegisterClass(MI, rs2, Address, Decoder); - if (status != MCDisassembler::Success) - return status; - } - return MCDisassembler::Success; -} - -static DecodeStatus DecodeReturn(MCInst &MI, unsigned insn, uint64_t Address, - const void *Decoder) { - - unsigned rs1 = fieldFromInstruction(insn, 14, 5); - unsigned isImm = fieldFromInstruction(insn, 13, 1); - unsigned rs2 = 0; - unsigned simm13 = 0; - if (isImm) - simm13 = SignExtend32<13>(fieldFromInstruction(insn, 0, 13)); - else - rs2 = fieldFromInstruction(insn, 0, 5); - - // Decode RS1. - DecodeStatus status = DecodeIntRegsRegisterClass(MI, rs1, Address, Decoder); - if (status != MCDisassembler::Success) - return status; - - // Decode RS2 | SIMM13. - if (isImm) - MI.addOperand(MCOperand::createImm(simm13)); - else { - status = DecodeIntRegsRegisterClass(MI, rs2, Address, Decoder); - if (status != MCDisassembler::Success) - return status; - } - return MCDisassembler::Success; -} - -static DecodeStatus DecodeSWAP(MCInst &MI, unsigned insn, uint64_t Address, - const void *Decoder) { - - unsigned rd = fieldFromInstruction(insn, 25, 5); - unsigned rs1 = fieldFromInstruction(insn, 14, 5); - unsigned isImm = fieldFromInstruction(insn, 13, 1); - bool hasAsi = fieldFromInstruction(insn, 23, 1); // (in op3 field) - unsigned asi = fieldFromInstruction(insn, 5, 8); - unsigned rs2 = 0; - unsigned simm13 = 0; - if (isImm) - simm13 = SignExtend32<13>(fieldFromInstruction(insn, 0, 13)); - else - rs2 = fieldFromInstruction(insn, 0, 5); - - // Decode RD. - DecodeStatus status = DecodeIntRegsRegisterClass(MI, rd, Address, Decoder); - if (status != MCDisassembler::Success) - return status; - - // Decode RS1. - status = DecodeIntRegsRegisterClass(MI, rs1, Address, Decoder); - if (status != MCDisassembler::Success) - return status; - - // Decode RS1 | SIMM13. - if (isImm) - MI.addOperand(MCOperand::createImm(simm13)); - else { - status = DecodeIntRegsRegisterClass(MI, rs2, Address, Decoder); - if (status != MCDisassembler::Success) - return status; - } - - if (hasAsi) - MI.addOperand(MCOperand::createImm(asi)); - - return MCDisassembler::Success; -} - -static DecodeStatus DecodeTRAP(MCInst &MI, unsigned insn, uint64_t Address, - const void *Decoder) { - - unsigned rs1 = fieldFromInstruction(insn, 14, 5); - unsigned isImm = fieldFromInstruction(insn, 13, 1); - unsigned cc =fieldFromInstruction(insn, 25, 4); - unsigned rs2 = 0; - unsigned imm7 = 0; - if (isImm) - imm7 = fieldFromInstruction(insn, 0, 7); - else - rs2 = fieldFromInstruction(insn, 0, 5); - - // Decode RS1. - DecodeStatus status = DecodeIntRegsRegisterClass(MI, rs1, Address, Decoder); - if (status != MCDisassembler::Success) - return status; - - // Decode RS1 | IMM7. - if (isImm) - MI.addOperand(MCOperand::createImm(imm7)); - else { - status = DecodeIntRegsRegisterClass(MI, rs2, Address, Decoder); - if (status != MCDisassembler::Success) - return status; - } - - // Decode CC - MI.addOperand(MCOperand::createImm(cc)); - - return MCDisassembler::Success; -} diff --git a/contrib/llvm/lib/Target/Sparc/LeonFeatures.td b/contrib/llvm/lib/Target/Sparc/LeonFeatures.td deleted file mode 100755 index e0ea4e9c7645..000000000000 --- a/contrib/llvm/lib/Target/Sparc/LeonFeatures.td +++ /dev/null @@ -1,63 +0,0 @@ -//===-- LeonFeatures.td - Describe the Leon Features -------*- 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 -// -//===----------------------------------------------------------------------===// -// -// -//===----------------------------------------------------------------------===// - - -//===----------------------------------------------------------------------===// -// UMAC and SMAC support for LEON3 and LEON4 processors. -//===----------------------------------------------------------------------===// - -//support to casa instruction; for leon3 subtarget only -def UMACSMACSupport : SubtargetFeature< - "hasumacsmac", - "HasUmacSmac", - "true", - "Enable UMAC and SMAC for LEON3 and LEON4 processors" ->; - - -//===----------------------------------------------------------------------===// -// CASA Support differs between LEON3-FT GR712RC and LEON3-FT UT699 -// We need to have the option to switch this on and off. -//===----------------------------------------------------------------------===// - -//support to casa instruction; for leon3 subtarget only -def LeonCASA : SubtargetFeature< - "hasleoncasa", - "HasLeonCasa", - "true", - "Enable CASA instruction for LEON3 and LEON4 processors" ->; - -def InsertNOPLoad: SubtargetFeature< - "insertnopload", - "InsertNOPLoad", - "true", - "LEON3 erratum fix: Insert a NOP instruction after every single-cycle load instruction when the next instruction is another load/store instruction" ->; - -def DetectRoundChange : SubtargetFeature< - "detectroundchange", - "DetectRoundChange", - "true", - "LEON3 erratum detection: Detects any rounding mode change " - "request: use only the round-to-nearest rounding mode" ->; - -def FixAllFDIVSQRT : SubtargetFeature< - "fixallfdivsqrt", - "FixAllFDIVSQRT", - "true", - "LEON erratum fix: Fix FDIVS/FDIVD/FSQRTS/FSQRTD instructions with NOPs and floating-point store" ->; - -def LeonCycleCounter - : SubtargetFeature<"leoncyclecounter", "HasLeonCycleCounter", "true", - "Use the Leon cycle counter register">; diff --git a/contrib/llvm/lib/Target/Sparc/LeonPasses.cpp b/contrib/llvm/lib/Target/Sparc/LeonPasses.cpp deleted file mode 100755 index e9d3aaeb9cfe..000000000000 --- a/contrib/llvm/lib/Target/Sparc/LeonPasses.cpp +++ /dev/null @@ -1,157 +0,0 @@ -//===------ LeonPasses.cpp - Define passes specific to LEON ---------------===// -// -// Part of the LLVM Project, under the Apache 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 "LeonPasses.h" -#include "llvm/CodeGen/ISDOpcodes.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/IR/DiagnosticInfo.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/Support/raw_ostream.h" -using namespace llvm; - -LEONMachineFunctionPass::LEONMachineFunctionPass(char &ID) - : MachineFunctionPass(ID) {} - -//***************************************************************************** -//**** InsertNOPLoad pass -//***************************************************************************** -// This pass fixes the incorrectly working Load instructions that exists for -// some earlier versions of the LEON processor line. NOP instructions must -// be inserted after the load instruction to ensure that the Load instruction -// behaves as expected for these processors. -// -// This pass inserts a NOP after any LD or LDF instruction. -// -char InsertNOPLoad::ID = 0; - -InsertNOPLoad::InsertNOPLoad() : LEONMachineFunctionPass(ID) {} - -bool InsertNOPLoad::runOnMachineFunction(MachineFunction &MF) { - Subtarget = &MF.getSubtarget(); - const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); - DebugLoc DL = DebugLoc(); - - bool Modified = false; - for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) { - MachineBasicBlock &MBB = *MFI; - for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) { - MachineInstr &MI = *MBBI; - unsigned Opcode = MI.getOpcode(); - if (Opcode >= SP::LDDArr && Opcode <= SP::LDrr) { - MachineBasicBlock::iterator NMBBI = std::next(MBBI); - BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP)); - Modified = true; - } - } - } - - return Modified; -} - - - -//***************************************************************************** -//**** DetectRoundChange pass -//***************************************************************************** -// To prevent any explicit change of the default rounding mode, this pass -// detects any call of the fesetround function. -// A warning is generated to ensure the user knows this has happened. -// -// Detects an erratum in UT699 LEON 3 processor - -char DetectRoundChange::ID = 0; - -DetectRoundChange::DetectRoundChange() : LEONMachineFunctionPass(ID) {} - -bool DetectRoundChange::runOnMachineFunction(MachineFunction &MF) { - Subtarget = &MF.getSubtarget(); - - bool Modified = false; - for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) { - MachineBasicBlock &MBB = *MFI; - for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) { - MachineInstr &MI = *MBBI; - unsigned Opcode = MI.getOpcode(); - if (Opcode == SP::CALL && MI.getNumOperands() > 0) { - MachineOperand &MO = MI.getOperand(0); - - if (MO.isGlobal()) { - StringRef FuncName = MO.getGlobal()->getName(); - if (FuncName.compare_lower("fesetround") == 0) { - errs() << "Error: You are using the detectroundchange " - "option to detect rounding changes that will " - "cause LEON errata. The only way to fix this " - "is to remove the call to fesetround from " - "the source code.\n"; - } - } - } - } - } - - return Modified; -} - -//***************************************************************************** -//**** FixAllFDIVSQRT pass -//***************************************************************************** -// This pass fixes the incorrectly working FDIVx and FSQRTx instructions that -// exist for some earlier versions of the LEON processor line. Five NOP -// instructions need to be inserted after these instructions to ensure the -// correct result is placed in the destination registers before they are used. -// -// This pass implements two fixes: -// 1) fixing the FSQRTS and FSQRTD instructions. -// 2) fixing the FDIVS and FDIVD instructions. -// -// FSQRTS and FDIVS are converted to FDIVD and FSQRTD respectively earlier in -// the pipeline when this option is enabled, so this pass needs only to deal -// with the changes that still need implementing for the "double" versions -// of these instructions. -// -char FixAllFDIVSQRT::ID = 0; - -FixAllFDIVSQRT::FixAllFDIVSQRT() : LEONMachineFunctionPass(ID) {} - -bool FixAllFDIVSQRT::runOnMachineFunction(MachineFunction &MF) { - Subtarget = &MF.getSubtarget(); - const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); - DebugLoc DL = DebugLoc(); - - bool Modified = false; - for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) { - MachineBasicBlock &MBB = *MFI; - for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++MBBI) { - MachineInstr &MI = *MBBI; - unsigned Opcode = MI.getOpcode(); - - // Note: FDIVS and FSQRTS cannot be generated when this erratum fix is - // switched on so we don't need to check for them here. They will - // already have been converted to FSQRTD or FDIVD earlier in the - // pipeline. - if (Opcode == SP::FSQRTD || Opcode == SP::FDIVD) { - for (int InsertedCount = 0; InsertedCount < 5; InsertedCount++) - BuildMI(MBB, MBBI, DL, TII.get(SP::NOP)); - - MachineBasicBlock::iterator NMBBI = std::next(MBBI); - for (int InsertedCount = 0; InsertedCount < 28; InsertedCount++) - BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP)); - - Modified = true; - } - } - } - - return Modified; -} diff --git a/contrib/llvm/lib/Target/Sparc/LeonPasses.h b/contrib/llvm/lib/Target/Sparc/LeonPasses.h deleted file mode 100755 index 154a2b467e16..000000000000 --- a/contrib/llvm/lib/Target/Sparc/LeonPasses.h +++ /dev/null @@ -1,87 +0,0 @@ -//===------- LeonPasses.h - Define passes specific to LEON ----------------===// -// -// Part of the LLVM Project, under the Apache 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_SPARC_LEON_PASSES_H -#define LLVM_LIB_TARGET_SPARC_LEON_PASSES_H - -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/Passes.h" - -#include "Sparc.h" -#include "SparcSubtarget.h" - -namespace llvm { -class LLVM_LIBRARY_VISIBILITY LEONMachineFunctionPass - : public MachineFunctionPass { -protected: - const SparcSubtarget *Subtarget; - const int LAST_OPERAND = -1; - - // this vector holds free registers that we allocate in groups for some of the - // LEON passes - std::vector UsedRegisters; - -protected: - LEONMachineFunctionPass(char &ID); - - int GetRegIndexForOperand(MachineInstr &MI, int OperandIndex); - void clearUsedRegisterList() { UsedRegisters.clear(); } - - void markRegisterUsed(int registerIndex) { - UsedRegisters.push_back(registerIndex); - } - int getUnusedFPRegister(MachineRegisterInfo &MRI); -}; - -class LLVM_LIBRARY_VISIBILITY InsertNOPLoad : public LEONMachineFunctionPass { -public: - static char ID; - - InsertNOPLoad(); - bool runOnMachineFunction(MachineFunction &MF) override; - - StringRef getPassName() const override { - return "InsertNOPLoad: Erratum Fix LBR35: insert a NOP instruction after " - "every single-cycle load instruction when the next instruction is " - "another load/store instruction"; - } -}; - -class LLVM_LIBRARY_VISIBILITY DetectRoundChange - : public LEONMachineFunctionPass { -public: - static char ID; - - DetectRoundChange(); - bool runOnMachineFunction(MachineFunction &MF) override; - - StringRef getPassName() const override { - return "DetectRoundChange: Leon erratum detection: detect any rounding " - "mode change request: use only the round-to-nearest rounding mode"; - } -}; - -class LLVM_LIBRARY_VISIBILITY FixAllFDIVSQRT : public LEONMachineFunctionPass { -public: - static char ID; - - FixAllFDIVSQRT(); - bool runOnMachineFunction(MachineFunction &MF) override; - - StringRef getPassName() const override { - return "FixAllFDIVSQRT: Erratum Fix LBR34: fix FDIVS/FDIVD/FSQRTS/FSQRTD " - "instructions with NOPs and floating-point store"; - } -}; -} // namespace llvm - -#endif // LLVM_LIB_TARGET_SPARC_LEON_PASSES_H diff --git a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp deleted file mode 100644 index 2e8fa0dbaf4c..000000000000 --- a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp +++ /dev/null @@ -1,331 +0,0 @@ -//===-- SparcAsmBackend.cpp - Sparc Assembler 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 -// -//===----------------------------------------------------------------------===// - -#include "MCTargetDesc/SparcFixupKinds.h" -#include "MCTargetDesc/SparcMCTargetDesc.h" -#include "llvm/MC/MCAsmBackend.h" -#include "llvm/MC/MCELFObjectWriter.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCFixupKindInfo.h" -#include "llvm/MC/MCObjectWriter.h" -#include "llvm/MC/MCSubtargetInfo.h" -#include "llvm/MC/MCValue.h" -#include "llvm/Support/TargetRegistry.h" - -using namespace llvm; - -static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) { - switch (Kind) { - default: - llvm_unreachable("Unknown fixup kind!"); - case FK_Data_1: - case FK_Data_2: - case FK_Data_4: - case FK_Data_8: - return Value; - - case Sparc::fixup_sparc_wplt30: - case Sparc::fixup_sparc_call30: - return (Value >> 2) & 0x3fffffff; - - case Sparc::fixup_sparc_br22: - return (Value >> 2) & 0x3fffff; - - case Sparc::fixup_sparc_br19: - return (Value >> 2) & 0x7ffff; - - case Sparc::fixup_sparc_br16_2: - return (Value >> 2) & 0xc000; - - case Sparc::fixup_sparc_br16_14: - return (Value >> 2) & 0x3fff; - - case Sparc::fixup_sparc_pc22: - case Sparc::fixup_sparc_got22: - case Sparc::fixup_sparc_tls_gd_hi22: - case Sparc::fixup_sparc_tls_ldm_hi22: - case Sparc::fixup_sparc_tls_ie_hi22: - case Sparc::fixup_sparc_hi22: - return (Value >> 10) & 0x3fffff; - - case Sparc::fixup_sparc_got13: - case Sparc::fixup_sparc_13: - return Value & 0x1fff; - - case Sparc::fixup_sparc_pc10: - case Sparc::fixup_sparc_got10: - case Sparc::fixup_sparc_tls_gd_lo10: - case Sparc::fixup_sparc_tls_ldm_lo10: - case Sparc::fixup_sparc_tls_ie_lo10: - case Sparc::fixup_sparc_lo10: - return Value & 0x3ff; - - case Sparc::fixup_sparc_h44: - return (Value >> 22) & 0x3fffff; - - case Sparc::fixup_sparc_m44: - return (Value >> 12) & 0x3ff; - - case Sparc::fixup_sparc_l44: - return Value & 0xfff; - - case Sparc::fixup_sparc_hh: - return (Value >> 42) & 0x3fffff; - - case Sparc::fixup_sparc_hm: - return (Value >> 32) & 0x3ff; - - case Sparc::fixup_sparc_tls_ldo_hix22: - case Sparc::fixup_sparc_tls_le_hix22: - case Sparc::fixup_sparc_tls_ldo_lox10: - case Sparc::fixup_sparc_tls_le_lox10: - assert(Value == 0 && "Sparc TLS relocs expect zero Value"); - return 0; - - case Sparc::fixup_sparc_tls_gd_add: - case Sparc::fixup_sparc_tls_gd_call: - case Sparc::fixup_sparc_tls_ldm_add: - case Sparc::fixup_sparc_tls_ldm_call: - case Sparc::fixup_sparc_tls_ldo_add: - case Sparc::fixup_sparc_tls_ie_ld: - case Sparc::fixup_sparc_tls_ie_ldx: - case Sparc::fixup_sparc_tls_ie_add: - return 0; - } -} - -/// getFixupKindNumBytes - The number of bytes the fixup may change. -static unsigned getFixupKindNumBytes(unsigned Kind) { - switch (Kind) { - default: - return 4; - case FK_Data_1: - return 1; - case FK_Data_2: - return 2; - case FK_Data_8: - return 8; - } -} - -namespace { - class SparcAsmBackend : public MCAsmBackend { - protected: - const Target &TheTarget; - bool Is64Bit; - - public: - SparcAsmBackend(const Target &T) - : MCAsmBackend(StringRef(T.getName()) == "sparcel" ? support::little - : support::big), - TheTarget(T), Is64Bit(StringRef(TheTarget.getName()) == "sparcv9") {} - - unsigned getNumFixupKinds() const override { - return Sparc::NumTargetFixupKinds; - } - - const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override { - const static MCFixupKindInfo InfosBE[Sparc::NumTargetFixupKinds] = { - // name offset bits flags - { "fixup_sparc_call30", 2, 30, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_sparc_br22", 10, 22, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_sparc_br19", 13, 19, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_sparc_br16_2", 10, 2, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_sparc_br16_14", 18, 14, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_sparc_13", 19, 13, 0 }, - { "fixup_sparc_hi22", 10, 22, 0 }, - { "fixup_sparc_lo10", 22, 10, 0 }, - { "fixup_sparc_h44", 10, 22, 0 }, - { "fixup_sparc_m44", 22, 10, 0 }, - { "fixup_sparc_l44", 20, 12, 0 }, - { "fixup_sparc_hh", 10, 22, 0 }, - { "fixup_sparc_hm", 22, 10, 0 }, - { "fixup_sparc_pc22", 10, 22, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_sparc_pc10", 22, 10, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_sparc_got22", 10, 22, 0 }, - { "fixup_sparc_got10", 22, 10, 0 }, - { "fixup_sparc_got13", 19, 13, 0 }, - { "fixup_sparc_wplt30", 2, 30, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_sparc_tls_gd_hi22", 10, 22, 0 }, - { "fixup_sparc_tls_gd_lo10", 22, 10, 0 }, - { "fixup_sparc_tls_gd_add", 0, 0, 0 }, - { "fixup_sparc_tls_gd_call", 0, 0, 0 }, - { "fixup_sparc_tls_ldm_hi22", 10, 22, 0 }, - { "fixup_sparc_tls_ldm_lo10", 22, 10, 0 }, - { "fixup_sparc_tls_ldm_add", 0, 0, 0 }, - { "fixup_sparc_tls_ldm_call", 0, 0, 0 }, - { "fixup_sparc_tls_ldo_hix22", 10, 22, 0 }, - { "fixup_sparc_tls_ldo_lox10", 22, 10, 0 }, - { "fixup_sparc_tls_ldo_add", 0, 0, 0 }, - { "fixup_sparc_tls_ie_hi22", 10, 22, 0 }, - { "fixup_sparc_tls_ie_lo10", 22, 10, 0 }, - { "fixup_sparc_tls_ie_ld", 0, 0, 0 }, - { "fixup_sparc_tls_ie_ldx", 0, 0, 0 }, - { "fixup_sparc_tls_ie_add", 0, 0, 0 }, - { "fixup_sparc_tls_le_hix22", 0, 0, 0 }, - { "fixup_sparc_tls_le_lox10", 0, 0, 0 } - }; - - const static MCFixupKindInfo InfosLE[Sparc::NumTargetFixupKinds] = { - // name offset bits flags - { "fixup_sparc_call30", 0, 30, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_sparc_br22", 0, 22, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_sparc_br19", 0, 19, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_sparc_br16_2", 20, 2, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_sparc_br16_14", 0, 14, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_sparc_13", 0, 13, 0 }, - { "fixup_sparc_hi22", 0, 22, 0 }, - { "fixup_sparc_lo10", 0, 10, 0 }, - { "fixup_sparc_h44", 0, 22, 0 }, - { "fixup_sparc_m44", 0, 10, 0 }, - { "fixup_sparc_l44", 0, 12, 0 }, - { "fixup_sparc_hh", 0, 22, 0 }, - { "fixup_sparc_hm", 0, 10, 0 }, - { "fixup_sparc_pc22", 0, 22, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_sparc_pc10", 0, 10, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_sparc_got22", 0, 22, 0 }, - { "fixup_sparc_got10", 0, 10, 0 }, - { "fixup_sparc_got13", 0, 13, 0 }, - { "fixup_sparc_wplt30", 0, 30, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_sparc_tls_gd_hi22", 0, 22, 0 }, - { "fixup_sparc_tls_gd_lo10", 0, 10, 0 }, - { "fixup_sparc_tls_gd_add", 0, 0, 0 }, - { "fixup_sparc_tls_gd_call", 0, 0, 0 }, - { "fixup_sparc_tls_ldm_hi22", 0, 22, 0 }, - { "fixup_sparc_tls_ldm_lo10", 0, 10, 0 }, - { "fixup_sparc_tls_ldm_add", 0, 0, 0 }, - { "fixup_sparc_tls_ldm_call", 0, 0, 0 }, - { "fixup_sparc_tls_ldo_hix22", 0, 22, 0 }, - { "fixup_sparc_tls_ldo_lox10", 0, 10, 0 }, - { "fixup_sparc_tls_ldo_add", 0, 0, 0 }, - { "fixup_sparc_tls_ie_hi22", 0, 22, 0 }, - { "fixup_sparc_tls_ie_lo10", 0, 10, 0 }, - { "fixup_sparc_tls_ie_ld", 0, 0, 0 }, - { "fixup_sparc_tls_ie_ldx", 0, 0, 0 }, - { "fixup_sparc_tls_ie_add", 0, 0, 0 }, - { "fixup_sparc_tls_le_hix22", 0, 0, 0 }, - { "fixup_sparc_tls_le_lox10", 0, 0, 0 } - }; - - if (Kind < FirstTargetFixupKind) - return MCAsmBackend::getFixupKindInfo(Kind); - - assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && - "Invalid kind!"); - if (Endian == support::little) - return InfosLE[Kind - FirstTargetFixupKind]; - - return InfosBE[Kind - FirstTargetFixupKind]; - } - - bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup, - const MCValue &Target) override { - switch ((Sparc::Fixups)Fixup.getKind()) { - default: - return false; - case Sparc::fixup_sparc_wplt30: - if (Target.getSymA()->getSymbol().isTemporary()) - return false; - LLVM_FALLTHROUGH; - case Sparc::fixup_sparc_tls_gd_hi22: - case Sparc::fixup_sparc_tls_gd_lo10: - case Sparc::fixup_sparc_tls_gd_add: - case Sparc::fixup_sparc_tls_gd_call: - case Sparc::fixup_sparc_tls_ldm_hi22: - case Sparc::fixup_sparc_tls_ldm_lo10: - case Sparc::fixup_sparc_tls_ldm_add: - case Sparc::fixup_sparc_tls_ldm_call: - case Sparc::fixup_sparc_tls_ldo_hix22: - case Sparc::fixup_sparc_tls_ldo_lox10: - case Sparc::fixup_sparc_tls_ldo_add: - case Sparc::fixup_sparc_tls_ie_hi22: - case Sparc::fixup_sparc_tls_ie_lo10: - case Sparc::fixup_sparc_tls_ie_ld: - case Sparc::fixup_sparc_tls_ie_ldx: - case Sparc::fixup_sparc_tls_ie_add: - case Sparc::fixup_sparc_tls_le_hix22: - case Sparc::fixup_sparc_tls_le_lox10: - return true; - } - } - - bool mayNeedRelaxation(const MCInst &Inst, - const MCSubtargetInfo &STI) const override { - // FIXME. - 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("fixupNeedsRelaxation() unimplemented"); - return false; - } - void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI, - MCInst &Res) const override { - // FIXME. - llvm_unreachable("relaxInstruction() unimplemented"); - } - - bool writeNopData(raw_ostream &OS, uint64_t Count) const override { - // Cannot emit NOP with size not multiple of 32 bits. - if (Count % 4 != 0) - return false; - - uint64_t NumNops = Count / 4; - for (uint64_t i = 0; i != NumNops; ++i) - support::endian::write(OS, 0x01000000, Endian); - - return true; - } - }; - - class ELFSparcAsmBackend : public SparcAsmBackend { - Triple::OSType OSType; - public: - ELFSparcAsmBackend(const Target &T, Triple::OSType OSType) : - SparcAsmBackend(T), OSType(OSType) { } - - void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, - const MCValue &Target, MutableArrayRef Data, - uint64_t Value, bool IsResolved, - const MCSubtargetInfo *STI) const override { - - Value = adjustFixupValue(Fixup.getKind(), Value); - if (!Value) return; // Doesn't change encoding. - - unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind()); - unsigned Offset = Fixup.getOffset(); - // For each byte of the fragment that the fixup touches, mask in the bits - // from the fixup value. The Value has been "split up" into the - // appropriate bitfields above. - for (unsigned i = 0; i != NumBytes; ++i) { - unsigned Idx = Endian == support::little ? i : (NumBytes - 1) - i; - Data[Offset + Idx] |= uint8_t((Value >> (i * 8)) & 0xff); - } - } - - std::unique_ptr - createObjectTargetWriter() const override { - uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(OSType); - return createSparcELFObjectWriter(Is64Bit, OSABI); - } - }; - -} // end anonymous namespace - -MCAsmBackend *llvm::createSparcAsmBackend(const Target &T, - const MCSubtargetInfo &STI, - const MCRegisterInfo &MRI, - const MCTargetOptions &Options) { - return new ELFSparcAsmBackend(T, STI.getTargetTriple().getOS()); -} diff --git a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp deleted file mode 100644 index 88547075c5ae..000000000000 --- a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp +++ /dev/null @@ -1,139 +0,0 @@ -//===-- SparcELFObjectWriter.cpp - Sparc 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/SparcFixupKinds.h" -#include "MCTargetDesc/SparcMCExpr.h" -#include "MCTargetDesc/SparcMCTargetDesc.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/MC/MCELFObjectWriter.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCObjectWriter.h" -#include "llvm/MC/MCValue.h" -#include "llvm/Support/ErrorHandling.h" - -using namespace llvm; - -namespace { - class SparcELFObjectWriter : public MCELFObjectTargetWriter { - public: - SparcELFObjectWriter(bool Is64Bit, uint8_t OSABI) - : MCELFObjectTargetWriter(Is64Bit, OSABI, - Is64Bit ? ELF::EM_SPARCV9 : ELF::EM_SPARC, - /*HasRelocationAddend*/ true) {} - - ~SparcELFObjectWriter() override {} - - protected: - unsigned getRelocType(MCContext &Ctx, const MCValue &Target, - const MCFixup &Fixup, bool IsPCRel) const override; - - bool needsRelocateWithSymbol(const MCSymbol &Sym, - unsigned Type) const override; - - }; -} - -unsigned SparcELFObjectWriter::getRelocType(MCContext &Ctx, - const MCValue &Target, - const MCFixup &Fixup, - bool IsPCRel) const { - - if (const SparcMCExpr *SExpr = dyn_cast(Fixup.getValue())) { - if (SExpr->getKind() == SparcMCExpr::VK_Sparc_R_DISP32) - return ELF::R_SPARC_DISP32; - } - - if (IsPCRel) { - switch((unsigned)Fixup.getKind()) { - default: - llvm_unreachable("Unimplemented fixup -> relocation"); - case FK_Data_1: return ELF::R_SPARC_DISP8; - case FK_Data_2: return ELF::R_SPARC_DISP16; - case FK_Data_4: return ELF::R_SPARC_DISP32; - case FK_Data_8: return ELF::R_SPARC_DISP64; - case Sparc::fixup_sparc_call30: return ELF::R_SPARC_WDISP30; - case Sparc::fixup_sparc_br22: return ELF::R_SPARC_WDISP22; - case Sparc::fixup_sparc_br19: return ELF::R_SPARC_WDISP19; - case Sparc::fixup_sparc_pc22: return ELF::R_SPARC_PC22; - case Sparc::fixup_sparc_pc10: return ELF::R_SPARC_PC10; - case Sparc::fixup_sparc_wplt30: return ELF::R_SPARC_WPLT30; - } - } - - switch((unsigned)Fixup.getKind()) { - default: - llvm_unreachable("Unimplemented fixup -> relocation"); - case FK_Data_1: return ELF::R_SPARC_8; - case FK_Data_2: return ((Fixup.getOffset() % 2) - ? ELF::R_SPARC_UA16 - : ELF::R_SPARC_16); - case FK_Data_4: return ((Fixup.getOffset() % 4) - ? ELF::R_SPARC_UA32 - : ELF::R_SPARC_32); - case FK_Data_8: return ((Fixup.getOffset() % 8) - ? ELF::R_SPARC_UA64 - : ELF::R_SPARC_64); - case Sparc::fixup_sparc_13: return ELF::R_SPARC_13; - case Sparc::fixup_sparc_hi22: return ELF::R_SPARC_HI22; - case Sparc::fixup_sparc_lo10: return ELF::R_SPARC_LO10; - case Sparc::fixup_sparc_h44: return ELF::R_SPARC_H44; - case Sparc::fixup_sparc_m44: return ELF::R_SPARC_M44; - case Sparc::fixup_sparc_l44: return ELF::R_SPARC_L44; - case Sparc::fixup_sparc_hh: return ELF::R_SPARC_HH22; - case Sparc::fixup_sparc_hm: return ELF::R_SPARC_HM10; - case Sparc::fixup_sparc_got22: return ELF::R_SPARC_GOT22; - case Sparc::fixup_sparc_got10: return ELF::R_SPARC_GOT10; - case Sparc::fixup_sparc_got13: return ELF::R_SPARC_GOT13; - case Sparc::fixup_sparc_tls_gd_hi22: return ELF::R_SPARC_TLS_GD_HI22; - case Sparc::fixup_sparc_tls_gd_lo10: return ELF::R_SPARC_TLS_GD_LO10; - case Sparc::fixup_sparc_tls_gd_add: return ELF::R_SPARC_TLS_GD_ADD; - case Sparc::fixup_sparc_tls_gd_call: return ELF::R_SPARC_TLS_GD_CALL; - case Sparc::fixup_sparc_tls_ldm_hi22: return ELF::R_SPARC_TLS_LDM_HI22; - case Sparc::fixup_sparc_tls_ldm_lo10: return ELF::R_SPARC_TLS_LDM_LO10; - case Sparc::fixup_sparc_tls_ldm_add: return ELF::R_SPARC_TLS_LDM_ADD; - case Sparc::fixup_sparc_tls_ldm_call: return ELF::R_SPARC_TLS_LDM_CALL; - case Sparc::fixup_sparc_tls_ldo_hix22: return ELF::R_SPARC_TLS_LDO_HIX22; - case Sparc::fixup_sparc_tls_ldo_lox10: return ELF::R_SPARC_TLS_LDO_LOX10; - case Sparc::fixup_sparc_tls_ldo_add: return ELF::R_SPARC_TLS_LDO_ADD; - case Sparc::fixup_sparc_tls_ie_hi22: return ELF::R_SPARC_TLS_IE_HI22; - case Sparc::fixup_sparc_tls_ie_lo10: return ELF::R_SPARC_TLS_IE_LO10; - case Sparc::fixup_sparc_tls_ie_ld: return ELF::R_SPARC_TLS_IE_LD; - case Sparc::fixup_sparc_tls_ie_ldx: return ELF::R_SPARC_TLS_IE_LDX; - case Sparc::fixup_sparc_tls_ie_add: return ELF::R_SPARC_TLS_IE_ADD; - case Sparc::fixup_sparc_tls_le_hix22: return ELF::R_SPARC_TLS_LE_HIX22; - case Sparc::fixup_sparc_tls_le_lox10: return ELF::R_SPARC_TLS_LE_LOX10; - } - - return ELF::R_SPARC_NONE; -} - -bool SparcELFObjectWriter::needsRelocateWithSymbol(const MCSymbol &Sym, - unsigned Type) const { - switch (Type) { - default: - return false; - - // All relocations that use a GOT need a symbol, not an offset, as - // the offset of the symbol within the section is irrelevant to - // where the GOT entry is. Don't need to list all the TLS entries, - // as they're all marked as requiring a symbol anyways. - case ELF::R_SPARC_GOT10: - case ELF::R_SPARC_GOT13: - case ELF::R_SPARC_GOT22: - case ELF::R_SPARC_GOTDATA_HIX22: - case ELF::R_SPARC_GOTDATA_LOX10: - case ELF::R_SPARC_GOTDATA_OP_HIX22: - case ELF::R_SPARC_GOTDATA_OP_LOX10: - return true; - } -} - -std::unique_ptr -llvm::createSparcELFObjectWriter(bool Is64Bit, uint8_t OSABI) { - return llvm::make_unique(Is64Bit, OSABI); -} diff --git a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h deleted file mode 100644 index b5fac0264019..000000000000 --- a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h +++ /dev/null @@ -1,102 +0,0 @@ -//===-- SparcFixupKinds.h - Sparc 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_SPARC_MCTARGETDESC_SPARCFIXUPKINDS_H -#define LLVM_LIB_TARGET_SPARC_MCTARGETDESC_SPARCFIXUPKINDS_H - -#include "llvm/MC/MCFixup.h" - -namespace llvm { - namespace Sparc { - enum Fixups { - // fixup_sparc_call30 - 30-bit PC relative relocation for call - fixup_sparc_call30 = FirstTargetFixupKind, - - /// fixup_sparc_br22 - 22-bit PC relative relocation for - /// branches - fixup_sparc_br22, - - /// fixup_sparc_br19 - 19-bit PC relative relocation for - /// branches on icc/xcc - fixup_sparc_br19, - - /// fixup_sparc_bpr - 16-bit fixup for bpr - fixup_sparc_br16_2, - fixup_sparc_br16_14, - - /// fixup_sparc_13 - 13-bit fixup - fixup_sparc_13, - - /// fixup_sparc_hi22 - 22-bit fixup corresponding to %hi(foo) - /// for sethi - fixup_sparc_hi22, - - /// fixup_sparc_lo10 - 10-bit fixup corresponding to %lo(foo) - fixup_sparc_lo10, - - /// fixup_sparc_h44 - 22-bit fixup corresponding to %h44(foo) - fixup_sparc_h44, - - /// fixup_sparc_m44 - 10-bit fixup corresponding to %m44(foo) - fixup_sparc_m44, - - /// fixup_sparc_l44 - 12-bit fixup corresponding to %l44(foo) - fixup_sparc_l44, - - /// fixup_sparc_hh - 22-bit fixup corresponding to %hh(foo) - fixup_sparc_hh, - - /// fixup_sparc_hm - 10-bit fixup corresponding to %hm(foo) - fixup_sparc_hm, - - /// fixup_sparc_pc22 - 22-bit fixup corresponding to %pc22(foo) - fixup_sparc_pc22, - - /// fixup_sparc_pc10 - 10-bit fixup corresponding to %pc10(foo) - fixup_sparc_pc10, - - /// fixup_sparc_got22 - 22-bit fixup corresponding to %got22(foo) - fixup_sparc_got22, - - /// fixup_sparc_got10 - 10-bit fixup corresponding to %got10(foo) - fixup_sparc_got10, - - /// fixup_sparc_got13 - 13-bit fixup corresponding to %got13(foo) - fixup_sparc_got13, - - /// fixup_sparc_wplt30 - fixup_sparc_wplt30, - - /// fixups for Thread Local Storage - fixup_sparc_tls_gd_hi22, - fixup_sparc_tls_gd_lo10, - fixup_sparc_tls_gd_add, - fixup_sparc_tls_gd_call, - fixup_sparc_tls_ldm_hi22, - fixup_sparc_tls_ldm_lo10, - fixup_sparc_tls_ldm_add, - fixup_sparc_tls_ldm_call, - fixup_sparc_tls_ldo_hix22, - fixup_sparc_tls_ldo_lox10, - fixup_sparc_tls_ldo_add, - fixup_sparc_tls_ie_hi22, - fixup_sparc_tls_ie_lo10, - fixup_sparc_tls_ie_ld, - fixup_sparc_tls_ie_ldx, - fixup_sparc_tls_ie_add, - fixup_sparc_tls_le_hix22, - fixup_sparc_tls_le_lox10, - - // Marker - LastTargetFixupKind, - NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind - }; - } -} - -#endif diff --git a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp deleted file mode 100644 index c479459786d7..000000000000 --- a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.cpp +++ /dev/null @@ -1,219 +0,0 @@ -//===-- SparcInstPrinter.cpp - Convert Sparc 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 Sparc MCInst to a .s file. -// -//===----------------------------------------------------------------------===// - -#include "SparcInstPrinter.h" -#include "Sparc.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCInst.h" -#include "llvm/MC/MCRegisterInfo.h" -#include "llvm/MC/MCSubtargetInfo.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/Support/raw_ostream.h" -using namespace llvm; - -#define DEBUG_TYPE "asm-printer" - -// The generated AsmMatcher SparcGenAsmWriter uses "Sparc" as the target -// namespace. But SPARC backend uses "SP" as its namespace. -namespace llvm { -namespace Sparc { - using namespace SP; -} -} - -#define GET_INSTRUCTION_NAME -#define PRINT_ALIAS_INSTR -#include "SparcGenAsmWriter.inc" - -bool SparcInstPrinter::isV9(const MCSubtargetInfo &STI) const { - return (STI.getFeatureBits()[Sparc::FeatureV9]) != 0; -} - -void SparcInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const -{ - OS << '%' << StringRef(getRegisterName(RegNo)).lower(); -} - -void SparcInstPrinter::printInst(const MCInst *MI, raw_ostream &O, - StringRef Annot, const MCSubtargetInfo &STI) { - if (!printAliasInstr(MI, STI, O) && !printSparcAliasInstr(MI, STI, O)) - printInstruction(MI, STI, O); - printAnnotation(O, Annot); -} - -bool SparcInstPrinter::printSparcAliasInstr(const MCInst *MI, - const MCSubtargetInfo &STI, - raw_ostream &O) { - switch (MI->getOpcode()) { - default: return false; - case SP::JMPLrr: - case SP::JMPLri: { - if (MI->getNumOperands() != 3) - return false; - if (!MI->getOperand(0).isReg()) - return false; - switch (MI->getOperand(0).getReg()) { - default: return false; - case SP::G0: // jmp $addr | ret | retl - if (MI->getOperand(2).isImm() && - MI->getOperand(2).getImm() == 8) { - switch(MI->getOperand(1).getReg()) { - default: break; - case SP::I7: O << "\tret"; return true; - case SP::O7: O << "\tretl"; return true; - } - } - O << "\tjmp "; printMemOperand(MI, 1, STI, O); - return true; - case SP::O7: // call $addr - O << "\tcall "; printMemOperand(MI, 1, STI, O); - return true; - } - } - case SP::V9FCMPS: case SP::V9FCMPD: case SP::V9FCMPQ: - case SP::V9FCMPES: case SP::V9FCMPED: case SP::V9FCMPEQ: { - if (isV9(STI) - || (MI->getNumOperands() != 3) - || (!MI->getOperand(0).isReg()) - || (MI->getOperand(0).getReg() != SP::FCC0)) - return false; - // if V8, skip printing %fcc0. - switch(MI->getOpcode()) { - default: - case SP::V9FCMPS: O << "\tfcmps "; break; - case SP::V9FCMPD: O << "\tfcmpd "; break; - case SP::V9FCMPQ: O << "\tfcmpq "; break; - case SP::V9FCMPES: O << "\tfcmpes "; break; - case SP::V9FCMPED: O << "\tfcmped "; break; - case SP::V9FCMPEQ: O << "\tfcmpeq "; break; - } - printOperand(MI, 1, STI, O); - O << ", "; - printOperand(MI, 2, STI, O); - return true; - } - } -} - -void SparcInstPrinter::printOperand(const MCInst *MI, int opNum, - const MCSubtargetInfo &STI, - raw_ostream &O) { - const MCOperand &MO = MI->getOperand (opNum); - - if (MO.isReg()) { - printRegName(O, MO.getReg()); - return ; - } - - if (MO.isImm()) { - switch (MI->getOpcode()) { - default: - O << (int)MO.getImm(); - return; - - case SP::TICCri: // Fall through - case SP::TICCrr: // Fall through - case SP::TRAPri: // Fall through - case SP::TRAPrr: // Fall through - case SP::TXCCri: // Fall through - case SP::TXCCrr: // Fall through - // Only seven-bit values up to 127. - O << ((int) MO.getImm() & 0x7f); - return; - } - } - - assert(MO.isExpr() && "Unknown operand kind in printOperand"); - MO.getExpr()->print(O, &MAI); -} - -void SparcInstPrinter::printMemOperand(const MCInst *MI, int opNum, - const MCSubtargetInfo &STI, - raw_ostream &O, const char *Modifier) { - printOperand(MI, opNum, STI, O); - - // If this is an ADD operand, emit it like normal operands. - if (Modifier && !strcmp(Modifier, "arith")) { - O << ", "; - printOperand(MI, opNum+1, STI, O); - return; - } - const MCOperand &MO = MI->getOperand(opNum+1); - - if (MO.isReg() && MO.getReg() == SP::G0) - return; // don't print "+%g0" - if (MO.isImm() && MO.getImm() == 0) - return; // don't print "+0" - - O << "+"; - - printOperand(MI, opNum+1, STI, O); -} - -void SparcInstPrinter::printCCOperand(const MCInst *MI, int opNum, - const MCSubtargetInfo &STI, - raw_ostream &O) { - int CC = (int)MI->getOperand(opNum).getImm(); - switch (MI->getOpcode()) { - default: break; - case SP::FBCOND: - case SP::FBCONDA: - case SP::BPFCC: - case SP::BPFCCA: - case SP::BPFCCNT: - case SP::BPFCCANT: - case SP::MOVFCCrr: case SP::V9MOVFCCrr: - case SP::MOVFCCri: case SP::V9MOVFCCri: - case SP::FMOVS_FCC: case SP::V9FMOVS_FCC: - case SP::FMOVD_FCC: case SP::V9FMOVD_FCC: - case SP::FMOVQ_FCC: case SP::V9FMOVQ_FCC: - // Make sure CC is a fp conditional flag. - CC = (CC < 16) ? (CC + 16) : CC; - break; - case SP::CBCOND: - case SP::CBCONDA: - // Make sure CC is a cp conditional flag. - CC = (CC < 32) ? (CC + 32) : CC; - break; - } - O << SPARCCondCodeToString((SPCC::CondCodes)CC); -} - -bool SparcInstPrinter::printGetPCX(const MCInst *MI, unsigned opNum, - const MCSubtargetInfo &STI, - raw_ostream &O) { - llvm_unreachable("FIXME: Implement SparcInstPrinter::printGetPCX."); - return true; -} - -void SparcInstPrinter::printMembarTag(const MCInst *MI, int opNum, - const MCSubtargetInfo &STI, - raw_ostream &O) { - static const char *const TagNames[] = { - "#LoadLoad", "#StoreLoad", "#LoadStore", "#StoreStore", - "#Lookaside", "#MemIssue", "#Sync"}; - - unsigned Imm = MI->getOperand(opNum).getImm(); - - if (Imm > 127) { - O << Imm; - return; - } - - bool First = true; - for (unsigned i = 0; i < sizeof(TagNames) / sizeof(char *); i++) { - if (Imm & (1 << i)) { - O << (First ? "" : " | ") << TagNames[i]; - First = false; - } - } -} diff --git a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.h b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.h deleted file mode 100644 index 499bcadb0d4d..000000000000 --- a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcInstPrinter.h +++ /dev/null @@ -1,56 +0,0 @@ -//===-- SparcInstPrinter.h - Convert Sparc 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 Sparc MCInst to a .s file. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_SPARC_MCTARGETDESC_SPARCINSTPRINTER_H -#define LLVM_LIB_TARGET_SPARC_MCTARGETDESC_SPARCINSTPRINTER_H - -#include "llvm/MC/MCInstPrinter.h" - -namespace llvm { - -class SparcInstPrinter : public MCInstPrinter { -public: - SparcInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII, - const MCRegisterInfo &MRI) - : MCInstPrinter(MAI, MII, MRI) {} - - void printRegName(raw_ostream &OS, unsigned RegNo) const override; - void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot, - const MCSubtargetInfo &STI) override; - bool printSparcAliasInstr(const MCInst *MI, const MCSubtargetInfo &STI, - raw_ostream &OS); - bool isV9(const MCSubtargetInfo &STI) const; - - // Autogenerated by tblgen. - void printInstruction(const MCInst *MI, const MCSubtargetInfo &STI, - raw_ostream &O); - bool printAliasInstr(const MCInst *MI, const MCSubtargetInfo &STI, - raw_ostream &O); - void printCustomAliasOperand(const MCInst *MI, unsigned OpIdx, - unsigned PrintMethodIdx, - const MCSubtargetInfo &STI, raw_ostream &O); - static const char *getRegisterName(unsigned RegNo); - - void printOperand(const MCInst *MI, int opNum, const MCSubtargetInfo &STI, - raw_ostream &OS); - void printMemOperand(const MCInst *MI, int opNum, const MCSubtargetInfo &STI, - raw_ostream &OS, const char *Modifier = nullptr); - void printCCOperand(const MCInst *MI, int opNum, const MCSubtargetInfo &STI, - raw_ostream &OS); - bool printGetPCX(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, - raw_ostream &OS); - void printMembarTag(const MCInst *MI, int opNum, const MCSubtargetInfo &STI, - raw_ostream &O); -}; -} // end namespace llvm - -#endif diff --git a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp deleted file mode 100644 index 1a2a040990ae..000000000000 --- a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp +++ /dev/null @@ -1,72 +0,0 @@ -//===- SparcMCAsmInfo.cpp - Sparc 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 SparcMCAsmInfo properties. -// -//===----------------------------------------------------------------------===// - -#include "SparcMCAsmInfo.h" -#include "SparcMCExpr.h" -#include "llvm/ADT/Triple.h" -#include "llvm/BinaryFormat/Dwarf.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCStreamer.h" -#include "llvm/MC/MCTargetOptions.h" - -using namespace llvm; - -void SparcELFMCAsmInfo::anchor() {} - -SparcELFMCAsmInfo::SparcELFMCAsmInfo(const Triple &TheTriple) { - bool isV9 = (TheTriple.getArch() == Triple::sparcv9); - IsLittleEndian = (TheTriple.getArch() == Triple::sparcel); - - if (isV9) { - CodePointerSize = CalleeSaveStackSlotSize = 8; - } - - Data16bitsDirective = "\t.half\t"; - Data32bitsDirective = "\t.word\t"; - // .xword is only supported by V9. - Data64bitsDirective = (isV9) ? "\t.xword\t" : nullptr; - ZeroDirective = "\t.skip\t"; - CommentString = "!"; - SupportsDebugInformation = true; - - ExceptionsType = ExceptionHandling::DwarfCFI; - - SunStyleELFSectionSwitchSyntax = true; - UsesELFSectionDirectiveForBSS = true; - - UseIntegratedAssembler = true; -} - -const MCExpr* -SparcELFMCAsmInfo::getExprForPersonalitySymbol(const MCSymbol *Sym, - unsigned Encoding, - MCStreamer &Streamer) const { - if (Encoding & dwarf::DW_EH_PE_pcrel) { - MCContext &Ctx = Streamer.getContext(); - return SparcMCExpr::create(SparcMCExpr::VK_Sparc_R_DISP32, - MCSymbolRefExpr::create(Sym, Ctx), Ctx); - } - - return MCAsmInfo::getExprForPersonalitySymbol(Sym, Encoding, Streamer); -} - -const MCExpr* -SparcELFMCAsmInfo::getExprForFDESymbol(const MCSymbol *Sym, - unsigned Encoding, - MCStreamer &Streamer) const { - if (Encoding & dwarf::DW_EH_PE_pcrel) { - MCContext &Ctx = Streamer.getContext(); - return SparcMCExpr::create(SparcMCExpr::VK_Sparc_R_DISP32, - MCSymbolRefExpr::create(Sym, Ctx), Ctx); - } - return MCAsmInfo::getExprForFDESymbol(Sym, Encoding, Streamer); -} diff --git a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.h b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.h deleted file mode 100644 index c9162f2dc8a5..000000000000 --- a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.h +++ /dev/null @@ -1,39 +0,0 @@ -//===- SparcMCAsmInfo.h - Sparc asm properties -----------------*- 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 SparcMCAsmInfo class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_SPARC_MCTARGETDESC_SPARCMCASMINFO_H -#define LLVM_LIB_TARGET_SPARC_MCTARGETDESC_SPARCMCASMINFO_H - -#include "llvm/MC/MCAsmInfoELF.h" - -namespace llvm { - -class Triple; - -class SparcELFMCAsmInfo : public MCAsmInfoELF { - void anchor() override; - -public: - explicit SparcELFMCAsmInfo(const Triple &TheTriple); - - const MCExpr* - getExprForPersonalitySymbol(const MCSymbol *Sym, unsigned Encoding, - MCStreamer &Streamer) const override; - const MCExpr* getExprForFDESymbol(const MCSymbol *Sym, - unsigned Encoding, - MCStreamer &Streamer) const override; - -}; - -} // end namespace llvm - -#endif // LLVM_LIB_TARGET_SPARC_MCTARGETDESC_SPARCMCASMINFO_H diff --git a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp deleted file mode 100644 index 7e908011bd50..000000000000 --- a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp +++ /dev/null @@ -1,233 +0,0 @@ -//===-- SparcMCCodeEmitter.cpp - Convert Sparc 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 SparcMCCodeEmitter class. -// -//===----------------------------------------------------------------------===// - -#include "MCTargetDesc/SparcFixupKinds.h" -#include "SparcMCExpr.h" -#include "SparcMCTargetDesc.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/Statistic.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCCodeEmitter.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCFixup.h" -#include "llvm/MC/MCInst.h" -#include "llvm/MC/MCInstrInfo.h" -#include "llvm/MC/MCRegisterInfo.h" -#include "llvm/MC/MCSubtargetInfo.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/MC/SubtargetFeature.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/Endian.h" -#include "llvm/Support/EndianStream.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" -#include -#include - -using namespace llvm; - -#define DEBUG_TYPE "mccodeemitter" - -STATISTIC(MCNumEmitted, "Number of MC instructions emitted"); - -namespace { - -class SparcMCCodeEmitter : public MCCodeEmitter { - const MCInstrInfo &MCII; - MCContext &Ctx; - -public: - SparcMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx) - : MCII(mcii), Ctx(ctx) {} - SparcMCCodeEmitter(const SparcMCCodeEmitter &) = delete; - SparcMCCodeEmitter &operator=(const SparcMCCodeEmitter &) = delete; - ~SparcMCCodeEmitter() override = default; - - void encodeInstruction(const MCInst &MI, raw_ostream &OS, - SmallVectorImpl &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 &Fixups, - const MCSubtargetInfo &STI) const; - - /// getMachineOpValue - Return binary encoding of operand. If the machine - /// operand requires relocation, record the relocation and return zero. - unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO, - SmallVectorImpl &Fixups, - const MCSubtargetInfo &STI) const; - - unsigned getCallTargetOpValue(const MCInst &MI, unsigned OpNo, - SmallVectorImpl &Fixups, - const MCSubtargetInfo &STI) const; - unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, - SmallVectorImpl &Fixups, - const MCSubtargetInfo &STI) const; - unsigned getBranchPredTargetOpValue(const MCInst &MI, unsigned OpNo, - SmallVectorImpl &Fixups, - const MCSubtargetInfo &STI) const; - unsigned getBranchOnRegTargetOpValue(const MCInst &MI, unsigned OpNo, - SmallVectorImpl &Fixups, - const MCSubtargetInfo &STI) const; - -private: - FeatureBitset computeAvailableFeatures(const FeatureBitset &FB) const; - void - verifyInstructionPredicates(const MCInst &MI, - const FeatureBitset &AvailableFeatures) const; -}; - -} // end anonymous namespace - -void SparcMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, - SmallVectorImpl &Fixups, - const MCSubtargetInfo &STI) const { - verifyInstructionPredicates(MI, - computeAvailableFeatures(STI.getFeatureBits())); - - unsigned Bits = getBinaryCodeForInstr(MI, Fixups, STI); - support::endian::write(OS, Bits, - Ctx.getAsmInfo()->isLittleEndian() ? support::little - : support::big); - unsigned tlsOpNo = 0; - switch (MI.getOpcode()) { - default: break; - case SP::TLS_CALL: tlsOpNo = 1; break; - case SP::TLS_ADDrr: - case SP::TLS_ADDXrr: - case SP::TLS_LDrr: - case SP::TLS_LDXrr: tlsOpNo = 3; break; - } - if (tlsOpNo != 0) { - const MCOperand &MO = MI.getOperand(tlsOpNo); - uint64_t op = getMachineOpValue(MI, MO, Fixups, STI); - assert(op == 0 && "Unexpected operand value!"); - (void)op; // suppress warning. - } - - ++MCNumEmitted; // Keep track of the # of mi's emitted. -} - -unsigned SparcMCCodeEmitter:: -getMachineOpValue(const MCInst &MI, const MCOperand &MO, - SmallVectorImpl &Fixups, - const MCSubtargetInfo &STI) const { - if (MO.isReg()) - return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); - - if (MO.isImm()) - return MO.getImm(); - - assert(MO.isExpr()); - const MCExpr *Expr = MO.getExpr(); - if (const SparcMCExpr *SExpr = dyn_cast(Expr)) { - MCFixupKind Kind = (MCFixupKind)SExpr->getFixupKind(); - Fixups.push_back(MCFixup::create(0, Expr, Kind)); - return 0; - } - - int64_t Res; - if (Expr->evaluateAsAbsolute(Res)) - return Res; - - llvm_unreachable("Unhandled expression!"); - return 0; -} - -unsigned SparcMCCodeEmitter:: -getCallTargetOpValue(const MCInst &MI, unsigned OpNo, - SmallVectorImpl &Fixups, - const MCSubtargetInfo &STI) const { - const MCOperand &MO = MI.getOperand(OpNo); - if (MO.isReg() || MO.isImm()) - return getMachineOpValue(MI, MO, Fixups, STI); - - if (MI.getOpcode() == SP::TLS_CALL) { - // No fixups for __tls_get_addr. Will emit for fixups for tls_symbol in - // encodeInstruction. -#ifndef NDEBUG - // Verify that the callee is actually __tls_get_addr. - const SparcMCExpr *SExpr = dyn_cast(MO.getExpr()); - assert(SExpr && SExpr->getSubExpr()->getKind() == MCExpr::SymbolRef && - "Unexpected expression in TLS_CALL"); - const MCSymbolRefExpr *SymExpr = cast(SExpr->getSubExpr()); - assert(SymExpr->getSymbol().getName() == "__tls_get_addr" && - "Unexpected function for TLS_CALL"); -#endif - return 0; - } - - MCFixupKind fixupKind = (MCFixupKind)Sparc::fixup_sparc_call30; - - if (const SparcMCExpr *SExpr = dyn_cast(MO.getExpr())) { - if (SExpr->getKind() == SparcMCExpr::VK_Sparc_WPLT30) - fixupKind = (MCFixupKind)Sparc::fixup_sparc_wplt30; - } - - Fixups.push_back(MCFixup::create(0, MO.getExpr(), fixupKind)); - - return 0; -} - -unsigned SparcMCCodeEmitter:: -getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, - SmallVectorImpl &Fixups, - const MCSubtargetInfo &STI) const { - const MCOperand &MO = MI.getOperand(OpNo); - if (MO.isReg() || MO.isImm()) - return getMachineOpValue(MI, MO, Fixups, STI); - - Fixups.push_back(MCFixup::create(0, MO.getExpr(), - (MCFixupKind)Sparc::fixup_sparc_br22)); - return 0; -} - -unsigned SparcMCCodeEmitter:: -getBranchPredTargetOpValue(const MCInst &MI, unsigned OpNo, - SmallVectorImpl &Fixups, - const MCSubtargetInfo &STI) const { - const MCOperand &MO = MI.getOperand(OpNo); - if (MO.isReg() || MO.isImm()) - return getMachineOpValue(MI, MO, Fixups, STI); - - Fixups.push_back(MCFixup::create(0, MO.getExpr(), - (MCFixupKind)Sparc::fixup_sparc_br19)); - return 0; -} - -unsigned SparcMCCodeEmitter:: -getBranchOnRegTargetOpValue(const MCInst &MI, unsigned OpNo, - SmallVectorImpl &Fixups, - const MCSubtargetInfo &STI) const { - const MCOperand &MO = MI.getOperand(OpNo); - if (MO.isReg() || MO.isImm()) - return getMachineOpValue(MI, MO, Fixups, STI); - - Fixups.push_back(MCFixup::create(0, MO.getExpr(), - (MCFixupKind)Sparc::fixup_sparc_br16_2)); - Fixups.push_back(MCFixup::create(0, MO.getExpr(), - (MCFixupKind)Sparc::fixup_sparc_br16_14)); - - return 0; -} - -#define ENABLE_INSTR_PREDICATE_VERIFIER -#include "SparcGenMCCodeEmitter.inc" - -MCCodeEmitter *llvm::createSparcMCCodeEmitter(const MCInstrInfo &MCII, - const MCRegisterInfo &MRI, - MCContext &Ctx) { - return new SparcMCCodeEmitter(MCII, Ctx); -} diff --git a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp deleted file mode 100644 index 00f319fc37e1..000000000000 --- a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp +++ /dev/null @@ -1,236 +0,0 @@ -//===-- SparcMCExpr.cpp - Sparc 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 -// -//===----------------------------------------------------------------------===// -// -// This file contains the implementation of the assembly expression modifiers -// accepted by the Sparc architecture (e.g. "%hi", "%lo", ...). -// -//===----------------------------------------------------------------------===// - -#include "SparcMCExpr.h" -#include "llvm/BinaryFormat/ELF.h" -#include "llvm/MC/MCAssembler.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCObjectStreamer.h" -#include "llvm/MC/MCSymbolELF.h" - -using namespace llvm; - -#define DEBUG_TYPE "sparcmcexpr" - -const SparcMCExpr* -SparcMCExpr::create(VariantKind Kind, const MCExpr *Expr, - MCContext &Ctx) { - return new (Ctx) SparcMCExpr(Kind, Expr); -} - -void SparcMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const { - - bool closeParen = printVariantKind(OS, Kind); - - const MCExpr *Expr = getSubExpr(); - Expr->print(OS, MAI); - - if (closeParen) - OS << ')'; -} - -bool SparcMCExpr::printVariantKind(raw_ostream &OS, VariantKind Kind) -{ - bool closeParen = true; - switch (Kind) { - case VK_Sparc_None: closeParen = false; break; - case VK_Sparc_LO: OS << "%lo("; break; - case VK_Sparc_HI: OS << "%hi("; break; - case VK_Sparc_H44: OS << "%h44("; break; - case VK_Sparc_M44: OS << "%m44("; break; - case VK_Sparc_L44: OS << "%l44("; break; - case VK_Sparc_HH: OS << "%hh("; break; - case VK_Sparc_HM: OS << "%hm("; break; - // FIXME: use %pc22/%pc10, if system assembler supports them. - case VK_Sparc_PC22: OS << "%hi("; break; - case VK_Sparc_PC10: OS << "%lo("; break; - // FIXME: use %got22/%got10, if system assembler supports them. - case VK_Sparc_GOT22: OS << "%hi("; break; - case VK_Sparc_GOT10: OS << "%lo("; break; - case VK_Sparc_GOT13: closeParen = false; break; - case VK_Sparc_13: closeParen = false; break; - case VK_Sparc_WPLT30: closeParen = false; break; - case VK_Sparc_R_DISP32: OS << "%r_disp32("; break; - case VK_Sparc_TLS_GD_HI22: OS << "%tgd_hi22("; break; - case VK_Sparc_TLS_GD_LO10: OS << "%tgd_lo10("; break; - case VK_Sparc_TLS_GD_ADD: OS << "%tgd_add("; break; - case VK_Sparc_TLS_GD_CALL: OS << "%tgd_call("; break; - case VK_Sparc_TLS_LDM_HI22: OS << "%tldm_hi22("; break; - case VK_Sparc_TLS_LDM_LO10: OS << "%tldm_lo10("; break; - case VK_Sparc_TLS_LDM_ADD: OS << "%tldm_add("; break; - case VK_Sparc_TLS_LDM_CALL: OS << "%tldm_call("; break; - case VK_Sparc_TLS_LDO_HIX22: OS << "%tldo_hix22("; break; - case VK_Sparc_TLS_LDO_LOX10: OS << "%tldo_lox10("; break; - case VK_Sparc_TLS_LDO_ADD: OS << "%tldo_add("; break; - case VK_Sparc_TLS_IE_HI22: OS << "%tie_hi22("; break; - case VK_Sparc_TLS_IE_LO10: OS << "%tie_lo10("; break; - case VK_Sparc_TLS_IE_LD: OS << "%tie_ld("; break; - case VK_Sparc_TLS_IE_LDX: OS << "%tie_ldx("; break; - case VK_Sparc_TLS_IE_ADD: OS << "%tie_add("; break; - case VK_Sparc_TLS_LE_HIX22: OS << "%tle_hix22("; break; - case VK_Sparc_TLS_LE_LOX10: OS << "%tle_lox10("; break; - } - return closeParen; -} - -SparcMCExpr::VariantKind SparcMCExpr::parseVariantKind(StringRef name) -{ - return StringSwitch(name) - .Case("lo", VK_Sparc_LO) - .Case("hi", VK_Sparc_HI) - .Case("h44", VK_Sparc_H44) - .Case("m44", VK_Sparc_M44) - .Case("l44", VK_Sparc_L44) - .Case("hh", VK_Sparc_HH) - .Case("hm", VK_Sparc_HM) - .Case("pc22", VK_Sparc_PC22) - .Case("pc10", VK_Sparc_PC10) - .Case("got22", VK_Sparc_GOT22) - .Case("got10", VK_Sparc_GOT10) - .Case("got13", VK_Sparc_GOT13) - .Case("r_disp32", VK_Sparc_R_DISP32) - .Case("tgd_hi22", VK_Sparc_TLS_GD_HI22) - .Case("tgd_lo10", VK_Sparc_TLS_GD_LO10) - .Case("tgd_add", VK_Sparc_TLS_GD_ADD) - .Case("tgd_call", VK_Sparc_TLS_GD_CALL) - .Case("tldm_hi22", VK_Sparc_TLS_LDM_HI22) - .Case("tldm_lo10", VK_Sparc_TLS_LDM_LO10) - .Case("tldm_add", VK_Sparc_TLS_LDM_ADD) - .Case("tldm_call", VK_Sparc_TLS_LDM_CALL) - .Case("tldo_hix22", VK_Sparc_TLS_LDO_HIX22) - .Case("tldo_lox10", VK_Sparc_TLS_LDO_LOX10) - .Case("tldo_add", VK_Sparc_TLS_LDO_ADD) - .Case("tie_hi22", VK_Sparc_TLS_IE_HI22) - .Case("tie_lo10", VK_Sparc_TLS_IE_LO10) - .Case("tie_ld", VK_Sparc_TLS_IE_LD) - .Case("tie_ldx", VK_Sparc_TLS_IE_LDX) - .Case("tie_add", VK_Sparc_TLS_IE_ADD) - .Case("tle_hix22", VK_Sparc_TLS_LE_HIX22) - .Case("tle_lox10", VK_Sparc_TLS_LE_LOX10) - .Default(VK_Sparc_None); -} - -Sparc::Fixups SparcMCExpr::getFixupKind(SparcMCExpr::VariantKind Kind) { - switch (Kind) { - default: llvm_unreachable("Unhandled SparcMCExpr::VariantKind"); - case VK_Sparc_LO: return Sparc::fixup_sparc_lo10; - case VK_Sparc_HI: return Sparc::fixup_sparc_hi22; - case VK_Sparc_H44: return Sparc::fixup_sparc_h44; - case VK_Sparc_M44: return Sparc::fixup_sparc_m44; - case VK_Sparc_L44: return Sparc::fixup_sparc_l44; - case VK_Sparc_HH: return Sparc::fixup_sparc_hh; - case VK_Sparc_HM: return Sparc::fixup_sparc_hm; - case VK_Sparc_PC22: return Sparc::fixup_sparc_pc22; - case VK_Sparc_PC10: return Sparc::fixup_sparc_pc10; - case VK_Sparc_GOT22: return Sparc::fixup_sparc_got22; - case VK_Sparc_GOT10: return Sparc::fixup_sparc_got10; - case VK_Sparc_GOT13: return Sparc::fixup_sparc_got13; - case VK_Sparc_13: return Sparc::fixup_sparc_13; - case VK_Sparc_WPLT30: return Sparc::fixup_sparc_wplt30; - case VK_Sparc_TLS_GD_HI22: return Sparc::fixup_sparc_tls_gd_hi22; - case VK_Sparc_TLS_GD_LO10: return Sparc::fixup_sparc_tls_gd_lo10; - case VK_Sparc_TLS_GD_ADD: return Sparc::fixup_sparc_tls_gd_add; - case VK_Sparc_TLS_GD_CALL: return Sparc::fixup_sparc_tls_gd_call; - case VK_Sparc_TLS_LDM_HI22: return Sparc::fixup_sparc_tls_ldm_hi22; - case VK_Sparc_TLS_LDM_LO10: return Sparc::fixup_sparc_tls_ldm_lo10; - case VK_Sparc_TLS_LDM_ADD: return Sparc::fixup_sparc_tls_ldm_add; - case VK_Sparc_TLS_LDM_CALL: return Sparc::fixup_sparc_tls_ldm_call; - case VK_Sparc_TLS_LDO_HIX22: return Sparc::fixup_sparc_tls_ldo_hix22; - case VK_Sparc_TLS_LDO_LOX10: return Sparc::fixup_sparc_tls_ldo_lox10; - case VK_Sparc_TLS_LDO_ADD: return Sparc::fixup_sparc_tls_ldo_add; - case VK_Sparc_TLS_IE_HI22: return Sparc::fixup_sparc_tls_ie_hi22; - case VK_Sparc_TLS_IE_LO10: return Sparc::fixup_sparc_tls_ie_lo10; - case VK_Sparc_TLS_IE_LD: return Sparc::fixup_sparc_tls_ie_ld; - case VK_Sparc_TLS_IE_LDX: return Sparc::fixup_sparc_tls_ie_ldx; - case VK_Sparc_TLS_IE_ADD: return Sparc::fixup_sparc_tls_ie_add; - case VK_Sparc_TLS_LE_HIX22: return Sparc::fixup_sparc_tls_le_hix22; - case VK_Sparc_TLS_LE_LOX10: return Sparc::fixup_sparc_tls_le_lox10; - } -} - -bool -SparcMCExpr::evaluateAsRelocatableImpl(MCValue &Res, - const MCAsmLayout *Layout, - const MCFixup *Fixup) const { - return getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup); -} - -static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) { - switch (Expr->getKind()) { - case MCExpr::Target: - llvm_unreachable("Can't handle nested target expr!"); - break; - - case MCExpr::Constant: - break; - - case MCExpr::Binary: { - const MCBinaryExpr *BE = cast(Expr); - fixELFSymbolsInTLSFixupsImpl(BE->getLHS(), Asm); - fixELFSymbolsInTLSFixupsImpl(BE->getRHS(), Asm); - break; - } - - case MCExpr::SymbolRef: { - const MCSymbolRefExpr &SymRef = *cast(Expr); - cast(SymRef.getSymbol()).setType(ELF::STT_TLS); - break; - } - - case MCExpr::Unary: - fixELFSymbolsInTLSFixupsImpl(cast(Expr)->getSubExpr(), Asm); - break; - } - -} - -void SparcMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const { - switch(getKind()) { - default: return; - case VK_Sparc_TLS_GD_CALL: - case VK_Sparc_TLS_LDM_CALL: { - // The corresponding relocations reference __tls_get_addr, as they call it, - // but this is only implicit; we must explicitly add it to our symbol table - // to bind it for these uses. - MCSymbol *Symbol = Asm.getContext().getOrCreateSymbol("__tls_get_addr"); - Asm.registerSymbol(*Symbol); - auto ELFSymbol = cast(Symbol); - if (!ELFSymbol->isBindingSet()) { - ELFSymbol->setBinding(ELF::STB_GLOBAL); - ELFSymbol->setExternal(true); - } - LLVM_FALLTHROUGH; - } - case VK_Sparc_TLS_GD_HI22: - case VK_Sparc_TLS_GD_LO10: - case VK_Sparc_TLS_GD_ADD: - case VK_Sparc_TLS_LDM_HI22: - case VK_Sparc_TLS_LDM_LO10: - case VK_Sparc_TLS_LDM_ADD: - case VK_Sparc_TLS_LDO_HIX22: - case VK_Sparc_TLS_LDO_LOX10: - case VK_Sparc_TLS_LDO_ADD: - case VK_Sparc_TLS_IE_HI22: - case VK_Sparc_TLS_IE_LO10: - case VK_Sparc_TLS_IE_LD: - case VK_Sparc_TLS_IE_LDX: - case VK_Sparc_TLS_IE_ADD: - case VK_Sparc_TLS_LE_HIX22: - case VK_Sparc_TLS_LE_LOX10: break; - } - fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm); -} - -void SparcMCExpr::visitUsedExpr(MCStreamer &Streamer) const { - Streamer.visitUsedExpr(*getSubExpr()); -} diff --git a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h deleted file mode 100644 index c2467faca257..000000000000 --- a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h +++ /dev/null @@ -1,113 +0,0 @@ -//====- SparcMCExpr.h - Sparc 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 -// -//===----------------------------------------------------------------------===// -// -// This file describes Sparc-specific MCExprs, used for modifiers like -// "%hi" or "%lo" etc., -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_SPARC_MCTARGETDESC_SPARCMCEXPR_H -#define LLVM_LIB_TARGET_SPARC_MCTARGETDESC_SPARCMCEXPR_H - -#include "SparcFixupKinds.h" -#include "llvm/MC/MCExpr.h" - -namespace llvm { - -class StringRef; -class SparcMCExpr : public MCTargetExpr { -public: - enum VariantKind { - VK_Sparc_None, - VK_Sparc_LO, - VK_Sparc_HI, - VK_Sparc_H44, - VK_Sparc_M44, - VK_Sparc_L44, - VK_Sparc_HH, - VK_Sparc_HM, - VK_Sparc_PC22, - VK_Sparc_PC10, - VK_Sparc_GOT22, - VK_Sparc_GOT10, - VK_Sparc_GOT13, - VK_Sparc_13, - VK_Sparc_WPLT30, - VK_Sparc_R_DISP32, - VK_Sparc_TLS_GD_HI22, - VK_Sparc_TLS_GD_LO10, - VK_Sparc_TLS_GD_ADD, - VK_Sparc_TLS_GD_CALL, - VK_Sparc_TLS_LDM_HI22, - VK_Sparc_TLS_LDM_LO10, - VK_Sparc_TLS_LDM_ADD, - VK_Sparc_TLS_LDM_CALL, - VK_Sparc_TLS_LDO_HIX22, - VK_Sparc_TLS_LDO_LOX10, - VK_Sparc_TLS_LDO_ADD, - VK_Sparc_TLS_IE_HI22, - VK_Sparc_TLS_IE_LO10, - VK_Sparc_TLS_IE_LD, - VK_Sparc_TLS_IE_LDX, - VK_Sparc_TLS_IE_ADD, - VK_Sparc_TLS_LE_HIX22, - VK_Sparc_TLS_LE_LOX10 - }; - -private: - const VariantKind Kind; - const MCExpr *Expr; - - explicit SparcMCExpr(VariantKind Kind, const MCExpr *Expr) - : Kind(Kind), Expr(Expr) {} - -public: - /// @name Construction - /// @{ - - static const SparcMCExpr *create(VariantKind Kind, const MCExpr *Expr, - MCContext &Ctx); - /// @} - /// @name Accessors - /// @{ - - /// getOpcode - Get the kind of this expression. - VariantKind getKind() const { return Kind; } - - /// getSubExpr - Get the child of this expression. - const MCExpr *getSubExpr() const { return Expr; } - - /// getFixupKind - Get the fixup kind of this expression. - Sparc::Fixups getFixupKind() const { return getFixupKind(Kind); } - - /// @} - 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; - } - - static bool classof(const SparcMCExpr *) { return true; } - - static VariantKind parseVariantKind(StringRef name); - static bool printVariantKind(raw_ostream &OS, VariantKind Kind); - static Sparc::Fixups getFixupKind(VariantKind Kind); -}; - -} // end namespace llvm. - -#endif diff --git a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp deleted file mode 100644 index ce593bb66770..000000000000 --- a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp +++ /dev/null @@ -1,125 +0,0 @@ -//===-- SparcMCTargetDesc.cpp - Sparc 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 Sparc specific target descriptions. -// -//===----------------------------------------------------------------------===// - -#include "SparcMCTargetDesc.h" -#include "SparcInstPrinter.h" -#include "SparcMCAsmInfo.h" -#include "SparcTargetStreamer.h" -#include "TargetInfo/SparcTargetInfo.h" -#include "llvm/MC/MCInstrInfo.h" -#include "llvm/MC/MCRegisterInfo.h" -#include "llvm/MC/MCSubtargetInfo.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/TargetRegistry.h" - -using namespace llvm; - -#define GET_INSTRINFO_MC_DESC -#include "SparcGenInstrInfo.inc" - -#define GET_SUBTARGETINFO_MC_DESC -#include "SparcGenSubtargetInfo.inc" - -#define GET_REGINFO_MC_DESC -#include "SparcGenRegisterInfo.inc" - -static MCAsmInfo *createSparcMCAsmInfo(const MCRegisterInfo &MRI, - const Triple &TT) { - MCAsmInfo *MAI = new SparcELFMCAsmInfo(TT); - unsigned Reg = MRI.getDwarfRegNum(SP::O6, true); - MCCFIInstruction Inst = MCCFIInstruction::createDefCfa(nullptr, Reg, 0); - MAI->addInitialFrameState(Inst); - return MAI; -} - -static MCAsmInfo *createSparcV9MCAsmInfo(const MCRegisterInfo &MRI, - const Triple &TT) { - MCAsmInfo *MAI = new SparcELFMCAsmInfo(TT); - unsigned Reg = MRI.getDwarfRegNum(SP::O6, true); - MCCFIInstruction Inst = MCCFIInstruction::createDefCfa(nullptr, Reg, 2047); - MAI->addInitialFrameState(Inst); - return MAI; -} - -static MCInstrInfo *createSparcMCInstrInfo() { - MCInstrInfo *X = new MCInstrInfo(); - InitSparcMCInstrInfo(X); - return X; -} - -static MCRegisterInfo *createSparcMCRegisterInfo(const Triple &TT) { - MCRegisterInfo *X = new MCRegisterInfo(); - InitSparcMCRegisterInfo(X, SP::O7); - return X; -} - -static MCSubtargetInfo * -createSparcMCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS) { - if (CPU.empty()) - CPU = (TT.getArch() == Triple::sparcv9) ? "v9" : "v8"; - return createSparcMCSubtargetInfoImpl(TT, CPU, FS); -} - -static MCTargetStreamer * -createObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) { - return new SparcTargetELFStreamer(S); -} - -static MCTargetStreamer *createTargetAsmStreamer(MCStreamer &S, - formatted_raw_ostream &OS, - MCInstPrinter *InstPrint, - bool isVerboseAsm) { - return new SparcTargetAsmStreamer(S, OS); -} - -static MCInstPrinter *createSparcMCInstPrinter(const Triple &T, - unsigned SyntaxVariant, - const MCAsmInfo &MAI, - const MCInstrInfo &MII, - const MCRegisterInfo &MRI) { - return new SparcInstPrinter(MAI, MII, MRI); -} - -extern "C" void LLVMInitializeSparcTargetMC() { - // Register the MC asm info. - RegisterMCAsmInfoFn X(getTheSparcTarget(), createSparcMCAsmInfo); - RegisterMCAsmInfoFn Y(getTheSparcV9Target(), createSparcV9MCAsmInfo); - RegisterMCAsmInfoFn Z(getTheSparcelTarget(), createSparcMCAsmInfo); - - for (Target *T : - {&getTheSparcTarget(), &getTheSparcV9Target(), &getTheSparcelTarget()}) { - // Register the MC instruction info. - TargetRegistry::RegisterMCInstrInfo(*T, createSparcMCInstrInfo); - - // Register the MC register info. - TargetRegistry::RegisterMCRegInfo(*T, createSparcMCRegisterInfo); - - // Register the MC subtarget info. - TargetRegistry::RegisterMCSubtargetInfo(*T, createSparcMCSubtargetInfo); - - // Register the MC Code Emitter. - TargetRegistry::RegisterMCCodeEmitter(*T, createSparcMCCodeEmitter); - - // Register the asm backend. - TargetRegistry::RegisterMCAsmBackend(*T, createSparcAsmBackend); - - // Register the object target streamer. - TargetRegistry::RegisterObjectTargetStreamer(*T, - createObjectTargetStreamer); - - // Register the asm streamer. - TargetRegistry::RegisterAsmTargetStreamer(*T, createTargetAsmStreamer); - - // Register the MCInstPrinter - TargetRegistry::RegisterMCInstPrinter(*T, createSparcMCInstPrinter); - } -} diff --git a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h deleted file mode 100644 index e5699bb1c133..000000000000 --- a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h +++ /dev/null @@ -1,59 +0,0 @@ -//===-- SparcMCTargetDesc.h - Sparc 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 Sparc specific target descriptions. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_SPARC_MCTARGETDESC_SPARCMCTARGETDESC_H -#define LLVM_LIB_TARGET_SPARC_MCTARGETDESC_SPARCMCTARGETDESC_H - -#include "llvm/Support/DataTypes.h" - -#include - -namespace llvm { -class MCAsmBackend; -class MCCodeEmitter; -class MCContext; -class MCInstrInfo; -class MCObjectTargetWriter; -class MCRegisterInfo; -class MCSubtargetInfo; -class MCTargetOptions; -class Target; -class Triple; -class StringRef; -class raw_pwrite_stream; -class raw_ostream; - -MCCodeEmitter *createSparcMCCodeEmitter(const MCInstrInfo &MCII, - const MCRegisterInfo &MRI, - MCContext &Ctx); -MCAsmBackend *createSparcAsmBackend(const Target &T, const MCSubtargetInfo &STI, - const MCRegisterInfo &MRI, - const MCTargetOptions &Options); -std::unique_ptr createSparcELFObjectWriter(bool Is64Bit, - uint8_t OSABI); -} // End llvm namespace - -// Defines symbolic names for Sparc registers. This defines a mapping from -// register name to register number. -// -#define GET_REGINFO_ENUM -#include "SparcGenRegisterInfo.inc" - -// Defines symbolic names for the Sparc instructions. -// -#define GET_INSTRINFO_ENUM -#include "SparcGenInstrInfo.inc" - -#define GET_SUBTARGETINFO_ENUM -#include "SparcGenSubtargetInfo.inc" - -#endif diff --git a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.cpp b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.cpp deleted file mode 100644 index a322d49adb87..000000000000 --- a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.cpp +++ /dev/null @@ -1,45 +0,0 @@ -//===-- SparcTargetStreamer.cpp - Sparc 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 Sparc specific target streamer methods. -// -//===----------------------------------------------------------------------===// - -#include "SparcTargetStreamer.h" -#include "SparcInstPrinter.h" -#include "llvm/Support/FormattedStream.h" - -using namespace llvm; - -// pin vtable to this file -SparcTargetStreamer::SparcTargetStreamer(MCStreamer &S) : MCTargetStreamer(S) {} - -void SparcTargetStreamer::anchor() {} - -SparcTargetAsmStreamer::SparcTargetAsmStreamer(MCStreamer &S, - formatted_raw_ostream &OS) - : SparcTargetStreamer(S), OS(OS) {} - -void SparcTargetAsmStreamer::emitSparcRegisterIgnore(unsigned reg) { - OS << "\t.register " - << "%" << StringRef(SparcInstPrinter::getRegisterName(reg)).lower() - << ", #ignore\n"; -} - -void SparcTargetAsmStreamer::emitSparcRegisterScratch(unsigned reg) { - OS << "\t.register " - << "%" << StringRef(SparcInstPrinter::getRegisterName(reg)).lower() - << ", #scratch\n"; -} - -SparcTargetELFStreamer::SparcTargetELFStreamer(MCStreamer &S) - : SparcTargetStreamer(S) {} - -MCELFStreamer &SparcTargetELFStreamer::getStreamer() { - return static_cast(Streamer); -} diff --git a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.h b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.h deleted file mode 100644 index 9f729a6c2cf4..000000000000 --- a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.h +++ /dev/null @@ -1,47 +0,0 @@ -//===-- SparcTargetStreamer.h - Sparc 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_SPARC_MCTARGETDESC_SPARCTARGETSTREAMER_H -#define LLVM_LIB_TARGET_SPARC_MCTARGETDESC_SPARCTARGETSTREAMER_H - -#include "llvm/MC/MCELFStreamer.h" -#include "llvm/MC/MCStreamer.h" - -namespace llvm { -class SparcTargetStreamer : public MCTargetStreamer { - virtual void anchor(); - -public: - SparcTargetStreamer(MCStreamer &S); - /// Emit ".register , #ignore". - virtual void emitSparcRegisterIgnore(unsigned reg) = 0; - /// Emit ".register , #scratch". - virtual void emitSparcRegisterScratch(unsigned reg) = 0; -}; - -// This part is for ascii assembly output -class SparcTargetAsmStreamer : public SparcTargetStreamer { - formatted_raw_ostream &OS; - -public: - SparcTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS); - void emitSparcRegisterIgnore(unsigned reg) override; - void emitSparcRegisterScratch(unsigned reg) override; -}; - -// This part is for ELF object output -class SparcTargetELFStreamer : public SparcTargetStreamer { -public: - SparcTargetELFStreamer(MCStreamer &S); - MCELFStreamer &getStreamer(); - void emitSparcRegisterIgnore(unsigned reg) override {} - void emitSparcRegisterScratch(unsigned reg) override {} -}; -} // end namespace llvm - -#endif diff --git a/contrib/llvm/lib/Target/Sparc/Sparc.h b/contrib/llvm/lib/Target/Sparc/Sparc.h deleted file mode 100644 index 967c463f5281..000000000000 --- a/contrib/llvm/lib/Target/Sparc/Sparc.h +++ /dev/null @@ -1,166 +0,0 @@ -//===-- Sparc.h - Top-level interface for Sparc 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 -// Sparc back-end. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_SPARC_SPARC_H -#define LLVM_LIB_TARGET_SPARC_SPARC_H - -#include "MCTargetDesc/SparcMCTargetDesc.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Target/TargetMachine.h" - -namespace llvm { - class FunctionPass; - class SparcTargetMachine; - class formatted_raw_ostream; - class AsmPrinter; - class MCInst; - class MachineInstr; - - FunctionPass *createSparcISelDag(SparcTargetMachine &TM); - FunctionPass *createSparcDelaySlotFillerPass(); - - void LowerSparcMachineInstrToMCInst(const MachineInstr *MI, - MCInst &OutMI, - AsmPrinter &AP); -} // end namespace llvm; - -namespace llvm { - // Enums corresponding to Sparc condition codes, both icc's and fcc's. These - // values must be kept in sync with the ones in the .td file. - namespace SPCC { - enum CondCodes { - ICC_A = 8 , // Always - ICC_N = 0 , // Never - ICC_NE = 9 , // Not Equal - ICC_E = 1 , // Equal - ICC_G = 10 , // Greater - ICC_LE = 2 , // Less or Equal - ICC_GE = 11 , // Greater or Equal - ICC_L = 3 , // Less - ICC_GU = 12 , // Greater Unsigned - ICC_LEU = 4 , // Less or Equal Unsigned - ICC_CC = 13 , // Carry Clear/Great or Equal Unsigned - ICC_CS = 5 , // Carry Set/Less Unsigned - ICC_POS = 14 , // Positive - ICC_NEG = 6 , // Negative - ICC_VC = 15 , // Overflow Clear - ICC_VS = 7 , // Overflow Set - - FCC_A = 8+16, // Always - FCC_N = 0+16, // Never - FCC_U = 7+16, // Unordered - FCC_G = 6+16, // Greater - FCC_UG = 5+16, // Unordered or Greater - FCC_L = 4+16, // Less - FCC_UL = 3+16, // Unordered or Less - FCC_LG = 2+16, // Less or Greater - FCC_NE = 1+16, // Not Equal - FCC_E = 9+16, // Equal - FCC_UE = 10+16, // Unordered or Equal - FCC_GE = 11+16, // Greater or Equal - FCC_UGE = 12+16, // Unordered or Greater or Equal - FCC_LE = 13+16, // Less or Equal - FCC_ULE = 14+16, // Unordered or Less or Equal - FCC_O = 15+16, // Ordered - - CPCC_A = 8+32, // Always - CPCC_N = 0+32, // Never - CPCC_3 = 7+32, - CPCC_2 = 6+32, - CPCC_23 = 5+32, - CPCC_1 = 4+32, - CPCC_13 = 3+32, - CPCC_12 = 2+32, - CPCC_123 = 1+32, - CPCC_0 = 9+32, - CPCC_03 = 10+32, - CPCC_02 = 11+32, - CPCC_023 = 12+32, - CPCC_01 = 13+32, - CPCC_013 = 14+32, - CPCC_012 = 15+32 - }; - } - - inline static const char *SPARCCondCodeToString(SPCC::CondCodes CC) { - switch (CC) { - case SPCC::ICC_A: return "a"; - case SPCC::ICC_N: return "n"; - case SPCC::ICC_NE: return "ne"; - case SPCC::ICC_E: return "e"; - case SPCC::ICC_G: return "g"; - case SPCC::ICC_LE: return "le"; - case SPCC::ICC_GE: return "ge"; - case SPCC::ICC_L: return "l"; - case SPCC::ICC_GU: return "gu"; - case SPCC::ICC_LEU: return "leu"; - case SPCC::ICC_CC: return "cc"; - case SPCC::ICC_CS: return "cs"; - case SPCC::ICC_POS: return "pos"; - case SPCC::ICC_NEG: return "neg"; - case SPCC::ICC_VC: return "vc"; - case SPCC::ICC_VS: return "vs"; - case SPCC::FCC_A: return "a"; - case SPCC::FCC_N: return "n"; - case SPCC::FCC_U: return "u"; - case SPCC::FCC_G: return "g"; - case SPCC::FCC_UG: return "ug"; - case SPCC::FCC_L: return "l"; - case SPCC::FCC_UL: return "ul"; - case SPCC::FCC_LG: return "lg"; - case SPCC::FCC_NE: return "ne"; - case SPCC::FCC_E: return "e"; - case SPCC::FCC_UE: return "ue"; - case SPCC::FCC_GE: return "ge"; - case SPCC::FCC_UGE: return "uge"; - case SPCC::FCC_LE: return "le"; - case SPCC::FCC_ULE: return "ule"; - case SPCC::FCC_O: return "o"; - case SPCC::CPCC_A: return "a"; - case SPCC::CPCC_N: return "n"; - case SPCC::CPCC_3: return "3"; - case SPCC::CPCC_2: return "2"; - case SPCC::CPCC_23: return "23"; - case SPCC::CPCC_1: return "1"; - case SPCC::CPCC_13: return "13"; - case SPCC::CPCC_12: return "12"; - case SPCC::CPCC_123: return "123"; - case SPCC::CPCC_0: return "0"; - case SPCC::CPCC_03: return "03"; - case SPCC::CPCC_02: return "02"; - case SPCC::CPCC_023: return "023"; - case SPCC::CPCC_01: return "01"; - case SPCC::CPCC_013: return "013"; - case SPCC::CPCC_012: return "012"; - } - llvm_unreachable("Invalid cond code"); - } - - inline static unsigned HI22(int64_t imm) { - return (unsigned)((imm >> 10) & ((1 << 22)-1)); - } - - inline static unsigned LO10(int64_t imm) { - return (unsigned)(imm & 0x3FF); - } - - inline static unsigned HIX22(int64_t imm) { - return HI22(~imm); - } - - inline static unsigned LOX10(int64_t imm) { - return ~LO10(~imm); - } - -} // end namespace llvm -#endif diff --git a/contrib/llvm/lib/Target/Sparc/Sparc.td b/contrib/llvm/lib/Target/Sparc/Sparc.td deleted file mode 100644 index ca6147edc46b..000000000000 --- a/contrib/llvm/lib/Target/Sparc/Sparc.td +++ /dev/null @@ -1,183 +0,0 @@ -//===-- Sparc.td - Describe the Sparc 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 -// -//===----------------------------------------------------------------------===// -// -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// Target-independent interfaces which we are implementing -//===----------------------------------------------------------------------===// - -include "llvm/Target/Target.td" - -//===----------------------------------------------------------------------===// -// SPARC Subtarget features. -// - -def FeatureSoftMulDiv - : SubtargetFeature<"soft-mul-div", "UseSoftMulDiv", "true", - "Use software emulation for integer multiply and divide">; - -def FeatureNoFSMULD - : SubtargetFeature<"no-fsmuld", "HasNoFSMULD", "true", - "Disable the fsmuld instruction.">; -def FeatureNoFMULS - : SubtargetFeature<"no-fmuls", "HasNoFMULS", "true", - "Disable the fmuls instruction.">; - -def FeatureV9 - : SubtargetFeature<"v9", "IsV9", "true", - "Enable SPARC-V9 instructions">; -def FeatureV8Deprecated - : SubtargetFeature<"deprecated-v8", "V8DeprecatedInsts", "true", - "Enable deprecated V8 instructions in V9 mode">; -def FeatureVIS - : SubtargetFeature<"vis", "IsVIS", "true", - "Enable UltraSPARC Visual Instruction Set extensions">; -def FeatureVIS2 - : SubtargetFeature<"vis2", "IsVIS2", "true", - "Enable Visual Instruction Set extensions II">; -def FeatureVIS3 - : SubtargetFeature<"vis3", "IsVIS3", "true", - "Enable Visual Instruction Set extensions III">; -def FeatureLeon - : SubtargetFeature<"leon", "IsLeon", "true", - "Enable LEON extensions">; -def FeaturePWRPSR - : SubtargetFeature<"leonpwrpsr", "HasPWRPSR", "true", - "Enable the PWRPSR instruction">; - -def FeatureHardQuad - : SubtargetFeature<"hard-quad-float", "HasHardQuad", "true", - "Enable quad-word floating point instructions">; - -def UsePopc : SubtargetFeature<"popc", "UsePopc", "true", - "Use the popc (population count) instruction">; - -def FeatureSoftFloat : SubtargetFeature<"soft-float", "UseSoftFloat", "true", - "Use software emulation for floating point">; - -//==== Features added predmoninantly for LEON subtarget support -include "LeonFeatures.td" - -//===----------------------------------------------------------------------===// -// Register File, Calling Conv, Instruction Descriptions -//===----------------------------------------------------------------------===// - -include "SparcRegisterInfo.td" -include "SparcCallingConv.td" -include "SparcSchedule.td" -include "SparcInstrInfo.td" - -def SparcInstrInfo : InstrInfo; - -def SparcAsmParser : AsmParser { - bit ShouldEmitMatchRegisterName = 0; -} - -//===----------------------------------------------------------------------===// -// SPARC processors supported. -//===----------------------------------------------------------------------===// - -class Proc Features> - : Processor; - -def : Proc<"generic", []>; -def : Proc<"v7", [FeatureSoftMulDiv, FeatureNoFSMULD]>; -def : Proc<"v8", []>; -def : Proc<"supersparc", []>; -def : Proc<"sparclite", []>; -def : Proc<"f934", []>; -def : Proc<"hypersparc", []>; -def : Proc<"sparclite86x", []>; -def : Proc<"sparclet", []>; -def : Proc<"tsc701", []>; -def : Proc<"myriad2", [FeatureLeon, LeonCASA]>; -def : Proc<"myriad2.1", [FeatureLeon, LeonCASA]>; -def : Proc<"myriad2.2", [FeatureLeon, LeonCASA]>; -def : Proc<"myriad2.3", [FeatureLeon, LeonCASA]>; -def : Proc<"ma2100", [FeatureLeon, LeonCASA]>; -def : Proc<"ma2150", [FeatureLeon, LeonCASA]>; -def : Proc<"ma2155", [FeatureLeon, LeonCASA]>; -def : Proc<"ma2450", [FeatureLeon, LeonCASA]>; -def : Proc<"ma2455", [FeatureLeon, LeonCASA]>; -def : Proc<"ma2x5x", [FeatureLeon, LeonCASA]>; -def : Proc<"ma2080", [FeatureLeon, LeonCASA]>; -def : Proc<"ma2085", [FeatureLeon, LeonCASA]>; -def : Proc<"ma2480", [FeatureLeon, LeonCASA]>; -def : Proc<"ma2485", [FeatureLeon, LeonCASA]>; -def : Proc<"ma2x8x", [FeatureLeon, LeonCASA]>; -def : Proc<"v9", [FeatureV9]>; -def : Proc<"ultrasparc", [FeatureV9, FeatureV8Deprecated, FeatureVIS]>; -def : Proc<"ultrasparc3", [FeatureV9, FeatureV8Deprecated, FeatureVIS, - FeatureVIS2]>; -def : Proc<"niagara", [FeatureV9, FeatureV8Deprecated, FeatureVIS, - FeatureVIS2]>; -def : Proc<"niagara2", [FeatureV9, FeatureV8Deprecated, UsePopc, - FeatureVIS, FeatureVIS2]>; -def : Proc<"niagara3", [FeatureV9, FeatureV8Deprecated, UsePopc, - FeatureVIS, FeatureVIS2]>; -def : Proc<"niagara4", [FeatureV9, FeatureV8Deprecated, UsePopc, - FeatureVIS, FeatureVIS2, FeatureVIS3]>; - -// LEON 2 FT generic -def : Processor<"leon2", LEON2Itineraries, - [FeatureLeon]>; - -// LEON 2 FT (AT697E) -// TO DO: Place-holder: Processor specific features will be added *very* soon here. -def : Processor<"at697e", LEON2Itineraries, - [FeatureLeon, InsertNOPLoad]>; - -// LEON 2 FT (AT697F) -// TO DO: Place-holder: Processor specific features will be added *very* soon here. -def : Processor<"at697f", LEON2Itineraries, - [FeatureLeon, InsertNOPLoad]>; - - -// LEON 3 FT generic -def : Processor<"leon3", LEON3Itineraries, - [FeatureLeon, UMACSMACSupport]>; - -// LEON 3 FT (UT699). Provides features for the UT699 processor -// - covers all the erratum fixes for LEON3, but does not support the CASA instruction. -def : Processor<"ut699", LEON3Itineraries, - [FeatureLeon, InsertNOPLoad, FeatureNoFSMULD, FeatureNoFMULS, FixAllFDIVSQRT]>; - -// LEON3 FT (GR712RC). Provides features for the GR712RC processor. -// - covers all the erratum fixed for LEON3 and support for the CASA instruction. -def : Processor<"gr712rc", LEON3Itineraries, - [FeatureLeon, LeonCASA]>; - -// LEON 4 FT generic -def : Processor<"leon4", LEON4Itineraries, - [FeatureLeon, UMACSMACSupport, LeonCASA]>; - -// LEON 4 FT (GR740) -// TO DO: Place-holder: Processor specific features will be added *very* soon here. -def : Processor<"gr740", LEON4Itineraries, - [FeatureLeon, UMACSMACSupport, LeonCASA, LeonCycleCounter, - FeaturePWRPSR]>; - -//===----------------------------------------------------------------------===// -// Declare the target which we are implementing -//===----------------------------------------------------------------------===// - -def SparcAsmWriter : AsmWriter { - string AsmWriterClassName = "InstPrinter"; - int PassSubtarget = 1; - int Variant = 0; -} - -def Sparc : Target { - // Pull in Instruction Info: - let InstructionSet = SparcInstrInfo; - let AssemblyParsers = [SparcAsmParser]; - let AssemblyWriters = [SparcAsmWriter]; - let AllowRegisterRenaming = 1; -} diff --git a/contrib/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp b/contrib/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp deleted file mode 100644 index 4d5cbfbadc9d..000000000000 --- a/contrib/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp +++ /dev/null @@ -1,446 +0,0 @@ -//===-- SparcAsmPrinter.cpp - Sparc LLVM assembly 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 -// -//===----------------------------------------------------------------------===// -// -// This file contains a printer that converts from our internal representation -// of machine-dependent LLVM code to GAS-format SPARC assembly language. -// -//===----------------------------------------------------------------------===// - -#include "MCTargetDesc/SparcInstPrinter.h" -#include "MCTargetDesc/SparcMCExpr.h" -#include "MCTargetDesc/SparcTargetStreamer.h" -#include "Sparc.h" -#include "SparcInstrInfo.h" -#include "SparcTargetMachine.h" -#include "TargetInfo/SparcTargetInfo.h" -#include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/CodeGen/MachineModuleInfoImpls.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" -#include "llvm/IR/Mangler.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCInst.h" -#include "llvm/MC/MCStreamer.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/Support/TargetRegistry.h" -#include "llvm/Support/raw_ostream.h" -using namespace llvm; - -#define DEBUG_TYPE "asm-printer" - -namespace { - class SparcAsmPrinter : public AsmPrinter { - SparcTargetStreamer &getTargetStreamer() { - return static_cast( - *OutStreamer->getTargetStreamer()); - } - public: - explicit SparcAsmPrinter(TargetMachine &TM, - std::unique_ptr Streamer) - : AsmPrinter(TM, std::move(Streamer)) {} - - StringRef getPassName() const override { return "Sparc Assembly Printer"; } - - void printOperand(const MachineInstr *MI, int opNum, raw_ostream &OS); - void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &OS, - const char *Modifier = nullptr); - - void EmitFunctionBodyStart() override; - void EmitInstruction(const MachineInstr *MI) override; - - static const char *getRegisterName(unsigned RegNo) { - return SparcInstPrinter::getRegisterName(RegNo); - } - - bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, - const char *ExtraCode, raw_ostream &O) override; - bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, - const char *ExtraCode, raw_ostream &O) override; - - void LowerGETPCXAndEmitMCInsts(const MachineInstr *MI, - const MCSubtargetInfo &STI); - - }; -} // end of anonymous namespace - -static MCOperand createSparcMCOperand(SparcMCExpr::VariantKind Kind, - MCSymbol *Sym, MCContext &OutContext) { - const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::create(Sym, - OutContext); - const SparcMCExpr *expr = SparcMCExpr::create(Kind, MCSym, OutContext); - return MCOperand::createExpr(expr); - -} -static MCOperand createPCXCallOP(MCSymbol *Label, - MCContext &OutContext) { - return createSparcMCOperand(SparcMCExpr::VK_Sparc_None, Label, OutContext); -} - -static MCOperand createPCXRelExprOp(SparcMCExpr::VariantKind Kind, - MCSymbol *GOTLabel, MCSymbol *StartLabel, - MCSymbol *CurLabel, - MCContext &OutContext) -{ - const MCSymbolRefExpr *GOT = MCSymbolRefExpr::create(GOTLabel, OutContext); - const MCSymbolRefExpr *Start = MCSymbolRefExpr::create(StartLabel, - OutContext); - const MCSymbolRefExpr *Cur = MCSymbolRefExpr::create(CurLabel, - OutContext); - - const MCBinaryExpr *Sub = MCBinaryExpr::createSub(Cur, Start, OutContext); - const MCBinaryExpr *Add = MCBinaryExpr::createAdd(GOT, Sub, OutContext); - const SparcMCExpr *expr = SparcMCExpr::create(Kind, - Add, OutContext); - return MCOperand::createExpr(expr); -} - -static void EmitCall(MCStreamer &OutStreamer, - MCOperand &Callee, - const MCSubtargetInfo &STI) -{ - MCInst CallInst; - CallInst.setOpcode(SP::CALL); - CallInst.addOperand(Callee); - OutStreamer.EmitInstruction(CallInst, STI); -} - -static void EmitSETHI(MCStreamer &OutStreamer, - MCOperand &Imm, MCOperand &RD, - const MCSubtargetInfo &STI) -{ - MCInst SETHIInst; - SETHIInst.setOpcode(SP::SETHIi); - SETHIInst.addOperand(RD); - SETHIInst.addOperand(Imm); - OutStreamer.EmitInstruction(SETHIInst, STI); -} - -static void EmitBinary(MCStreamer &OutStreamer, unsigned Opcode, - MCOperand &RS1, MCOperand &Src2, MCOperand &RD, - const MCSubtargetInfo &STI) -{ - MCInst Inst; - Inst.setOpcode(Opcode); - Inst.addOperand(RD); - Inst.addOperand(RS1); - Inst.addOperand(Src2); - OutStreamer.EmitInstruction(Inst, STI); -} - -static void EmitOR(MCStreamer &OutStreamer, - MCOperand &RS1, MCOperand &Imm, MCOperand &RD, - const MCSubtargetInfo &STI) { - EmitBinary(OutStreamer, SP::ORri, RS1, Imm, RD, STI); -} - -static void EmitADD(MCStreamer &OutStreamer, - MCOperand &RS1, MCOperand &RS2, MCOperand &RD, - const MCSubtargetInfo &STI) { - EmitBinary(OutStreamer, SP::ADDrr, RS1, RS2, RD, STI); -} - -static void EmitSHL(MCStreamer &OutStreamer, - MCOperand &RS1, MCOperand &Imm, MCOperand &RD, - const MCSubtargetInfo &STI) { - EmitBinary(OutStreamer, SP::SLLri, RS1, Imm, RD, STI); -} - - -static void EmitHiLo(MCStreamer &OutStreamer, MCSymbol *GOTSym, - SparcMCExpr::VariantKind HiKind, - SparcMCExpr::VariantKind LoKind, - MCOperand &RD, - MCContext &OutContext, - const MCSubtargetInfo &STI) { - - MCOperand hi = createSparcMCOperand(HiKind, GOTSym, OutContext); - MCOperand lo = createSparcMCOperand(LoKind, GOTSym, OutContext); - EmitSETHI(OutStreamer, hi, RD, STI); - EmitOR(OutStreamer, RD, lo, RD, STI); -} - -void SparcAsmPrinter::LowerGETPCXAndEmitMCInsts(const MachineInstr *MI, - const MCSubtargetInfo &STI) -{ - MCSymbol *GOTLabel = - OutContext.getOrCreateSymbol(Twine("_GLOBAL_OFFSET_TABLE_")); - - const MachineOperand &MO = MI->getOperand(0); - assert(MO.getReg() != SP::O7 && - "%o7 is assigned as destination for getpcx!"); - - MCOperand MCRegOP = MCOperand::createReg(MO.getReg()); - - - if (!isPositionIndependent()) { - // Just load the address of GOT to MCRegOP. - switch(TM.getCodeModel()) { - default: - llvm_unreachable("Unsupported absolute code model"); - case CodeModel::Small: - EmitHiLo(*OutStreamer, GOTLabel, - SparcMCExpr::VK_Sparc_HI, SparcMCExpr::VK_Sparc_LO, - MCRegOP, OutContext, STI); - break; - case CodeModel::Medium: { - EmitHiLo(*OutStreamer, GOTLabel, - SparcMCExpr::VK_Sparc_H44, SparcMCExpr::VK_Sparc_M44, - MCRegOP, OutContext, STI); - MCOperand imm = MCOperand::createExpr(MCConstantExpr::create(12, - OutContext)); - EmitSHL(*OutStreamer, MCRegOP, imm, MCRegOP, STI); - MCOperand lo = createSparcMCOperand(SparcMCExpr::VK_Sparc_L44, - GOTLabel, OutContext); - EmitOR(*OutStreamer, MCRegOP, lo, MCRegOP, STI); - break; - } - case CodeModel::Large: { - EmitHiLo(*OutStreamer, GOTLabel, - SparcMCExpr::VK_Sparc_HH, SparcMCExpr::VK_Sparc_HM, - MCRegOP, OutContext, STI); - MCOperand imm = MCOperand::createExpr(MCConstantExpr::create(32, - OutContext)); - EmitSHL(*OutStreamer, MCRegOP, imm, MCRegOP, STI); - // Use register %o7 to load the lower 32 bits. - MCOperand RegO7 = MCOperand::createReg(SP::O7); - EmitHiLo(*OutStreamer, GOTLabel, - SparcMCExpr::VK_Sparc_HI, SparcMCExpr::VK_Sparc_LO, - RegO7, OutContext, STI); - EmitADD(*OutStreamer, MCRegOP, RegO7, MCRegOP, STI); - } - } - return; - } - - MCSymbol *StartLabel = OutContext.createTempSymbol(); - MCSymbol *EndLabel = OutContext.createTempSymbol(); - MCSymbol *SethiLabel = OutContext.createTempSymbol(); - - MCOperand RegO7 = MCOperand::createReg(SP::O7); - - // : - // call - // : - // sethi %hi(_GLOBAL_OFFSET_TABLE_+(-)), - // : - // or , %lo(_GLOBAL_OFFSET_TABLE_+(-))), - // add , %o7, - - OutStreamer->EmitLabel(StartLabel); - MCOperand Callee = createPCXCallOP(EndLabel, OutContext); - EmitCall(*OutStreamer, Callee, STI); - OutStreamer->EmitLabel(SethiLabel); - MCOperand hiImm = createPCXRelExprOp(SparcMCExpr::VK_Sparc_PC22, - GOTLabel, StartLabel, SethiLabel, - OutContext); - EmitSETHI(*OutStreamer, hiImm, MCRegOP, STI); - OutStreamer->EmitLabel(EndLabel); - MCOperand loImm = createPCXRelExprOp(SparcMCExpr::VK_Sparc_PC10, - GOTLabel, StartLabel, EndLabel, - OutContext); - EmitOR(*OutStreamer, MCRegOP, loImm, MCRegOP, STI); - EmitADD(*OutStreamer, MCRegOP, RegO7, MCRegOP, STI); -} - -void SparcAsmPrinter::EmitInstruction(const MachineInstr *MI) -{ - - switch (MI->getOpcode()) { - default: break; - case TargetOpcode::DBG_VALUE: - // FIXME: Debug Value. - return; - case SP::GETPCX: - LowerGETPCXAndEmitMCInsts(MI, getSubtargetInfo()); - return; - } - MachineBasicBlock::const_instr_iterator I = MI->getIterator(); - MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end(); - do { - MCInst TmpInst; - LowerSparcMachineInstrToMCInst(&*I, TmpInst, *this); - EmitToStreamer(*OutStreamer, TmpInst); - } while ((++I != E) && I->isInsideBundle()); // Delay slot check. -} - -void SparcAsmPrinter::EmitFunctionBodyStart() { - if (!MF->getSubtarget().is64Bit()) - return; - - const MachineRegisterInfo &MRI = MF->getRegInfo(); - const unsigned globalRegs[] = { SP::G2, SP::G3, SP::G6, SP::G7, 0 }; - for (unsigned i = 0; globalRegs[i] != 0; ++i) { - unsigned reg = globalRegs[i]; - if (MRI.use_empty(reg)) - continue; - - if (reg == SP::G6 || reg == SP::G7) - getTargetStreamer().emitSparcRegisterIgnore(reg); - else - getTargetStreamer().emitSparcRegisterScratch(reg); - } -} - -void SparcAsmPrinter::printOperand(const MachineInstr *MI, int opNum, - raw_ostream &O) { - const DataLayout &DL = getDataLayout(); - const MachineOperand &MO = MI->getOperand (opNum); - SparcMCExpr::VariantKind TF = (SparcMCExpr::VariantKind) MO.getTargetFlags(); - -#ifndef NDEBUG - // Verify the target flags. - if (MO.isGlobal() || MO.isSymbol() || MO.isCPI()) { - if (MI->getOpcode() == SP::CALL) - assert(TF == SparcMCExpr::VK_Sparc_None && - "Cannot handle target flags on call address"); - else if (MI->getOpcode() == SP::SETHIi || MI->getOpcode() == SP::SETHIXi) - assert((TF == SparcMCExpr::VK_Sparc_HI - || TF == SparcMCExpr::VK_Sparc_H44 - || TF == SparcMCExpr::VK_Sparc_HH - || TF == SparcMCExpr::VK_Sparc_TLS_GD_HI22 - || TF == SparcMCExpr::VK_Sparc_TLS_LDM_HI22 - || TF == SparcMCExpr::VK_Sparc_TLS_LDO_HIX22 - || TF == SparcMCExpr::VK_Sparc_TLS_IE_HI22 - || TF == SparcMCExpr::VK_Sparc_TLS_LE_HIX22) && - "Invalid target flags for address operand on sethi"); - else if (MI->getOpcode() == SP::TLS_CALL) - assert((TF == SparcMCExpr::VK_Sparc_None - || TF == SparcMCExpr::VK_Sparc_TLS_GD_CALL - || TF == SparcMCExpr::VK_Sparc_TLS_LDM_CALL) && - "Cannot handle target flags on tls call address"); - else if (MI->getOpcode() == SP::TLS_ADDrr) - assert((TF == SparcMCExpr::VK_Sparc_TLS_GD_ADD - || TF == SparcMCExpr::VK_Sparc_TLS_LDM_ADD - || TF == SparcMCExpr::VK_Sparc_TLS_LDO_ADD - || TF == SparcMCExpr::VK_Sparc_TLS_IE_ADD) && - "Cannot handle target flags on add for TLS"); - else if (MI->getOpcode() == SP::TLS_LDrr) - assert(TF == SparcMCExpr::VK_Sparc_TLS_IE_LD && - "Cannot handle target flags on ld for TLS"); - else if (MI->getOpcode() == SP::TLS_LDXrr) - assert(TF == SparcMCExpr::VK_Sparc_TLS_IE_LDX && - "Cannot handle target flags on ldx for TLS"); - else if (MI->getOpcode() == SP::XORri || MI->getOpcode() == SP::XORXri) - assert((TF == SparcMCExpr::VK_Sparc_TLS_LDO_LOX10 - || TF == SparcMCExpr::VK_Sparc_TLS_LE_LOX10) && - "Cannot handle target flags on xor for TLS"); - else - assert((TF == SparcMCExpr::VK_Sparc_LO - || TF == SparcMCExpr::VK_Sparc_M44 - || TF == SparcMCExpr::VK_Sparc_L44 - || TF == SparcMCExpr::VK_Sparc_HM - || TF == SparcMCExpr::VK_Sparc_TLS_GD_LO10 - || TF == SparcMCExpr::VK_Sparc_TLS_LDM_LO10 - || TF == SparcMCExpr::VK_Sparc_TLS_IE_LO10 ) && - "Invalid target flags for small address operand"); - } -#endif - - - bool CloseParen = SparcMCExpr::printVariantKind(O, TF); - - switch (MO.getType()) { - case MachineOperand::MO_Register: - O << "%" << StringRef(getRegisterName(MO.getReg())).lower(); - break; - - case MachineOperand::MO_Immediate: - O << (int)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: - O << GetBlockAddressSymbol(MO.getBlockAddress())->getName(); - break; - case MachineOperand::MO_ExternalSymbol: - O << MO.getSymbolName(); - break; - case MachineOperand::MO_ConstantPoolIndex: - O << DL.getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_" - << MO.getIndex(); - break; - case MachineOperand::MO_Metadata: - MO.getMetadata()->printAsOperand(O, MMI->getModule()); - break; - default: - llvm_unreachable(""); - } - if (CloseParen) O << ")"; -} - -void SparcAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum, - raw_ostream &O, const char *Modifier) { - printOperand(MI, opNum, O); - - // If this is an ADD operand, emit it like normal operands. - if (Modifier && !strcmp(Modifier, "arith")) { - O << ", "; - printOperand(MI, opNum+1, O); - return; - } - - if (MI->getOperand(opNum+1).isReg() && - MI->getOperand(opNum+1).getReg() == SP::G0) - return; // don't print "+%g0" - if (MI->getOperand(opNum+1).isImm() && - MI->getOperand(opNum+1).getImm() == 0) - return; // don't print "+0" - - O << "+"; - printOperand(MI, opNum+1, O); -} - -/// PrintAsmOperand - Print out an operand for an inline asm expression. -/// -bool SparcAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, - const char *ExtraCode, - raw_ostream &O) { - if (ExtraCode && ExtraCode[0]) { - if (ExtraCode[1] != 0) return true; // Unknown modifier. - - switch (ExtraCode[0]) { - default: - // See if this is a generic print operand - return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O); - case 'f': - case 'r': - break; - } - } - - printOperand(MI, OpNo, O); - - return false; -} - -bool SparcAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, - unsigned OpNo, - const char *ExtraCode, - raw_ostream &O) { - if (ExtraCode && ExtraCode[0]) - return true; // Unknown modifier - - O << '['; - printMemOperand(MI, OpNo, O); - O << ']'; - - return false; -} - -// Force static initialization. -extern "C" void LLVMInitializeSparcAsmPrinter() { - RegisterAsmPrinter X(getTheSparcTarget()); - RegisterAsmPrinter Y(getTheSparcV9Target()); - RegisterAsmPrinter Z(getTheSparcelTarget()); -} diff --git a/contrib/llvm/lib/Target/Sparc/SparcCallingConv.td b/contrib/llvm/lib/Target/Sparc/SparcCallingConv.td deleted file mode 100644 index 4be432211f1d..000000000000 --- a/contrib/llvm/lib/Target/Sparc/SparcCallingConv.td +++ /dev/null @@ -1,143 +0,0 @@ -//===-- SparcCallingConv.td - Calling Conventions Sparc ----*- 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 the Sparc architectures. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// SPARC v8 32-bit. -//===----------------------------------------------------------------------===// - -def CC_Sparc32 : CallingConv<[ - // Custom assign SRet to [sp+64]. - CCIfSRet>, - // i32 f32 arguments get passed in integer registers if there is space. - CCIfType<[i32, f32], CCAssignToReg<[I0, I1, I2, I3, I4, I5]>>, - // f64 arguments are split and passed through registers or through stack. - CCIfType<[f64], CCCustom<"CC_Sparc_Assign_Split_64">>, - // As are v2i32 arguments (this would be the default behavior for - // v2i32 if it wasn't allocated to the IntPair register-class) - CCIfType<[v2i32], CCCustom<"CC_Sparc_Assign_Split_64">>, - - - // Alternatively, they are assigned to the stack in 4-byte aligned units. - CCAssignToStack<4, 4> -]>; - -def RetCC_Sparc32 : CallingConv<[ - CCIfType<[i32], CCAssignToReg<[I0, I1, I2, I3, I4, I5]>>, - CCIfType<[f32], CCAssignToReg<[F0, F1, F2, F3]>>, - CCIfType<[f64], CCAssignToReg<[D0, D1]>>, - CCIfType<[v2i32], CCCustom<"CC_Sparc_Assign_Ret_Split_64">> -]>; - - -//===----------------------------------------------------------------------===// -// SPARC v9 64-bit. -//===----------------------------------------------------------------------===// -// -// The 64-bit ABI conceptually assigns all function arguments to a parameter -// array starting at [%fp+BIAS+128] in the callee's stack frame. All arguments -// occupy a multiple of 8 bytes in the array. Integer arguments are extended to -// 64 bits by the caller. Floats are right-aligned in their 8-byte slot, the -// first 4 bytes in the slot are undefined. -// -// The integer registers %i0 to %i5 shadow the first 48 bytes of the parameter -// array at fixed offsets. Integer arguments are promoted to registers when -// possible. -// -// The floating point registers %f0 to %f31 shadow the first 128 bytes of the -// parameter array at fixed offsets. Float and double parameters are promoted -// to these registers when possible. -// -// Structs up to 16 bytes in size are passed by value. They are right-aligned -// in one or two 8-byte slots in the parameter array. Struct members are -// promoted to both floating point and integer registers when possible. A -// struct containing two floats would thus be passed in %f0 and %f1, while two -// float function arguments would occupy 8 bytes each, and be passed in %f1 and -// %f3. -// -// When a struct { int, float } is passed by value, the int goes in the high -// bits of an integer register while the float goes in a floating point -// register. -// -// The difference is encoded in LLVM IR using the inreg atttribute on function -// arguments: -// -// C: void f(float, float); -// IR: declare void f(float %f1, float %f3) -// -// C: void f(struct { float f0, f1; }); -// IR: declare void f(float inreg %f0, float inreg %f1) -// -// C: void f(int, float); -// IR: declare void f(int signext %i0, float %f3) -// -// C: void f(struct { int i0high; float f1; }); -// IR: declare void f(i32 inreg %i0high, float inreg %f1) -// -// Two ints in a struct are simply coerced to i64: -// -// C: void f(struct { int i0high, i0low; }); -// IR: declare void f(i64 %i0.coerced) -// -// The frontend and backend divide the task of producing ABI compliant code for -// C functions. The C frontend will: -// -// - Annotate integer arguments with zeroext or signext attributes. -// -// - Split structs into one or two 64-bit sized chunks, or 32-bit chunks with -// inreg attributes. -// -// - Pass structs larger than 16 bytes indirectly with an explicit pointer -// argument. The byval attribute is not used. -// -// The backend will: -// -// - Assign all arguments to 64-bit aligned stack slots, 32-bits for inreg. -// -// - Promote to integer or floating point registers depending on type. -// -// Function return values are passed exactly like function arguments, except a -// struct up to 32 bytes in size can be returned in registers. - -// Function arguments AND most return values. -def CC_Sparc64 : CallingConv<[ - // The frontend uses the inreg flag to indicate i32 and float arguments from - // structs. These arguments are not promoted to 64 bits, but they can still - // be assigned to integer and float registers. - CCIfInReg>>, - - // All integers are promoted to i64 by the caller. - CCIfType<[i32], CCPromoteToType>, - - // Custom assignment is required because stack space is reserved for all - // arguments whether they are passed in registers or not. - CCCustom<"CC_Sparc64_Full"> -]>; - -def RetCC_Sparc64 : CallingConv<[ - // A single f32 return value always goes in %f0. The ABI doesn't specify what - // happens to multiple f32 return values outside a struct. - CCIfType<[f32], CCCustom<"CC_Sparc64_Half">>, - - // Otherwise, return values are passed exactly like arguments. - CCDelegateTo -]>; - -// Callee-saved registers are handled by the register window mechanism. -def CSR : CalleeSavedRegs<(add)> { - let OtherPreserved = (add (sequence "I%u", 0, 7), - (sequence "L%u", 0, 7)); -} - -// Callee-saved registers for calls with ReturnsTwice attribute. -def RTCSR : CalleeSavedRegs<(add)> { - let OtherPreserved = (add I6, I7); -} diff --git a/contrib/llvm/lib/Target/Sparc/SparcFrameLowering.cpp b/contrib/llvm/lib/Target/Sparc/SparcFrameLowering.cpp deleted file mode 100644 index 1834a6fd861d..000000000000 --- a/contrib/llvm/lib/Target/Sparc/SparcFrameLowering.cpp +++ /dev/null @@ -1,385 +0,0 @@ -//===-- SparcFrameLowering.cpp - Sparc 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 Sparc implementation of TargetFrameLowering class. -// -//===----------------------------------------------------------------------===// - -#include "SparcFrameLowering.h" -#include "SparcInstrInfo.h" -#include "SparcMachineFunctionInfo.h" -#include "SparcSubtarget.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/Support/CommandLine.h" -#include "llvm/Target/TargetOptions.h" - -using namespace llvm; - -static cl::opt -DisableLeafProc("disable-sparc-leaf-proc", - cl::init(false), - cl::desc("Disable Sparc leaf procedure optimization."), - cl::Hidden); - -SparcFrameLowering::SparcFrameLowering(const SparcSubtarget &ST) - : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, - ST.is64Bit() ? 16 : 8, 0, ST.is64Bit() ? 16 : 8) {} - -void SparcFrameLowering::emitSPAdjustment(MachineFunction &MF, - MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI, - int NumBytes, - unsigned ADDrr, - unsigned ADDri) const { - - DebugLoc dl; - const SparcInstrInfo &TII = - *static_cast(MF.getSubtarget().getInstrInfo()); - - if (NumBytes >= -4096 && NumBytes < 4096) { - BuildMI(MBB, MBBI, dl, TII.get(ADDri), SP::O6) - .addReg(SP::O6).addImm(NumBytes); - return; - } - - // Emit this the hard way. This clobbers G1 which we always know is - // available here. - if (NumBytes >= 0) { - // Emit nonnegative numbers with sethi + or. - // sethi %hi(NumBytes), %g1 - // or %g1, %lo(NumBytes), %g1 - // add %sp, %g1, %sp - BuildMI(MBB, MBBI, dl, TII.get(SP::SETHIi), SP::G1) - .addImm(HI22(NumBytes)); - BuildMI(MBB, MBBI, dl, TII.get(SP::ORri), SP::G1) - .addReg(SP::G1).addImm(LO10(NumBytes)); - BuildMI(MBB, MBBI, dl, TII.get(ADDrr), SP::O6) - .addReg(SP::O6).addReg(SP::G1); - return ; - } - - // Emit negative numbers with sethi + xor. - // sethi %hix(NumBytes), %g1 - // xor %g1, %lox(NumBytes), %g1 - // add %sp, %g1, %sp - BuildMI(MBB, MBBI, dl, TII.get(SP::SETHIi), SP::G1) - .addImm(HIX22(NumBytes)); - BuildMI(MBB, MBBI, dl, TII.get(SP::XORri), SP::G1) - .addReg(SP::G1).addImm(LOX10(NumBytes)); - BuildMI(MBB, MBBI, dl, TII.get(ADDrr), SP::O6) - .addReg(SP::O6).addReg(SP::G1); -} - -void SparcFrameLowering::emitPrologue(MachineFunction &MF, - MachineBasicBlock &MBB) const { - SparcMachineFunctionInfo *FuncInfo = MF.getInfo(); - - assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported"); - MachineFrameInfo &MFI = MF.getFrameInfo(); - const SparcSubtarget &Subtarget = MF.getSubtarget(); - const SparcInstrInfo &TII = - *static_cast(Subtarget.getInstrInfo()); - const SparcRegisterInfo &RegInfo = - *static_cast(Subtarget.getRegisterInfo()); - 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; - bool NeedsStackRealignment = RegInfo.needsStackRealignment(MF); - - // FIXME: unfortunately, returning false from canRealignStack - // actually just causes needsStackRealignment to return false, - // rather than reporting an error, as would be sensible. This is - // poor, but fixing that bogosity is going to be a large project. - // For now, just see if it's lied, and report an error here. - if (!NeedsStackRealignment && MFI.getMaxAlignment() > getStackAlignment()) - report_fatal_error("Function \"" + Twine(MF.getName()) + "\" required " - "stack re-alignment, but LLVM couldn't handle it " - "(probably because it has a dynamic alloca)."); - - // Get the number of bytes to allocate from the FrameInfo - int NumBytes = (int) MFI.getStackSize(); - - unsigned SAVEri = SP::SAVEri; - unsigned SAVErr = SP::SAVErr; - if (FuncInfo->isLeafProc()) { - if (NumBytes == 0) - return; - SAVEri = SP::ADDri; - SAVErr = SP::ADDrr; - } - - // The SPARC ABI is a bit odd in that it requires a reserved 92-byte - // (128 in v9) area in the user's stack, starting at %sp. Thus, the - // first part of the stack that can actually be used is located at - // %sp + 92. - // - // We therefore need to add that offset to the total stack size - // after all the stack objects are placed by - // PrologEpilogInserter calculateFrameObjectOffsets. However, since the stack needs to be - // aligned *after* the extra size is added, we need to disable - // calculateFrameObjectOffsets's built-in stack alignment, by having - // targetHandlesStackFrameRounding return true. - - - // Add the extra call frame stack size, if needed. (This is the same - // code as in PrologEpilogInserter, but also gets disabled by - // targetHandlesStackFrameRounding) - if (MFI.adjustsStack() && hasReservedCallFrame(MF)) - NumBytes += MFI.getMaxCallFrameSize(); - - // Adds the SPARC subtarget-specific spill area to the stack - // size. Also ensures target-required alignment. - NumBytes = Subtarget.getAdjustedFrameSize(NumBytes); - - // Finally, ensure that the size is sufficiently aligned for the - // data on the stack. - if (MFI.getMaxAlignment() > 0) { - NumBytes = alignTo(NumBytes, MFI.getMaxAlignment()); - } - - // Update stack size with corrected value. - MFI.setStackSize(NumBytes); - - emitSPAdjustment(MF, MBB, MBBI, -NumBytes, SAVErr, SAVEri); - - unsigned regFP = RegInfo.getDwarfRegNum(SP::I6, true); - - // Emit ".cfi_def_cfa_register 30". - unsigned CFIIndex = - MF.addFrameInst(MCCFIInstruction::createDefCfaRegister(nullptr, regFP)); - BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) - .addCFIIndex(CFIIndex); - - // Emit ".cfi_window_save". - CFIIndex = MF.addFrameInst(MCCFIInstruction::createWindowSave(nullptr)); - BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) - .addCFIIndex(CFIIndex); - - unsigned regInRA = RegInfo.getDwarfRegNum(SP::I7, true); - unsigned regOutRA = RegInfo.getDwarfRegNum(SP::O7, true); - // Emit ".cfi_register 15, 31". - CFIIndex = MF.addFrameInst( - MCCFIInstruction::createRegister(nullptr, regOutRA, regInRA)); - BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) - .addCFIIndex(CFIIndex); - - if (NeedsStackRealignment) { - int64_t Bias = Subtarget.getStackPointerBias(); - unsigned regUnbiased; - if (Bias) { - // This clobbers G1 which we always know is available here. - regUnbiased = SP::G1; - // add %o6, BIAS, %g1 - BuildMI(MBB, MBBI, dl, TII.get(SP::ADDri), regUnbiased) - .addReg(SP::O6).addImm(Bias); - } else - regUnbiased = SP::O6; - - // andn %regUnbiased, MaxAlign-1, %regUnbiased - int MaxAlign = MFI.getMaxAlignment(); - BuildMI(MBB, MBBI, dl, TII.get(SP::ANDNri), regUnbiased) - .addReg(regUnbiased).addImm(MaxAlign - 1); - - if (Bias) { - // add %g1, -BIAS, %o6 - BuildMI(MBB, MBBI, dl, TII.get(SP::ADDri), SP::O6) - .addReg(regUnbiased).addImm(-Bias); - } - } -} - -MachineBasicBlock::iterator SparcFrameLowering:: -eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, - MachineBasicBlock::iterator I) const { - if (!hasReservedCallFrame(MF)) { - MachineInstr &MI = *I; - int Size = MI.getOperand(0).getImm(); - if (MI.getOpcode() == SP::ADJCALLSTACKDOWN) - Size = -Size; - - if (Size) - emitSPAdjustment(MF, MBB, I, Size, SP::ADDrr, SP::ADDri); - } - return MBB.erase(I); -} - - -void SparcFrameLowering::emitEpilogue(MachineFunction &MF, - MachineBasicBlock &MBB) const { - SparcMachineFunctionInfo *FuncInfo = MF.getInfo(); - MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); - const SparcInstrInfo &TII = - *static_cast(MF.getSubtarget().getInstrInfo()); - DebugLoc dl = MBBI->getDebugLoc(); - assert(MBBI->getOpcode() == SP::RETL && - "Can only put epilog before 'retl' instruction!"); - if (!FuncInfo->isLeafProc()) { - BuildMI(MBB, MBBI, dl, TII.get(SP::RESTORErr), SP::G0).addReg(SP::G0) - .addReg(SP::G0); - return; - } - MachineFrameInfo &MFI = MF.getFrameInfo(); - - int NumBytes = (int) MFI.getStackSize(); - if (NumBytes == 0) - return; - - emitSPAdjustment(MF, MBB, MBBI, NumBytes, SP::ADDrr, SP::ADDri); -} - -bool SparcFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const { - // Reserve call frame if there are no variable sized objects on the stack. - return !MF.getFrameInfo().hasVarSizedObjects(); -} - -// hasFP - Return true if the specified function should have a dedicated frame -// pointer register. This is true if the function has variable sized allocas or -// if frame pointer elimination is disabled. -bool SparcFrameLowering::hasFP(const MachineFunction &MF) const { - const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo(); - - const MachineFrameInfo &MFI = MF.getFrameInfo(); - return MF.getTarget().Options.DisableFramePointerElim(MF) || - RegInfo->needsStackRealignment(MF) || - MFI.hasVarSizedObjects() || - MFI.isFrameAddressTaken(); -} - - -int SparcFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI, - unsigned &FrameReg) const { - const SparcSubtarget &Subtarget = MF.getSubtarget(); - const MachineFrameInfo &MFI = MF.getFrameInfo(); - const SparcRegisterInfo *RegInfo = Subtarget.getRegisterInfo(); - const SparcMachineFunctionInfo *FuncInfo = MF.getInfo(); - bool isFixed = MFI.isFixedObjectIndex(FI); - - // Addressable stack objects are accessed using neg. offsets from - // %fp, or positive offsets from %sp. - bool UseFP; - - // Sparc uses FP-based references in general, even when "hasFP" is - // false. That function is rather a misnomer, because %fp is - // actually always available, unless isLeafProc. - if (FuncInfo->isLeafProc()) { - // If there's a leaf proc, all offsets need to be %sp-based, - // because we haven't caused %fp to actually point to our frame. - UseFP = false; - } else if (isFixed) { - // Otherwise, argument access should always use %fp. - UseFP = true; - } else if (RegInfo->needsStackRealignment(MF)) { - // If there is dynamic stack realignment, all local object - // references need to be via %sp, to take account of the - // re-alignment. - UseFP = false; - } else { - // Finally, default to using %fp. - UseFP = true; - } - - int64_t FrameOffset = MF.getFrameInfo().getObjectOffset(FI) + - Subtarget.getStackPointerBias(); - - if (UseFP) { - FrameReg = RegInfo->getFrameRegister(MF); - return FrameOffset; - } else { - FrameReg = SP::O6; // %sp - return FrameOffset + MF.getFrameInfo().getStackSize(); - } -} - -static bool LLVM_ATTRIBUTE_UNUSED verifyLeafProcRegUse(MachineRegisterInfo *MRI) -{ - - for (unsigned reg = SP::I0; reg <= SP::I7; ++reg) - if (MRI->isPhysRegUsed(reg)) - return false; - - for (unsigned reg = SP::L0; reg <= SP::L7; ++reg) - if (MRI->isPhysRegUsed(reg)) - return false; - - return true; -} - -bool SparcFrameLowering::isLeafProc(MachineFunction &MF) const -{ - - MachineRegisterInfo &MRI = MF.getRegInfo(); - MachineFrameInfo &MFI = MF.getFrameInfo(); - - return !(MFI.hasCalls() // has calls - || MRI.isPhysRegUsed(SP::L0) // Too many registers needed - || MRI.isPhysRegUsed(SP::O6) // %sp is used - || hasFP(MF)); // need %fp -} - -void SparcFrameLowering::remapRegsForLeafProc(MachineFunction &MF) const { - MachineRegisterInfo &MRI = MF.getRegInfo(); - // Remap %i[0-7] to %o[0-7]. - for (unsigned reg = SP::I0; reg <= SP::I7; ++reg) { - if (!MRI.isPhysRegUsed(reg)) - continue; - - unsigned mapped_reg = reg - SP::I0 + SP::O0; - - // Replace I register with O register. - MRI.replaceRegWith(reg, mapped_reg); - - // Also replace register pair super-registers. - if ((reg - SP::I0) % 2 == 0) { - unsigned preg = (reg - SP::I0) / 2 + SP::I0_I1; - unsigned mapped_preg = preg - SP::I0_I1 + SP::O0_O1; - MRI.replaceRegWith(preg, mapped_preg); - } - } - - // Rewrite MBB's Live-ins. - for (MachineFunction::iterator MBB = MF.begin(), E = MF.end(); - MBB != E; ++MBB) { - for (unsigned reg = SP::I0_I1; reg <= SP::I6_I7; ++reg) { - if (!MBB->isLiveIn(reg)) - continue; - MBB->removeLiveIn(reg); - MBB->addLiveIn(reg - SP::I0_I1 + SP::O0_O1); - } - for (unsigned reg = SP::I0; reg <= SP::I7; ++reg) { - if (!MBB->isLiveIn(reg)) - continue; - MBB->removeLiveIn(reg); - MBB->addLiveIn(reg - SP::I0 + SP::O0); - } - } - - assert(verifyLeafProcRegUse(&MRI)); -#ifdef EXPENSIVE_CHECKS - MF.verify(0, "After LeafProc Remapping"); -#endif -} - -void SparcFrameLowering::determineCalleeSaves(MachineFunction &MF, - BitVector &SavedRegs, - RegScavenger *RS) const { - TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); - if (!DisableLeafProc && isLeafProc(MF)) { - SparcMachineFunctionInfo *MFI = MF.getInfo(); - MFI->setLeafProc(true); - - remapRegsForLeafProc(MF); - } - -} diff --git a/contrib/llvm/lib/Target/Sparc/SparcFrameLowering.h b/contrib/llvm/lib/Target/Sparc/SparcFrameLowering.h deleted file mode 100644 index 8e6001da05db..000000000000 --- a/contrib/llvm/lib/Target/Sparc/SparcFrameLowering.h +++ /dev/null @@ -1,67 +0,0 @@ -//===-- SparcFrameLowering.h - Define frame lowering for Sparc --*- 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_SPARC_SPARCFRAMELOWERING_H -#define LLVM_LIB_TARGET_SPARC_SPARCFRAMELOWERING_H - -#include "Sparc.h" -#include "llvm/CodeGen/TargetFrameLowering.h" - -namespace llvm { - -class SparcSubtarget; -class SparcFrameLowering : public TargetFrameLowering { -public: - explicit SparcFrameLowering(const SparcSubtarget &ST); - - /// 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; - - MachineBasicBlock::iterator - eliminateCallFramePseudoInstr(MachineFunction &MF, - MachineBasicBlock &MBB, - MachineBasicBlock::iterator I) const override; - - bool hasReservedCallFrame(const MachineFunction &MF) const override; - bool hasFP(const MachineFunction &MF) const override; - void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, - RegScavenger *RS = nullptr) const override; - - int getFrameIndexReference(const MachineFunction &MF, int FI, - unsigned &FrameReg) const override; - - /// targetHandlesStackFrameRounding - Returns true if the target is - /// responsible for rounding up the stack frame (probably at emitPrologue - /// time). - bool targetHandlesStackFrameRounding() const override { return true; } - -private: - // Remap input registers to output registers for leaf procedure. - void remapRegsForLeafProc(MachineFunction &MF) const; - - // Returns true if MF is a leaf procedure. - bool isLeafProc(MachineFunction &MF) const; - - - // Emits code for adjusting SP in function prologue/epilogue. - void emitSPAdjustment(MachineFunction &MF, - MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI, - int NumBytes, unsigned ADDrr, unsigned ADDri) const; - -}; - -} // End llvm namespace - -#endif diff --git a/contrib/llvm/lib/Target/Sparc/SparcISelDAGToDAG.cpp b/contrib/llvm/lib/Target/Sparc/SparcISelDAGToDAG.cpp deleted file mode 100644 index 8cff50d19ed4..000000000000 --- a/contrib/llvm/lib/Target/Sparc/SparcISelDAGToDAG.cpp +++ /dev/null @@ -1,401 +0,0 @@ -//===-- SparcISelDAGToDAG.cpp - A dag to dag inst selector for Sparc ------===// -// -// Part of the LLVM Project, under the Apache 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 SPARC target. -// -//===----------------------------------------------------------------------===// - -#include "SparcTargetMachine.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/SelectionDAGISel.h" -#include "llvm/IR/Intrinsics.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" -using namespace llvm; - -//===----------------------------------------------------------------------===// -// Instruction Selector Implementation -//===----------------------------------------------------------------------===// - -//===--------------------------------------------------------------------===// -/// SparcDAGToDAGISel - SPARC specific code to select SPARC machine -/// instructions for SelectionDAG operations. -/// -namespace { -class SparcDAGToDAGISel : public SelectionDAGISel { - /// Subtarget - Keep a pointer to the Sparc Subtarget around so that we can - /// make the right decision when generating code for different targets. - const SparcSubtarget *Subtarget; -public: - explicit SparcDAGToDAGISel(SparcTargetMachine &tm) : SelectionDAGISel(tm) {} - - bool runOnMachineFunction(MachineFunction &MF) override { - Subtarget = &MF.getSubtarget(); - return SelectionDAGISel::runOnMachineFunction(MF); - } - - void Select(SDNode *N) override; - - // Complex Pattern Selectors. - bool SelectADDRrr(SDValue N, SDValue &R1, SDValue &R2); - bool SelectADDRri(SDValue N, SDValue &Base, SDValue &Offset); - - /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for - /// inline asm expressions. - bool SelectInlineAsmMemoryOperand(const SDValue &Op, - unsigned ConstraintID, - std::vector &OutOps) override; - - StringRef getPassName() const override { - return "SPARC DAG->DAG Pattern Instruction Selection"; - } - - // Include the pieces autogenerated from the target description. -#include "SparcGenDAGISel.inc" - -private: - SDNode* getGlobalBaseReg(); - bool tryInlineAsm(SDNode *N); -}; -} // end anonymous namespace - -SDNode* SparcDAGToDAGISel::getGlobalBaseReg() { - unsigned GlobalBaseReg = Subtarget->getInstrInfo()->getGlobalBaseReg(MF); - return CurDAG->getRegister(GlobalBaseReg, - TLI->getPointerTy(CurDAG->getDataLayout())) - .getNode(); -} - -bool SparcDAGToDAGISel::SelectADDRri(SDValue Addr, - SDValue &Base, SDValue &Offset) { - if (FrameIndexSDNode *FIN = dyn_cast(Addr)) { - Base = CurDAG->getTargetFrameIndex( - FIN->getIndex(), TLI->getPointerTy(CurDAG->getDataLayout())); - Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); - return true; - } - if (Addr.getOpcode() == ISD::TargetExternalSymbol || - Addr.getOpcode() == ISD::TargetGlobalAddress || - Addr.getOpcode() == ISD::TargetGlobalTLSAddress) - return false; // direct calls. - - if (Addr.getOpcode() == ISD::ADD) { - if (ConstantSDNode *CN = dyn_cast(Addr.getOperand(1))) { - if (isInt<13>(CN->getSExtValue())) { - if (FrameIndexSDNode *FIN = - dyn_cast(Addr.getOperand(0))) { - // Constant offset from frame ref. - Base = CurDAG->getTargetFrameIndex( - FIN->getIndex(), TLI->getPointerTy(CurDAG->getDataLayout())); - } else { - Base = Addr.getOperand(0); - } - Offset = CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), - MVT::i32); - return true; - } - } - if (Addr.getOperand(0).getOpcode() == SPISD::Lo) { - Base = Addr.getOperand(1); - Offset = Addr.getOperand(0).getOperand(0); - return true; - } - if (Addr.getOperand(1).getOpcode() == SPISD::Lo) { - Base = Addr.getOperand(0); - Offset = Addr.getOperand(1).getOperand(0); - return true; - } - } - Base = Addr; - Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); - return true; -} - -bool SparcDAGToDAGISel::SelectADDRrr(SDValue Addr, SDValue &R1, SDValue &R2) { - if (Addr.getOpcode() == ISD::FrameIndex) return false; - if (Addr.getOpcode() == ISD::TargetExternalSymbol || - Addr.getOpcode() == ISD::TargetGlobalAddress || - Addr.getOpcode() == ISD::TargetGlobalTLSAddress) - return false; // direct calls. - - if (Addr.getOpcode() == ISD::ADD) { - if (ConstantSDNode *CN = dyn_cast(Addr.getOperand(1))) - if (isInt<13>(CN->getSExtValue())) - return false; // Let the reg+imm pattern catch this! - if (Addr.getOperand(0).getOpcode() == SPISD::Lo || - Addr.getOperand(1).getOpcode() == SPISD::Lo) - return false; // Let the reg+imm pattern catch this! - R1 = Addr.getOperand(0); - R2 = Addr.getOperand(1); - return true; - } - - R1 = Addr; - R2 = CurDAG->getRegister(SP::G0, TLI->getPointerTy(CurDAG->getDataLayout())); - return true; -} - - -// Re-assemble i64 arguments split up in SelectionDAGBuilder's -// visitInlineAsm / GetRegistersForValue functions. -// -// Note: This function was copied from, and is essentially identical -// to ARMISelDAGToDAG::SelectInlineAsm. It is very unfortunate that -// such hacking-up is necessary; a rethink of how inline asm operands -// are handled may be in order to make doing this more sane. -// -// TODO: fix inline asm support so I can simply tell it that 'i64' -// inputs to asm need to be allocated to the IntPair register type, -// and have that work. Then, delete this function. -bool SparcDAGToDAGISel::tryInlineAsm(SDNode *N){ - std::vector AsmNodeOperands; - unsigned Flag, Kind; - bool Changed = false; - unsigned NumOps = N->getNumOperands(); - - // Normally, i64 data is bounded to two arbitrary GPRs for "%r" - // constraint. However, some instructions (e.g. ldd/std) require - // (even/even+1) GPRs. - - // So, here, we check for this case, and mutate the inlineasm to use - // a single IntPair register instead, which guarantees such even/odd - // placement. - - SDLoc dl(N); - SDValue Glue = N->getGluedNode() ? N->getOperand(NumOps-1) - : SDValue(nullptr,0); - - SmallVector OpChanged; - // Glue node will be appended late. - for(unsigned i = 0, e = N->getGluedNode() ? NumOps - 1 : NumOps; i < e; ++i) { - SDValue op = N->getOperand(i); - AsmNodeOperands.push_back(op); - - if (i < InlineAsm::Op_FirstOperand) - continue; - - if (ConstantSDNode *C = dyn_cast(N->getOperand(i))) { - Flag = C->getZExtValue(); - Kind = InlineAsm::getKind(Flag); - } - else - continue; - - // Immediate operands to inline asm in the SelectionDAG are modeled with - // two operands. The first is a constant of value InlineAsm::Kind_Imm, and - // the second is a constant with the value of the immediate. If we get here - // and we have a Kind_Imm, skip the next operand, and continue. - if (Kind == InlineAsm::Kind_Imm) { - SDValue op = N->getOperand(++i); - AsmNodeOperands.push_back(op); - continue; - } - - unsigned NumRegs = InlineAsm::getNumOperandRegisters(Flag); - if (NumRegs) - OpChanged.push_back(false); - - unsigned DefIdx = 0; - bool IsTiedToChangedOp = false; - // If it's a use that is tied with a previous def, it has no - // reg class constraint. - if (Changed && InlineAsm::isUseOperandTiedToDef(Flag, DefIdx)) - IsTiedToChangedOp = OpChanged[DefIdx]; - - if (Kind != InlineAsm::Kind_RegUse && Kind != InlineAsm::Kind_RegDef - && Kind != InlineAsm::Kind_RegDefEarlyClobber) - continue; - - unsigned RC; - bool HasRC = InlineAsm::hasRegClassConstraint(Flag, RC); - if ((!IsTiedToChangedOp && (!HasRC || RC != SP::IntRegsRegClassID)) - || NumRegs != 2) - continue; - - assert((i+2 < NumOps) && "Invalid number of operands in inline asm"); - SDValue V0 = N->getOperand(i+1); - SDValue V1 = N->getOperand(i+2); - unsigned Reg0 = cast(V0)->getReg(); - unsigned Reg1 = cast(V1)->getReg(); - SDValue PairedReg; - MachineRegisterInfo &MRI = MF->getRegInfo(); - - if (Kind == InlineAsm::Kind_RegDef || - Kind == InlineAsm::Kind_RegDefEarlyClobber) { - // Replace the two GPRs with 1 GPRPair and copy values from GPRPair to - // the original GPRs. - - unsigned GPVR = MRI.createVirtualRegister(&SP::IntPairRegClass); - PairedReg = CurDAG->getRegister(GPVR, MVT::v2i32); - SDValue Chain = SDValue(N,0); - - SDNode *GU = N->getGluedUser(); - SDValue RegCopy = CurDAG->getCopyFromReg(Chain, dl, GPVR, MVT::v2i32, - Chain.getValue(1)); - - // Extract values from a GPRPair reg and copy to the original GPR reg. - SDValue Sub0 = CurDAG->getTargetExtractSubreg(SP::sub_even, dl, MVT::i32, - RegCopy); - SDValue Sub1 = CurDAG->getTargetExtractSubreg(SP::sub_odd, dl, MVT::i32, - RegCopy); - SDValue T0 = CurDAG->getCopyToReg(Sub0, dl, Reg0, Sub0, - RegCopy.getValue(1)); - SDValue T1 = CurDAG->getCopyToReg(Sub1, dl, Reg1, Sub1, T0.getValue(1)); - - // Update the original glue user. - std::vector Ops(GU->op_begin(), GU->op_end()-1); - Ops.push_back(T1.getValue(1)); - CurDAG->UpdateNodeOperands(GU, Ops); - } - else { - // For Kind == InlineAsm::Kind_RegUse, we first copy two GPRs into a - // GPRPair and then pass the GPRPair to the inline asm. - SDValue Chain = AsmNodeOperands[InlineAsm::Op_InputChain]; - - // As REG_SEQ doesn't take RegisterSDNode, we copy them first. - SDValue T0 = CurDAG->getCopyFromReg(Chain, dl, Reg0, MVT::i32, - Chain.getValue(1)); - SDValue T1 = CurDAG->getCopyFromReg(Chain, dl, Reg1, MVT::i32, - T0.getValue(1)); - SDValue Pair = SDValue( - CurDAG->getMachineNode( - TargetOpcode::REG_SEQUENCE, dl, MVT::v2i32, - { - CurDAG->getTargetConstant(SP::IntPairRegClassID, dl, - MVT::i32), - T0, - CurDAG->getTargetConstant(SP::sub_even, dl, MVT::i32), - T1, - CurDAG->getTargetConstant(SP::sub_odd, dl, MVT::i32), - }), - 0); - - // Copy REG_SEQ into a GPRPair-typed VR and replace the original two - // i32 VRs of inline asm with it. - unsigned GPVR = MRI.createVirtualRegister(&SP::IntPairRegClass); - PairedReg = CurDAG->getRegister(GPVR, MVT::v2i32); - Chain = CurDAG->getCopyToReg(T1, dl, GPVR, Pair, T1.getValue(1)); - - AsmNodeOperands[InlineAsm::Op_InputChain] = Chain; - Glue = Chain.getValue(1); - } - - Changed = true; - - if(PairedReg.getNode()) { - OpChanged[OpChanged.size() -1 ] = true; - Flag = InlineAsm::getFlagWord(Kind, 1 /* RegNum*/); - if (IsTiedToChangedOp) - Flag = InlineAsm::getFlagWordForMatchingOp(Flag, DefIdx); - else - Flag = InlineAsm::getFlagWordForRegClass(Flag, SP::IntPairRegClassID); - // Replace the current flag. - AsmNodeOperands[AsmNodeOperands.size() -1] = CurDAG->getTargetConstant( - Flag, dl, MVT::i32); - // Add the new register node and skip the original two GPRs. - AsmNodeOperands.push_back(PairedReg); - // Skip the next two GPRs. - i += 2; - } - } - - if (Glue.getNode()) - AsmNodeOperands.push_back(Glue); - if (!Changed) - return false; - - SelectInlineAsmMemoryOperands(AsmNodeOperands, SDLoc(N)); - - SDValue New = CurDAG->getNode(N->getOpcode(), SDLoc(N), - CurDAG->getVTList(MVT::Other, MVT::Glue), AsmNodeOperands); - New->setNodeId(-1); - ReplaceNode(N, New.getNode()); - return true; -} - -void SparcDAGToDAGISel::Select(SDNode *N) { - SDLoc dl(N); - if (N->isMachineOpcode()) { - N->setNodeId(-1); - return; // Already selected. - } - - switch (N->getOpcode()) { - default: break; - case ISD::INLINEASM: - case ISD::INLINEASM_BR: { - if (tryInlineAsm(N)) - return; - break; - } - case SPISD::GLOBAL_BASE_REG: - ReplaceNode(N, getGlobalBaseReg()); - return; - - case ISD::SDIV: - case ISD::UDIV: { - // sdivx / udivx handle 64-bit divides. - if (N->getValueType(0) == MVT::i64) - break; - // FIXME: should use a custom expander to expose the SRA to the dag. - SDValue DivLHS = N->getOperand(0); - SDValue DivRHS = N->getOperand(1); - - // Set the Y register to the high-part. - SDValue TopPart; - if (N->getOpcode() == ISD::SDIV) { - TopPart = SDValue(CurDAG->getMachineNode(SP::SRAri, dl, MVT::i32, DivLHS, - CurDAG->getTargetConstant(31, dl, MVT::i32)), - 0); - } else { - TopPart = CurDAG->getRegister(SP::G0, MVT::i32); - } - TopPart = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, SP::Y, TopPart, - SDValue()) - .getValue(1); - - // FIXME: Handle div by immediate. - unsigned Opcode = N->getOpcode() == ISD::SDIV ? SP::SDIVrr : SP::UDIVrr; - CurDAG->SelectNodeTo(N, Opcode, MVT::i32, DivLHS, DivRHS, TopPart); - return; - } - } - - SelectCode(N); -} - - -/// SelectInlineAsmMemoryOperand - Implement addressing mode selection for -/// inline asm expressions. -bool -SparcDAGToDAGISel::SelectInlineAsmMemoryOperand(const SDValue &Op, - unsigned ConstraintID, - std::vector &OutOps) { - SDValue Op0, Op1; - switch (ConstraintID) { - default: return true; - case InlineAsm::Constraint_i: - case InlineAsm::Constraint_o: - case InlineAsm::Constraint_m: // memory - if (!SelectADDRrr(Op, Op0, Op1)) - SelectADDRri(Op, Op0, Op1); - break; - } - - OutOps.push_back(Op0); - OutOps.push_back(Op1); - return false; -} - -/// createSparcISelDag - This pass converts a legalized DAG into a -/// SPARC-specific DAG, ready for instruction scheduling. -/// -FunctionPass *llvm::createSparcISelDag(SparcTargetMachine &TM) { - return new SparcDAGToDAGISel(TM); -} diff --git a/contrib/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/contrib/llvm/lib/Target/Sparc/SparcISelLowering.cpp deleted file mode 100644 index 804f7ba74edf..000000000000 --- a/contrib/llvm/lib/Target/Sparc/SparcISelLowering.cpp +++ /dev/null @@ -1,3417 +0,0 @@ -//===-- SparcISelLowering.cpp - Sparc 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 implements the interfaces that Sparc uses to lower LLVM code into a -// selection DAG. -// -//===----------------------------------------------------------------------===// - -#include "SparcISelLowering.h" -#include "MCTargetDesc/SparcMCExpr.h" -#include "SparcMachineFunctionInfo.h" -#include "SparcRegisterInfo.h" -#include "SparcTargetMachine.h" -#include "SparcTargetObjectFile.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/StringSwitch.h" -#include "llvm/CodeGen/CallingConvLower.h" -#include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/SelectionDAG.h" -#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/Module.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/KnownBits.h" -using namespace llvm; - - -//===----------------------------------------------------------------------===// -// Calling Convention Implementation -//===----------------------------------------------------------------------===// - -static bool CC_Sparc_Assign_SRet(unsigned &ValNo, MVT &ValVT, - MVT &LocVT, CCValAssign::LocInfo &LocInfo, - ISD::ArgFlagsTy &ArgFlags, CCState &State) -{ - assert (ArgFlags.isSRet()); - - // Assign SRet argument. - State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT, - 0, - LocVT, LocInfo)); - return true; -} - -static bool CC_Sparc_Assign_Split_64(unsigned &ValNo, MVT &ValVT, - MVT &LocVT, CCValAssign::LocInfo &LocInfo, - ISD::ArgFlagsTy &ArgFlags, CCState &State) -{ - static const MCPhysReg RegList[] = { - SP::I0, SP::I1, SP::I2, SP::I3, SP::I4, SP::I5 - }; - // Try to get first reg. - if (unsigned Reg = State.AllocateReg(RegList)) { - State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); - } else { - // Assign whole thing in stack. - State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT, - State.AllocateStack(8,4), - LocVT, LocInfo)); - return true; - } - - // Try to get second reg. - if (unsigned Reg = State.AllocateReg(RegList)) - State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); - else - State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT, - State.AllocateStack(4,4), - LocVT, LocInfo)); - return true; -} - -static bool CC_Sparc_Assign_Ret_Split_64(unsigned &ValNo, MVT &ValVT, - MVT &LocVT, CCValAssign::LocInfo &LocInfo, - ISD::ArgFlagsTy &ArgFlags, CCState &State) -{ - static const MCPhysReg RegList[] = { - SP::I0, SP::I1, SP::I2, SP::I3, SP::I4, SP::I5 - }; - - // Try to get first reg. - if (unsigned Reg = State.AllocateReg(RegList)) - State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); - else - return false; - - // Try to get second reg. - if (unsigned Reg = State.AllocateReg(RegList)) - State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); - else - return false; - - return true; -} - -// Allocate a full-sized argument for the 64-bit ABI. -static bool CC_Sparc64_Full(unsigned &ValNo, MVT &ValVT, - MVT &LocVT, CCValAssign::LocInfo &LocInfo, - ISD::ArgFlagsTy &ArgFlags, CCState &State) { - assert((LocVT == MVT::f32 || LocVT == MVT::f128 - || LocVT.getSizeInBits() == 64) && - "Can't handle non-64 bits locations"); - - // Stack space is allocated for all arguments starting from [%fp+BIAS+128]. - unsigned size = (LocVT == MVT::f128) ? 16 : 8; - unsigned alignment = (LocVT == MVT::f128) ? 16 : 8; - unsigned Offset = State.AllocateStack(size, alignment); - unsigned Reg = 0; - - if (LocVT == MVT::i64 && Offset < 6*8) - // Promote integers to %i0-%i5. - Reg = SP::I0 + Offset/8; - else if (LocVT == MVT::f64 && Offset < 16*8) - // Promote doubles to %d0-%d30. (Which LLVM calls D0-D15). - Reg = SP::D0 + Offset/8; - else if (LocVT == MVT::f32 && Offset < 16*8) - // Promote floats to %f1, %f3, ... - Reg = SP::F1 + Offset/4; - else if (LocVT == MVT::f128 && Offset < 16*8) - // Promote long doubles to %q0-%q28. (Which LLVM calls Q0-Q7). - Reg = SP::Q0 + Offset/16; - - // Promote to register when possible, otherwise use the stack slot. - if (Reg) { - State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); - return true; - } - - // This argument goes on the stack in an 8-byte slot. - // When passing floats, LocVT is smaller than 8 bytes. Adjust the offset to - // the right-aligned float. The first 4 bytes of the stack slot are undefined. - if (LocVT == MVT::f32) - Offset += 4; - - State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo)); - return true; -} - -// Allocate a half-sized argument for the 64-bit ABI. -// -// This is used when passing { float, int } structs by value in registers. -static bool CC_Sparc64_Half(unsigned &ValNo, MVT &ValVT, - MVT &LocVT, CCValAssign::LocInfo &LocInfo, - ISD::ArgFlagsTy &ArgFlags, CCState &State) { - assert(LocVT.getSizeInBits() == 32 && "Can't handle non-32 bits locations"); - unsigned Offset = State.AllocateStack(4, 4); - - if (LocVT == MVT::f32 && Offset < 16*8) { - // Promote floats to %f0-%f31. - State.addLoc(CCValAssign::getReg(ValNo, ValVT, SP::F0 + Offset/4, - LocVT, LocInfo)); - return true; - } - - if (LocVT == MVT::i32 && Offset < 6*8) { - // Promote integers to %i0-%i5, using half the register. - unsigned Reg = SP::I0 + Offset/8; - LocVT = MVT::i64; - LocInfo = CCValAssign::AExt; - - // Set the Custom bit if this i32 goes in the high bits of a register. - if (Offset % 8 == 0) - State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, - LocVT, LocInfo)); - else - State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); - return true; - } - - State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo)); - return true; -} - -#include "SparcGenCallingConv.inc" - -// The calling conventions in SparcCallingConv.td are described in terms of the -// callee's register window. This function translates registers to the -// corresponding caller window %o register. -static unsigned toCallerWindow(unsigned Reg) { - static_assert(SP::I0 + 7 == SP::I7 && SP::O0 + 7 == SP::O7, - "Unexpected enum"); - if (Reg >= SP::I0 && Reg <= SP::I7) - return Reg - SP::I0 + SP::O0; - return Reg; -} - -SDValue -SparcTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, - bool IsVarArg, - const SmallVectorImpl &Outs, - const SmallVectorImpl &OutVals, - const SDLoc &DL, SelectionDAG &DAG) const { - if (Subtarget->is64Bit()) - return LowerReturn_64(Chain, CallConv, IsVarArg, Outs, OutVals, DL, DAG); - return LowerReturn_32(Chain, CallConv, IsVarArg, Outs, OutVals, DL, DAG); -} - -SDValue -SparcTargetLowering::LowerReturn_32(SDValue Chain, CallingConv::ID CallConv, - bool IsVarArg, - const SmallVectorImpl &Outs, - const SmallVectorImpl &OutVals, - const SDLoc &DL, SelectionDAG &DAG) const { - MachineFunction &MF = DAG.getMachineFunction(); - - // CCValAssign - represent the assignment of the return value to locations. - SmallVector RVLocs; - - // CCState - Info about the registers and stack slot. - CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs, - *DAG.getContext()); - - // Analyze return values. - CCInfo.AnalyzeReturn(Outs, RetCC_Sparc32); - - SDValue Flag; - SmallVector RetOps(1, Chain); - // Make room for the return address offset. - RetOps.push_back(SDValue()); - - // Copy the result values into the output registers. - for (unsigned i = 0, realRVLocIdx = 0; - i != RVLocs.size(); - ++i, ++realRVLocIdx) { - CCValAssign &VA = RVLocs[i]; - assert(VA.isRegLoc() && "Can only return in registers!"); - - SDValue Arg = OutVals[realRVLocIdx]; - - if (VA.needsCustom()) { - assert(VA.getLocVT() == MVT::v2i32); - // Legalize ret v2i32 -> ret 2 x i32 (Basically: do what would - // happen by default if this wasn't a legal type) - - SDValue Part0 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, - Arg, - DAG.getConstant(0, DL, getVectorIdxTy(DAG.getDataLayout()))); - SDValue Part1 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, - Arg, - DAG.getConstant(1, DL, getVectorIdxTy(DAG.getDataLayout()))); - - Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Part0, Flag); - Flag = Chain.getValue(1); - RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); - VA = RVLocs[++i]; // skip ahead to next loc - Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Part1, - Flag); - } else - Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Arg, Flag); - - // Guarantee that all emitted copies are stuck together with flags. - Flag = Chain.getValue(1); - RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); - } - - unsigned RetAddrOffset = 8; // Call Inst + Delay Slot - // If the function returns a struct, copy the SRetReturnReg to I0 - if (MF.getFunction().hasStructRetAttr()) { - SparcMachineFunctionInfo *SFI = MF.getInfo(); - unsigned Reg = SFI->getSRetReturnReg(); - if (!Reg) - llvm_unreachable("sret virtual register not created in the entry block"); - auto PtrVT = getPointerTy(DAG.getDataLayout()); - SDValue Val = DAG.getCopyFromReg(Chain, DL, Reg, PtrVT); - Chain = DAG.getCopyToReg(Chain, DL, SP::I0, Val, Flag); - Flag = Chain.getValue(1); - RetOps.push_back(DAG.getRegister(SP::I0, PtrVT)); - RetAddrOffset = 12; // CallInst + Delay Slot + Unimp - } - - RetOps[0] = Chain; // Update chain. - RetOps[1] = DAG.getConstant(RetAddrOffset, DL, MVT::i32); - - // Add the flag if we have it. - if (Flag.getNode()) - RetOps.push_back(Flag); - - return DAG.getNode(SPISD::RET_FLAG, DL, MVT::Other, RetOps); -} - -// Lower return values for the 64-bit ABI. -// Return values are passed the exactly the same way as function arguments. -SDValue -SparcTargetLowering::LowerReturn_64(SDValue Chain, CallingConv::ID CallConv, - bool IsVarArg, - const SmallVectorImpl &Outs, - const SmallVectorImpl &OutVals, - const SDLoc &DL, SelectionDAG &DAG) const { - // CCValAssign - represent the assignment of the return value to locations. - SmallVector RVLocs; - - // CCState - Info about the registers and stack slot. - CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs, - *DAG.getContext()); - - // Analyze return values. - CCInfo.AnalyzeReturn(Outs, RetCC_Sparc64); - - SDValue Flag; - SmallVector RetOps(1, Chain); - - // The second operand on the return instruction is the return address offset. - // The return address is always %i7+8 with the 64-bit ABI. - RetOps.push_back(DAG.getConstant(8, DL, MVT::i32)); - - // Copy the result values into the output registers. - for (unsigned i = 0; i != RVLocs.size(); ++i) { - CCValAssign &VA = RVLocs[i]; - assert(VA.isRegLoc() && "Can only return in registers!"); - SDValue OutVal = OutVals[i]; - - // Integer return values must be sign or zero extended by the callee. - switch (VA.getLocInfo()) { - case CCValAssign::Full: break; - case CCValAssign::SExt: - OutVal = DAG.getNode(ISD::SIGN_EXTEND, DL, VA.getLocVT(), OutVal); - break; - case CCValAssign::ZExt: - OutVal = DAG.getNode(ISD::ZERO_EXTEND, DL, VA.getLocVT(), OutVal); - break; - case CCValAssign::AExt: - OutVal = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), OutVal); - break; - default: - llvm_unreachable("Unknown loc info!"); - } - - // The custom bit on an i32 return value indicates that it should be passed - // in the high bits of the register. - if (VA.getValVT() == MVT::i32 && VA.needsCustom()) { - OutVal = DAG.getNode(ISD::SHL, DL, MVT::i64, OutVal, - DAG.getConstant(32, DL, MVT::i32)); - - // The next value may go in the low bits of the same register. - // Handle both at once. - if (i+1 < RVLocs.size() && RVLocs[i+1].getLocReg() == VA.getLocReg()) { - SDValue NV = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i64, OutVals[i+1]); - OutVal = DAG.getNode(ISD::OR, DL, MVT::i64, OutVal, NV); - // Skip the next value, it's already done. - ++i; - } - } - - Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), OutVal, Flag); - - // Guarantee that all emitted copies are stuck together with flags. - Flag = Chain.getValue(1); - RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); - } - - RetOps[0] = Chain; // Update chain. - - // Add the flag if we have it. - if (Flag.getNode()) - RetOps.push_back(Flag); - - return DAG.getNode(SPISD::RET_FLAG, DL, MVT::Other, RetOps); -} - -SDValue SparcTargetLowering::LowerFormalArguments( - SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, - const SmallVectorImpl &Ins, const SDLoc &DL, - SelectionDAG &DAG, SmallVectorImpl &InVals) const { - if (Subtarget->is64Bit()) - return LowerFormalArguments_64(Chain, CallConv, IsVarArg, Ins, - DL, DAG, InVals); - return LowerFormalArguments_32(Chain, CallConv, IsVarArg, Ins, - DL, DAG, InVals); -} - -/// LowerFormalArguments32 - V8 uses a very simple ABI, where all values are -/// passed in either one or two GPRs, including FP values. TODO: we should -/// pass FP values in FP registers for fastcc functions. -SDValue SparcTargetLowering::LowerFormalArguments_32( - SDValue Chain, CallingConv::ID CallConv, bool isVarArg, - const SmallVectorImpl &Ins, const SDLoc &dl, - SelectionDAG &DAG, SmallVectorImpl &InVals) const { - MachineFunction &MF = DAG.getMachineFunction(); - MachineRegisterInfo &RegInfo = MF.getRegInfo(); - SparcMachineFunctionInfo *FuncInfo = MF.getInfo(); - - // Assign locations to all of the incoming arguments. - SmallVector ArgLocs; - CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs, - *DAG.getContext()); - CCInfo.AnalyzeFormalArguments(Ins, CC_Sparc32); - - const unsigned StackOffset = 92; - bool IsLittleEndian = DAG.getDataLayout().isLittleEndian(); - - unsigned InIdx = 0; - for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i, ++InIdx) { - CCValAssign &VA = ArgLocs[i]; - - if (Ins[InIdx].Flags.isSRet()) { - if (InIdx != 0) - report_fatal_error("sparc only supports sret on the first parameter"); - // Get SRet from [%fp+64]. - int FrameIdx = MF.getFrameInfo().CreateFixedObject(4, 64, true); - SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32); - SDValue Arg = - DAG.getLoad(MVT::i32, dl, Chain, FIPtr, MachinePointerInfo()); - InVals.push_back(Arg); - continue; - } - - if (VA.isRegLoc()) { - if (VA.needsCustom()) { - assert(VA.getLocVT() == MVT::f64 || VA.getLocVT() == MVT::v2i32); - - unsigned VRegHi = RegInfo.createVirtualRegister(&SP::IntRegsRegClass); - MF.getRegInfo().addLiveIn(VA.getLocReg(), VRegHi); - SDValue HiVal = DAG.getCopyFromReg(Chain, dl, VRegHi, MVT::i32); - - assert(i+1 < e); - CCValAssign &NextVA = ArgLocs[++i]; - - SDValue LoVal; - if (NextVA.isMemLoc()) { - int FrameIdx = MF.getFrameInfo(). - CreateFixedObject(4, StackOffset+NextVA.getLocMemOffset(),true); - SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32); - LoVal = DAG.getLoad(MVT::i32, dl, Chain, FIPtr, MachinePointerInfo()); - } else { - unsigned loReg = MF.addLiveIn(NextVA.getLocReg(), - &SP::IntRegsRegClass); - LoVal = DAG.getCopyFromReg(Chain, dl, loReg, MVT::i32); - } - - if (IsLittleEndian) - std::swap(LoVal, HiVal); - - SDValue WholeValue = - DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, LoVal, HiVal); - WholeValue = DAG.getNode(ISD::BITCAST, dl, VA.getLocVT(), WholeValue); - InVals.push_back(WholeValue); - continue; - } - unsigned VReg = RegInfo.createVirtualRegister(&SP::IntRegsRegClass); - MF.getRegInfo().addLiveIn(VA.getLocReg(), VReg); - SDValue Arg = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32); - if (VA.getLocVT() == MVT::f32) - Arg = DAG.getNode(ISD::BITCAST, dl, MVT::f32, Arg); - else if (VA.getLocVT() != MVT::i32) { - Arg = DAG.getNode(ISD::AssertSext, dl, MVT::i32, Arg, - DAG.getValueType(VA.getLocVT())); - Arg = DAG.getNode(ISD::TRUNCATE, dl, VA.getLocVT(), Arg); - } - InVals.push_back(Arg); - continue; - } - - assert(VA.isMemLoc()); - - unsigned Offset = VA.getLocMemOffset()+StackOffset; - auto PtrVT = getPointerTy(DAG.getDataLayout()); - - if (VA.needsCustom()) { - assert(VA.getValVT() == MVT::f64 || VA.getValVT() == MVT::v2i32); - // If it is double-word aligned, just load. - if (Offset % 8 == 0) { - int FI = MF.getFrameInfo().CreateFixedObject(8, - Offset, - true); - SDValue FIPtr = DAG.getFrameIndex(FI, PtrVT); - SDValue Load = - DAG.getLoad(VA.getValVT(), dl, Chain, FIPtr, MachinePointerInfo()); - InVals.push_back(Load); - continue; - } - - int FI = MF.getFrameInfo().CreateFixedObject(4, - Offset, - true); - SDValue FIPtr = DAG.getFrameIndex(FI, PtrVT); - SDValue HiVal = - DAG.getLoad(MVT::i32, dl, Chain, FIPtr, MachinePointerInfo()); - int FI2 = MF.getFrameInfo().CreateFixedObject(4, - Offset+4, - true); - SDValue FIPtr2 = DAG.getFrameIndex(FI2, PtrVT); - - SDValue LoVal = - DAG.getLoad(MVT::i32, dl, Chain, FIPtr2, MachinePointerInfo()); - - if (IsLittleEndian) - std::swap(LoVal, HiVal); - - SDValue WholeValue = - DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, LoVal, HiVal); - WholeValue = DAG.getNode(ISD::BITCAST, dl, VA.getValVT(), WholeValue); - InVals.push_back(WholeValue); - continue; - } - - int FI = MF.getFrameInfo().CreateFixedObject(4, - Offset, - true); - SDValue FIPtr = DAG.getFrameIndex(FI, PtrVT); - SDValue Load ; - if (VA.getValVT() == MVT::i32 || VA.getValVT() == MVT::f32) { - Load = DAG.getLoad(VA.getValVT(), dl, Chain, FIPtr, MachinePointerInfo()); - } else if (VA.getValVT() == MVT::f128) { - report_fatal_error("SPARCv8 does not handle f128 in calls; " - "pass indirectly"); - } else { - // We shouldn't see any other value types here. - llvm_unreachable("Unexpected ValVT encountered in frame lowering."); - } - InVals.push_back(Load); - } - - if (MF.getFunction().hasStructRetAttr()) { - // Copy the SRet Argument to SRetReturnReg. - SparcMachineFunctionInfo *SFI = MF.getInfo(); - unsigned Reg = SFI->getSRetReturnReg(); - if (!Reg) { - Reg = MF.getRegInfo().createVirtualRegister(&SP::IntRegsRegClass); - SFI->setSRetReturnReg(Reg); - } - SDValue Copy = DAG.getCopyToReg(DAG.getEntryNode(), dl, Reg, InVals[0]); - Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Copy, Chain); - } - - // Store remaining ArgRegs to the stack if this is a varargs function. - if (isVarArg) { - static const MCPhysReg ArgRegs[] = { - SP::I0, SP::I1, SP::I2, SP::I3, SP::I4, SP::I5 - }; - unsigned NumAllocated = CCInfo.getFirstUnallocated(ArgRegs); - const MCPhysReg *CurArgReg = ArgRegs+NumAllocated, *ArgRegEnd = ArgRegs+6; - unsigned ArgOffset = CCInfo.getNextStackOffset(); - if (NumAllocated == 6) - ArgOffset += StackOffset; - else { - assert(!ArgOffset); - ArgOffset = 68+4*NumAllocated; - } - - // Remember the vararg offset for the va_start implementation. - FuncInfo->setVarArgsFrameOffset(ArgOffset); - - std::vector OutChains; - - for (; CurArgReg != ArgRegEnd; ++CurArgReg) { - unsigned VReg = RegInfo.createVirtualRegister(&SP::IntRegsRegClass); - MF.getRegInfo().addLiveIn(*CurArgReg, VReg); - SDValue Arg = DAG.getCopyFromReg(DAG.getRoot(), dl, VReg, MVT::i32); - - int FrameIdx = MF.getFrameInfo().CreateFixedObject(4, ArgOffset, - true); - SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32); - - OutChains.push_back( - DAG.getStore(DAG.getRoot(), dl, Arg, FIPtr, MachinePointerInfo())); - ArgOffset += 4; - } - - if (!OutChains.empty()) { - OutChains.push_back(Chain); - Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains); - } - } - - return Chain; -} - -// Lower formal arguments for the 64 bit ABI. -SDValue SparcTargetLowering::LowerFormalArguments_64( - SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, - const SmallVectorImpl &Ins, const SDLoc &DL, - SelectionDAG &DAG, SmallVectorImpl &InVals) const { - MachineFunction &MF = DAG.getMachineFunction(); - - // Analyze arguments according to CC_Sparc64. - SmallVector ArgLocs; - CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs, - *DAG.getContext()); - CCInfo.AnalyzeFormalArguments(Ins, CC_Sparc64); - - // The argument array begins at %fp+BIAS+128, after the register save area. - const unsigned ArgArea = 128; - - for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { - CCValAssign &VA = ArgLocs[i]; - if (VA.isRegLoc()) { - // This argument is passed in a register. - // All integer register arguments are promoted by the caller to i64. - - // Create a virtual register for the promoted live-in value. - unsigned VReg = MF.addLiveIn(VA.getLocReg(), - getRegClassFor(VA.getLocVT())); - SDValue Arg = DAG.getCopyFromReg(Chain, DL, VReg, VA.getLocVT()); - - // Get the high bits for i32 struct elements. - if (VA.getValVT() == MVT::i32 && VA.needsCustom()) - Arg = DAG.getNode(ISD::SRL, DL, VA.getLocVT(), Arg, - DAG.getConstant(32, DL, MVT::i32)); - - // The caller promoted the argument, so insert an Assert?ext SDNode so we - // won't promote the value again in this function. - switch (VA.getLocInfo()) { - case CCValAssign::SExt: - Arg = DAG.getNode(ISD::AssertSext, DL, VA.getLocVT(), Arg, - DAG.getValueType(VA.getValVT())); - break; - case CCValAssign::ZExt: - Arg = DAG.getNode(ISD::AssertZext, DL, VA.getLocVT(), Arg, - DAG.getValueType(VA.getValVT())); - break; - default: - break; - } - - // Truncate the register down to the argument type. - if (VA.isExtInLoc()) - Arg = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Arg); - - InVals.push_back(Arg); - continue; - } - - // The registers are exhausted. This argument was passed on the stack. - assert(VA.isMemLoc()); - // The CC_Sparc64_Full/Half functions compute stack offsets relative to the - // beginning of the arguments area at %fp+BIAS+128. - unsigned Offset = VA.getLocMemOffset() + ArgArea; - unsigned ValSize = VA.getValVT().getSizeInBits() / 8; - // Adjust offset for extended arguments, SPARC is big-endian. - // The caller will have written the full slot with extended bytes, but we - // prefer our own extending loads. - if (VA.isExtInLoc()) - Offset += 8 - ValSize; - int FI = MF.getFrameInfo().CreateFixedObject(ValSize, Offset, true); - InVals.push_back( - DAG.getLoad(VA.getValVT(), DL, Chain, - DAG.getFrameIndex(FI, getPointerTy(MF.getDataLayout())), - MachinePointerInfo::getFixedStack(MF, FI))); - } - - if (!IsVarArg) - return Chain; - - // This function takes variable arguments, some of which may have been passed - // in registers %i0-%i5. Variable floating point arguments are never passed - // in floating point registers. They go on %i0-%i5 or on the stack like - // integer arguments. - // - // The va_start intrinsic needs to know the offset to the first variable - // argument. - unsigned ArgOffset = CCInfo.getNextStackOffset(); - SparcMachineFunctionInfo *FuncInfo = MF.getInfo(); - // Skip the 128 bytes of register save area. - FuncInfo->setVarArgsFrameOffset(ArgOffset + ArgArea + - Subtarget->getStackPointerBias()); - - // Save the variable arguments that were passed in registers. - // The caller is required to reserve stack space for 6 arguments regardless - // of how many arguments were actually passed. - SmallVector OutChains; - for (; ArgOffset < 6*8; ArgOffset += 8) { - unsigned VReg = MF.addLiveIn(SP::I0 + ArgOffset/8, &SP::I64RegsRegClass); - SDValue VArg = DAG.getCopyFromReg(Chain, DL, VReg, MVT::i64); - int FI = MF.getFrameInfo().CreateFixedObject(8, ArgOffset + ArgArea, true); - auto PtrVT = getPointerTy(MF.getDataLayout()); - OutChains.push_back( - DAG.getStore(Chain, DL, VArg, DAG.getFrameIndex(FI, PtrVT), - MachinePointerInfo::getFixedStack(MF, FI))); - } - - if (!OutChains.empty()) - Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains); - - return Chain; -} - -SDValue -SparcTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, - SmallVectorImpl &InVals) const { - if (Subtarget->is64Bit()) - return LowerCall_64(CLI, InVals); - return LowerCall_32(CLI, InVals); -} - -static bool hasReturnsTwiceAttr(SelectionDAG &DAG, SDValue Callee, - ImmutableCallSite CS) { - if (CS) - return CS.hasFnAttr(Attribute::ReturnsTwice); - - const Function *CalleeFn = nullptr; - if (GlobalAddressSDNode *G = dyn_cast(Callee)) { - CalleeFn = dyn_cast(G->getGlobal()); - } else if (ExternalSymbolSDNode *E = - dyn_cast(Callee)) { - const Function &Fn = DAG.getMachineFunction().getFunction(); - const Module *M = Fn.getParent(); - const char *CalleeName = E->getSymbol(); - CalleeFn = M->getFunction(CalleeName); - } - - if (!CalleeFn) - return false; - return CalleeFn->hasFnAttribute(Attribute::ReturnsTwice); -} - -// Lower a call for the 32-bit ABI. -SDValue -SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI, - SmallVectorImpl &InVals) const { - SelectionDAG &DAG = CLI.DAG; - SDLoc &dl = CLI.DL; - SmallVectorImpl &Outs = CLI.Outs; - SmallVectorImpl &OutVals = CLI.OutVals; - SmallVectorImpl &Ins = CLI.Ins; - SDValue Chain = CLI.Chain; - SDValue Callee = CLI.Callee; - bool &isTailCall = CLI.IsTailCall; - CallingConv::ID CallConv = CLI.CallConv; - bool isVarArg = CLI.IsVarArg; - - // Sparc target does not yet support tail call optimization. - isTailCall = false; - - // Analyze operands of the call, assigning locations to each operand. - SmallVector ArgLocs; - CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs, - *DAG.getContext()); - CCInfo.AnalyzeCallOperands(Outs, CC_Sparc32); - - // Get the size of the outgoing arguments stack space requirement. - unsigned ArgsSize = CCInfo.getNextStackOffset(); - - // Keep stack frames 8-byte aligned. - ArgsSize = (ArgsSize+7) & ~7; - - MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo(); - - // Create local copies for byval args. - SmallVector ByValArgs; - for (unsigned i = 0, e = Outs.size(); i != e; ++i) { - ISD::ArgFlagsTy Flags = Outs[i].Flags; - if (!Flags.isByVal()) - continue; - - SDValue Arg = OutVals[i]; - unsigned Size = Flags.getByValSize(); - unsigned Align = Flags.getByValAlign(); - - if (Size > 0U) { - int FI = MFI.CreateStackObject(Size, Align, false); - SDValue FIPtr = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout())); - SDValue SizeNode = DAG.getConstant(Size, dl, MVT::i32); - - Chain = DAG.getMemcpy(Chain, dl, FIPtr, Arg, SizeNode, Align, - false, // isVolatile, - (Size <= 32), // AlwaysInline if size <= 32, - false, // isTailCall - MachinePointerInfo(), MachinePointerInfo()); - ByValArgs.push_back(FIPtr); - } - else { - SDValue nullVal; - ByValArgs.push_back(nullVal); - } - } - - Chain = DAG.getCALLSEQ_START(Chain, ArgsSize, 0, dl); - - SmallVector, 8> RegsToPass; - SmallVector MemOpChains; - - const unsigned StackOffset = 92; - bool hasStructRetAttr = false; - unsigned SRetArgSize = 0; - // Walk the register/memloc assignments, inserting copies/loads. - for (unsigned i = 0, realArgIdx = 0, byvalArgIdx = 0, e = ArgLocs.size(); - i != e; - ++i, ++realArgIdx) { - CCValAssign &VA = ArgLocs[i]; - SDValue Arg = OutVals[realArgIdx]; - - ISD::ArgFlagsTy Flags = Outs[realArgIdx].Flags; - - // Use local copy if it is a byval arg. - if (Flags.isByVal()) { - Arg = ByValArgs[byvalArgIdx++]; - if (!Arg) { - continue; - } - } - - // Promote the value if needed. - switch (VA.getLocInfo()) { - default: llvm_unreachable("Unknown loc info!"); - case CCValAssign::Full: break; - case CCValAssign::SExt: - Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg); - break; - case CCValAssign::ZExt: - Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg); - break; - case CCValAssign::AExt: - Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg); - break; - case CCValAssign::BCvt: - Arg = DAG.getNode(ISD::BITCAST, dl, VA.getLocVT(), Arg); - break; - } - - if (Flags.isSRet()) { - assert(VA.needsCustom()); - // store SRet argument in %sp+64 - SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32); - SDValue PtrOff = DAG.getIntPtrConstant(64, dl); - PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff); - MemOpChains.push_back( - DAG.getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo())); - hasStructRetAttr = true; - // sret only allowed on first argument - assert(Outs[realArgIdx].OrigArgIndex == 0); - PointerType *Ty = cast(CLI.getArgs()[0].Ty); - Type *ElementTy = Ty->getElementType(); - SRetArgSize = DAG.getDataLayout().getTypeAllocSize(ElementTy); - continue; - } - - if (VA.needsCustom()) { - assert(VA.getLocVT() == MVT::f64 || VA.getLocVT() == MVT::v2i32); - - if (VA.isMemLoc()) { - unsigned Offset = VA.getLocMemOffset() + StackOffset; - // if it is double-word aligned, just store. - if (Offset % 8 == 0) { - SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32); - SDValue PtrOff = DAG.getIntPtrConstant(Offset, dl); - PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff); - MemOpChains.push_back( - DAG.getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo())); - continue; - } - } - - if (VA.getLocVT() == MVT::f64) { - // Move from the float value from float registers into the - // integer registers. - if (ConstantFPSDNode *C = dyn_cast(Arg)) - Arg = bitcastConstantFPToInt(C, dl, DAG); - else - Arg = DAG.getNode(ISD::BITCAST, dl, MVT::v2i32, Arg); - } - - SDValue Part0 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::i32, - Arg, - DAG.getConstant(0, dl, getVectorIdxTy(DAG.getDataLayout()))); - SDValue Part1 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::i32, - Arg, - DAG.getConstant(1, dl, getVectorIdxTy(DAG.getDataLayout()))); - - if (VA.isRegLoc()) { - RegsToPass.push_back(std::make_pair(VA.getLocReg(), Part0)); - assert(i+1 != e); - CCValAssign &NextVA = ArgLocs[++i]; - if (NextVA.isRegLoc()) { - RegsToPass.push_back(std::make_pair(NextVA.getLocReg(), Part1)); - } else { - // Store the second part in stack. - unsigned Offset = NextVA.getLocMemOffset() + StackOffset; - SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32); - SDValue PtrOff = DAG.getIntPtrConstant(Offset, dl); - PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff); - MemOpChains.push_back( - DAG.getStore(Chain, dl, Part1, PtrOff, MachinePointerInfo())); - } - } else { - unsigned Offset = VA.getLocMemOffset() + StackOffset; - // Store the first part. - SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32); - SDValue PtrOff = DAG.getIntPtrConstant(Offset, dl); - PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff); - MemOpChains.push_back( - DAG.getStore(Chain, dl, Part0, PtrOff, MachinePointerInfo())); - // Store the second part. - PtrOff = DAG.getIntPtrConstant(Offset + 4, dl); - PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff); - MemOpChains.push_back( - DAG.getStore(Chain, dl, Part1, PtrOff, MachinePointerInfo())); - } - continue; - } - - // Arguments that can be passed on register must be kept at - // RegsToPass vector - if (VA.isRegLoc()) { - if (VA.getLocVT() != MVT::f32) { - RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); - continue; - } - Arg = DAG.getNode(ISD::BITCAST, dl, MVT::i32, Arg); - RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); - continue; - } - - assert(VA.isMemLoc()); - - // Create a store off the stack pointer for this argument. - SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32); - SDValue PtrOff = DAG.getIntPtrConstant(VA.getLocMemOffset() + StackOffset, - dl); - PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff); - MemOpChains.push_back( - DAG.getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo())); - } - - - // Emit all stores, make sure the occur before any copies into physregs. - if (!MemOpChains.empty()) - Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains); - - // 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) { - unsigned Reg = toCallerWindow(RegsToPass[i].first); - Chain = DAG.getCopyToReg(Chain, dl, Reg, RegsToPass[i].second, InFlag); - InFlag = Chain.getValue(1); - } - - bool hasReturnsTwice = hasReturnsTwiceAttr(DAG, Callee, CLI.CS); - - // If the callee is a GlobalAddress node (quite common, every direct call is) - // turn it into a TargetGlobalAddress node so that legalize doesn't hack it. - // Likewise ExternalSymbol -> TargetExternalSymbol. - unsigned TF = isPositionIndependent() ? SparcMCExpr::VK_Sparc_WPLT30 : 0; - if (GlobalAddressSDNode *G = dyn_cast(Callee)) - Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i32, 0, TF); - else if (ExternalSymbolSDNode *E = dyn_cast(Callee)) - Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32, TF); - - // Returns a chain & a flag for retval copy to use - SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); - SmallVector Ops; - Ops.push_back(Chain); - Ops.push_back(Callee); - if (hasStructRetAttr) - Ops.push_back(DAG.getTargetConstant(SRetArgSize, dl, MVT::i32)); - for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) - Ops.push_back(DAG.getRegister(toCallerWindow(RegsToPass[i].first), - RegsToPass[i].second.getValueType())); - - // Add a register mask operand representing the call-preserved registers. - const SparcRegisterInfo *TRI = Subtarget->getRegisterInfo(); - const uint32_t *Mask = - ((hasReturnsTwice) - ? TRI->getRTCallPreservedMask(CallConv) - : TRI->getCallPreservedMask(DAG.getMachineFunction(), CallConv)); - assert(Mask && "Missing call preserved mask for calling convention"); - Ops.push_back(DAG.getRegisterMask(Mask)); - - if (InFlag.getNode()) - Ops.push_back(InFlag); - - Chain = DAG.getNode(SPISD::CALL, dl, NodeTys, Ops); - InFlag = Chain.getValue(1); - - Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(ArgsSize, dl, true), - DAG.getIntPtrConstant(0, dl, true), InFlag, dl); - InFlag = Chain.getValue(1); - - // Assign locations to each value returned by this call. - SmallVector RVLocs; - CCState RVInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs, - *DAG.getContext()); - - RVInfo.AnalyzeCallResult(Ins, RetCC_Sparc32); - - // Copy all of the result registers out of their specified physreg. - for (unsigned i = 0; i != RVLocs.size(); ++i) { - if (RVLocs[i].getLocVT() == MVT::v2i32) { - SDValue Vec = DAG.getNode(ISD::UNDEF, dl, MVT::v2i32); - SDValue Lo = DAG.getCopyFromReg( - Chain, dl, toCallerWindow(RVLocs[i++].getLocReg()), MVT::i32, InFlag); - Chain = Lo.getValue(1); - InFlag = Lo.getValue(2); - Vec = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, MVT::v2i32, Vec, Lo, - DAG.getConstant(0, dl, MVT::i32)); - SDValue Hi = DAG.getCopyFromReg( - Chain, dl, toCallerWindow(RVLocs[i].getLocReg()), MVT::i32, InFlag); - Chain = Hi.getValue(1); - InFlag = Hi.getValue(2); - Vec = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, MVT::v2i32, Vec, Hi, - DAG.getConstant(1, dl, MVT::i32)); - InVals.push_back(Vec); - } else { - Chain = - DAG.getCopyFromReg(Chain, dl, toCallerWindow(RVLocs[i].getLocReg()), - RVLocs[i].getValVT(), InFlag) - .getValue(1); - InFlag = Chain.getValue(2); - InVals.push_back(Chain.getValue(0)); - } - } - - return Chain; -} - -// FIXME? Maybe this could be a TableGen attribute on some registers and -// this table could be generated automatically from RegInfo. -unsigned SparcTargetLowering::getRegisterByName(const char* RegName, EVT VT, - SelectionDAG &DAG) const { - unsigned Reg = StringSwitch(RegName) - .Case("i0", SP::I0).Case("i1", SP::I1).Case("i2", SP::I2).Case("i3", SP::I3) - .Case("i4", SP::I4).Case("i5", SP::I5).Case("i6", SP::I6).Case("i7", SP::I7) - .Case("o0", SP::O0).Case("o1", SP::O1).Case("o2", SP::O2).Case("o3", SP::O3) - .Case("o4", SP::O4).Case("o5", SP::O5).Case("o6", SP::O6).Case("o7", SP::O7) - .Case("l0", SP::L0).Case("l1", SP::L1).Case("l2", SP::L2).Case("l3", SP::L3) - .Case("l4", SP::L4).Case("l5", SP::L5).Case("l6", SP::L6).Case("l7", SP::L7) - .Case("g0", SP::G0).Case("g1", SP::G1).Case("g2", SP::G2).Case("g3", SP::G3) - .Case("g4", SP::G4).Case("g5", SP::G5).Case("g6", SP::G6).Case("g7", SP::G7) - .Default(0); - - if (Reg) - return Reg; - - report_fatal_error("Invalid register name global variable"); -} - -// Fixup floating point arguments in the ... part of a varargs call. -// -// The SPARC v9 ABI requires that floating point arguments are treated the same -// as integers when calling a varargs function. This does not apply to the -// fixed arguments that are part of the function's prototype. -// -// This function post-processes a CCValAssign array created by -// AnalyzeCallOperands(). -static void fixupVariableFloatArgs(SmallVectorImpl &ArgLocs, - ArrayRef Outs) { - for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { - const CCValAssign &VA = ArgLocs[i]; - MVT ValTy = VA.getLocVT(); - // FIXME: What about f32 arguments? C promotes them to f64 when calling - // varargs functions. - if (!VA.isRegLoc() || (ValTy != MVT::f64 && ValTy != MVT::f128)) - continue; - // The fixed arguments to a varargs function still go in FP registers. - if (Outs[VA.getValNo()].IsFixed) - continue; - - // This floating point argument should be reassigned. - CCValAssign NewVA; - - // Determine the offset into the argument array. - unsigned firstReg = (ValTy == MVT::f64) ? SP::D0 : SP::Q0; - unsigned argSize = (ValTy == MVT::f64) ? 8 : 16; - unsigned Offset = argSize * (VA.getLocReg() - firstReg); - assert(Offset < 16*8 && "Offset out of range, bad register enum?"); - - if (Offset < 6*8) { - // This argument should go in %i0-%i5. - unsigned IReg = SP::I0 + Offset/8; - if (ValTy == MVT::f64) - // Full register, just bitconvert into i64. - NewVA = CCValAssign::getReg(VA.getValNo(), VA.getValVT(), - IReg, MVT::i64, CCValAssign::BCvt); - else { - assert(ValTy == MVT::f128 && "Unexpected type!"); - // Full register, just bitconvert into i128 -- We will lower this into - // two i64s in LowerCall_64. - NewVA = CCValAssign::getCustomReg(VA.getValNo(), VA.getValVT(), - IReg, MVT::i128, CCValAssign::BCvt); - } - } else { - // This needs to go to memory, we're out of integer registers. - NewVA = CCValAssign::getMem(VA.getValNo(), VA.getValVT(), - Offset, VA.getLocVT(), VA.getLocInfo()); - } - ArgLocs[i] = NewVA; - } -} - -// Lower a call for the 64-bit ABI. -SDValue -SparcTargetLowering::LowerCall_64(TargetLowering::CallLoweringInfo &CLI, - SmallVectorImpl &InVals) const { - SelectionDAG &DAG = CLI.DAG; - SDLoc DL = CLI.DL; - SDValue Chain = CLI.Chain; - auto PtrVT = getPointerTy(DAG.getDataLayout()); - - // Sparc target does not yet support tail call optimization. - CLI.IsTailCall = false; - - // Analyze operands of the call, assigning locations to each operand. - SmallVector ArgLocs; - CCState CCInfo(CLI.CallConv, CLI.IsVarArg, DAG.getMachineFunction(), ArgLocs, - *DAG.getContext()); - CCInfo.AnalyzeCallOperands(CLI.Outs, CC_Sparc64); - - // Get the size of the outgoing arguments stack space requirement. - // The stack offset computed by CC_Sparc64 includes all arguments. - // Called functions expect 6 argument words to exist in the stack frame, used - // or not. - unsigned ArgsSize = std::max(6*8u, CCInfo.getNextStackOffset()); - - // Keep stack frames 16-byte aligned. - ArgsSize = alignTo(ArgsSize, 16); - - // Varargs calls require special treatment. - if (CLI.IsVarArg) - fixupVariableFloatArgs(ArgLocs, CLI.Outs); - - // Adjust the stack pointer to make room for the arguments. - // FIXME: Use hasReservedCallFrame to avoid %sp adjustments around all calls - // with more than 6 arguments. - Chain = DAG.getCALLSEQ_START(Chain, ArgsSize, 0, DL); - - // Collect the set of registers to pass to the function and their values. - // This will be emitted as a sequence of CopyToReg nodes glued to the call - // instruction. - SmallVector, 8> RegsToPass; - - // Collect chains from all the memory opeations that copy arguments to the - // stack. They must follow the stack pointer adjustment above and precede the - // call instruction itself. - SmallVector MemOpChains; - - for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { - const CCValAssign &VA = ArgLocs[i]; - SDValue Arg = CLI.OutVals[i]; - - // Promote the value if needed. - switch (VA.getLocInfo()) { - default: - llvm_unreachable("Unknown location info!"); - case CCValAssign::Full: - break; - case CCValAssign::SExt: - Arg = DAG.getNode(ISD::SIGN_EXTEND, DL, VA.getLocVT(), Arg); - break; - case CCValAssign::ZExt: - Arg = DAG.getNode(ISD::ZERO_EXTEND, DL, VA.getLocVT(), Arg); - break; - case CCValAssign::AExt: - Arg = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), Arg); - break; - case CCValAssign::BCvt: - // fixupVariableFloatArgs() may create bitcasts from f128 to i128. But - // SPARC does not support i128 natively. Lower it into two i64, see below. - if (!VA.needsCustom() || VA.getValVT() != MVT::f128 - || VA.getLocVT() != MVT::i128) - Arg = DAG.getNode(ISD::BITCAST, DL, VA.getLocVT(), Arg); - break; - } - - if (VA.isRegLoc()) { - if (VA.needsCustom() && VA.getValVT() == MVT::f128 - && VA.getLocVT() == MVT::i128) { - // Store and reload into the integer register reg and reg+1. - unsigned Offset = 8 * (VA.getLocReg() - SP::I0); - unsigned StackOffset = Offset + Subtarget->getStackPointerBias() + 128; - SDValue StackPtr = DAG.getRegister(SP::O6, PtrVT); - SDValue HiPtrOff = DAG.getIntPtrConstant(StackOffset, DL); - HiPtrOff = DAG.getNode(ISD::ADD, DL, PtrVT, StackPtr, HiPtrOff); - SDValue LoPtrOff = DAG.getIntPtrConstant(StackOffset + 8, DL); - LoPtrOff = DAG.getNode(ISD::ADD, DL, PtrVT, StackPtr, LoPtrOff); - - // Store to %sp+BIAS+128+Offset - SDValue Store = - DAG.getStore(Chain, DL, Arg, HiPtrOff, MachinePointerInfo()); - // Load into Reg and Reg+1 - SDValue Hi64 = - DAG.getLoad(MVT::i64, DL, Store, HiPtrOff, MachinePointerInfo()); - SDValue Lo64 = - DAG.getLoad(MVT::i64, DL, Store, LoPtrOff, MachinePointerInfo()); - RegsToPass.push_back(std::make_pair(toCallerWindow(VA.getLocReg()), - Hi64)); - RegsToPass.push_back(std::make_pair(toCallerWindow(VA.getLocReg()+1), - Lo64)); - continue; - } - - // The custom bit on an i32 return value indicates that it should be - // passed in the high bits of the register. - if (VA.getValVT() == MVT::i32 && VA.needsCustom()) { - Arg = DAG.getNode(ISD::SHL, DL, MVT::i64, Arg, - DAG.getConstant(32, DL, MVT::i32)); - - // The next value may go in the low bits of the same register. - // Handle both at once. - if (i+1 < ArgLocs.size() && ArgLocs[i+1].isRegLoc() && - ArgLocs[i+1].getLocReg() == VA.getLocReg()) { - SDValue NV = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i64, - CLI.OutVals[i+1]); - Arg = DAG.getNode(ISD::OR, DL, MVT::i64, Arg, NV); - // Skip the next value, it's already done. - ++i; - } - } - RegsToPass.push_back(std::make_pair(toCallerWindow(VA.getLocReg()), Arg)); - continue; - } - - assert(VA.isMemLoc()); - - // Create a store off the stack pointer for this argument. - SDValue StackPtr = DAG.getRegister(SP::O6, PtrVT); - // The argument area starts at %fp+BIAS+128 in the callee frame, - // %sp+BIAS+128 in ours. - SDValue PtrOff = DAG.getIntPtrConstant(VA.getLocMemOffset() + - Subtarget->getStackPointerBias() + - 128, DL); - PtrOff = DAG.getNode(ISD::ADD, DL, PtrVT, StackPtr, PtrOff); - MemOpChains.push_back( - DAG.getStore(Chain, DL, Arg, PtrOff, MachinePointerInfo())); - } - - // Emit all stores, make sure they occur before the call. - if (!MemOpChains.empty()) - Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOpChains); - - // Build a sequence of CopyToReg nodes glued together with token chain and - // glue operands which copy the outgoing args into registers. The InGlue is - // necessary since all emitted instructions must be stuck together in order - // to pass the live physical registers. - SDValue InGlue; - for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { - Chain = DAG.getCopyToReg(Chain, DL, - RegsToPass[i].first, RegsToPass[i].second, InGlue); - InGlue = Chain.getValue(1); - } - - // If the callee is a GlobalAddress node (quite common, every direct call is) - // turn it into a TargetGlobalAddress node so that legalize doesn't hack it. - // Likewise ExternalSymbol -> TargetExternalSymbol. - SDValue Callee = CLI.Callee; - bool hasReturnsTwice = hasReturnsTwiceAttr(DAG, Callee, CLI.CS); - unsigned TF = isPositionIndependent() ? SparcMCExpr::VK_Sparc_WPLT30 : 0; - if (GlobalAddressSDNode *G = dyn_cast(Callee)) - Callee = DAG.getTargetGlobalAddress(G->getGlobal(), DL, PtrVT, 0, TF); - else if (ExternalSymbolSDNode *E = dyn_cast(Callee)) - Callee = DAG.getTargetExternalSymbol(E->getSymbol(), PtrVT, TF); - - // Build the operands for the call instruction itself. - SmallVector Ops; - Ops.push_back(Chain); - Ops.push_back(Callee); - for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) - Ops.push_back(DAG.getRegister(RegsToPass[i].first, - RegsToPass[i].second.getValueType())); - - // Add a register mask operand representing the call-preserved registers. - const SparcRegisterInfo *TRI = Subtarget->getRegisterInfo(); - const uint32_t *Mask = - ((hasReturnsTwice) ? TRI->getRTCallPreservedMask(CLI.CallConv) - : TRI->getCallPreservedMask(DAG.getMachineFunction(), - CLI.CallConv)); - assert(Mask && "Missing call preserved mask for calling convention"); - Ops.push_back(DAG.getRegisterMask(Mask)); - - // Make sure the CopyToReg nodes are glued to the call instruction which - // consumes the registers. - if (InGlue.getNode()) - Ops.push_back(InGlue); - - // Now the call itself. - SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); - Chain = DAG.getNode(SPISD::CALL, DL, NodeTys, Ops); - InGlue = Chain.getValue(1); - - // Revert the stack pointer immediately after the call. - Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(ArgsSize, DL, true), - DAG.getIntPtrConstant(0, DL, true), InGlue, DL); - InGlue = Chain.getValue(1); - - // Now extract the return values. This is more or less the same as - // LowerFormalArguments_64. - - // Assign locations to each value returned by this call. - SmallVector RVLocs; - CCState RVInfo(CLI.CallConv, CLI.IsVarArg, DAG.getMachineFunction(), RVLocs, - *DAG.getContext()); - - // Set inreg flag manually for codegen generated library calls that - // return float. - if (CLI.Ins.size() == 1 && CLI.Ins[0].VT == MVT::f32 && !CLI.CS) - CLI.Ins[0].Flags.setInReg(); - - RVInfo.AnalyzeCallResult(CLI.Ins, RetCC_Sparc64); - - // Copy all of the result registers out of their specified physreg. - for (unsigned i = 0; i != RVLocs.size(); ++i) { - CCValAssign &VA = RVLocs[i]; - unsigned Reg = toCallerWindow(VA.getLocReg()); - - // When returning 'inreg {i32, i32 }', two consecutive i32 arguments can - // reside in the same register in the high and low bits. Reuse the - // CopyFromReg previous node to avoid duplicate copies. - SDValue RV; - if (RegisterSDNode *SrcReg = dyn_cast(Chain.getOperand(1))) - if (SrcReg->getReg() == Reg && Chain->getOpcode() == ISD::CopyFromReg) - RV = Chain.getValue(0); - - // But usually we'll create a new CopyFromReg for a different register. - if (!RV.getNode()) { - RV = DAG.getCopyFromReg(Chain, DL, Reg, RVLocs[i].getLocVT(), InGlue); - Chain = RV.getValue(1); - InGlue = Chain.getValue(2); - } - - // Get the high bits for i32 struct elements. - if (VA.getValVT() == MVT::i32 && VA.needsCustom()) - RV = DAG.getNode(ISD::SRL, DL, VA.getLocVT(), RV, - DAG.getConstant(32, DL, MVT::i32)); - - // The callee promoted the return value, so insert an Assert?ext SDNode so - // we won't promote the value again in this function. - switch (VA.getLocInfo()) { - case CCValAssign::SExt: - RV = DAG.getNode(ISD::AssertSext, DL, VA.getLocVT(), RV, - DAG.getValueType(VA.getValVT())); - break; - case CCValAssign::ZExt: - RV = DAG.getNode(ISD::AssertZext, DL, VA.getLocVT(), RV, - DAG.getValueType(VA.getValVT())); - break; - default: - break; - } - - // Truncate the register down to the return value type. - if (VA.isExtInLoc()) - RV = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), RV); - - InVals.push_back(RV); - } - - return Chain; -} - -//===----------------------------------------------------------------------===// -// TargetLowering Implementation -//===----------------------------------------------------------------------===// - -TargetLowering::AtomicExpansionKind SparcTargetLowering::shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const { - if (AI->getOperation() == AtomicRMWInst::Xchg && - AI->getType()->getPrimitiveSizeInBits() == 32) - return AtomicExpansionKind::None; // Uses xchg instruction - - return AtomicExpansionKind::CmpXChg; -} - -/// IntCondCCodeToICC - Convert a DAG integer condition code to a SPARC ICC -/// condition. -static SPCC::CondCodes IntCondCCodeToICC(ISD::CondCode CC) { - switch (CC) { - default: llvm_unreachable("Unknown integer condition code!"); - case ISD::SETEQ: return SPCC::ICC_E; - case ISD::SETNE: return SPCC::ICC_NE; - case ISD::SETLT: return SPCC::ICC_L; - case ISD::SETGT: return SPCC::ICC_G; - case ISD::SETLE: return SPCC::ICC_LE; - case ISD::SETGE: return SPCC::ICC_GE; - case ISD::SETULT: return SPCC::ICC_CS; - case ISD::SETULE: return SPCC::ICC_LEU; - case ISD::SETUGT: return SPCC::ICC_GU; - case ISD::SETUGE: return SPCC::ICC_CC; - } -} - -/// FPCondCCodeToFCC - Convert a DAG floatingp oint condition code to a SPARC -/// FCC condition. -static SPCC::CondCodes FPCondCCodeToFCC(ISD::CondCode CC) { - switch (CC) { - default: llvm_unreachable("Unknown fp condition code!"); - case ISD::SETEQ: - case ISD::SETOEQ: return SPCC::FCC_E; - case ISD::SETNE: - case ISD::SETUNE: return SPCC::FCC_NE; - case ISD::SETLT: - case ISD::SETOLT: return SPCC::FCC_L; - case ISD::SETGT: - case ISD::SETOGT: return SPCC::FCC_G; - case ISD::SETLE: - case ISD::SETOLE: return SPCC::FCC_LE; - case ISD::SETGE: - case ISD::SETOGE: return SPCC::FCC_GE; - case ISD::SETULT: return SPCC::FCC_UL; - case ISD::SETULE: return SPCC::FCC_ULE; - case ISD::SETUGT: return SPCC::FCC_UG; - case ISD::SETUGE: return SPCC::FCC_UGE; - case ISD::SETUO: return SPCC::FCC_U; - case ISD::SETO: return SPCC::FCC_O; - case ISD::SETONE: return SPCC::FCC_LG; - case ISD::SETUEQ: return SPCC::FCC_UE; - } -} - -SparcTargetLowering::SparcTargetLowering(const TargetMachine &TM, - const SparcSubtarget &STI) - : TargetLowering(TM), Subtarget(&STI) { - MVT PtrVT = MVT::getIntegerVT(8 * TM.getPointerSize(0)); - - // Instructions which use registers as conditionals examine all the - // bits (as does the pseudo SELECT_CC expansion). I don't think it - // matters much whether it's ZeroOrOneBooleanContent, or - // ZeroOrNegativeOneBooleanContent, so, arbitrarily choose the - // former. - setBooleanContents(ZeroOrOneBooleanContent); - setBooleanVectorContents(ZeroOrOneBooleanContent); - - // Set up the register classes. - addRegisterClass(MVT::i32, &SP::IntRegsRegClass); - if (!Subtarget->useSoftFloat()) { - addRegisterClass(MVT::f32, &SP::FPRegsRegClass); - addRegisterClass(MVT::f64, &SP::DFPRegsRegClass); - addRegisterClass(MVT::f128, &SP::QFPRegsRegClass); - } - if (Subtarget->is64Bit()) { - addRegisterClass(MVT::i64, &SP::I64RegsRegClass); - } else { - // On 32bit sparc, we define a double-register 32bit register - // class, as well. This is modeled in LLVM as a 2-vector of i32. - addRegisterClass(MVT::v2i32, &SP::IntPairRegClass); - - // ...but almost all operations must be expanded, so set that as - // the default. - for (unsigned Op = 0; Op < ISD::BUILTIN_OP_END; ++Op) { - setOperationAction(Op, MVT::v2i32, Expand); - } - // Truncating/extending stores/loads are also not supported. - for (MVT VT : MVT::integer_vector_valuetypes()) { - setLoadExtAction(ISD::SEXTLOAD, VT, MVT::v2i32, Expand); - setLoadExtAction(ISD::ZEXTLOAD, VT, MVT::v2i32, Expand); - setLoadExtAction(ISD::EXTLOAD, VT, MVT::v2i32, Expand); - - setLoadExtAction(ISD::SEXTLOAD, MVT::v2i32, VT, Expand); - setLoadExtAction(ISD::ZEXTLOAD, MVT::v2i32, VT, Expand); - setLoadExtAction(ISD::EXTLOAD, MVT::v2i32, VT, Expand); - - setTruncStoreAction(VT, MVT::v2i32, Expand); - setTruncStoreAction(MVT::v2i32, VT, Expand); - } - // However, load and store *are* legal. - setOperationAction(ISD::LOAD, MVT::v2i32, Legal); - setOperationAction(ISD::STORE, MVT::v2i32, Legal); - setOperationAction(ISD::EXTRACT_VECTOR_ELT, MVT::v2i32, Legal); - setOperationAction(ISD::BUILD_VECTOR, MVT::v2i32, Legal); - - // And we need to promote i64 loads/stores into vector load/store - setOperationAction(ISD::LOAD, MVT::i64, Custom); - setOperationAction(ISD::STORE, MVT::i64, Custom); - - // Sadly, this doesn't work: - // AddPromotedToType(ISD::LOAD, MVT::i64, MVT::v2i32); - // AddPromotedToType(ISD::STORE, MVT::i64, MVT::v2i32); - } - - // Turn FP extload into load/fpextend - for (MVT VT : MVT::fp_valuetypes()) { - setLoadExtAction(ISD::EXTLOAD, VT, MVT::f32, Expand); - setLoadExtAction(ISD::EXTLOAD, VT, MVT::f64, Expand); - } - - // Sparc doesn't have i1 sign extending load - for (MVT VT : MVT::integer_valuetypes()) - setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i1, Promote); - - // Turn FP truncstore into trunc + store. - setTruncStoreAction(MVT::f64, MVT::f32, Expand); - setTruncStoreAction(MVT::f128, MVT::f32, Expand); - setTruncStoreAction(MVT::f128, MVT::f64, Expand); - - // Custom legalize GlobalAddress nodes into LO/HI parts. - setOperationAction(ISD::GlobalAddress, PtrVT, Custom); - setOperationAction(ISD::GlobalTLSAddress, PtrVT, Custom); - setOperationAction(ISD::ConstantPool, PtrVT, Custom); - setOperationAction(ISD::BlockAddress, PtrVT, Custom); - - // Sparc doesn't have sext_inreg, replace them with shl/sra - setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16, Expand); - setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8 , Expand); - setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1 , Expand); - - // Sparc has no REM or DIVREM operations. - setOperationAction(ISD::UREM, MVT::i32, Expand); - setOperationAction(ISD::SREM, MVT::i32, Expand); - setOperationAction(ISD::SDIVREM, MVT::i32, Expand); - setOperationAction(ISD::UDIVREM, MVT::i32, Expand); - - // ... nor does SparcV9. - if (Subtarget->is64Bit()) { - setOperationAction(ISD::UREM, MVT::i64, Expand); - setOperationAction(ISD::SREM, MVT::i64, Expand); - setOperationAction(ISD::SDIVREM, MVT::i64, Expand); - setOperationAction(ISD::UDIVREM, MVT::i64, Expand); - } - - // Custom expand fp<->sint - setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom); - setOperationAction(ISD::SINT_TO_FP, MVT::i32, Custom); - setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom); - setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom); - - // Custom Expand fp<->uint - setOperationAction(ISD::FP_TO_UINT, MVT::i32, Custom); - setOperationAction(ISD::UINT_TO_FP, MVT::i32, Custom); - setOperationAction(ISD::FP_TO_UINT, MVT::i64, Custom); - setOperationAction(ISD::UINT_TO_FP, MVT::i64, Custom); - - setOperationAction(ISD::BITCAST, MVT::f32, Expand); - setOperationAction(ISD::BITCAST, MVT::i32, Expand); - - // Sparc has no select or setcc: expand to SELECT_CC. - setOperationAction(ISD::SELECT, MVT::i32, Expand); - setOperationAction(ISD::SELECT, MVT::f32, Expand); - setOperationAction(ISD::SELECT, MVT::f64, Expand); - setOperationAction(ISD::SELECT, MVT::f128, Expand); - - setOperationAction(ISD::SETCC, MVT::i32, Expand); - setOperationAction(ISD::SETCC, MVT::f32, Expand); - setOperationAction(ISD::SETCC, MVT::f64, Expand); - setOperationAction(ISD::SETCC, MVT::f128, Expand); - - // Sparc doesn't have BRCOND either, it has BR_CC. - setOperationAction(ISD::BRCOND, MVT::Other, Expand); - setOperationAction(ISD::BRIND, MVT::Other, Expand); - setOperationAction(ISD::BR_JT, MVT::Other, Expand); - setOperationAction(ISD::BR_CC, MVT::i32, Custom); - setOperationAction(ISD::BR_CC, MVT::f32, Custom); - setOperationAction(ISD::BR_CC, MVT::f64, Custom); - setOperationAction(ISD::BR_CC, MVT::f128, Custom); - - setOperationAction(ISD::SELECT_CC, MVT::i32, Custom); - setOperationAction(ISD::SELECT_CC, MVT::f32, Custom); - setOperationAction(ISD::SELECT_CC, MVT::f64, Custom); - setOperationAction(ISD::SELECT_CC, MVT::f128, Custom); - - setOperationAction(ISD::ADDC, MVT::i32, Custom); - setOperationAction(ISD::ADDE, MVT::i32, Custom); - setOperationAction(ISD::SUBC, MVT::i32, Custom); - setOperationAction(ISD::SUBE, MVT::i32, Custom); - - if (Subtarget->is64Bit()) { - setOperationAction(ISD::ADDC, MVT::i64, Custom); - setOperationAction(ISD::ADDE, MVT::i64, Custom); - setOperationAction(ISD::SUBC, MVT::i64, Custom); - setOperationAction(ISD::SUBE, MVT::i64, Custom); - setOperationAction(ISD::BITCAST, MVT::f64, Expand); - setOperationAction(ISD::BITCAST, MVT::i64, Expand); - setOperationAction(ISD::SELECT, MVT::i64, Expand); - setOperationAction(ISD::SETCC, MVT::i64, Expand); - setOperationAction(ISD::BR_CC, MVT::i64, Custom); - setOperationAction(ISD::SELECT_CC, MVT::i64, Custom); - - setOperationAction(ISD::CTPOP, MVT::i64, - Subtarget->usePopc() ? Legal : Expand); - setOperationAction(ISD::CTTZ , MVT::i64, Expand); - setOperationAction(ISD::CTLZ , MVT::i64, Expand); - setOperationAction(ISD::BSWAP, MVT::i64, Expand); - setOperationAction(ISD::ROTL , MVT::i64, Expand); - setOperationAction(ISD::ROTR , MVT::i64, Expand); - setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64, Custom); - } - - // ATOMICs. - // Atomics are supported on SparcV9. 32-bit atomics are also - // supported by some Leon SparcV8 variants. Otherwise, atomics - // are unsupported. - if (Subtarget->isV9()) - setMaxAtomicSizeInBitsSupported(64); - else if (Subtarget->hasLeonCasa()) - setMaxAtomicSizeInBitsSupported(32); - else - setMaxAtomicSizeInBitsSupported(0); - - setMinCmpXchgSizeInBits(32); - - setOperationAction(ISD::ATOMIC_SWAP, MVT::i32, Legal); - - setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Legal); - - // Custom Lower Atomic LOAD/STORE - setOperationAction(ISD::ATOMIC_LOAD, MVT::i32, Custom); - setOperationAction(ISD::ATOMIC_STORE, MVT::i32, Custom); - - if (Subtarget->is64Bit()) { - setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i64, Legal); - setOperationAction(ISD::ATOMIC_SWAP, MVT::i64, Legal); - setOperationAction(ISD::ATOMIC_LOAD, MVT::i64, Custom); - setOperationAction(ISD::ATOMIC_STORE, MVT::i64, Custom); - } - - if (!Subtarget->is64Bit()) { - // These libcalls are not available in 32-bit. - setLibcallName(RTLIB::SHL_I128, nullptr); - setLibcallName(RTLIB::SRL_I128, nullptr); - setLibcallName(RTLIB::SRA_I128, nullptr); - } - - if (!Subtarget->isV9()) { - // SparcV8 does not have FNEGD and FABSD. - setOperationAction(ISD::FNEG, MVT::f64, Custom); - setOperationAction(ISD::FABS, MVT::f64, Custom); - } - - setOperationAction(ISD::FSIN , MVT::f128, Expand); - setOperationAction(ISD::FCOS , MVT::f128, Expand); - setOperationAction(ISD::FSINCOS, MVT::f128, Expand); - setOperationAction(ISD::FREM , MVT::f128, Expand); - setOperationAction(ISD::FMA , MVT::f128, Expand); - setOperationAction(ISD::FSIN , MVT::f64, Expand); - setOperationAction(ISD::FCOS , MVT::f64, Expand); - setOperationAction(ISD::FSINCOS, MVT::f64, Expand); - setOperationAction(ISD::FREM , MVT::f64, Expand); - setOperationAction(ISD::FMA , MVT::f64, Expand); - setOperationAction(ISD::FSIN , MVT::f32, Expand); - setOperationAction(ISD::FCOS , MVT::f32, Expand); - setOperationAction(ISD::FSINCOS, MVT::f32, Expand); - setOperationAction(ISD::FREM , MVT::f32, Expand); - setOperationAction(ISD::FMA , MVT::f32, Expand); - setOperationAction(ISD::CTTZ , MVT::i32, Expand); - setOperationAction(ISD::CTLZ , MVT::i32, Expand); - setOperationAction(ISD::ROTL , MVT::i32, Expand); - setOperationAction(ISD::ROTR , MVT::i32, Expand); - setOperationAction(ISD::BSWAP, MVT::i32, Expand); - setOperationAction(ISD::FCOPYSIGN, MVT::f128, Expand); - setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand); - setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand); - setOperationAction(ISD::FPOW , MVT::f128, Expand); - setOperationAction(ISD::FPOW , MVT::f64, Expand); - setOperationAction(ISD::FPOW , MVT::f32, Expand); - - setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand); - setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand); - setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand); - - // Expands to [SU]MUL_LOHI. - setOperationAction(ISD::MULHU, MVT::i32, Expand); - setOperationAction(ISD::MULHS, MVT::i32, Expand); - setOperationAction(ISD::MUL, MVT::i32, Expand); - - if (Subtarget->useSoftMulDiv()) { - // .umul works for both signed and unsigned - setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand); - setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand); - setLibcallName(RTLIB::MUL_I32, ".umul"); - - setOperationAction(ISD::SDIV, MVT::i32, Expand); - setLibcallName(RTLIB::SDIV_I32, ".div"); - - setOperationAction(ISD::UDIV, MVT::i32, Expand); - setLibcallName(RTLIB::UDIV_I32, ".udiv"); - - setLibcallName(RTLIB::SREM_I32, ".rem"); - setLibcallName(RTLIB::UREM_I32, ".urem"); - } - - if (Subtarget->is64Bit()) { - setOperationAction(ISD::UMUL_LOHI, MVT::i64, Expand); - setOperationAction(ISD::SMUL_LOHI, MVT::i64, Expand); - setOperationAction(ISD::MULHU, MVT::i64, Expand); - setOperationAction(ISD::MULHS, MVT::i64, Expand); - - setOperationAction(ISD::UMULO, MVT::i64, Custom); - setOperationAction(ISD::SMULO, MVT::i64, Custom); - - setOperationAction(ISD::SHL_PARTS, MVT::i64, Expand); - setOperationAction(ISD::SRA_PARTS, MVT::i64, Expand); - setOperationAction(ISD::SRL_PARTS, MVT::i64, Expand); - } - - // VASTART needs to be custom lowered to use the VarArgsFrameIndex. - setOperationAction(ISD::VASTART , MVT::Other, Custom); - // VAARG needs to be lowered to not do unaligned accesses for doubles. - setOperationAction(ISD::VAARG , MVT::Other, Custom); - - setOperationAction(ISD::TRAP , MVT::Other, Legal); - setOperationAction(ISD::DEBUGTRAP , MVT::Other, Legal); - - // Use the default implementation. - setOperationAction(ISD::VACOPY , MVT::Other, Expand); - setOperationAction(ISD::VAEND , MVT::Other, Expand); - setOperationAction(ISD::STACKSAVE , MVT::Other, Expand); - setOperationAction(ISD::STACKRESTORE , MVT::Other, Expand); - setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32 , Custom); - - setStackPointerRegisterToSaveRestore(SP::O6); - - setOperationAction(ISD::CTPOP, MVT::i32, - Subtarget->usePopc() ? Legal : Expand); - - if (Subtarget->isV9() && Subtarget->hasHardQuad()) { - setOperationAction(ISD::LOAD, MVT::f128, Legal); - setOperationAction(ISD::STORE, MVT::f128, Legal); - } else { - setOperationAction(ISD::LOAD, MVT::f128, Custom); - setOperationAction(ISD::STORE, MVT::f128, Custom); - } - - if (Subtarget->hasHardQuad()) { - setOperationAction(ISD::FADD, MVT::f128, Legal); - setOperationAction(ISD::FSUB, MVT::f128, Legal); - setOperationAction(ISD::FMUL, MVT::f128, Legal); - setOperationAction(ISD::FDIV, MVT::f128, Legal); - setOperationAction(ISD::FSQRT, MVT::f128, Legal); - setOperationAction(ISD::FP_EXTEND, MVT::f128, Legal); - setOperationAction(ISD::FP_ROUND, MVT::f64, Legal); - if (Subtarget->isV9()) { - setOperationAction(ISD::FNEG, MVT::f128, Legal); - setOperationAction(ISD::FABS, MVT::f128, Legal); - } else { - setOperationAction(ISD::FNEG, MVT::f128, Custom); - setOperationAction(ISD::FABS, MVT::f128, Custom); - } - - if (!Subtarget->is64Bit()) { - setLibcallName(RTLIB::FPTOSINT_F128_I64, "_Q_qtoll"); - setLibcallName(RTLIB::FPTOUINT_F128_I64, "_Q_qtoull"); - setLibcallName(RTLIB::SINTTOFP_I64_F128, "_Q_lltoq"); - setLibcallName(RTLIB::UINTTOFP_I64_F128, "_Q_ulltoq"); - } - - } else { - // Custom legalize f128 operations. - - setOperationAction(ISD::FADD, MVT::f128, Custom); - setOperationAction(ISD::FSUB, MVT::f128, Custom); - setOperationAction(ISD::FMUL, MVT::f128, Custom); - setOperationAction(ISD::FDIV, MVT::f128, Custom); - setOperationAction(ISD::FSQRT, MVT::f128, Custom); - setOperationAction(ISD::FNEG, MVT::f128, Custom); - setOperationAction(ISD::FABS, MVT::f128, Custom); - - setOperationAction(ISD::FP_EXTEND, MVT::f128, Custom); - setOperationAction(ISD::FP_ROUND, MVT::f64, Custom); - setOperationAction(ISD::FP_ROUND, MVT::f32, Custom); - - // Setup Runtime library names. - if (Subtarget->is64Bit() && !Subtarget->useSoftFloat()) { - setLibcallName(RTLIB::ADD_F128, "_Qp_add"); - setLibcallName(RTLIB::SUB_F128, "_Qp_sub"); - setLibcallName(RTLIB::MUL_F128, "_Qp_mul"); - setLibcallName(RTLIB::DIV_F128, "_Qp_div"); - setLibcallName(RTLIB::SQRT_F128, "_Qp_sqrt"); - setLibcallName(RTLIB::FPTOSINT_F128_I32, "_Qp_qtoi"); - setLibcallName(RTLIB::FPTOUINT_F128_I32, "_Qp_qtoui"); - setLibcallName(RTLIB::SINTTOFP_I32_F128, "_Qp_itoq"); - setLibcallName(RTLIB::UINTTOFP_I32_F128, "_Qp_uitoq"); - setLibcallName(RTLIB::FPTOSINT_F128_I64, "_Qp_qtox"); - setLibcallName(RTLIB::FPTOUINT_F128_I64, "_Qp_qtoux"); - setLibcallName(RTLIB::SINTTOFP_I64_F128, "_Qp_xtoq"); - setLibcallName(RTLIB::UINTTOFP_I64_F128, "_Qp_uxtoq"); - setLibcallName(RTLIB::FPEXT_F32_F128, "_Qp_stoq"); - setLibcallName(RTLIB::FPEXT_F64_F128, "_Qp_dtoq"); - setLibcallName(RTLIB::FPROUND_F128_F32, "_Qp_qtos"); - setLibcallName(RTLIB::FPROUND_F128_F64, "_Qp_qtod"); - } else if (!Subtarget->useSoftFloat()) { - setLibcallName(RTLIB::ADD_F128, "_Q_add"); - setLibcallName(RTLIB::SUB_F128, "_Q_sub"); - setLibcallName(RTLIB::MUL_F128, "_Q_mul"); - setLibcallName(RTLIB::DIV_F128, "_Q_div"); - setLibcallName(RTLIB::SQRT_F128, "_Q_sqrt"); - setLibcallName(RTLIB::FPTOSINT_F128_I32, "_Q_qtoi"); - setLibcallName(RTLIB::FPTOUINT_F128_I32, "_Q_qtou"); - setLibcallName(RTLIB::SINTTOFP_I32_F128, "_Q_itoq"); - setLibcallName(RTLIB::UINTTOFP_I32_F128, "_Q_utoq"); - setLibcallName(RTLIB::FPTOSINT_F128_I64, "_Q_qtoll"); - setLibcallName(RTLIB::FPTOUINT_F128_I64, "_Q_qtoull"); - setLibcallName(RTLIB::SINTTOFP_I64_F128, "_Q_lltoq"); - setLibcallName(RTLIB::UINTTOFP_I64_F128, "_Q_ulltoq"); - setLibcallName(RTLIB::FPEXT_F32_F128, "_Q_stoq"); - setLibcallName(RTLIB::FPEXT_F64_F128, "_Q_dtoq"); - setLibcallName(RTLIB::FPROUND_F128_F32, "_Q_qtos"); - setLibcallName(RTLIB::FPROUND_F128_F64, "_Q_qtod"); - } - } - - if (Subtarget->fixAllFDIVSQRT()) { - // Promote FDIVS and FSQRTS to FDIVD and FSQRTD instructions instead as - // the former instructions generate errata on LEON processors. - setOperationAction(ISD::FDIV, MVT::f32, Promote); - setOperationAction(ISD::FSQRT, MVT::f32, Promote); - } - - if (Subtarget->hasNoFMULS()) { - setOperationAction(ISD::FMUL, MVT::f32, Promote); - } - - // Custom combine bitcast between f64 and v2i32 - if (!Subtarget->is64Bit()) - setTargetDAGCombine(ISD::BITCAST); - - if (Subtarget->hasLeonCycleCounter()) - setOperationAction(ISD::READCYCLECOUNTER, MVT::i64, Custom); - - setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom); - - setMinFunctionAlignment(2); - - computeRegisterProperties(Subtarget->getRegisterInfo()); -} - -bool SparcTargetLowering::useSoftFloat() const { - return Subtarget->useSoftFloat(); -} - -const char *SparcTargetLowering::getTargetNodeName(unsigned Opcode) const { - switch ((SPISD::NodeType)Opcode) { - case SPISD::FIRST_NUMBER: break; - case SPISD::CMPICC: return "SPISD::CMPICC"; - case SPISD::CMPFCC: return "SPISD::CMPFCC"; - case SPISD::BRICC: return "SPISD::BRICC"; - case SPISD::BRXCC: return "SPISD::BRXCC"; - case SPISD::BRFCC: return "SPISD::BRFCC"; - case SPISD::SELECT_ICC: return "SPISD::SELECT_ICC"; - case SPISD::SELECT_XCC: return "SPISD::SELECT_XCC"; - case SPISD::SELECT_FCC: return "SPISD::SELECT_FCC"; - case SPISD::Hi: return "SPISD::Hi"; - case SPISD::Lo: return "SPISD::Lo"; - case SPISD::FTOI: return "SPISD::FTOI"; - case SPISD::ITOF: return "SPISD::ITOF"; - case SPISD::FTOX: return "SPISD::FTOX"; - case SPISD::XTOF: return "SPISD::XTOF"; - case SPISD::CALL: return "SPISD::CALL"; - case SPISD::RET_FLAG: return "SPISD::RET_FLAG"; - case SPISD::GLOBAL_BASE_REG: return "SPISD::GLOBAL_BASE_REG"; - case SPISD::FLUSHW: return "SPISD::FLUSHW"; - case SPISD::TLS_ADD: return "SPISD::TLS_ADD"; - case SPISD::TLS_LD: return "SPISD::TLS_LD"; - case SPISD::TLS_CALL: return "SPISD::TLS_CALL"; - } - return nullptr; -} - -EVT SparcTargetLowering::getSetCCResultType(const DataLayout &, LLVMContext &, - EVT VT) const { - if (!VT.isVector()) - return MVT::i32; - return VT.changeVectorElementTypeToInteger(); -} - -/// isMaskedValueZeroForTargetNode - Return true if 'Op & Mask' is known to -/// be zero. Op is expected to be a target specific node. Used by DAG -/// combiner. -void SparcTargetLowering::computeKnownBitsForTargetNode - (const SDValue Op, - KnownBits &Known, - const APInt &DemandedElts, - const SelectionDAG &DAG, - unsigned Depth) const { - KnownBits Known2; - Known.resetAll(); - - switch (Op.getOpcode()) { - default: break; - case SPISD::SELECT_ICC: - case SPISD::SELECT_XCC: - case SPISD::SELECT_FCC: - Known = DAG.computeKnownBits(Op.getOperand(1), Depth + 1); - Known2 = DAG.computeKnownBits(Op.getOperand(0), Depth + 1); - - // Only known if known in both the LHS and RHS. - Known.One &= Known2.One; - Known.Zero &= Known2.Zero; - break; - } -} - -// Look at LHS/RHS/CC and see if they are a lowered setcc instruction. If so -// set LHS/RHS and SPCC to the LHS/RHS of the setcc and SPCC to the condition. -static void LookThroughSetCC(SDValue &LHS, SDValue &RHS, - ISD::CondCode CC, unsigned &SPCC) { - if (isNullConstant(RHS) && - CC == ISD::SETNE && - (((LHS.getOpcode() == SPISD::SELECT_ICC || - LHS.getOpcode() == SPISD::SELECT_XCC) && - LHS.getOperand(3).getOpcode() == SPISD::CMPICC) || - (LHS.getOpcode() == SPISD::SELECT_FCC && - LHS.getOperand(3).getOpcode() == SPISD::CMPFCC)) && - isOneConstant(LHS.getOperand(0)) && - isNullConstant(LHS.getOperand(1))) { - SDValue CMPCC = LHS.getOperand(3); - SPCC = cast(LHS.getOperand(2))->getZExtValue(); - LHS = CMPCC.getOperand(0); - RHS = CMPCC.getOperand(1); - } -} - -// Convert to a target node and set target flags. -SDValue SparcTargetLowering::withTargetFlags(SDValue Op, unsigned TF, - SelectionDAG &DAG) const { - if (const GlobalAddressSDNode *GA = dyn_cast(Op)) - return DAG.getTargetGlobalAddress(GA->getGlobal(), - SDLoc(GA), - GA->getValueType(0), - GA->getOffset(), TF); - - if (const ConstantPoolSDNode *CP = dyn_cast(Op)) - return DAG.getTargetConstantPool(CP->getConstVal(), - CP->getValueType(0), - CP->getAlignment(), - CP->getOffset(), TF); - - if (const BlockAddressSDNode *BA = dyn_cast(Op)) - return DAG.getTargetBlockAddress(BA->getBlockAddress(), - Op.getValueType(), - 0, - TF); - - if (const ExternalSymbolSDNode *ES = dyn_cast(Op)) - return DAG.getTargetExternalSymbol(ES->getSymbol(), - ES->getValueType(0), TF); - - llvm_unreachable("Unhandled address SDNode"); -} - -// Split Op into high and low parts according to HiTF and LoTF. -// Return an ADD node combining the parts. -SDValue SparcTargetLowering::makeHiLoPair(SDValue Op, - unsigned HiTF, unsigned LoTF, - SelectionDAG &DAG) const { - SDLoc DL(Op); - EVT VT = Op.getValueType(); - SDValue Hi = DAG.getNode(SPISD::Hi, DL, VT, withTargetFlags(Op, HiTF, DAG)); - SDValue Lo = DAG.getNode(SPISD::Lo, DL, VT, withTargetFlags(Op, LoTF, DAG)); - return DAG.getNode(ISD::ADD, DL, VT, Hi, Lo); -} - -// Build SDNodes for producing an address from a GlobalAddress, ConstantPool, -// or ExternalSymbol SDNode. -SDValue SparcTargetLowering::makeAddress(SDValue Op, SelectionDAG &DAG) const { - SDLoc DL(Op); - EVT VT = getPointerTy(DAG.getDataLayout()); - - // Handle PIC mode first. SPARC needs a got load for every variable! - if (isPositionIndependent()) { - const Module *M = DAG.getMachineFunction().getFunction().getParent(); - PICLevel::Level picLevel = M->getPICLevel(); - SDValue Idx; - - if (picLevel == PICLevel::SmallPIC) { - // This is the pic13 code model, the GOT is known to be smaller than 8KiB. - Idx = DAG.getNode(SPISD::Lo, DL, Op.getValueType(), - withTargetFlags(Op, SparcMCExpr::VK_Sparc_GOT13, DAG)); - } else { - // This is the pic32 code model, the GOT is known to be smaller than 4GB. - Idx = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_GOT22, - SparcMCExpr::VK_Sparc_GOT10, DAG); - } - - SDValue GlobalBase = DAG.getNode(SPISD::GLOBAL_BASE_REG, DL, VT); - SDValue AbsAddr = DAG.getNode(ISD::ADD, DL, VT, GlobalBase, Idx); - // GLOBAL_BASE_REG codegen'ed with call. Inform MFI that this - // function has calls. - MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo(); - MFI.setHasCalls(true); - return DAG.getLoad(VT, DL, DAG.getEntryNode(), AbsAddr, - MachinePointerInfo::getGOT(DAG.getMachineFunction())); - } - - // This is one of the absolute code models. - switch(getTargetMachine().getCodeModel()) { - default: - llvm_unreachable("Unsupported absolute code model"); - case CodeModel::Small: - // abs32. - return makeHiLoPair(Op, SparcMCExpr::VK_Sparc_HI, - SparcMCExpr::VK_Sparc_LO, DAG); - case CodeModel::Medium: { - // abs44. - SDValue H44 = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_H44, - SparcMCExpr::VK_Sparc_M44, DAG); - H44 = DAG.getNode(ISD::SHL, DL, VT, H44, DAG.getConstant(12, DL, MVT::i32)); - SDValue L44 = withTargetFlags(Op, SparcMCExpr::VK_Sparc_L44, DAG); - L44 = DAG.getNode(SPISD::Lo, DL, VT, L44); - return DAG.getNode(ISD::ADD, DL, VT, H44, L44); - } - case CodeModel::Large: { - // abs64. - SDValue Hi = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_HH, - SparcMCExpr::VK_Sparc_HM, DAG); - Hi = DAG.getNode(ISD::SHL, DL, VT, Hi, DAG.getConstant(32, DL, MVT::i32)); - SDValue Lo = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_HI, - SparcMCExpr::VK_Sparc_LO, DAG); - return DAG.getNode(ISD::ADD, DL, VT, Hi, Lo); - } - } -} - -SDValue SparcTargetLowering::LowerGlobalAddress(SDValue Op, - SelectionDAG &DAG) const { - return makeAddress(Op, DAG); -} - -SDValue SparcTargetLowering::LowerConstantPool(SDValue Op, - SelectionDAG &DAG) const { - return makeAddress(Op, DAG); -} - -SDValue SparcTargetLowering::LowerBlockAddress(SDValue Op, - SelectionDAG &DAG) const { - return makeAddress(Op, DAG); -} - -SDValue SparcTargetLowering::LowerGlobalTLSAddress(SDValue Op, - SelectionDAG &DAG) const { - - GlobalAddressSDNode *GA = cast(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) { - unsigned HiTF = ((model == TLSModel::GeneralDynamic) - ? SparcMCExpr::VK_Sparc_TLS_GD_HI22 - : SparcMCExpr::VK_Sparc_TLS_LDM_HI22); - unsigned LoTF = ((model == TLSModel::GeneralDynamic) - ? SparcMCExpr::VK_Sparc_TLS_GD_LO10 - : SparcMCExpr::VK_Sparc_TLS_LDM_LO10); - unsigned addTF = ((model == TLSModel::GeneralDynamic) - ? SparcMCExpr::VK_Sparc_TLS_GD_ADD - : SparcMCExpr::VK_Sparc_TLS_LDM_ADD); - unsigned callTF = ((model == TLSModel::GeneralDynamic) - ? SparcMCExpr::VK_Sparc_TLS_GD_CALL - : SparcMCExpr::VK_Sparc_TLS_LDM_CALL); - - SDValue HiLo = makeHiLoPair(Op, HiTF, LoTF, DAG); - SDValue Base = DAG.getNode(SPISD::GLOBAL_BASE_REG, DL, PtrVT); - SDValue Argument = DAG.getNode(SPISD::TLS_ADD, DL, PtrVT, Base, HiLo, - withTargetFlags(Op, addTF, DAG)); - - SDValue Chain = DAG.getEntryNode(); - SDValue InFlag; - - Chain = DAG.getCALLSEQ_START(Chain, 1, 0, DL); - Chain = DAG.getCopyToReg(Chain, DL, SP::O0, Argument, InFlag); - InFlag = Chain.getValue(1); - SDValue Callee = DAG.getTargetExternalSymbol("__tls_get_addr", PtrVT); - SDValue Symbol = withTargetFlags(Op, callTF, DAG); - - SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); - const uint32_t *Mask = Subtarget->getRegisterInfo()->getCallPreservedMask( - DAG.getMachineFunction(), CallingConv::C); - assert(Mask && "Missing call preserved mask for calling convention"); - SDValue Ops[] = {Chain, - Callee, - Symbol, - DAG.getRegister(SP::O0, PtrVT), - DAG.getRegisterMask(Mask), - InFlag}; - Chain = DAG.getNode(SPISD::TLS_CALL, DL, NodeTys, Ops); - InFlag = Chain.getValue(1); - Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(1, DL, true), - DAG.getIntPtrConstant(0, DL, true), InFlag, DL); - InFlag = Chain.getValue(1); - SDValue Ret = DAG.getCopyFromReg(Chain, DL, SP::O0, PtrVT, InFlag); - - if (model != TLSModel::LocalDynamic) - return Ret; - - SDValue Hi = DAG.getNode(SPISD::Hi, DL, PtrVT, - withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LDO_HIX22, DAG)); - SDValue Lo = DAG.getNode(SPISD::Lo, DL, PtrVT, - withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LDO_LOX10, DAG)); - HiLo = DAG.getNode(ISD::XOR, DL, PtrVT, Hi, Lo); - return DAG.getNode(SPISD::TLS_ADD, DL, PtrVT, Ret, HiLo, - withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LDO_ADD, DAG)); - } - - if (model == TLSModel::InitialExec) { - unsigned ldTF = ((PtrVT == MVT::i64)? SparcMCExpr::VK_Sparc_TLS_IE_LDX - : SparcMCExpr::VK_Sparc_TLS_IE_LD); - - SDValue Base = DAG.getNode(SPISD::GLOBAL_BASE_REG, DL, PtrVT); - - // GLOBAL_BASE_REG codegen'ed with call. Inform MFI that this - // function has calls. - MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo(); - MFI.setHasCalls(true); - - SDValue TGA = makeHiLoPair(Op, - SparcMCExpr::VK_Sparc_TLS_IE_HI22, - SparcMCExpr::VK_Sparc_TLS_IE_LO10, DAG); - SDValue Ptr = DAG.getNode(ISD::ADD, DL, PtrVT, Base, TGA); - SDValue Offset = DAG.getNode(SPISD::TLS_LD, - DL, PtrVT, Ptr, - withTargetFlags(Op, ldTF, DAG)); - return DAG.getNode(SPISD::TLS_ADD, DL, PtrVT, - DAG.getRegister(SP::G7, PtrVT), Offset, - withTargetFlags(Op, - SparcMCExpr::VK_Sparc_TLS_IE_ADD, DAG)); - } - - assert(model == TLSModel::LocalExec); - SDValue Hi = DAG.getNode(SPISD::Hi, DL, PtrVT, - withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LE_HIX22, DAG)); - SDValue Lo = DAG.getNode(SPISD::Lo, DL, PtrVT, - withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LE_LOX10, DAG)); - SDValue Offset = DAG.getNode(ISD::XOR, DL, PtrVT, Hi, Lo); - - return DAG.getNode(ISD::ADD, DL, PtrVT, - DAG.getRegister(SP::G7, PtrVT), Offset); -} - -SDValue SparcTargetLowering::LowerF128_LibCallArg(SDValue Chain, - ArgListTy &Args, SDValue Arg, - const SDLoc &DL, - SelectionDAG &DAG) const { - MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo(); - EVT ArgVT = Arg.getValueType(); - Type *ArgTy = ArgVT.getTypeForEVT(*DAG.getContext()); - - ArgListEntry Entry; - Entry.Node = Arg; - Entry.Ty = ArgTy; - - if (ArgTy->isFP128Ty()) { - // Create a stack object and pass the pointer to the library function. - int FI = MFI.CreateStackObject(16, 8, false); - SDValue FIPtr = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout())); - Chain = DAG.getStore(Chain, DL, Entry.Node, FIPtr, MachinePointerInfo(), - /* Alignment = */ 8); - - Entry.Node = FIPtr; - Entry.Ty = PointerType::getUnqual(ArgTy); - } - Args.push_back(Entry); - return Chain; -} - -SDValue -SparcTargetLowering::LowerF128Op(SDValue Op, SelectionDAG &DAG, - const char *LibFuncName, - unsigned numArgs) const { - - ArgListTy Args; - - MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo(); - auto PtrVT = getPointerTy(DAG.getDataLayout()); - - SDValue Callee = DAG.getExternalSymbol(LibFuncName, PtrVT); - Type *RetTy = Op.getValueType().getTypeForEVT(*DAG.getContext()); - Type *RetTyABI = RetTy; - SDValue Chain = DAG.getEntryNode(); - SDValue RetPtr; - - if (RetTy->isFP128Ty()) { - // Create a Stack Object to receive the return value of type f128. - ArgListEntry Entry; - int RetFI = MFI.CreateStackObject(16, 8, false); - RetPtr = DAG.getFrameIndex(RetFI, PtrVT); - Entry.Node = RetPtr; - Entry.Ty = PointerType::getUnqual(RetTy); - if (!Subtarget->is64Bit()) - Entry.IsSRet = true; - Entry.IsReturned = false; - Args.push_back(Entry); - RetTyABI = Type::getVoidTy(*DAG.getContext()); - } - - assert(Op->getNumOperands() >= numArgs && "Not enough operands!"); - for (unsigned i = 0, e = numArgs; i != e; ++i) { - Chain = LowerF128_LibCallArg(Chain, Args, Op.getOperand(i), SDLoc(Op), DAG); - } - TargetLowering::CallLoweringInfo CLI(DAG); - CLI.setDebugLoc(SDLoc(Op)).setChain(Chain) - .setCallee(CallingConv::C, RetTyABI, Callee, std::move(Args)); - - std::pair CallInfo = LowerCallTo(CLI); - - // chain is in second result. - if (RetTyABI == RetTy) - return CallInfo.first; - - assert (RetTy->isFP128Ty() && "Unexpected return type!"); - - Chain = CallInfo.second; - - // Load RetPtr to get the return value. - return DAG.getLoad(Op.getValueType(), SDLoc(Op), Chain, RetPtr, - MachinePointerInfo(), /* Alignment = */ 8); -} - -SDValue SparcTargetLowering::LowerF128Compare(SDValue LHS, SDValue RHS, - unsigned &SPCC, const SDLoc &DL, - SelectionDAG &DAG) const { - - const char *LibCall = nullptr; - bool is64Bit = Subtarget->is64Bit(); - switch(SPCC) { - default: llvm_unreachable("Unhandled conditional code!"); - case SPCC::FCC_E : LibCall = is64Bit? "_Qp_feq" : "_Q_feq"; break; - case SPCC::FCC_NE : LibCall = is64Bit? "_Qp_fne" : "_Q_fne"; break; - case SPCC::FCC_L : LibCall = is64Bit? "_Qp_flt" : "_Q_flt"; break; - case SPCC::FCC_G : LibCall = is64Bit? "_Qp_fgt" : "_Q_fgt"; break; - case SPCC::FCC_LE : LibCall = is64Bit? "_Qp_fle" : "_Q_fle"; break; - case SPCC::FCC_GE : LibCall = is64Bit? "_Qp_fge" : "_Q_fge"; break; - case SPCC::FCC_UL : - case SPCC::FCC_ULE: - case SPCC::FCC_UG : - case SPCC::FCC_UGE: - case SPCC::FCC_U : - case SPCC::FCC_O : - case SPCC::FCC_LG : - case SPCC::FCC_UE : LibCall = is64Bit? "_Qp_cmp" : "_Q_cmp"; break; - } - - auto PtrVT = getPointerTy(DAG.getDataLayout()); - SDValue Callee = DAG.getExternalSymbol(LibCall, PtrVT); - Type *RetTy = Type::getInt32Ty(*DAG.getContext()); - ArgListTy Args; - SDValue Chain = DAG.getEntryNode(); - Chain = LowerF128_LibCallArg(Chain, Args, LHS, DL, DAG); - Chain = LowerF128_LibCallArg(Chain, Args, RHS, DL, DAG); - - TargetLowering::CallLoweringInfo CLI(DAG); - CLI.setDebugLoc(DL).setChain(Chain) - .setCallee(CallingConv::C, RetTy, Callee, std::move(Args)); - - std::pair CallInfo = LowerCallTo(CLI); - - // result is in first, and chain is in second result. - SDValue Result = CallInfo.first; - - switch(SPCC) { - default: { - SDValue RHS = DAG.getTargetConstant(0, DL, Result.getValueType()); - SPCC = SPCC::ICC_NE; - return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS); - } - case SPCC::FCC_UL : { - SDValue Mask = DAG.getTargetConstant(1, DL, Result.getValueType()); - Result = DAG.getNode(ISD::AND, DL, Result.getValueType(), Result, Mask); - SDValue RHS = DAG.getTargetConstant(0, DL, Result.getValueType()); - SPCC = SPCC::ICC_NE; - return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS); - } - case SPCC::FCC_ULE: { - SDValue RHS = DAG.getTargetConstant(2, DL, Result.getValueType()); - SPCC = SPCC::ICC_NE; - return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS); - } - case SPCC::FCC_UG : { - SDValue RHS = DAG.getTargetConstant(1, DL, Result.getValueType()); - SPCC = SPCC::ICC_G; - return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS); - } - case SPCC::FCC_UGE: { - SDValue RHS = DAG.getTargetConstant(1, DL, Result.getValueType()); - SPCC = SPCC::ICC_NE; - return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS); - } - - case SPCC::FCC_U : { - SDValue RHS = DAG.getTargetConstant(3, DL, Result.getValueType()); - SPCC = SPCC::ICC_E; - return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS); - } - case SPCC::FCC_O : { - SDValue RHS = DAG.getTargetConstant(3, DL, Result.getValueType()); - SPCC = SPCC::ICC_NE; - return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS); - } - case SPCC::FCC_LG : { - SDValue Mask = DAG.getTargetConstant(3, DL, Result.getValueType()); - Result = DAG.getNode(ISD::AND, DL, Result.getValueType(), Result, Mask); - SDValue RHS = DAG.getTargetConstant(0, DL, Result.getValueType()); - SPCC = SPCC::ICC_NE; - return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS); - } - case SPCC::FCC_UE : { - SDValue Mask = DAG.getTargetConstant(3, DL, Result.getValueType()); - Result = DAG.getNode(ISD::AND, DL, Result.getValueType(), Result, Mask); - SDValue RHS = DAG.getTargetConstant(0, DL, Result.getValueType()); - SPCC = SPCC::ICC_E; - return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS); - } - } -} - -static SDValue -LowerF128_FPEXTEND(SDValue Op, SelectionDAG &DAG, - const SparcTargetLowering &TLI) { - - if (Op.getOperand(0).getValueType() == MVT::f64) - return TLI.LowerF128Op(Op, DAG, - TLI.getLibcallName(RTLIB::FPEXT_F64_F128), 1); - - if (Op.getOperand(0).getValueType() == MVT::f32) - return TLI.LowerF128Op(Op, DAG, - TLI.getLibcallName(RTLIB::FPEXT_F32_F128), 1); - - llvm_unreachable("fpextend with non-float operand!"); - return SDValue(); -} - -static SDValue -LowerF128_FPROUND(SDValue Op, SelectionDAG &DAG, - const SparcTargetLowering &TLI) { - // FP_ROUND on f64 and f32 are legal. - if (Op.getOperand(0).getValueType() != MVT::f128) - return Op; - - if (Op.getValueType() == MVT::f64) - return TLI.LowerF128Op(Op, DAG, - TLI.getLibcallName(RTLIB::FPROUND_F128_F64), 1); - if (Op.getValueType() == MVT::f32) - return TLI.LowerF128Op(Op, DAG, - TLI.getLibcallName(RTLIB::FPROUND_F128_F32), 1); - - llvm_unreachable("fpround to non-float!"); - return SDValue(); -} - -static SDValue LowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG, - const SparcTargetLowering &TLI, - bool hasHardQuad) { - SDLoc dl(Op); - EVT VT = Op.getValueType(); - assert(VT == MVT::i32 || VT == MVT::i64); - - // Expand f128 operations to fp128 abi calls. - if (Op.getOperand(0).getValueType() == MVT::f128 - && (!hasHardQuad || !TLI.isTypeLegal(VT))) { - const char *libName = TLI.getLibcallName(VT == MVT::i32 - ? RTLIB::FPTOSINT_F128_I32 - : RTLIB::FPTOSINT_F128_I64); - return TLI.LowerF128Op(Op, DAG, libName, 1); - } - - // Expand if the resulting type is illegal. - if (!TLI.isTypeLegal(VT)) - return SDValue(); - - // Otherwise, Convert the fp value to integer in an FP register. - if (VT == MVT::i32) - Op = DAG.getNode(SPISD::FTOI, dl, MVT::f32, Op.getOperand(0)); - else - Op = DAG.getNode(SPISD::FTOX, dl, MVT::f64, Op.getOperand(0)); - - return DAG.getNode(ISD::BITCAST, dl, VT, Op); -} - -static SDValue LowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG, - const SparcTargetLowering &TLI, - bool hasHardQuad) { - SDLoc dl(Op); - EVT OpVT = Op.getOperand(0).getValueType(); - assert(OpVT == MVT::i32 || (OpVT == MVT::i64)); - - EVT floatVT = (OpVT == MVT::i32) ? MVT::f32 : MVT::f64; - - // Expand f128 operations to fp128 ABI calls. - if (Op.getValueType() == MVT::f128 - && (!hasHardQuad || !TLI.isTypeLegal(OpVT))) { - const char *libName = TLI.getLibcallName(OpVT == MVT::i32 - ? RTLIB::SINTTOFP_I32_F128 - : RTLIB::SINTTOFP_I64_F128); - return TLI.LowerF128Op(Op, DAG, libName, 1); - } - - // Expand if the operand type is illegal. - if (!TLI.isTypeLegal(OpVT)) - return SDValue(); - - // Otherwise, Convert the int value to FP in an FP register. - SDValue Tmp = DAG.getNode(ISD::BITCAST, dl, floatVT, Op.getOperand(0)); - unsigned opcode = (OpVT == MVT::i32)? SPISD::ITOF : SPISD::XTOF; - return DAG.getNode(opcode, dl, Op.getValueType(), Tmp); -} - -static SDValue LowerFP_TO_UINT(SDValue Op, SelectionDAG &DAG, - const SparcTargetLowering &TLI, - bool hasHardQuad) { - SDLoc dl(Op); - EVT VT = Op.getValueType(); - - // Expand if it does not involve f128 or the target has support for - // quad floating point instructions and the resulting type is legal. - if (Op.getOperand(0).getValueType() != MVT::f128 || - (hasHardQuad && TLI.isTypeLegal(VT))) - return SDValue(); - - assert(VT == MVT::i32 || VT == MVT::i64); - - return TLI.LowerF128Op(Op, DAG, - TLI.getLibcallName(VT == MVT::i32 - ? RTLIB::FPTOUINT_F128_I32 - : RTLIB::FPTOUINT_F128_I64), - 1); -} - -static SDValue LowerUINT_TO_FP(SDValue Op, SelectionDAG &DAG, - const SparcTargetLowering &TLI, - bool hasHardQuad) { - SDLoc dl(Op); - EVT OpVT = Op.getOperand(0).getValueType(); - assert(OpVT == MVT::i32 || OpVT == MVT::i64); - - // Expand if it does not involve f128 or the target has support for - // quad floating point instructions and the operand type is legal. - if (Op.getValueType() != MVT::f128 || (hasHardQuad && TLI.isTypeLegal(OpVT))) - return SDValue(); - - return TLI.LowerF128Op(Op, DAG, - TLI.getLibcallName(OpVT == MVT::i32 - ? RTLIB::UINTTOFP_I32_F128 - : RTLIB::UINTTOFP_I64_F128), - 1); -} - -static SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG, - const SparcTargetLowering &TLI, - bool hasHardQuad) { - SDValue Chain = Op.getOperand(0); - ISD::CondCode CC = cast(Op.getOperand(1))->get(); - SDValue LHS = Op.getOperand(2); - SDValue RHS = Op.getOperand(3); - SDValue Dest = Op.getOperand(4); - SDLoc dl(Op); - unsigned Opc, SPCC = ~0U; - - // If this is a br_cc of a "setcc", and if the setcc got lowered into - // an CMP[IF]CC/SELECT_[IF]CC pair, find the original compared values. - LookThroughSetCC(LHS, RHS, CC, SPCC); - - // Get the condition flag. - SDValue CompareFlag; - if (LHS.getValueType().isInteger()) { - CompareFlag = DAG.getNode(SPISD::CMPICC, dl, MVT::Glue, LHS, RHS); - if (SPCC == ~0U) SPCC = IntCondCCodeToICC(CC); - // 32-bit compares use the icc flags, 64-bit uses the xcc flags. - Opc = LHS.getValueType() == MVT::i32 ? SPISD::BRICC : SPISD::BRXCC; - } else { - if (!hasHardQuad && LHS.getValueType() == MVT::f128) { - if (SPCC == ~0U) SPCC = FPCondCCodeToFCC(CC); - CompareFlag = TLI.LowerF128Compare(LHS, RHS, SPCC, dl, DAG); - Opc = SPISD::BRICC; - } else { - CompareFlag = DAG.getNode(SPISD::CMPFCC, dl, MVT::Glue, LHS, RHS); - if (SPCC == ~0U) SPCC = FPCondCCodeToFCC(CC); - Opc = SPISD::BRFCC; - } - } - return DAG.getNode(Opc, dl, MVT::Other, Chain, Dest, - DAG.getConstant(SPCC, dl, MVT::i32), CompareFlag); -} - -static SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG, - const SparcTargetLowering &TLI, - bool hasHardQuad) { - SDValue LHS = Op.getOperand(0); - SDValue RHS = Op.getOperand(1); - ISD::CondCode CC = cast(Op.getOperand(4))->get(); - SDValue TrueVal = Op.getOperand(2); - SDValue FalseVal = Op.getOperand(3); - SDLoc dl(Op); - unsigned Opc, SPCC = ~0U; - - // If this is a select_cc of a "setcc", and if the setcc got lowered into - // an CMP[IF]CC/SELECT_[IF]CC pair, find the original compared values. - LookThroughSetCC(LHS, RHS, CC, SPCC); - - SDValue CompareFlag; - if (LHS.getValueType().isInteger()) { - CompareFlag = DAG.getNode(SPISD::CMPICC, dl, MVT::Glue, LHS, RHS); - Opc = LHS.getValueType() == MVT::i32 ? - SPISD::SELECT_ICC : SPISD::SELECT_XCC; - if (SPCC == ~0U) SPCC = IntCondCCodeToICC(CC); - } else { - if (!hasHardQuad && LHS.getValueType() == MVT::f128) { - if (SPCC == ~0U) SPCC = FPCondCCodeToFCC(CC); - CompareFlag = TLI.LowerF128Compare(LHS, RHS, SPCC, dl, DAG); - Opc = SPISD::SELECT_ICC; - } else { - CompareFlag = DAG.getNode(SPISD::CMPFCC, dl, MVT::Glue, LHS, RHS); - Opc = SPISD::SELECT_FCC; - if (SPCC == ~0U) SPCC = FPCondCCodeToFCC(CC); - } - } - return DAG.getNode(Opc, dl, TrueVal.getValueType(), TrueVal, FalseVal, - DAG.getConstant(SPCC, dl, MVT::i32), CompareFlag); -} - -static SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG, - const SparcTargetLowering &TLI) { - MachineFunction &MF = DAG.getMachineFunction(); - SparcMachineFunctionInfo *FuncInfo = MF.getInfo(); - auto PtrVT = TLI.getPointerTy(DAG.getDataLayout()); - - // Need frame address to find the address of VarArgsFrameIndex. - MF.getFrameInfo().setFrameAddressIsTaken(true); - - // vastart just stores the address of the VarArgsFrameIndex slot into the - // memory location argument. - SDLoc DL(Op); - SDValue Offset = - DAG.getNode(ISD::ADD, DL, PtrVT, DAG.getRegister(SP::I6, PtrVT), - DAG.getIntPtrConstant(FuncInfo->getVarArgsFrameOffset(), DL)); - const Value *SV = cast(Op.getOperand(2))->getValue(); - return DAG.getStore(Op.getOperand(0), DL, Offset, Op.getOperand(1), - MachinePointerInfo(SV)); -} - -static SDValue LowerVAARG(SDValue Op, SelectionDAG &DAG) { - SDNode *Node = Op.getNode(); - EVT VT = Node->getValueType(0); - SDValue InChain = Node->getOperand(0); - SDValue VAListPtr = Node->getOperand(1); - EVT PtrVT = VAListPtr.getValueType(); - const Value *SV = cast(Node->getOperand(2))->getValue(); - SDLoc DL(Node); - SDValue VAList = - DAG.getLoad(PtrVT, DL, InChain, VAListPtr, MachinePointerInfo(SV)); - // Increment the pointer, VAList, to the next vaarg. - SDValue NextPtr = DAG.getNode(ISD::ADD, DL, PtrVT, VAList, - DAG.getIntPtrConstant(VT.getSizeInBits()/8, - DL)); - // Store the incremented VAList to the legalized pointer. - InChain = DAG.getStore(VAList.getValue(1), DL, NextPtr, VAListPtr, - MachinePointerInfo(SV)); - // Load the actual argument out of the pointer VAList. - // We can't count on greater alignment than the word size. - return DAG.getLoad(VT, DL, InChain, VAList, MachinePointerInfo(), - std::min(PtrVT.getSizeInBits(), VT.getSizeInBits()) / 8); -} - -static SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG, - const SparcSubtarget *Subtarget) { - SDValue Chain = Op.getOperand(0); // Legalize the chain. - SDValue Size = Op.getOperand(1); // Legalize the size. - unsigned Align = cast(Op.getOperand(2))->getZExtValue(); - unsigned StackAlign = Subtarget->getFrameLowering()->getStackAlignment(); - EVT VT = Size->getValueType(0); - SDLoc dl(Op); - - // TODO: implement over-aligned alloca. (Note: also implies - // supporting support for overaligned function frames + dynamic - // allocations, at all, which currently isn't supported) - if (Align > StackAlign) { - const MachineFunction &MF = DAG.getMachineFunction(); - report_fatal_error("Function \"" + Twine(MF.getName()) + "\": " - "over-aligned dynamic alloca not supported."); - } - - // The resultant pointer needs to be above the register spill area - // at the bottom of the stack. - unsigned regSpillArea; - if (Subtarget->is64Bit()) { - regSpillArea = 128; - } else { - // On Sparc32, the size of the spill area is 92. Unfortunately, - // that's only 4-byte aligned, not 8-byte aligned (the stack - // pointer is 8-byte aligned). So, if the user asked for an 8-byte - // aligned dynamic allocation, we actually need to add 96 to the - // bottom of the stack, instead of 92, to ensure 8-byte alignment. - - // That also means adding 4 to the size of the allocation -- - // before applying the 8-byte rounding. Unfortunately, we the - // value we get here has already had rounding applied. So, we need - // to add 8, instead, wasting a bit more memory. - - // Further, this only actually needs to be done if the required - // alignment is > 4, but, we've lost that info by this point, too, - // so we always apply it. - - // (An alternative approach would be to always reserve 96 bytes - // instead of the required 92, but then we'd waste 4 extra bytes - // in every frame, not just those with dynamic stack allocations) - - // TODO: modify code in SelectionDAGBuilder to make this less sad. - - Size = DAG.getNode(ISD::ADD, dl, VT, Size, - DAG.getConstant(8, dl, VT)); - regSpillArea = 96; - } - - unsigned SPReg = SP::O6; - SDValue SP = DAG.getCopyFromReg(Chain, dl, SPReg, VT); - SDValue NewSP = DAG.getNode(ISD::SUB, dl, VT, SP, Size); // Value - Chain = DAG.getCopyToReg(SP.getValue(1), dl, SPReg, NewSP); // Output chain - - regSpillArea += Subtarget->getStackPointerBias(); - - SDValue NewVal = DAG.getNode(ISD::ADD, dl, VT, NewSP, - DAG.getConstant(regSpillArea, dl, VT)); - SDValue Ops[2] = { NewVal, Chain }; - return DAG.getMergeValues(Ops, dl); -} - - -static SDValue getFLUSHW(SDValue Op, SelectionDAG &DAG) { - SDLoc dl(Op); - SDValue Chain = DAG.getNode(SPISD::FLUSHW, - dl, MVT::Other, DAG.getEntryNode()); - return Chain; -} - -static SDValue getFRAMEADDR(uint64_t depth, SDValue Op, SelectionDAG &DAG, - const SparcSubtarget *Subtarget, - bool AlwaysFlush = false) { - MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo(); - MFI.setFrameAddressIsTaken(true); - - EVT VT = Op.getValueType(); - SDLoc dl(Op); - unsigned FrameReg = SP::I6; - unsigned stackBias = Subtarget->getStackPointerBias(); - - SDValue FrameAddr; - SDValue Chain; - - // flush first to make sure the windowed registers' values are in stack - Chain = (depth || AlwaysFlush) ? getFLUSHW(Op, DAG) : DAG.getEntryNode(); - - FrameAddr = DAG.getCopyFromReg(Chain, dl, FrameReg, VT); - - unsigned Offset = (Subtarget->is64Bit()) ? (stackBias + 112) : 56; - - while (depth--) { - SDValue Ptr = DAG.getNode(ISD::ADD, dl, VT, FrameAddr, - DAG.getIntPtrConstant(Offset, dl)); - FrameAddr = DAG.getLoad(VT, dl, Chain, Ptr, MachinePointerInfo()); - } - if (Subtarget->is64Bit()) - FrameAddr = DAG.getNode(ISD::ADD, dl, VT, FrameAddr, - DAG.getIntPtrConstant(stackBias, dl)); - return FrameAddr; -} - - -static SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG, - const SparcSubtarget *Subtarget) { - - uint64_t depth = Op.getConstantOperandVal(0); - - return getFRAMEADDR(depth, Op, DAG, Subtarget); - -} - -static SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG, - const SparcTargetLowering &TLI, - const SparcSubtarget *Subtarget) { - MachineFunction &MF = DAG.getMachineFunction(); - MachineFrameInfo &MFI = MF.getFrameInfo(); - MFI.setReturnAddressIsTaken(true); - - if (TLI.verifyReturnAddressArgumentIsConstant(Op, DAG)) - return SDValue(); - - EVT VT = Op.getValueType(); - SDLoc dl(Op); - uint64_t depth = Op.getConstantOperandVal(0); - - SDValue RetAddr; - if (depth == 0) { - auto PtrVT = TLI.getPointerTy(DAG.getDataLayout()); - unsigned RetReg = MF.addLiveIn(SP::I7, TLI.getRegClassFor(PtrVT)); - RetAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, RetReg, VT); - return RetAddr; - } - - // Need frame address to find return address of the caller. - SDValue FrameAddr = getFRAMEADDR(depth - 1, Op, DAG, Subtarget, true); - - unsigned Offset = (Subtarget->is64Bit()) ? 120 : 60; - SDValue Ptr = DAG.getNode(ISD::ADD, - dl, VT, - FrameAddr, - DAG.getIntPtrConstant(Offset, dl)); - RetAddr = DAG.getLoad(VT, dl, DAG.getEntryNode(), Ptr, MachinePointerInfo()); - - return RetAddr; -} - -static SDValue LowerF64Op(SDValue SrcReg64, const SDLoc &dl, SelectionDAG &DAG, - unsigned opcode) { - assert(SrcReg64.getValueType() == MVT::f64 && "LowerF64Op called on non-double!"); - assert(opcode == ISD::FNEG || opcode == ISD::FABS); - - // Lower fneg/fabs on f64 to fneg/fabs on f32. - // fneg f64 => fneg f32:sub_even, fmov f32:sub_odd. - // fabs f64 => fabs f32:sub_even, fmov f32:sub_odd. - - // Note: in little-endian, the floating-point value is stored in the - // registers are in the opposite order, so the subreg with the sign - // bit is the highest-numbered (odd), rather than the - // lowest-numbered (even). - - SDValue Hi32 = DAG.getTargetExtractSubreg(SP::sub_even, dl, MVT::f32, - SrcReg64); - SDValue Lo32 = DAG.getTargetExtractSubreg(SP::sub_odd, dl, MVT::f32, - SrcReg64); - - if (DAG.getDataLayout().isLittleEndian()) - Lo32 = DAG.getNode(opcode, dl, MVT::f32, Lo32); - else - Hi32 = DAG.getNode(opcode, dl, MVT::f32, Hi32); - - SDValue DstReg64 = SDValue(DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF, - dl, MVT::f64), 0); - DstReg64 = DAG.getTargetInsertSubreg(SP::sub_even, dl, MVT::f64, - DstReg64, Hi32); - DstReg64 = DAG.getTargetInsertSubreg(SP::sub_odd, dl, MVT::f64, - DstReg64, Lo32); - return DstReg64; -} - -// Lower a f128 load into two f64 loads. -static SDValue LowerF128Load(SDValue Op, SelectionDAG &DAG) -{ - SDLoc dl(Op); - LoadSDNode *LdNode = dyn_cast(Op.getNode()); - assert(LdNode && LdNode->getOffset().isUndef() - && "Unexpected node type"); - - unsigned alignment = LdNode->getAlignment(); - if (alignment > 8) - alignment = 8; - - SDValue Hi64 = - DAG.getLoad(MVT::f64, dl, LdNode->getChain(), LdNode->getBasePtr(), - LdNode->getPointerInfo(), alignment); - EVT addrVT = LdNode->getBasePtr().getValueType(); - SDValue LoPtr = DAG.getNode(ISD::ADD, dl, addrVT, - LdNode->getBasePtr(), - DAG.getConstant(8, dl, addrVT)); - SDValue Lo64 = DAG.getLoad(MVT::f64, dl, LdNode->getChain(), LoPtr, - LdNode->getPointerInfo(), alignment); - - SDValue SubRegEven = DAG.getTargetConstant(SP::sub_even64, dl, MVT::i32); - SDValue SubRegOdd = DAG.getTargetConstant(SP::sub_odd64, dl, MVT::i32); - - SDNode *InFP128 = DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF, - dl, MVT::f128); - InFP128 = DAG.getMachineNode(TargetOpcode::INSERT_SUBREG, dl, - MVT::f128, - SDValue(InFP128, 0), - Hi64, - SubRegEven); - InFP128 = DAG.getMachineNode(TargetOpcode::INSERT_SUBREG, dl, - MVT::f128, - SDValue(InFP128, 0), - Lo64, - SubRegOdd); - SDValue OutChains[2] = { SDValue(Hi64.getNode(), 1), - SDValue(Lo64.getNode(), 1) }; - SDValue OutChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains); - SDValue Ops[2] = {SDValue(InFP128,0), OutChain}; - return DAG.getMergeValues(Ops, dl); -} - -static SDValue LowerLOAD(SDValue Op, SelectionDAG &DAG) -{ - LoadSDNode *LdNode = cast(Op.getNode()); - - EVT MemVT = LdNode->getMemoryVT(); - if (MemVT == MVT::f128) - return LowerF128Load(Op, DAG); - - return Op; -} - -// Lower a f128 store into two f64 stores. -static SDValue LowerF128Store(SDValue Op, SelectionDAG &DAG) { - SDLoc dl(Op); - StoreSDNode *StNode = dyn_cast(Op.getNode()); - assert(StNode && StNode->getOffset().isUndef() - && "Unexpected node type"); - SDValue SubRegEven = DAG.getTargetConstant(SP::sub_even64, dl, MVT::i32); - SDValue SubRegOdd = DAG.getTargetConstant(SP::sub_odd64, dl, MVT::i32); - - SDNode *Hi64 = DAG.getMachineNode(TargetOpcode::EXTRACT_SUBREG, - dl, - MVT::f64, - StNode->getValue(), - SubRegEven); - SDNode *Lo64 = DAG.getMachineNode(TargetOpcode::EXTRACT_SUBREG, - dl, - MVT::f64, - StNode->getValue(), - SubRegOdd); - - unsigned alignment = StNode->getAlignment(); - if (alignment > 8) - alignment = 8; - - SDValue OutChains[2]; - OutChains[0] = - DAG.getStore(StNode->getChain(), dl, SDValue(Hi64, 0), - StNode->getBasePtr(), MachinePointerInfo(), alignment); - EVT addrVT = StNode->getBasePtr().getValueType(); - SDValue LoPtr = DAG.getNode(ISD::ADD, dl, addrVT, - StNode->getBasePtr(), - DAG.getConstant(8, dl, addrVT)); - OutChains[1] = DAG.getStore(StNode->getChain(), dl, SDValue(Lo64, 0), LoPtr, - MachinePointerInfo(), alignment); - return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains); -} - -static SDValue LowerSTORE(SDValue Op, SelectionDAG &DAG) -{ - SDLoc dl(Op); - StoreSDNode *St = cast(Op.getNode()); - - EVT MemVT = St->getMemoryVT(); - if (MemVT == MVT::f128) - return LowerF128Store(Op, DAG); - - if (MemVT == MVT::i64) { - // Custom handling for i64 stores: turn it into a bitcast and a - // v2i32 store. - SDValue Val = DAG.getNode(ISD::BITCAST, dl, MVT::v2i32, St->getValue()); - SDValue Chain = DAG.getStore( - St->getChain(), dl, Val, St->getBasePtr(), St->getPointerInfo(), - St->getAlignment(), St->getMemOperand()->getFlags(), St->getAAInfo()); - return Chain; - } - - return SDValue(); -} - -static SDValue LowerFNEGorFABS(SDValue Op, SelectionDAG &DAG, bool isV9) { - assert((Op.getOpcode() == ISD::FNEG || Op.getOpcode() == ISD::FABS) - && "invalid opcode"); - - SDLoc dl(Op); - - if (Op.getValueType() == MVT::f64) - return LowerF64Op(Op.getOperand(0), dl, DAG, Op.getOpcode()); - if (Op.getValueType() != MVT::f128) - return Op; - - // Lower fabs/fneg on f128 to fabs/fneg on f64 - // fabs/fneg f128 => fabs/fneg f64:sub_even64, fmov f64:sub_odd64 - // (As with LowerF64Op, on little-endian, we need to negate the odd - // subreg) - - SDValue SrcReg128 = Op.getOperand(0); - SDValue Hi64 = DAG.getTargetExtractSubreg(SP::sub_even64, dl, MVT::f64, - SrcReg128); - SDValue Lo64 = DAG.getTargetExtractSubreg(SP::sub_odd64, dl, MVT::f64, - SrcReg128); - - if (DAG.getDataLayout().isLittleEndian()) { - if (isV9) - Lo64 = DAG.getNode(Op.getOpcode(), dl, MVT::f64, Lo64); - else - Lo64 = LowerF64Op(Lo64, dl, DAG, Op.getOpcode()); - } else { - if (isV9) - Hi64 = DAG.getNode(Op.getOpcode(), dl, MVT::f64, Hi64); - else - Hi64 = LowerF64Op(Hi64, dl, DAG, Op.getOpcode()); - } - - SDValue DstReg128 = SDValue(DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF, - dl, MVT::f128), 0); - DstReg128 = DAG.getTargetInsertSubreg(SP::sub_even64, dl, MVT::f128, - DstReg128, Hi64); - DstReg128 = DAG.getTargetInsertSubreg(SP::sub_odd64, dl, MVT::f128, - DstReg128, Lo64); - return DstReg128; -} - -static SDValue LowerADDC_ADDE_SUBC_SUBE(SDValue Op, SelectionDAG &DAG) { - - if (Op.getValueType() != MVT::i64) - return Op; - - SDLoc dl(Op); - SDValue Src1 = Op.getOperand(0); - SDValue Src1Lo = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Src1); - SDValue Src1Hi = DAG.getNode(ISD::SRL, dl, MVT::i64, Src1, - DAG.getConstant(32, dl, MVT::i64)); - Src1Hi = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Src1Hi); - - SDValue Src2 = Op.getOperand(1); - SDValue Src2Lo = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Src2); - SDValue Src2Hi = DAG.getNode(ISD::SRL, dl, MVT::i64, Src2, - DAG.getConstant(32, dl, MVT::i64)); - Src2Hi = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Src2Hi); - - - bool hasChain = false; - unsigned hiOpc = Op.getOpcode(); - switch (Op.getOpcode()) { - default: llvm_unreachable("Invalid opcode"); - case ISD::ADDC: hiOpc = ISD::ADDE; break; - case ISD::ADDE: hasChain = true; break; - case ISD::SUBC: hiOpc = ISD::SUBE; break; - case ISD::SUBE: hasChain = true; break; - } - SDValue Lo; - SDVTList VTs = DAG.getVTList(MVT::i32, MVT::Glue); - if (hasChain) { - Lo = DAG.getNode(Op.getOpcode(), dl, VTs, Src1Lo, Src2Lo, - Op.getOperand(2)); - } else { - Lo = DAG.getNode(Op.getOpcode(), dl, VTs, Src1Lo, Src2Lo); - } - SDValue Hi = DAG.getNode(hiOpc, dl, VTs, Src1Hi, Src2Hi, Lo.getValue(1)); - SDValue Carry = Hi.getValue(1); - - Lo = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i64, Lo); - Hi = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i64, Hi); - Hi = DAG.getNode(ISD::SHL, dl, MVT::i64, Hi, - DAG.getConstant(32, dl, MVT::i64)); - - SDValue Dst = DAG.getNode(ISD::OR, dl, MVT::i64, Hi, Lo); - SDValue Ops[2] = { Dst, Carry }; - return DAG.getMergeValues(Ops, dl); -} - -// Custom lower UMULO/SMULO for SPARC. This code is similar to ExpandNode() -// in LegalizeDAG.cpp except the order of arguments to the library function. -static SDValue LowerUMULO_SMULO(SDValue Op, SelectionDAG &DAG, - const SparcTargetLowering &TLI) -{ - unsigned opcode = Op.getOpcode(); - assert((opcode == ISD::UMULO || opcode == ISD::SMULO) && "Invalid Opcode."); - - bool isSigned = (opcode == ISD::SMULO); - EVT VT = MVT::i64; - EVT WideVT = MVT::i128; - SDLoc dl(Op); - SDValue LHS = Op.getOperand(0); - - if (LHS.getValueType() != VT) - return Op; - - SDValue ShiftAmt = DAG.getConstant(63, dl, VT); - - SDValue RHS = Op.getOperand(1); - SDValue HiLHS = DAG.getNode(ISD::SRA, dl, VT, LHS, ShiftAmt); - SDValue HiRHS = DAG.getNode(ISD::SRA, dl, MVT::i64, RHS, ShiftAmt); - SDValue Args[] = { HiLHS, LHS, HiRHS, RHS }; - - SDValue MulResult = TLI.makeLibCall(DAG, - RTLIB::MUL_I128, WideVT, - Args, isSigned, dl).first; - SDValue BottomHalf = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, VT, - MulResult, DAG.getIntPtrConstant(0, dl)); - SDValue TopHalf = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, VT, - MulResult, DAG.getIntPtrConstant(1, dl)); - if (isSigned) { - SDValue Tmp1 = DAG.getNode(ISD::SRA, dl, VT, BottomHalf, ShiftAmt); - TopHalf = DAG.getSetCC(dl, MVT::i32, TopHalf, Tmp1, ISD::SETNE); - } else { - TopHalf = DAG.getSetCC(dl, MVT::i32, TopHalf, DAG.getConstant(0, dl, VT), - ISD::SETNE); - } - // MulResult is a node with an illegal type. Because such things are not - // generally permitted during this phase of legalization, ensure that - // nothing is left using the node. The above EXTRACT_ELEMENT nodes should have - // been folded. - assert(MulResult->use_empty() && "Illegally typed node still in use!"); - - SDValue Ops[2] = { BottomHalf, TopHalf } ; - return DAG.getMergeValues(Ops, dl); -} - -static SDValue LowerATOMIC_LOAD_STORE(SDValue Op, SelectionDAG &DAG) { - if (isStrongerThanMonotonic(cast(Op)->getOrdering())) - // Expand with a fence. - return SDValue(); - - // Monotonic load/stores are legal. - return Op; -} - -SDValue SparcTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op, - SelectionDAG &DAG) const { - unsigned IntNo = cast(Op.getOperand(0))->getZExtValue(); - SDLoc dl(Op); - switch (IntNo) { - default: return SDValue(); // Don't custom lower most intrinsics. - case Intrinsic::thread_pointer: { - EVT PtrVT = getPointerTy(DAG.getDataLayout()); - return DAG.getRegister(SP::G7, PtrVT); - } - } -} - -SDValue SparcTargetLowering:: -LowerOperation(SDValue Op, SelectionDAG &DAG) const { - - bool hasHardQuad = Subtarget->hasHardQuad(); - bool isV9 = Subtarget->isV9(); - - switch (Op.getOpcode()) { - default: llvm_unreachable("Should not custom lower this!"); - - case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG, *this, - Subtarget); - case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG, - Subtarget); - case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG); - case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG); - case ISD::BlockAddress: return LowerBlockAddress(Op, DAG); - case ISD::ConstantPool: return LowerConstantPool(Op, DAG); - case ISD::FP_TO_SINT: return LowerFP_TO_SINT(Op, DAG, *this, - hasHardQuad); - case ISD::SINT_TO_FP: return LowerSINT_TO_FP(Op, DAG, *this, - hasHardQuad); - case ISD::FP_TO_UINT: return LowerFP_TO_UINT(Op, DAG, *this, - hasHardQuad); - case ISD::UINT_TO_FP: return LowerUINT_TO_FP(Op, DAG, *this, - hasHardQuad); - case ISD::BR_CC: return LowerBR_CC(Op, DAG, *this, - hasHardQuad); - case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG, *this, - hasHardQuad); - case ISD::VASTART: return LowerVASTART(Op, DAG, *this); - case ISD::VAARG: return LowerVAARG(Op, DAG); - case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG, - Subtarget); - - case ISD::LOAD: return LowerLOAD(Op, DAG); - case ISD::STORE: return LowerSTORE(Op, DAG); - case ISD::FADD: return LowerF128Op(Op, DAG, - getLibcallName(RTLIB::ADD_F128), 2); - case ISD::FSUB: return LowerF128Op(Op, DAG, - getLibcallName(RTLIB::SUB_F128), 2); - case ISD::FMUL: return LowerF128Op(Op, DAG, - getLibcallName(RTLIB::MUL_F128), 2); - case ISD::FDIV: return LowerF128Op(Op, DAG, - getLibcallName(RTLIB::DIV_F128), 2); - case ISD::FSQRT: return LowerF128Op(Op, DAG, - getLibcallName(RTLIB::SQRT_F128),1); - case ISD::FABS: - case ISD::FNEG: return LowerFNEGorFABS(Op, DAG, isV9); - case ISD::FP_EXTEND: return LowerF128_FPEXTEND(Op, DAG, *this); - case ISD::FP_ROUND: return LowerF128_FPROUND(Op, DAG, *this); - case ISD::ADDC: - case ISD::ADDE: - case ISD::SUBC: - case ISD::SUBE: return LowerADDC_ADDE_SUBC_SUBE(Op, DAG); - case ISD::UMULO: - case ISD::SMULO: return LowerUMULO_SMULO(Op, DAG, *this); - case ISD::ATOMIC_LOAD: - case ISD::ATOMIC_STORE: return LowerATOMIC_LOAD_STORE(Op, DAG); - case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG); - } -} - -SDValue SparcTargetLowering::bitcastConstantFPToInt(ConstantFPSDNode *C, - const SDLoc &DL, - SelectionDAG &DAG) const { - APInt V = C->getValueAPF().bitcastToAPInt(); - SDValue Lo = DAG.getConstant(V.zextOrTrunc(32), DL, MVT::i32); - SDValue Hi = DAG.getConstant(V.lshr(32).zextOrTrunc(32), DL, MVT::i32); - if (DAG.getDataLayout().isLittleEndian()) - std::swap(Lo, Hi); - return DAG.getBuildVector(MVT::v2i32, DL, {Hi, Lo}); -} - -SDValue SparcTargetLowering::PerformBITCASTCombine(SDNode *N, - DAGCombinerInfo &DCI) const { - SDLoc dl(N); - SDValue Src = N->getOperand(0); - - if (isa(Src) && N->getSimpleValueType(0) == MVT::v2i32 && - Src.getSimpleValueType() == MVT::f64) - return bitcastConstantFPToInt(cast(Src), dl, DCI.DAG); - - return SDValue(); -} - -SDValue SparcTargetLowering::PerformDAGCombine(SDNode *N, - DAGCombinerInfo &DCI) const { - switch (N->getOpcode()) { - default: - break; - case ISD::BITCAST: - return PerformBITCASTCombine(N, DCI); - } - return SDValue(); -} - -MachineBasicBlock * -SparcTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, - MachineBasicBlock *BB) const { - switch (MI.getOpcode()) { - default: llvm_unreachable("Unknown SELECT_CC!"); - case SP::SELECT_CC_Int_ICC: - case SP::SELECT_CC_FP_ICC: - case SP::SELECT_CC_DFP_ICC: - case SP::SELECT_CC_QFP_ICC: - return expandSelectCC(MI, BB, SP::BCOND); - case SP::SELECT_CC_Int_FCC: - case SP::SELECT_CC_FP_FCC: - case SP::SELECT_CC_DFP_FCC: - case SP::SELECT_CC_QFP_FCC: - return expandSelectCC(MI, BB, SP::FBCOND); - } -} - -MachineBasicBlock * -SparcTargetLowering::expandSelectCC(MachineInstr &MI, MachineBasicBlock *BB, - unsigned BROpcode) const { - const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); - DebugLoc dl = MI.getDebugLoc(); - unsigned CC = (SPCC::CondCodes)MI.getOperand(3).getImm(); - - // To "insert" a SELECT_CC instruction, we actually have to insert the - // triangle 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 the condition code for the branch. - // - // We produce the following control flow: - // ThisMBB - // | \ - // | IfFalseMBB - // | / - // SinkMBB - const BasicBlock *LLVM_BB = BB->getBasicBlock(); - MachineFunction::iterator It = ++BB->getIterator(); - - MachineBasicBlock *ThisMBB = BB; - MachineFunction *F = BB->getParent(); - MachineBasicBlock *IfFalseMBB = F->CreateMachineBasicBlock(LLVM_BB); - MachineBasicBlock *SinkMBB = F->CreateMachineBasicBlock(LLVM_BB); - F->insert(It, IfFalseMBB); - F->insert(It, SinkMBB); - - // Transfer the remainder of ThisMBB and its successor edges to SinkMBB. - SinkMBB->splice(SinkMBB->begin(), ThisMBB, - std::next(MachineBasicBlock::iterator(MI)), ThisMBB->end()); - SinkMBB->transferSuccessorsAndUpdatePHIs(ThisMBB); - - // Set the new successors for ThisMBB. - ThisMBB->addSuccessor(IfFalseMBB); - ThisMBB->addSuccessor(SinkMBB); - - BuildMI(ThisMBB, dl, TII.get(BROpcode)) - .addMBB(SinkMBB) - .addImm(CC); - - // IfFalseMBB just falls through to SinkMBB. - IfFalseMBB->addSuccessor(SinkMBB); - - // %Result = phi [ %TrueValue, ThisMBB ], [ %FalseValue, IfFalseMBB ] - BuildMI(*SinkMBB, SinkMBB->begin(), dl, TII.get(SP::PHI), - MI.getOperand(0).getReg()) - .addReg(MI.getOperand(1).getReg()) - .addMBB(ThisMBB) - .addReg(MI.getOperand(2).getReg()) - .addMBB(IfFalseMBB); - - MI.eraseFromParent(); // The pseudo instruction is gone now. - return SinkMBB; -} - -//===----------------------------------------------------------------------===// -// Sparc Inline Assembly Support -//===----------------------------------------------------------------------===// - -/// getConstraintType - Given a constraint letter, return the type of -/// constraint it is for this target. -SparcTargetLowering::ConstraintType -SparcTargetLowering::getConstraintType(StringRef Constraint) const { - if (Constraint.size() == 1) { - switch (Constraint[0]) { - default: break; - case 'r': - case 'f': - case 'e': - return C_RegisterClass; - case 'I': // SIMM13 - return C_Immediate; - } - } - - return TargetLowering::getConstraintType(Constraint); -} - -TargetLowering::ConstraintWeight SparcTargetLowering:: -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; - - // Look at the constraint type. - switch (*constraint) { - default: - weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint); - break; - case 'I': // SIMM13 - if (ConstantInt *C = dyn_cast(info.CallOperandVal)) { - if (isInt<13>(C->getSExtValue())) - weight = CW_Constant; - } - break; - } - return weight; -} - -/// LowerAsmOperandForConstraint - Lower the specified operand into the Ops -/// vector. If it is invalid, don't add anything to Ops. -void SparcTargetLowering:: -LowerAsmOperandForConstraint(SDValue Op, - std::string &Constraint, - std::vector &Ops, - SelectionDAG &DAG) const { - SDValue Result(nullptr, 0); - - // Only support length 1 constraints for now. - if (Constraint.length() > 1) - return; - - char ConstraintLetter = Constraint[0]; - switch (ConstraintLetter) { - default: break; - case 'I': - if (ConstantSDNode *C = dyn_cast(Op)) { - if (isInt<13>(C->getSExtValue())) { - Result = DAG.getTargetConstant(C->getSExtValue(), SDLoc(Op), - Op.getValueType()); - break; - } - return; - } - } - - if (Result.getNode()) { - Ops.push_back(Result); - return; - } - TargetLowering::LowerAsmOperandForConstraint(Op, Constraint, Ops, DAG); -} - -std::pair -SparcTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, - StringRef Constraint, - MVT VT) const { - if (Constraint.size() == 1) { - switch (Constraint[0]) { - case 'r': - if (VT == MVT::v2i32) - return std::make_pair(0U, &SP::IntPairRegClass); - else if (Subtarget->is64Bit()) - return std::make_pair(0U, &SP::I64RegsRegClass); - else - return std::make_pair(0U, &SP::IntRegsRegClass); - case 'f': - if (VT == MVT::f32 || VT == MVT::i32) - return std::make_pair(0U, &SP::FPRegsRegClass); - else if (VT == MVT::f64 || VT == MVT::i64) - return std::make_pair(0U, &SP::LowDFPRegsRegClass); - else if (VT == MVT::f128) - return std::make_pair(0U, &SP::LowQFPRegsRegClass); - // This will generate an error message - return std::make_pair(0U, nullptr); - case 'e': - if (VT == MVT::f32 || VT == MVT::i32) - return std::make_pair(0U, &SP::FPRegsRegClass); - else if (VT == MVT::f64 || VT == MVT::i64 ) - return std::make_pair(0U, &SP::DFPRegsRegClass); - else if (VT == MVT::f128) - return std::make_pair(0U, &SP::QFPRegsRegClass); - // This will generate an error message - return std::make_pair(0U, nullptr); - } - } else if (!Constraint.empty() && Constraint.size() <= 5 - && Constraint[0] == '{' && *(Constraint.end()-1) == '}') { - // constraint = '{r}' - // Remove the braces from around the name. - StringRef name(Constraint.data()+1, Constraint.size()-2); - // Handle register aliases: - // r0-r7 -> g0-g7 - // r8-r15 -> o0-o7 - // r16-r23 -> l0-l7 - // r24-r31 -> i0-i7 - uint64_t intVal = 0; - if (name.substr(0, 1).equals("r") - && !name.substr(1).getAsInteger(10, intVal) && intVal <= 31) { - const char regTypes[] = { 'g', 'o', 'l', 'i' }; - char regType = regTypes[intVal/8]; - char regIdx = '0' + (intVal % 8); - char tmp[] = { '{', regType, regIdx, '}', 0 }; - std::string newConstraint = std::string(tmp); - return TargetLowering::getRegForInlineAsmConstraint(TRI, newConstraint, - VT); - } - if (name.substr(0, 1).equals("f") && - !name.substr(1).getAsInteger(10, intVal) && intVal <= 63) { - std::string newConstraint; - - if (VT == MVT::f32 || VT == MVT::Other) { - newConstraint = "{f" + utostr(intVal) + "}"; - } else if (VT == MVT::f64 && (intVal % 2 == 0)) { - newConstraint = "{d" + utostr(intVal / 2) + "}"; - } else if (VT == MVT::f128 && (intVal % 4 == 0)) { - newConstraint = "{q" + utostr(intVal / 4) + "}"; - } else { - return std::make_pair(0U, nullptr); - } - return TargetLowering::getRegForInlineAsmConstraint(TRI, newConstraint, - VT); - } - } - - return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT); -} - -bool -SparcTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const { - // The Sparc target isn't yet aware of offsets. - return false; -} - -void SparcTargetLowering::ReplaceNodeResults(SDNode *N, - SmallVectorImpl& Results, - SelectionDAG &DAG) const { - - SDLoc dl(N); - - RTLIB::Libcall libCall = RTLIB::UNKNOWN_LIBCALL; - - switch (N->getOpcode()) { - default: - llvm_unreachable("Do not know how to custom type legalize this operation!"); - - case ISD::FP_TO_SINT: - case ISD::FP_TO_UINT: - // Custom lower only if it involves f128 or i64. - if (N->getOperand(0).getValueType() != MVT::f128 - || N->getValueType(0) != MVT::i64) - return; - libCall = ((N->getOpcode() == ISD::FP_TO_SINT) - ? RTLIB::FPTOSINT_F128_I64 - : RTLIB::FPTOUINT_F128_I64); - - Results.push_back(LowerF128Op(SDValue(N, 0), - DAG, - getLibcallName(libCall), - 1)); - return; - case ISD::READCYCLECOUNTER: { - assert(Subtarget->hasLeonCycleCounter()); - SDValue Lo = DAG.getCopyFromReg(N->getOperand(0), dl, SP::ASR23, MVT::i32); - SDValue Hi = DAG.getCopyFromReg(Lo, dl, SP::G0, MVT::i32); - SDValue Ops[] = { Lo, Hi }; - SDValue Pair = DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Ops); - Results.push_back(Pair); - Results.push_back(N->getOperand(0)); - return; - } - case ISD::SINT_TO_FP: - case ISD::UINT_TO_FP: - // Custom lower only if it involves f128 or i64. - if (N->getValueType(0) != MVT::f128 - || N->getOperand(0).getValueType() != MVT::i64) - return; - - libCall = ((N->getOpcode() == ISD::SINT_TO_FP) - ? RTLIB::SINTTOFP_I64_F128 - : RTLIB::UINTTOFP_I64_F128); - - Results.push_back(LowerF128Op(SDValue(N, 0), - DAG, - getLibcallName(libCall), - 1)); - return; - case ISD::LOAD: { - LoadSDNode *Ld = cast(N); - // Custom handling only for i64: turn i64 load into a v2i32 load, - // and a bitcast. - if (Ld->getValueType(0) != MVT::i64 || Ld->getMemoryVT() != MVT::i64) - return; - - SDLoc dl(N); - SDValue LoadRes = DAG.getExtLoad( - Ld->getExtensionType(), dl, MVT::v2i32, Ld->getChain(), - Ld->getBasePtr(), Ld->getPointerInfo(), MVT::v2i32, Ld->getAlignment(), - Ld->getMemOperand()->getFlags(), Ld->getAAInfo()); - - SDValue Res = DAG.getNode(ISD::BITCAST, dl, MVT::i64, LoadRes); - Results.push_back(Res); - Results.push_back(LoadRes.getValue(1)); - return; - } - } -} - -// Override to enable LOAD_STACK_GUARD lowering on Linux. -bool SparcTargetLowering::useLoadStackGuardNode() const { - if (!Subtarget->isTargetLinux()) - return TargetLowering::useLoadStackGuardNode(); - return true; -} - -// Override to disable global variable loading on Linux. -void SparcTargetLowering::insertSSPDeclarations(Module &M) const { - if (!Subtarget->isTargetLinux()) - return TargetLowering::insertSSPDeclarations(M); -} diff --git a/contrib/llvm/lib/Target/Sparc/SparcISelLowering.h b/contrib/llvm/lib/Target/Sparc/SparcISelLowering.h deleted file mode 100644 index 8d557a4225e5..000000000000 --- a/contrib/llvm/lib/Target/Sparc/SparcISelLowering.h +++ /dev/null @@ -1,216 +0,0 @@ -//===-- SparcISelLowering.h - Sparc 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 Sparc uses to lower LLVM code into a -// selection DAG. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_SPARC_SPARCISELLOWERING_H -#define LLVM_LIB_TARGET_SPARC_SPARCISELLOWERING_H - -#include "Sparc.h" -#include "llvm/CodeGen/TargetLowering.h" - -namespace llvm { - class SparcSubtarget; - - namespace SPISD { - enum NodeType : unsigned { - FIRST_NUMBER = ISD::BUILTIN_OP_END, - CMPICC, // Compare two GPR operands, set icc+xcc. - CMPFCC, // Compare two FP operands, set fcc. - BRICC, // Branch to dest on icc condition - BRXCC, // Branch to dest on xcc condition (64-bit only). - BRFCC, // Branch to dest on fcc condition - SELECT_ICC, // Select between two values using the current ICC flags. - SELECT_XCC, // Select between two values using the current XCC flags. - SELECT_FCC, // Select between two values using the current FCC flags. - - Hi, Lo, // Hi/Lo operations, typically on a global address. - - FTOI, // FP to Int within a FP register. - ITOF, // Int to FP within a FP register. - FTOX, // FP to Int64 within a FP register. - XTOF, // Int64 to FP within a FP register. - - CALL, // A call instruction. - RET_FLAG, // Return with a flag operand. - GLOBAL_BASE_REG, // Global base reg for PIC. - FLUSHW, // FLUSH register windows to stack. - - TLS_ADD, // For Thread Local Storage (TLS). - TLS_LD, - TLS_CALL - }; - } - - class SparcTargetLowering : public TargetLowering { - const SparcSubtarget *Subtarget; - public: - SparcTargetLowering(const TargetMachine &TM, const SparcSubtarget &STI); - SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override; - - bool useSoftFloat() const override; - - /// computeKnownBitsForTargetNode - Determine which of the bits specified - /// in Mask are known to be either zero or one and return them in the - /// KnownZero/KnownOne bitsets. - void computeKnownBitsForTargetNode(const SDValue Op, - KnownBits &Known, - const APInt &DemandedElts, - const SelectionDAG &DAG, - unsigned Depth = 0) const override; - - MachineBasicBlock * - EmitInstrWithCustomInserter(MachineInstr &MI, - MachineBasicBlock *MBB) const override; - - const char *getTargetNodeName(unsigned Opcode) const override; - - ConstraintType getConstraintType(StringRef Constraint) const override; - ConstraintWeight - getSingleConstraintMatchWeight(AsmOperandInfo &info, - const char *constraint) const override; - void LowerAsmOperandForConstraint(SDValue Op, - std::string &Constraint, - std::vector &Ops, - SelectionDAG &DAG) const override; - - unsigned - getInlineAsmMemConstraint(StringRef ConstraintCode) const override { - if (ConstraintCode == "o") - return InlineAsm::Constraint_o; - return TargetLowering::getInlineAsmMemConstraint(ConstraintCode); - } - - std::pair - getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, - StringRef Constraint, MVT VT) const override; - - bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override; - MVT getScalarShiftAmountTy(const DataLayout &, EVT) const override { - return MVT::i32; - } - - 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 SP::I0; - } - - /// 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 SP::I1; - } - - /// Override to support customized stack guard loading. - bool useLoadStackGuardNode() const override; - void insertSSPDeclarations(Module &M) const override; - - /// getSetCCResultType - Return the ISD::SETCC ValueType - EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, - EVT VT) const override; - - SDValue - LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, - const SmallVectorImpl &Ins, - const SDLoc &dl, SelectionDAG &DAG, - SmallVectorImpl &InVals) const override; - SDValue LowerFormalArguments_32(SDValue Chain, CallingConv::ID CallConv, - bool isVarArg, - const SmallVectorImpl &Ins, - const SDLoc &dl, SelectionDAG &DAG, - SmallVectorImpl &InVals) const; - SDValue LowerFormalArguments_64(SDValue Chain, CallingConv::ID CallConv, - bool isVarArg, - const SmallVectorImpl &Ins, - const SDLoc &dl, SelectionDAG &DAG, - SmallVectorImpl &InVals) const; - - SDValue - LowerCall(TargetLowering::CallLoweringInfo &CLI, - SmallVectorImpl &InVals) const override; - SDValue LowerCall_32(TargetLowering::CallLoweringInfo &CLI, - SmallVectorImpl &InVals) const; - SDValue LowerCall_64(TargetLowering::CallLoweringInfo &CLI, - SmallVectorImpl &InVals) const; - - SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, - const SmallVectorImpl &Outs, - const SmallVectorImpl &OutVals, - const SDLoc &dl, SelectionDAG &DAG) const override; - SDValue LowerReturn_32(SDValue Chain, CallingConv::ID CallConv, - bool IsVarArg, - const SmallVectorImpl &Outs, - const SmallVectorImpl &OutVals, - const SDLoc &DL, SelectionDAG &DAG) const; - SDValue LowerReturn_64(SDValue Chain, CallingConv::ID CallConv, - bool IsVarArg, - const SmallVectorImpl &Outs, - const SmallVectorImpl &OutVals, - const SDLoc &DL, SelectionDAG &DAG) const; - - SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const; - SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const; - SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG) const; - SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const; - - SDValue withTargetFlags(SDValue Op, unsigned TF, SelectionDAG &DAG) const; - SDValue makeHiLoPair(SDValue Op, unsigned HiTF, unsigned LoTF, - SelectionDAG &DAG) const; - SDValue makeAddress(SDValue Op, SelectionDAG &DAG) const; - - SDValue LowerF128_LibCallArg(SDValue Chain, ArgListTy &Args, SDValue Arg, - const SDLoc &DL, SelectionDAG &DAG) const; - SDValue LowerF128Op(SDValue Op, SelectionDAG &DAG, - const char *LibFuncName, - unsigned numArgs) const; - SDValue LowerF128Compare(SDValue LHS, SDValue RHS, unsigned &SPCC, - const SDLoc &DL, SelectionDAG &DAG) const; - - SDValue LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const; - - SDValue PerformBITCASTCombine(SDNode *N, DAGCombinerInfo &DCI) const; - - SDValue bitcastConstantFPToInt(ConstantFPSDNode *C, const SDLoc &DL, - SelectionDAG &DAG) const; - - SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override; - - bool ShouldShrinkFPConstant(EVT VT) const override { - // Do not shrink FP constpool if VT == MVT::f128. - // (ldd, call _Q_fdtoq) is more expensive than two ldds. - return VT != MVT::f128; - } - - bool shouldInsertFencesForAtomic(const Instruction *I) const override { - // FIXME: We insert fences for each atomics and generate - // sub-optimal code for PSO/TSO. (Approximately nobody uses any - // mode but TSO, which makes this even more silly) - return true; - } - - AtomicExpansionKind shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const override; - - void ReplaceNodeResults(SDNode *N, - SmallVectorImpl& Results, - SelectionDAG &DAG) const override; - - MachineBasicBlock *expandSelectCC(MachineInstr &MI, MachineBasicBlock *BB, - unsigned BROpcode) const; - }; -} // end namespace llvm - -#endif // SPARC_ISELLOWERING_H diff --git a/contrib/llvm/lib/Target/Sparc/SparcInstr64Bit.td b/contrib/llvm/lib/Target/Sparc/SparcInstr64Bit.td deleted file mode 100644 index 2d4f687f72d2..000000000000 --- a/contrib/llvm/lib/Target/Sparc/SparcInstr64Bit.td +++ /dev/null @@ -1,540 +0,0 @@ -//===-- SparcInstr64Bit.td - 64-bit instructions for Sparc Target ---------===// -// -// Part of the LLVM Project, under the Apache 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 instruction definitions and patterns needed for 64-bit -// code generation on SPARC v9. -// -// Some SPARC v9 instructions are defined in SparcInstrInfo.td because they can -// also be used in 32-bit code running on a SPARC v9 CPU. -// -//===----------------------------------------------------------------------===// - -let Predicates = [Is64Bit] in { -// The same integer registers are used for i32 and i64 values. -// When registers hold i32 values, the high bits are don't care. -// This give us free trunc and anyext. -def : Pat<(i64 (anyext i32:$val)), (COPY_TO_REGCLASS $val, I64Regs)>; -def : Pat<(i32 (trunc i64:$val)), (COPY_TO_REGCLASS $val, IntRegs)>; - -} // Predicates = [Is64Bit] - - -//===----------------------------------------------------------------------===// -// 64-bit Shift Instructions. -//===----------------------------------------------------------------------===// -// -// The 32-bit shift instructions are still available. The left shift srl -// instructions shift all 64 bits, but it only accepts a 5-bit shift amount. -// -// The srl instructions only shift the low 32 bits and clear the high 32 bits. -// Finally, sra shifts the low 32 bits and sign-extends to 64 bits. - -let Predicates = [Is64Bit] in { - -def : Pat<(i64 (zext i32:$val)), (SRLri $val, 0)>; -def : Pat<(i64 (sext i32:$val)), (SRAri $val, 0)>; - -def : Pat<(i64 (and i64:$val, 0xffffffff)), (SRLri $val, 0)>; -def : Pat<(i64 (sext_inreg i64:$val, i32)), (SRAri $val, 0)>; - -defm SLLX : F3_S<"sllx", 0b100101, 1, shl, i64, I64Regs>; -defm SRLX : F3_S<"srlx", 0b100110, 1, srl, i64, I64Regs>; -defm SRAX : F3_S<"srax", 0b100111, 1, sra, i64, I64Regs>; - -} // Predicates = [Is64Bit] - - -//===----------------------------------------------------------------------===// -// 64-bit Immediates. -//===----------------------------------------------------------------------===// -// -// All 32-bit immediates can be materialized with sethi+or, but 64-bit -// immediates may require more code. There may be a point where it is -// preferable to use a constant pool load instead, depending on the -// microarchitecture. - -// Single-instruction patterns. - -// The ALU instructions want their simm13 operands as i32 immediates. -def as_i32imm : SDNodeXFormgetTargetConstant(N->getSExtValue(), SDLoc(N), MVT::i32); -}]>; -def : Pat<(i64 simm13:$val), (ORri (i64 G0), (as_i32imm $val))>; -def : Pat<(i64 SETHIimm:$val), (SETHIi (HI22 $val))>; - -// Double-instruction patterns. - -// All unsigned i32 immediates can be handled by sethi+or. -def uimm32 : PatLeaf<(imm), [{ return isUInt<32>(N->getZExtValue()); }]>; -def : Pat<(i64 uimm32:$val), (ORri (SETHIi (HI22 $val)), (LO10 $val))>, - Requires<[Is64Bit]>; - -// All negative i33 immediates can be handled by sethi+xor. -def nimm33 : PatLeaf<(imm), [{ - int64_t Imm = N->getSExtValue(); - return Imm < 0 && isInt<33>(Imm); -}]>; -// Bits 10-31 inverted. Same as assembler's %hix. -def HIX22 : SDNodeXFormgetZExtValue() >> 10) & ((1u << 22) - 1); - return CurDAG->getTargetConstant(Val, SDLoc(N), MVT::i32); -}]>; -// Bits 0-9 with ones in bits 10-31. Same as assembler's %lox. -def LOX10 : SDNodeXFormgetTargetConstant(~(~N->getZExtValue() & 0x3ff), SDLoc(N), - MVT::i32); -}]>; -def : Pat<(i64 nimm33:$val), (XORri (SETHIi (HIX22 $val)), (LOX10 $val))>, - Requires<[Is64Bit]>; - -// More possible patterns: -// -// (sllx sethi, n) -// (sllx simm13, n) -// -// 3 instrs: -// -// (xor (sllx sethi), simm13) -// (sllx (xor sethi, simm13)) -// -// 4 instrs: -// -// (or sethi, (sllx sethi)) -// (xnor sethi, (sllx sethi)) -// -// 5 instrs: -// -// (or (sllx sethi), (or sethi, simm13)) -// (xnor (sllx sethi), (or sethi, simm13)) -// (or (sllx sethi), (sllx sethi)) -// (xnor (sllx sethi), (sllx sethi)) -// -// Worst case is 6 instrs: -// -// (or (sllx (or sethi, simmm13)), (or sethi, simm13)) - -// Bits 42-63, same as assembler's %hh. -def HH22 : SDNodeXFormgetZExtValue() >> 42) & ((1u << 22) - 1); - return CurDAG->getTargetConstant(Val, SDLoc(N), MVT::i32); -}]>; -// Bits 32-41, same as assembler's %hm. -def HM10 : SDNodeXFormgetZExtValue() >> 32) & ((1u << 10) - 1); - return CurDAG->getTargetConstant(Val, SDLoc(N), MVT::i32); -}]>; -def : Pat<(i64 imm:$val), - (ORrr (SLLXri (ORri (SETHIi (HH22 $val)), (HM10 $val)), (i32 32)), - (ORri (SETHIi (HI22 $val)), (LO10 $val)))>, - Requires<[Is64Bit]>; - - -//===----------------------------------------------------------------------===// -// 64-bit Integer Arithmetic and Logic. -//===----------------------------------------------------------------------===// - -let Predicates = [Is64Bit] in { - -// Register-register instructions. -let isCodeGenOnly = 1 in { -defm ANDX : F3_12<"and", 0b000001, and, I64Regs, i64, i64imm>; -defm ORX : F3_12<"or", 0b000010, or, I64Regs, i64, i64imm>; -defm XORX : F3_12<"xor", 0b000011, xor, I64Regs, i64, i64imm>; - -def ANDXNrr : F3_1<2, 0b000101, - (outs I64Regs:$dst), (ins I64Regs:$b, I64Regs:$c), - "andn $b, $c, $dst", - [(set i64:$dst, (and i64:$b, (not i64:$c)))]>; -def ORXNrr : F3_1<2, 0b000110, - (outs I64Regs:$dst), (ins I64Regs:$b, I64Regs:$c), - "orn $b, $c, $dst", - [(set i64:$dst, (or i64:$b, (not i64:$c)))]>; -def XNORXrr : F3_1<2, 0b000111, - (outs I64Regs:$dst), (ins I64Regs:$b, I64Regs:$c), - "xnor $b, $c, $dst", - [(set i64:$dst, (not (xor i64:$b, i64:$c)))]>; - -defm ADDX : F3_12<"add", 0b000000, add, I64Regs, i64, i64imm>; -defm SUBX : F3_12<"sub", 0b000100, sub, I64Regs, i64, i64imm>; - -def TLS_ADDXrr : F3_1<2, 0b000000, (outs I64Regs:$rd), - (ins I64Regs:$rs1, I64Regs:$rs2, TLSSym:$sym), - "add $rs1, $rs2, $rd, $sym", - [(set i64:$rd, - (tlsadd i64:$rs1, i64:$rs2, tglobaltlsaddr:$sym))]>; - -// "LEA" form of add -def LEAX_ADDri : F3_2<2, 0b000000, - (outs I64Regs:$dst), (ins MEMri:$addr), - "add ${addr:arith}, $dst", - [(set iPTR:$dst, ADDRri:$addr)]>; -} - -def : Pat<(SPcmpicc i64:$a, i64:$b), (CMPrr $a, $b)>; -def : Pat<(SPcmpicc i64:$a, (i64 simm13:$b)), (CMPri $a, (as_i32imm $b))>; -def : Pat<(ctpop i64:$src), (POPCrr $src)>; - -} // Predicates = [Is64Bit] - - -//===----------------------------------------------------------------------===// -// 64-bit Integer Multiply and Divide. -//===----------------------------------------------------------------------===// - -let Predicates = [Is64Bit] in { - -def MULXrr : F3_1<2, 0b001001, - (outs I64Regs:$rd), (ins I64Regs:$rs1, I64Regs:$rs2), - "mulx $rs1, $rs2, $rd", - [(set i64:$rd, (mul i64:$rs1, i64:$rs2))]>; -def MULXri : F3_2<2, 0b001001, - (outs IntRegs:$rd), (ins IntRegs:$rs1, i64imm:$simm13), - "mulx $rs1, $simm13, $rd", - [(set i64:$rd, (mul i64:$rs1, (i64 simm13:$simm13)))]>; - -// Division can trap. -let hasSideEffects = 1 in { -def SDIVXrr : F3_1<2, 0b101101, - (outs I64Regs:$rd), (ins I64Regs:$rs1, I64Regs:$rs2), - "sdivx $rs1, $rs2, $rd", - [(set i64:$rd, (sdiv i64:$rs1, i64:$rs2))]>; -def SDIVXri : F3_2<2, 0b101101, - (outs IntRegs:$rd), (ins IntRegs:$rs1, i64imm:$simm13), - "sdivx $rs1, $simm13, $rd", - [(set i64:$rd, (sdiv i64:$rs1, (i64 simm13:$simm13)))]>; - -def UDIVXrr : F3_1<2, 0b001101, - (outs I64Regs:$rd), (ins I64Regs:$rs1, I64Regs:$rs2), - "udivx $rs1, $rs2, $rd", - [(set i64:$rd, (udiv i64:$rs1, i64:$rs2))]>; -def UDIVXri : F3_2<2, 0b001101, - (outs IntRegs:$rd), (ins IntRegs:$rs1, i64imm:$simm13), - "udivx $rs1, $simm13, $rd", - [(set i64:$rd, (udiv i64:$rs1, (i64 simm13:$simm13)))]>; -} // hasSideEffects = 1 - -} // Predicates = [Is64Bit] - - -//===----------------------------------------------------------------------===// -// 64-bit Loads and Stores. -//===----------------------------------------------------------------------===// -// -// All the 32-bit loads and stores are available. The extending loads are sign -// or zero-extending to 64 bits. The LDrr and LDri instructions load 32 bits -// zero-extended to i64. Their mnemonic is lduw in SPARC v9 (Load Unsigned -// Word). -// -// SPARC v9 adds 64-bit loads as well as a sign-extending ldsw i32 loads. - -let Predicates = [Is64Bit] in { - -// 64-bit loads. -let DecoderMethod = "DecodeLoadInt" in - defm LDX : Load<"ldx", 0b001011, load, I64Regs, i64>; - -let mayLoad = 1, isAsmParserOnly = 1 in - def TLS_LDXrr : F3_1<3, 0b001011, - (outs IntRegs:$dst), (ins MEMrr:$addr, TLSSym:$sym), - "ldx [$addr], $dst, $sym", - [(set i64:$dst, - (tlsld ADDRrr:$addr, tglobaltlsaddr:$sym))]>; - -// Extending loads to i64. -def : Pat<(i64 (zextloadi1 ADDRrr:$addr)), (LDUBrr ADDRrr:$addr)>; -def : Pat<(i64 (zextloadi1 ADDRri:$addr)), (LDUBri ADDRri:$addr)>; -def : Pat<(i64 (extloadi1 ADDRrr:$addr)), (LDUBrr ADDRrr:$addr)>; -def : Pat<(i64 (extloadi1 ADDRri:$addr)), (LDUBri ADDRri:$addr)>; - -def : Pat<(i64 (zextloadi8 ADDRrr:$addr)), (LDUBrr ADDRrr:$addr)>; -def : Pat<(i64 (zextloadi8 ADDRri:$addr)), (LDUBri ADDRri:$addr)>; -def : Pat<(i64 (extloadi8 ADDRrr:$addr)), (LDUBrr ADDRrr:$addr)>; -def : Pat<(i64 (extloadi8 ADDRri:$addr)), (LDUBri ADDRri:$addr)>; -def : Pat<(i64 (sextloadi8 ADDRrr:$addr)), (LDSBrr ADDRrr:$addr)>; -def : Pat<(i64 (sextloadi8 ADDRri:$addr)), (LDSBri ADDRri:$addr)>; - -def : Pat<(i64 (zextloadi16 ADDRrr:$addr)), (LDUHrr ADDRrr:$addr)>; -def : Pat<(i64 (zextloadi16 ADDRri:$addr)), (LDUHri ADDRri:$addr)>; -def : Pat<(i64 (extloadi16 ADDRrr:$addr)), (LDUHrr ADDRrr:$addr)>; -def : Pat<(i64 (extloadi16 ADDRri:$addr)), (LDUHri ADDRri:$addr)>; -def : Pat<(i64 (sextloadi16 ADDRrr:$addr)), (LDSHrr ADDRrr:$addr)>; -def : Pat<(i64 (sextloadi16 ADDRri:$addr)), (LDSHri ADDRri:$addr)>; - -def : Pat<(i64 (zextloadi32 ADDRrr:$addr)), (LDrr ADDRrr:$addr)>; -def : Pat<(i64 (zextloadi32 ADDRri:$addr)), (LDri ADDRri:$addr)>; -def : Pat<(i64 (extloadi32 ADDRrr:$addr)), (LDrr ADDRrr:$addr)>; -def : Pat<(i64 (extloadi32 ADDRri:$addr)), (LDri ADDRri:$addr)>; - -// Sign-extending load of i32 into i64 is a new SPARC v9 instruction. -let DecoderMethod = "DecodeLoadInt" in - defm LDSW : Load<"ldsw", 0b001000, sextloadi32, I64Regs, i64>; - -// 64-bit stores. -let DecoderMethod = "DecodeStoreInt" in - defm STX : Store<"stx", 0b001110, store, I64Regs, i64>; - -// Truncating stores from i64 are identical to the i32 stores. -def : Pat<(truncstorei8 i64:$src, ADDRrr:$addr), (STBrr ADDRrr:$addr, $src)>; -def : Pat<(truncstorei8 i64:$src, ADDRri:$addr), (STBri ADDRri:$addr, $src)>; -def : Pat<(truncstorei16 i64:$src, ADDRrr:$addr), (STHrr ADDRrr:$addr, $src)>; -def : Pat<(truncstorei16 i64:$src, ADDRri:$addr), (STHri ADDRri:$addr, $src)>; -def : Pat<(truncstorei32 i64:$src, ADDRrr:$addr), (STrr ADDRrr:$addr, $src)>; -def : Pat<(truncstorei32 i64:$src, ADDRri:$addr), (STri ADDRri:$addr, $src)>; - -// store 0, addr -> store %g0, addr -def : Pat<(store (i64 0), ADDRrr:$dst), (STXrr ADDRrr:$dst, (i64 G0))>; -def : Pat<(store (i64 0), ADDRri:$dst), (STXri ADDRri:$dst, (i64 G0))>; - -} // Predicates = [Is64Bit] - - -//===----------------------------------------------------------------------===// -// 64-bit Conditionals. -//===----------------------------------------------------------------------===// - -// -// Flag-setting instructions like subcc and addcc set both icc and xcc flags. -// The icc flags correspond to the 32-bit result, and the xcc are for the -// full 64-bit result. -// -// We reuse CMPICC SDNodes for compares, but use new BRXCC branch nodes for -// 64-bit compares. See LowerBR_CC. - -let Predicates = [Is64Bit] in { - -let Uses = [ICC], cc = 0b10 in - defm BPX : IPredBranch<"%xcc", [(SPbrxcc bb:$imm19, imm:$cond)]>; - -// Conditional moves on %xcc. -let Uses = [ICC], Constraints = "$f = $rd" in { -let intcc = 1, cc = 0b10 in { -def MOVXCCrr : F4_1<0b101100, (outs IntRegs:$rd), - (ins IntRegs:$rs2, IntRegs:$f, CCOp:$cond), - "mov$cond %xcc, $rs2, $rd", - [(set i32:$rd, - (SPselectxcc i32:$rs2, i32:$f, imm:$cond))]>; -def MOVXCCri : F4_2<0b101100, (outs IntRegs:$rd), - (ins i32imm:$simm11, IntRegs:$f, CCOp:$cond), - "mov$cond %xcc, $simm11, $rd", - [(set i32:$rd, - (SPselectxcc simm11:$simm11, i32:$f, imm:$cond))]>; -} // cc - -let intcc = 1, opf_cc = 0b10 in { -def FMOVS_XCC : F4_3<0b110101, 0b000001, (outs FPRegs:$rd), - (ins FPRegs:$rs2, FPRegs:$f, CCOp:$cond), - "fmovs$cond %xcc, $rs2, $rd", - [(set f32:$rd, - (SPselectxcc f32:$rs2, f32:$f, imm:$cond))]>; -def FMOVD_XCC : F4_3<0b110101, 0b000010, (outs DFPRegs:$rd), - (ins DFPRegs:$rs2, DFPRegs:$f, CCOp:$cond), - "fmovd$cond %xcc, $rs2, $rd", - [(set f64:$rd, - (SPselectxcc f64:$rs2, f64:$f, imm:$cond))]>; -def FMOVQ_XCC : F4_3<0b110101, 0b000011, (outs QFPRegs:$rd), - (ins QFPRegs:$rs2, QFPRegs:$f, CCOp:$cond), - "fmovq$cond %xcc, $rs2, $rd", - [(set f128:$rd, - (SPselectxcc f128:$rs2, f128:$f, imm:$cond))]>; -} // opf_cc -} // Uses, Constraints - -// Branch On integer register with Prediction (BPr). -let isBranch = 1, isTerminator = 1, hasDelaySlot = 1 in -multiclass BranchOnReg cond, string OpcStr> { - def napt : F2_4; - def apt : F2_4; - def napn : F2_4; - def apn : F2_4; -} - -multiclass bpr_alias { - def : InstAlias; - def : InstAlias; -} - -defm BPZ : BranchOnReg<0b001, "brz">; -defm BPLEZ : BranchOnReg<0b010, "brlez">; -defm BPLZ : BranchOnReg<0b011, "brlz">; -defm BPNZ : BranchOnReg<0b101, "brnz">; -defm BPGZ : BranchOnReg<0b110, "brgz">; -defm BPGEZ : BranchOnReg<0b111, "brgez">; - -defm : bpr_alias<"brz", BPZnapt, BPZapt >; -defm : bpr_alias<"brlez", BPLEZnapt, BPLEZapt>; -defm : bpr_alias<"brlz", BPLZnapt, BPLZapt >; -defm : bpr_alias<"brnz", BPNZnapt, BPNZapt >; -defm : bpr_alias<"brgz", BPGZnapt, BPGZapt >; -defm : bpr_alias<"brgez", BPGEZnapt, BPGEZapt>; - -// Move integer register on register condition (MOVr). -multiclass MOVR< bits<3> rcond, string OpcStr> { - def rr : F4_4r<0b101111, 0b00000, rcond, (outs I64Regs:$rd), - (ins I64Regs:$rs1, IntRegs:$rs2), - !strconcat(OpcStr, " $rs1, $rs2, $rd"), []>; - - def ri : F4_4i<0b101111, rcond, (outs I64Regs:$rd), - (ins I64Regs:$rs1, i64imm:$simm10), - !strconcat(OpcStr, " $rs1, $simm10, $rd"), []>; -} - -defm MOVRRZ : MOVR<0b001, "movrz">; -defm MOVRLEZ : MOVR<0b010, "movrlez">; -defm MOVRLZ : MOVR<0b011, "movrlz">; -defm MOVRNZ : MOVR<0b101, "movrnz">; -defm MOVRGZ : MOVR<0b110, "movrgz">; -defm MOVRGEZ : MOVR<0b111, "movrgez">; - -// Move FP register on integer register condition (FMOVr). -multiclass FMOVR rcond, string OpcStr> { - - def S : F4_4r<0b110101, 0b00101, rcond, - (outs FPRegs:$rd), (ins I64Regs:$rs1, FPRegs:$rs2), - !strconcat(!strconcat("fmovrs", OpcStr)," $rs1, $rs2, $rd"), - []>; - def D : F4_4r<0b110101, 0b00110, rcond, - (outs FPRegs:$rd), (ins I64Regs:$rs1, FPRegs:$rs2), - !strconcat(!strconcat("fmovrd", OpcStr)," $rs1, $rs2, $rd"), - []>; - def Q : F4_4r<0b110101, 0b00111, rcond, - (outs FPRegs:$rd), (ins I64Regs:$rs1, FPRegs:$rs2), - !strconcat(!strconcat("fmovrq", OpcStr)," $rs1, $rs2, $rd"), - []>, Requires<[HasHardQuad]>; -} - -let Predicates = [HasV9] in { - defm FMOVRZ : FMOVR<0b001, "z">; - defm FMOVRLEZ : FMOVR<0b010, "lez">; - defm FMOVRLZ : FMOVR<0b011, "lz">; - defm FMOVRNZ : FMOVR<0b101, "nz">; - defm FMOVRGZ : FMOVR<0b110, "gz">; - defm FMOVRGEZ : FMOVR<0b111, "gez">; -} - -//===----------------------------------------------------------------------===// -// 64-bit Floating Point Conversions. -//===----------------------------------------------------------------------===// - -let Predicates = [Is64Bit] in { - -def FXTOS : F3_3u<2, 0b110100, 0b010000100, - (outs FPRegs:$rd), (ins DFPRegs:$rs2), - "fxtos $rs2, $rd", - [(set FPRegs:$rd, (SPxtof DFPRegs:$rs2))]>; -def FXTOD : F3_3u<2, 0b110100, 0b010001000, - (outs DFPRegs:$rd), (ins DFPRegs:$rs2), - "fxtod $rs2, $rd", - [(set DFPRegs:$rd, (SPxtof DFPRegs:$rs2))]>; -def FXTOQ : F3_3u<2, 0b110100, 0b010001100, - (outs QFPRegs:$rd), (ins DFPRegs:$rs2), - "fxtoq $rs2, $rd", - [(set QFPRegs:$rd, (SPxtof DFPRegs:$rs2))]>, - Requires<[HasHardQuad]>; - -def FSTOX : F3_3u<2, 0b110100, 0b010000001, - (outs DFPRegs:$rd), (ins FPRegs:$rs2), - "fstox $rs2, $rd", - [(set DFPRegs:$rd, (SPftox FPRegs:$rs2))]>; -def FDTOX : F3_3u<2, 0b110100, 0b010000010, - (outs DFPRegs:$rd), (ins DFPRegs:$rs2), - "fdtox $rs2, $rd", - [(set DFPRegs:$rd, (SPftox DFPRegs:$rs2))]>; -def FQTOX : F3_3u<2, 0b110100, 0b010000011, - (outs DFPRegs:$rd), (ins QFPRegs:$rs2), - "fqtox $rs2, $rd", - [(set DFPRegs:$rd, (SPftox QFPRegs:$rs2))]>, - Requires<[HasHardQuad]>; - -} // Predicates = [Is64Bit] - -def : Pat<(SPselectxcc i64:$t, i64:$f, imm:$cond), - (MOVXCCrr $t, $f, imm:$cond)>; -def : Pat<(SPselectxcc (i64 simm11:$t), i64:$f, imm:$cond), - (MOVXCCri (as_i32imm $t), $f, imm:$cond)>; - -def : Pat<(SPselecticc i64:$t, i64:$f, imm:$cond), - (MOVICCrr $t, $f, imm:$cond)>; -def : Pat<(SPselecticc (i64 simm11:$t), i64:$f, imm:$cond), - (MOVICCri (as_i32imm $t), $f, imm:$cond)>; - -def : Pat<(SPselectfcc i64:$t, i64:$f, imm:$cond), - (MOVFCCrr $t, $f, imm:$cond)>; -def : Pat<(SPselectfcc (i64 simm11:$t), i64:$f, imm:$cond), - (MOVFCCri (as_i32imm $t), $f, imm:$cond)>; - -} // Predicates = [Is64Bit] - - -// 64 bit SETHI -let Predicates = [Is64Bit], isCodeGenOnly = 1 in { -def SETHIXi : F2_1<0b100, - (outs IntRegs:$rd), (ins i64imm:$imm22), - "sethi $imm22, $rd", - [(set i64:$rd, SETHIimm:$imm22)]>; -} - -// ATOMICS. -let Predicates = [Is64Bit], Constraints = "$swap = $rd", asi = 0b10000000 in { - def CASXrr: F3_1_asi<3, 0b111110, - (outs I64Regs:$rd), (ins I64Regs:$rs1, I64Regs:$rs2, - I64Regs:$swap), - "casx [$rs1], $rs2, $rd", - [(set i64:$rd, - (atomic_cmp_swap_64 i64:$rs1, i64:$rs2, i64:$swap))]>; - -} // Predicates = [Is64Bit], Constraints = ... - -let Predicates = [Is64Bit] in { - -def : Pat<(atomic_fence imm, imm), (MEMBARi 0xf)>; - -// atomic_load_64 addr -> load addr -def : Pat<(i64 (atomic_load_64 ADDRrr:$src)), (LDXrr ADDRrr:$src)>; -def : Pat<(i64 (atomic_load_64 ADDRri:$src)), (LDXri ADDRri:$src)>; - -// atomic_store_64 val, addr -> store val, addr -def : Pat<(atomic_store_64 ADDRrr:$dst, i64:$val), (STXrr ADDRrr:$dst, $val)>; -def : Pat<(atomic_store_64 ADDRri:$dst, i64:$val), (STXri ADDRri:$dst, $val)>; - -} // Predicates = [Is64Bit] - -let Predicates = [Is64Bit], hasSideEffects = 1, Uses = [ICC], cc = 0b10 in - defm TXCC : TRAP<"%xcc">; - -// Global addresses, constant pool entries -let Predicates = [Is64Bit] in { - -def : Pat<(SPhi tglobaladdr:$in), (SETHIi tglobaladdr:$in)>; -def : Pat<(SPlo tglobaladdr:$in), (ORXri (i64 G0), tglobaladdr:$in)>; -def : Pat<(SPhi tconstpool:$in), (SETHIi tconstpool:$in)>; -def : Pat<(SPlo tconstpool:$in), (ORXri (i64 G0), tconstpool:$in)>; - -// GlobalTLS addresses -def : Pat<(SPhi tglobaltlsaddr:$in), (SETHIi tglobaltlsaddr:$in)>; -def : Pat<(SPlo tglobaltlsaddr:$in), (ORXri (i64 G0), tglobaltlsaddr:$in)>; -def : Pat<(add (SPhi tglobaltlsaddr:$in1), (SPlo tglobaltlsaddr:$in2)), - (ADDXri (SETHIXi tglobaltlsaddr:$in1), (tglobaltlsaddr:$in2))>; -def : Pat<(xor (SPhi tglobaltlsaddr:$in1), (SPlo tglobaltlsaddr:$in2)), - (XORXri (SETHIXi tglobaltlsaddr:$in1), (tglobaltlsaddr:$in2))>; - -// Blockaddress -def : Pat<(SPhi tblockaddress:$in), (SETHIi tblockaddress:$in)>; -def : Pat<(SPlo tblockaddress:$in), (ORXri (i64 G0), tblockaddress:$in)>; - -// Add reg, lo. This is used when taking the addr of a global/constpool entry. -def : Pat<(add iPTR:$r, (SPlo tglobaladdr:$in)), (ADDXri $r, tglobaladdr:$in)>; -def : Pat<(add iPTR:$r, (SPlo tconstpool:$in)), (ADDXri $r, tconstpool:$in)>; -def : Pat<(add iPTR:$r, (SPlo tblockaddress:$in)), - (ADDXri $r, tblockaddress:$in)>; -} diff --git a/contrib/llvm/lib/Target/Sparc/SparcInstrAliases.td b/contrib/llvm/lib/Target/Sparc/SparcInstrAliases.td deleted file mode 100644 index d4d056ea0af6..000000000000 --- a/contrib/llvm/lib/Target/Sparc/SparcInstrAliases.td +++ /dev/null @@ -1,523 +0,0 @@ -//===-- SparcInstrAliases.td - Instruction Aliases for Sparc Target -------===// -// -// Part of the LLVM Project, under the Apache 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 instruction aliases for Sparc. -//===----------------------------------------------------------------------===// - -// Instruction aliases for conditional moves. - -// mov rs2, rd -multiclass intcond_mov_alias { - - // mov (%icc|%xcc), rs2, rd - def : InstAlias; - - // mov (%icc|%xcc), simm11, rd - def : InstAlias; - - // fmovs (%icc|%xcc), $rs2, $rd - def : InstAlias; - - // fmovd (%icc|%xcc), $rs2, $rd - def : InstAlias; -} - -// mov rs2, rd -multiclass fpcond_mov_alias { - - // mov %fcc[0-3], rs2, rd - def : InstAlias; - - // mov %fcc[0-3], simm11, rd - def : InstAlias; - - // fmovs %fcc[0-3], $rs2, $rd - def : InstAlias; - - // fmovd %fcc[0-3], $rs2, $rd - def : InstAlias; -} - -// Instruction aliases for integer conditional branches and moves. -multiclass int_cond_alias { - - // b $imm - def : InstAlias; - - // b,a $imm - def : InstAlias; - - // b %icc, $imm - def : InstAlias, Requires<[HasV9]>; - - // b,pt %icc, $imm - def : InstAlias, Requires<[HasV9]>; - - // b,a %icc, $imm - def : InstAlias, Requires<[HasV9]>; - - // b,a,pt %icc, $imm - def : InstAlias, Requires<[HasV9]>; - - // b,pn %icc, $imm - def : InstAlias, Requires<[HasV9]>; - - // b,a,pn %icc, $imm - def : InstAlias, Requires<[HasV9]>; - - // b %xcc, $imm - def : InstAlias, Requires<[Is64Bit]>; - - // b,pt %xcc, $imm - def : InstAlias, Requires<[Is64Bit]>; - - // b,a %xcc, $imm - def : InstAlias, Requires<[Is64Bit]>; - - // b,a,pt %xcc, $imm - def : InstAlias, Requires<[Is64Bit]>; - - // b,pn %xcc, $imm - def : InstAlias, Requires<[Is64Bit]>; - - // b,a,pn %xcc, $imm - def : InstAlias, Requires<[Is64Bit]>; - - - defm : intcond_mov_alias, Requires<[HasV9]>; - - defm : intcond_mov_alias, Requires<[Is64Bit]>; - - // fmovq (%icc|%xcc), $rs2, $rd - def : InstAlias, - Requires<[HasV9, HasHardQuad]>; - def : InstAlias, - Requires<[Is64Bit, HasHardQuad]>; - - // t %icc, rs => t %icc, G0 + rs - def : InstAlias, - Requires<[HasV9]>; - // t %icc, rs1 + rs2 - def : InstAlias, - Requires<[HasV9]>; - - - // t %xcc, rs => t %xcc, G0 + rs - def : InstAlias, - Requires<[HasV9]>; - // t %xcc, rs1 + rs2 - def : InstAlias, - Requires<[HasV9]>; - - - // t rs=> t %icc, G0 + rs2 - //def : InstAlias, - // Requires<[HasV9]>; - - // t rs1 + rs2 => t %icc, rs1 + rs2 - //def : InstAlias, - // Requires<[HasV9]>; - - // t %icc, imm => t %icc, G0 + imm - def : InstAlias, - Requires<[HasV9]>; - // t %icc, rs1 + imm - def : InstAlias, - Requires<[HasV9]>; - // t %xcc, imm => t %xcc, G0 + imm - def : InstAlias, - Requires<[HasV9]>; - // t %xcc, rs1 + imm - def : InstAlias, - Requires<[HasV9]>; - - // t imm => t G0 + imm - def : InstAlias; - - // t rs1 + imm => t rs1 + imm - def : InstAlias; - - // t rs1 => t G0 + rs1 - def : InstAlias; - - // t rs1 + rs2 - def : InstAlias; -} - - -// Instruction aliases for floating point conditional branches and moves. -multiclass fp_cond_alias { - - // fb $imm - def : InstAlias; - - // fb,a $imm - def : InstAlias; - - // fb %fcc0, $imm - def : InstAlias, - Requires<[HasV9]>; - - // fb,pt %fcc0, $imm - def : InstAlias, - Requires<[HasV9]>; - - // fb,a %fcc0, $imm - def : InstAlias, - Requires<[HasV9]>; - - // fb,a,pt %fcc0, $imm - def : InstAlias, - Requires<[HasV9]>; - - // fb,pn %fcc0, $imm - def : InstAlias, - Requires<[HasV9]>; - - // fb,a,pn %fcc0, $imm - def : InstAlias, - Requires<[HasV9]>; - - defm : fpcond_mov_alias, Requires<[HasV9]>; - - // fmovq %fcc0, $rs2, $rd - def : InstAlias, - Requires<[HasV9, HasHardQuad]>; -} - - -// Instruction aliases for co-processor conditional branches. -multiclass cp_cond_alias { - - // cb $imm - def : InstAlias; - - // cb,a $imm - def : InstAlias; -} - -defm : int_cond_alias<"a", 0b1000>; -defm : int_cond_alias<"n", 0b0000>; -defm : int_cond_alias<"ne", 0b1001>; -defm : int_cond_alias<"e", 0b0001>; -defm : int_cond_alias<"g", 0b1010>; -defm : int_cond_alias<"le", 0b0010>; -defm : int_cond_alias<"ge", 0b1011>; -defm : int_cond_alias<"l", 0b0011>; -defm : int_cond_alias<"gu", 0b1100>; -defm : int_cond_alias<"leu", 0b0100>; -defm : int_cond_alias<"cc", 0b1101>; -defm : int_cond_alias<"cs", 0b0101>; -defm : int_cond_alias<"pos", 0b1110>; -defm : int_cond_alias<"neg", 0b0110>; -defm : int_cond_alias<"vc", 0b1111>; -defm : int_cond_alias<"vs", 0b0111>; -let EmitPriority = 0 in -{ - defm : int_cond_alias<"", 0b1000>; // same as a; gnu asm, not in manual - defm : int_cond_alias<"nz", 0b1001>; // same as ne - defm : int_cond_alias<"eq", 0b0001>; // same as e - defm : int_cond_alias<"z", 0b0001>; // same as e - defm : int_cond_alias<"geu", 0b1101>; // same as cc - defm : int_cond_alias<"lu", 0b0101>; // same as cs -} -defm : fp_cond_alias<"a", 0b1000>; -defm : fp_cond_alias<"n", 0b0000>; -defm : fp_cond_alias<"u", 0b0111>; -defm : fp_cond_alias<"g", 0b0110>; -defm : fp_cond_alias<"ug", 0b0101>; -defm : fp_cond_alias<"l", 0b0100>; -defm : fp_cond_alias<"ul", 0b0011>; -defm : fp_cond_alias<"lg", 0b0010>; -defm : fp_cond_alias<"ne", 0b0001>; -defm : fp_cond_alias<"e", 0b1001>; -defm : fp_cond_alias<"ue", 0b1010>; -defm : fp_cond_alias<"ge", 0b1011>; -defm : fp_cond_alias<"uge", 0b1100>; -defm : fp_cond_alias<"le", 0b1101>; -defm : fp_cond_alias<"ule", 0b1110>; -defm : fp_cond_alias<"o", 0b1111>; -let EmitPriority = 0 in -{ - defm : fp_cond_alias<"", 0b1000>; // same as a; gnu asm, not in manual - defm : fp_cond_alias<"nz", 0b0001>; // same as ne - defm : fp_cond_alias<"z", 0b1001>; // same as e -} - -defm : cp_cond_alias<"a", 0b1000>; -defm : cp_cond_alias<"n", 0b0000>; -defm : cp_cond_alias<"3", 0b0111>; -defm : cp_cond_alias<"2", 0b0110>; -defm : cp_cond_alias<"23", 0b0101>; -defm : cp_cond_alias<"1", 0b0100>; -defm : cp_cond_alias<"13", 0b0011>; -defm : cp_cond_alias<"12", 0b0010>; -defm : cp_cond_alias<"123", 0b0001>; -defm : cp_cond_alias<"0", 0b1001>; -defm : cp_cond_alias<"03", 0b1010>; -defm : cp_cond_alias<"02", 0b1011>; -defm : cp_cond_alias<"023", 0b1100>; -defm : cp_cond_alias<"01", 0b1101>; -defm : cp_cond_alias<"013", 0b1110>; -defm : cp_cond_alias<"012", 0b1111>; -let EmitPriority = 0 in defm : cp_cond_alias<"", 0b1000>; // same as a; gnu asm, not in manual - -// Section A.3 Synthetic Instructions - -// Most are marked as Emit=0, so that they are not used for disassembly. This is -// an aesthetic issue, but the chosen policy is to typically prefer using the -// non-alias form, except for the most obvious and clarifying aliases: cmp, jmp, -// call, tst, ret, retl. - -// Note: cmp is handled in SparcInstrInfo. -// jmp/call/ret/retl have special case handling for output in -// SparcInstPrinter.cpp - -// jmp addr -> jmpl addr, %g0 -def : InstAlias<"jmp $addr", (JMPLrr G0, MEMrr:$addr), 0>; -def : InstAlias<"jmp $addr", (JMPLri G0, MEMri:$addr), 0>; - -// call addr -> jmpl addr, %o7 -def : InstAlias<"call $addr", (JMPLrr O7, MEMrr:$addr), 0>; -def : InstAlias<"call $addr", (JMPLri O7, MEMri:$addr), 0>; - -// tst reg -> orcc %g0, reg, %g0 -def : InstAlias<"tst $rs2", (ORCCrr G0, IntRegs:$rs2, G0)>; - -// ret -> jmpl %i7+8, %g0 (aka RET 8) -def : InstAlias<"ret", (RET 8)>; - -// retl -> jmpl %o7+8, %g0 (aka RETL 8) -def : InstAlias<"retl", (RETL 8)>; - -// restore -> restore %g0, %g0, %g0 -def : InstAlias<"restore", (RESTORErr G0, G0, G0)>; - -// save -> restore %g0, %g0, %g0 -def : InstAlias<"save", (SAVErr G0, G0, G0)>; - -// set value, rd -// (turns into a sequence of sethi+or, depending on the value) -// def : InstAlias<"set $val, $rd", (ORri IntRegs:$rd, (SETHIi (HI22 imm:$val)), (LO10 imm:$val))>; -def SET : AsmPseudoInst<(outs IntRegs:$rd), (ins i32imm:$val), "set $val, $rd">; - -// not rd -> xnor rd, %g0, rd -def : InstAlias<"not $rd", (XNORrr IntRegs:$rd, IntRegs:$rd, G0), 0>; - -// not reg, rd -> xnor reg, %g0, rd -def : InstAlias<"not $rs1, $rd", (XNORrr IntRegs:$rd, IntRegs:$rs1, G0), 0>; - -// neg rd -> sub %g0, rd, rd -def : InstAlias<"neg $rd", (SUBrr IntRegs:$rd, G0, IntRegs:$rd), 0>; - -// neg reg, rd -> sub %g0, reg, rd -def : InstAlias<"neg $rs2, $rd", (SUBrr IntRegs:$rd, G0, IntRegs:$rs2), 0>; - -// inc rd -> add rd, 1, rd -def : InstAlias<"inc $rd", (ADDri IntRegs:$rd, IntRegs:$rd, 1), 0>; - -// inc simm13, rd -> add rd, simm13, rd -def : InstAlias<"inc $simm13, $rd", (ADDri IntRegs:$rd, IntRegs:$rd, i32imm:$simm13), 0>; - -// inccc rd -> addcc rd, 1, rd -def : InstAlias<"inccc $rd", (ADDCCri IntRegs:$rd, IntRegs:$rd, 1), 0>; - -// inccc simm13, rd -> addcc rd, simm13, rd -def : InstAlias<"inccc $simm13, $rd", (ADDCCri IntRegs:$rd, IntRegs:$rd, i32imm:$simm13), 0>; - -// dec rd -> sub rd, 1, rd -def : InstAlias<"dec $rd", (SUBri IntRegs:$rd, IntRegs:$rd, 1), 0>; - -// dec simm13, rd -> sub rd, simm13, rd -def : InstAlias<"dec $simm13, $rd", (SUBri IntRegs:$rd, IntRegs:$rd, i32imm:$simm13), 0>; - -// deccc rd -> subcc rd, 1, rd -def : InstAlias<"deccc $rd", (SUBCCri IntRegs:$rd, IntRegs:$rd, 1), 0>; - -// deccc simm13, rd -> subcc rd, simm13, rd -def : InstAlias<"deccc $simm13, $rd", (SUBCCri IntRegs:$rd, IntRegs:$rd, i32imm:$simm13), 0>; - -// btst reg_or_imm, reg -> andcc reg,reg_or_imm,%g0 -def : InstAlias<"btst $rs2, $rs1", (ANDCCrr G0, IntRegs:$rs1, IntRegs:$rs2), 0>; -def : InstAlias<"btst $simm13, $rs1", (ANDCCri G0, IntRegs:$rs1, i32imm:$simm13), 0>; - -// bset reg_or_imm, rd -> or rd,reg_or_imm,rd -def : InstAlias<"bset $rs2, $rd", (ORrr IntRegs:$rd, IntRegs:$rd, IntRegs:$rs2), 0>; -def : InstAlias<"bset $simm13, $rd", (ORri IntRegs:$rd, IntRegs:$rd, i32imm:$simm13), 0>; - -// bclr reg_or_imm, rd -> andn rd,reg_or_imm,rd -def : InstAlias<"bclr $rs2, $rd", (ANDNrr IntRegs:$rd, IntRegs:$rd, IntRegs:$rs2), 0>; -def : InstAlias<"bclr $simm13, $rd", (ANDNri IntRegs:$rd, IntRegs:$rd, i32imm:$simm13), 0>; - -// btog reg_or_imm, rd -> xor rd,reg_or_imm,rd -def : InstAlias<"btog $rs2, $rd", (XORrr IntRegs:$rd, IntRegs:$rd, IntRegs:$rs2), 0>; -def : InstAlias<"btog $simm13, $rd", (XORri IntRegs:$rd, IntRegs:$rd, i32imm:$simm13), 0>; - - -// clr rd -> or %g0, %g0, rd -def : InstAlias<"clr $rd", (ORrr IntRegs:$rd, G0, G0), 0>; - -// clr{b,h,} [addr] -> st{b,h,} %g0, [addr] -def : InstAlias<"clrb [$addr]", (STBrr MEMrr:$addr, G0), 0>; -def : InstAlias<"clrb [$addr]", (STBri MEMri:$addr, G0), 0>; -def : InstAlias<"clrh [$addr]", (STHrr MEMrr:$addr, G0), 0>; -def : InstAlias<"clrh [$addr]", (STHri MEMri:$addr, G0), 0>; -def : InstAlias<"clr [$addr]", (STrr MEMrr:$addr, G0), 0>; -def : InstAlias<"clr [$addr]", (STri MEMri:$addr, G0), 0>; - - -// mov reg_or_imm, rd -> or %g0, reg_or_imm, rd -def : InstAlias<"mov $rs2, $rd", (ORrr IntRegs:$rd, G0, IntRegs:$rs2)>; -def : InstAlias<"mov $simm13, $rd", (ORri IntRegs:$rd, G0, i32imm:$simm13)>; - -// mov specialreg, rd -> rd specialreg, rd -def : InstAlias<"mov $asr, $rd", (RDASR IntRegs:$rd, ASRRegs:$asr), 0>; -def : InstAlias<"mov %psr, $rd", (RDPSR IntRegs:$rd), 0>; -def : InstAlias<"mov %wim, $rd", (RDWIM IntRegs:$rd), 0>; -def : InstAlias<"mov %tbr, $rd", (RDTBR IntRegs:$rd), 0>; - -// mov reg_or_imm, specialreg -> wr %g0, reg_or_imm, specialreg -def : InstAlias<"mov $rs2, $asr", (WRASRrr ASRRegs:$asr, G0, IntRegs:$rs2), 0>; -def : InstAlias<"mov $simm13, $asr", (WRASRri ASRRegs:$asr, G0, i32imm:$simm13), 0>; -def : InstAlias<"mov $rs2, %psr", (WRPSRrr G0, IntRegs:$rs2), 0>; -def : InstAlias<"mov $simm13, %psr", (WRPSRri G0, i32imm:$simm13), 0>; -def : InstAlias<"mov $rs2, %wim", (WRWIMrr G0, IntRegs:$rs2), 0>; -def : InstAlias<"mov $simm13, %wim", (WRWIMri G0, i32imm:$simm13), 0>; -def : InstAlias<"mov $rs2, %tbr", (WRTBRrr G0, IntRegs:$rs2), 0>; -def : InstAlias<"mov $simm13, %tbr", (WRTBRri G0, i32imm:$simm13), 0>; - -// End of Section A.3 - -// wr reg_or_imm, specialreg -> wr %g0, reg_or_imm, specialreg -// (aka: omit the first arg when it's g0. This is not in the manual, but is -// supported by gnu and solaris as) -def : InstAlias<"wr $rs2, $asr", (WRASRrr ASRRegs:$asr, G0, IntRegs:$rs2), 0>; -def : InstAlias<"wr $simm13, $asr", (WRASRri ASRRegs:$asr, G0, i32imm:$simm13), 0>; -def : InstAlias<"wr $rs2, %psr", (WRPSRrr G0, IntRegs:$rs2), 0>; -def : InstAlias<"wr $simm13, %psr", (WRPSRri G0, i32imm:$simm13), 0>; -def : InstAlias<"wr $rs2, %wim", (WRWIMrr G0, IntRegs:$rs2), 0>; -def : InstAlias<"wr $simm13, %wim", (WRWIMri G0, i32imm:$simm13), 0>; -def : InstAlias<"wr $rs2, %tbr", (WRTBRrr G0, IntRegs:$rs2), 0>; -def : InstAlias<"wr $simm13, %tbr", (WRTBRri G0, i32imm:$simm13), 0>; - -def : InstAlias<"pwr $rs2, %psr", (PWRPSRrr G0, IntRegs:$rs2), 0>; -def : InstAlias<"pwr $simm13, %psr", (PWRPSRri G0, i32imm:$simm13), 0>; - -// flush -> flush %g0 -def : InstAlias<"flush", (FLUSH), 0>; - -// unimp -> unimp 0 -def : InstAlias<"unimp", (UNIMP 0), 0>; - -def : MnemonicAlias<"iflush", "flush">; - -def : MnemonicAlias<"stub", "stb">; -def : MnemonicAlias<"stsb", "stb">; - -def : MnemonicAlias<"stuba", "stba">; -def : MnemonicAlias<"stsba", "stba">; - -def : MnemonicAlias<"stuh", "sth">; -def : MnemonicAlias<"stsh", "sth">; - -def : MnemonicAlias<"stuha", "stha">; -def : MnemonicAlias<"stsha", "stha">; - -def : MnemonicAlias<"lduw", "ld">, Requires<[HasV9]>; -def : MnemonicAlias<"lduwa", "lda">, Requires<[HasV9]>; - -def : MnemonicAlias<"return", "rett">, Requires<[HasV9]>; - -def : MnemonicAlias<"addc", "addx">, Requires<[HasV9]>; -def : MnemonicAlias<"addccc", "addxcc">, Requires<[HasV9]>; - -def : MnemonicAlias<"subc", "subx">, Requires<[HasV9]>; -def : MnemonicAlias<"subccc", "subxcc">, Requires<[HasV9]>; - - -def : InstAlias<"fcmps $rs1, $rs2", (V9FCMPS FCC0, FPRegs:$rs1, FPRegs:$rs2)>; -def : InstAlias<"fcmpd $rs1, $rs2", (V9FCMPD FCC0, DFPRegs:$rs1, DFPRegs:$rs2)>; -def : InstAlias<"fcmpq $rs1, $rs2", (V9FCMPQ FCC0, QFPRegs:$rs1, QFPRegs:$rs2)>, - Requires<[HasHardQuad]>; - -def : InstAlias<"fcmpes $rs1, $rs2", (V9FCMPES FCC0, FPRegs:$rs1, FPRegs:$rs2)>; -def : InstAlias<"fcmped $rs1, $rs2", (V9FCMPED FCC0, DFPRegs:$rs1, - DFPRegs:$rs2)>; -def : InstAlias<"fcmpeq $rs1, $rs2", (V9FCMPEQ FCC0, QFPRegs:$rs1, - QFPRegs:$rs2)>, - Requires<[HasHardQuad]>; - -// signx rd -> sra rd, %g0, rd -def : InstAlias<"signx $rd", (SRArr IntRegs:$rd, IntRegs:$rd, G0), 0>, Requires<[HasV9]>; - -// signx reg, rd -> sra reg, %g0, rd -def : InstAlias<"signx $rs1, $rd", (SRArr IntRegs:$rd, IntRegs:$rs1, G0), 0>, Requires<[HasV9]>; diff --git a/contrib/llvm/lib/Target/Sparc/SparcInstrFormats.td b/contrib/llvm/lib/Target/Sparc/SparcInstrFormats.td deleted file mode 100644 index fbf08b49d60c..000000000000 --- a/contrib/llvm/lib/Target/Sparc/SparcInstrFormats.td +++ /dev/null @@ -1,368 +0,0 @@ -//===-- SparcInstrFormats.td - Sparc 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 InstSP pattern, - InstrItinClass itin = NoItinerary> - : Instruction { - field bits<32> Inst; - - let Namespace = "SP"; - let Size = 4; - - bits<2> op; - let Inst{31-30} = op; // Top two bits are the 'op' field - - dag OutOperandList = outs; - dag InOperandList = ins; - let AsmString = asmstr; - let Pattern = pattern; - - let DecoderNamespace = "Sparc"; - field bits<32> SoftFail = 0; - - let Itinerary = itin; -} - -//===----------------------------------------------------------------------===// -// Format #2 instruction classes in the Sparc -//===----------------------------------------------------------------------===// - -// Format 2 instructions -class F2 pattern, - InstrItinClass itin = NoItinerary> - : InstSP { - bits<3> op2; - bits<22> imm22; - let op = 0; // op = 0 - let Inst{24-22} = op2; - let Inst{21-0} = imm22; -} - -// Specific F2 classes: SparcV8 manual, page 44 -// -class F2_1 op2Val, dag outs, dag ins, string asmstr, list pattern, - InstrItinClass itin = NoItinerary> - : F2 { - bits<5> rd; - - let op2 = op2Val; - - let Inst{29-25} = rd; -} - -class F2_2 op2Val, bit annul, dag outs, dag ins, string asmstr, - list pattern, InstrItinClass itin = NoItinerary> - : F2 { - bits<4> cond; - let op2 = op2Val; - - let Inst{29} = annul; - let Inst{28-25} = cond; -} - -class F2_3 op2Val, bit annul, bit pred, - dag outs, dag ins, string asmstr, list pattern, - InstrItinClass itin = NoItinerary> - : InstSP { - bits<2> cc; - bits<4> cond; - bits<19> imm19; - - let op = 0; // op = 0 - - let Inst{29} = annul; - let Inst{28-25} = cond; - let Inst{24-22} = op2Val; - let Inst{21-20} = cc; - let Inst{19} = pred; - let Inst{18-0} = imm19; -} - -class F2_4 cond, bit annul, bit pred, dag outs, dag ins, - string asmstr, list pattern, InstrItinClass itin = NoItinerary> - : InstSP { - bits<16> imm16; - bits<5> rs1; - - let op = 0; // op = 0 - - let Inst{29} = annul; - let Inst{28} = 0; - let Inst{27-25} = cond; - let Inst{24-22} = 0b011; - let Inst{21-20} = imm16{15-14}; - let Inst{19} = pred; - let Inst{18-14} = rs1; - let Inst{13-0} = imm16{13-0}; -} - - -//===----------------------------------------------------------------------===// -// Format #3 instruction classes in the Sparc -//===----------------------------------------------------------------------===// - -class F3 pattern, - InstrItinClass itin = NoItinerary> - : InstSP { - bits<5> rd; - bits<6> op3; - bits<5> rs1; - let op{1} = 1; // Op = 2 or 3 - let Inst{29-25} = rd; - let Inst{24-19} = op3; - let Inst{18-14} = rs1; -} - -// Specific F3 classes: SparcV8 manual, page 44 -// -class F3_1_asi opVal, bits<6> op3val, dag outs, dag ins, - string asmstr, list pattern, InstrItinClass itin = NoItinerary> - : F3 { - bits<8> asi; - bits<5> rs2; - - let op = opVal; - let op3 = op3val; - - let Inst{13} = 0; // i field = 0 - let Inst{12-5} = asi; // address space identifier - let Inst{4-0} = rs2; -} - -class F3_1 opVal, bits<6> op3val, dag outs, dag ins, string asmstr, - list pattern, InstrItinClass itin = IIC_iu_instr> - : F3_1_asi { - let asi = 0; -} - -class F3_2 opVal, bits<6> op3val, dag outs, dag ins, - string asmstr, list pattern, InstrItinClass itin = IIC_iu_instr> - : F3 { - bits<13> simm13; - - let op = opVal; - let op3 = op3val; - - let Inst{13} = 1; // i field = 1 - let Inst{12-0} = simm13; -} - -// floating-point -class F3_3 opVal, bits<6> op3val, bits<9> opfval, dag outs, dag ins, - string asmstr, list pattern, InstrItinClass itin = NoItinerary> - : F3 { - bits<5> rs2; - - let op = opVal; - let op3 = op3val; - - let Inst{13-5} = opfval; // fp opcode - let Inst{4-0} = rs2; -} - -// floating-point unary operations. -class F3_3u opVal, bits<6> op3val, bits<9> opfval, dag outs, dag ins, - string asmstr, list pattern, InstrItinClass itin = NoItinerary> - : F3 { - bits<5> rs2; - - let op = opVal; - let op3 = op3val; - let rs1 = 0; - - let Inst{13-5} = opfval; // fp opcode - let Inst{4-0} = rs2; -} - -// floating-point compares. -class F3_3c opVal, bits<6> op3val, bits<9> opfval, dag outs, dag ins, - string asmstr, list pattern, InstrItinClass itin = NoItinerary> - : F3 { - bits<5> rs2; - - let op = opVal; - let op3 = op3val; - - let Inst{13-5} = opfval; // fp opcode - let Inst{4-0} = rs2; -} - -// Shift by register rs2. -class F3_Sr opVal, bits<6> op3val, bit xVal, dag outs, dag ins, - string asmstr, list pattern, InstrItinClass itin = IIC_iu_instr> - : F3 { - bit x = xVal; // 1 for 64-bit shifts. - bits<5> rs2; - - let op = opVal; - let op3 = op3val; - - let Inst{13} = 0; // i field = 0 - let Inst{12} = x; // extended registers. - let Inst{4-0} = rs2; -} - -// Shift by immediate. -class F3_Si opVal, bits<6> op3val, bit xVal, dag outs, dag ins, - string asmstr, list pattern, InstrItinClass itin = IIC_iu_instr> - : F3 { - bit x = xVal; // 1 for 64-bit shifts. - bits<6> shcnt; // shcnt32 / shcnt64. - - let op = opVal; - let op3 = op3val; - - let Inst{13} = 1; // i field = 1 - let Inst{12} = x; // extended registers. - let Inst{5-0} = shcnt; -} - -// Define rr and ri shift instructions with patterns. -multiclass F3_S Op3Val, bit XVal, SDNode OpNode, - ValueType VT, RegisterClass RC, - InstrItinClass itin = IIC_iu_instr> { - def rr : F3_Sr<2, Op3Val, XVal, (outs RC:$rd), (ins RC:$rs1, IntRegs:$rs2), - !strconcat(OpcStr, " $rs1, $rs2, $rd"), - [(set VT:$rd, (OpNode VT:$rs1, i32:$rs2))], - itin>; - def ri : F3_Si<2, Op3Val, XVal, (outs RC:$rd), (ins RC:$rs1, i32imm:$shcnt), - !strconcat(OpcStr, " $rs1, $shcnt, $rd"), - [(set VT:$rd, (OpNode VT:$rs1, (i32 imm:$shcnt)))], - itin>; -} - -class F4 op3, dag outs, dag ins, string asmstr, list pattern, - InstrItinClass itin = NoItinerary> - : InstSP { - bits<5> rd; - - let op = 2; - let Inst{29-25} = rd; - let Inst{24-19} = op3; -} - - -class F4_1 op3, dag outs, dag ins, - string asmstr, list pattern, - InstrItinClass itin = NoItinerary> - : F4 { - bit intcc; - bits<2> cc; - bits<4> cond; - bits<5> rs2; - - let Inst{4-0} = rs2; - let Inst{12-11} = cc; - let Inst{13} = 0; - let Inst{17-14} = cond; - let Inst{18} = intcc; -} - -class F4_2 op3, dag outs, dag ins, - string asmstr, list pattern, - InstrItinClass itin = NoItinerary> - : F4 { - bit intcc; - bits<2> cc; - bits<4> cond; - bits<11> simm11; - - let Inst{10-0} = simm11; - let Inst{12-11} = cc; - let Inst{13} = 1; - let Inst{17-14} = cond; - let Inst{18} = intcc; -} - -class F4_3 op3, bits<6> opf_low, dag outs, dag ins, - string asmstr, list pattern, - InstrItinClass itin = NoItinerary> - : F4 { - bits<4> cond; - bit intcc; - bits<2> opf_cc; - bits<5> rs2; - - let Inst{18} = 0; - let Inst{17-14} = cond; - let Inst{13} = intcc; - let Inst{12-11} = opf_cc; - let Inst{10-5} = opf_low; - let Inst{4-0} = rs2; -} - -class F4_4r op3, bits<5> opf_low, bits<3> rcond, dag outs, dag ins, - string asmstr, list pattern, - InstrItinClass itin = NoItinerary> - : F4 { - bits <5> rs1; - bits <5> rs2; - let Inst{18-14} = rs1; - let Inst{13} = 0; // IsImm - let Inst{12-10} = rcond; - let Inst{9-5} = opf_low; - let Inst{4-0} = rs2; -} - - -class F4_4i op3, bits<3> rcond, dag outs, dag ins, - string asmstr, list pattern, - InstrItinClass itin = NoItinerary> - : F4 { - bits<5> rs1; - bits<10> simm10; - let Inst{18-14} = rs1; - let Inst{13} = 1; // IsImm - let Inst{12-10} = rcond; - let Inst{9-0} = simm10; -} - - -class TRAPSP op3Val, bit isimm, dag outs, dag ins, - string asmstr, list pattern, - InstrItinClass itin = NoItinerary> - : F3 { - bits<4> cond; - bits<2> cc; - - let op = 0b10; - let rd{4} = 0; - let rd{3-0} = cond; - let op3 = op3Val; - let Inst{13} = isimm; - let Inst{12-11} = cc; - -} - -class TRAPSPrr op3Val, dag outs, dag ins, - string asmstr, list pattern, - InstrItinClass itin = NoItinerary> - : TRAPSP { - bits<5> rs2; - - let Inst{10-5} = 0; - let Inst{4-0} = rs2; -} - -class TRAPSPri op3Val, dag outs, dag ins, - string asmstr, list pattern, - InstrItinClass itin = NoItinerary> - : TRAPSP { - bits<8> imm; - - let Inst{10-8} = 0; - let Inst{7-0} = imm; -} - -// 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 AsmPseudoInst - : InstSP { - let isPseudo = 1; -} diff --git a/contrib/llvm/lib/Target/Sparc/SparcInstrInfo.cpp b/contrib/llvm/lib/Target/Sparc/SparcInstrInfo.cpp deleted file mode 100644 index ad343fe6f80a..000000000000 --- a/contrib/llvm/lib/Target/Sparc/SparcInstrInfo.cpp +++ /dev/null @@ -1,509 +0,0 @@ -//===-- SparcInstrInfo.cpp - Sparc 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 Sparc implementation of the TargetInstrInfo class. -// -//===----------------------------------------------------------------------===// - -#include "SparcInstrInfo.h" -#include "Sparc.h" -#include "SparcMachineFunctionInfo.h" -#include "SparcSubtarget.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/MachineMemOperand.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/TargetRegistry.h" - -using namespace llvm; - -#define GET_INSTRINFO_CTOR_DTOR -#include "SparcGenInstrInfo.inc" - -// Pin the vtable to this file. -void SparcInstrInfo::anchor() {} - -SparcInstrInfo::SparcInstrInfo(SparcSubtarget &ST) - : SparcGenInstrInfo(SP::ADJCALLSTACKDOWN, SP::ADJCALLSTACKUP), RI(), - Subtarget(ST) {} - -/// 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 SparcInstrInfo::isLoadFromStackSlot(const MachineInstr &MI, - int &FrameIndex) const { - if (MI.getOpcode() == SP::LDri || MI.getOpcode() == SP::LDXri || - MI.getOpcode() == SP::LDFri || MI.getOpcode() == SP::LDDFri || - MI.getOpcode() == SP::LDQFri) { - if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() && - MI.getOperand(2).getImm() == 0) { - 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 SparcInstrInfo::isStoreToStackSlot(const MachineInstr &MI, - int &FrameIndex) const { - if (MI.getOpcode() == SP::STri || MI.getOpcode() == SP::STXri || - MI.getOpcode() == SP::STFri || MI.getOpcode() == SP::STDFri || - MI.getOpcode() == SP::STQFri) { - if (MI.getOperand(0).isFI() && MI.getOperand(1).isImm() && - MI.getOperand(1).getImm() == 0) { - FrameIndex = MI.getOperand(0).getIndex(); - return MI.getOperand(2).getReg(); - } - } - return 0; -} - -static bool IsIntegerCC(unsigned CC) -{ - return (CC <= SPCC::ICC_VC); -} - -static SPCC::CondCodes GetOppositeBranchCondition(SPCC::CondCodes CC) -{ - switch(CC) { - case SPCC::ICC_A: return SPCC::ICC_N; - case SPCC::ICC_N: return SPCC::ICC_A; - case SPCC::ICC_NE: return SPCC::ICC_E; - case SPCC::ICC_E: return SPCC::ICC_NE; - case SPCC::ICC_G: return SPCC::ICC_LE; - case SPCC::ICC_LE: return SPCC::ICC_G; - case SPCC::ICC_GE: return SPCC::ICC_L; - case SPCC::ICC_L: return SPCC::ICC_GE; - case SPCC::ICC_GU: return SPCC::ICC_LEU; - case SPCC::ICC_LEU: return SPCC::ICC_GU; - case SPCC::ICC_CC: return SPCC::ICC_CS; - case SPCC::ICC_CS: return SPCC::ICC_CC; - case SPCC::ICC_POS: return SPCC::ICC_NEG; - case SPCC::ICC_NEG: return SPCC::ICC_POS; - case SPCC::ICC_VC: return SPCC::ICC_VS; - case SPCC::ICC_VS: return SPCC::ICC_VC; - - case SPCC::FCC_A: return SPCC::FCC_N; - case SPCC::FCC_N: return SPCC::FCC_A; - case SPCC::FCC_U: return SPCC::FCC_O; - case SPCC::FCC_O: return SPCC::FCC_U; - case SPCC::FCC_G: return SPCC::FCC_ULE; - case SPCC::FCC_LE: return SPCC::FCC_UG; - case SPCC::FCC_UG: return SPCC::FCC_LE; - case SPCC::FCC_ULE: return SPCC::FCC_G; - case SPCC::FCC_L: return SPCC::FCC_UGE; - case SPCC::FCC_GE: return SPCC::FCC_UL; - case SPCC::FCC_UL: return SPCC::FCC_GE; - case SPCC::FCC_UGE: return SPCC::FCC_L; - case SPCC::FCC_LG: return SPCC::FCC_UE; - case SPCC::FCC_UE: return SPCC::FCC_LG; - case SPCC::FCC_NE: return SPCC::FCC_E; - case SPCC::FCC_E: return SPCC::FCC_NE; - - case SPCC::CPCC_A: return SPCC::CPCC_N; - case SPCC::CPCC_N: return SPCC::CPCC_A; - case SPCC::CPCC_3: LLVM_FALLTHROUGH; - case SPCC::CPCC_2: LLVM_FALLTHROUGH; - case SPCC::CPCC_23: LLVM_FALLTHROUGH; - case SPCC::CPCC_1: LLVM_FALLTHROUGH; - case SPCC::CPCC_13: LLVM_FALLTHROUGH; - case SPCC::CPCC_12: LLVM_FALLTHROUGH; - case SPCC::CPCC_123: LLVM_FALLTHROUGH; - case SPCC::CPCC_0: LLVM_FALLTHROUGH; - case SPCC::CPCC_03: LLVM_FALLTHROUGH; - case SPCC::CPCC_02: LLVM_FALLTHROUGH; - case SPCC::CPCC_023: LLVM_FALLTHROUGH; - case SPCC::CPCC_01: LLVM_FALLTHROUGH; - case SPCC::CPCC_013: LLVM_FALLTHROUGH; - case SPCC::CPCC_012: - // "Opposite" code is not meaningful, as we don't know - // what the CoProc condition means here. The cond-code will - // only be used in inline assembler, so this code should - // not be reached in a normal compilation pass. - llvm_unreachable("Meaningless inversion of co-processor cond code"); - } - llvm_unreachable("Invalid cond code"); -} - -static bool isUncondBranchOpcode(int Opc) { return Opc == SP::BA; } - -static bool isCondBranchOpcode(int Opc) { - return Opc == SP::FBCOND || Opc == SP::BCOND; -} - -static bool isIndirectBranchOpcode(int Opc) { - return Opc == SP::BINDrr || Opc == SP::BINDri; -} - -static void parseCondBranch(MachineInstr *LastInst, MachineBasicBlock *&Target, - SmallVectorImpl &Cond) { - Cond.push_back(MachineOperand::CreateImm(LastInst->getOperand(1).getImm())); - Target = LastInst->getOperand(0).getMBB(); -} - -bool SparcInstrInfo::analyzeBranch(MachineBasicBlock &MBB, - MachineBasicBlock *&TBB, - MachineBasicBlock *&FBB, - SmallVectorImpl &Cond, - bool AllowModify) const { - MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr(); - if (I == MBB.end()) - return false; - - if (!isUnpredicatedTerminator(*I)) - return false; - - // Get the last instruction in the block. - MachineInstr *LastInst = &*I; - unsigned LastOpc = LastInst->getOpcode(); - - // If there is only one terminator instruction, process it. - if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) { - if (isUncondBranchOpcode(LastOpc)) { - TBB = LastInst->getOperand(0).getMBB(); - return false; - } - if (isCondBranchOpcode(LastOpc)) { - // Block ends with fall-through condbranch. - parseCondBranch(LastInst, TBB, Cond); - return false; - } - return true; // Can't handle indirect branch. - } - - // Get the instruction before it if it is a terminator. - MachineInstr *SecondLastInst = &*I; - unsigned SecondLastOpc = SecondLastInst->getOpcode(); - - // If AllowModify is true and the block ends with two or more unconditional - // branches, delete all but the first unconditional branch. - if (AllowModify && isUncondBranchOpcode(LastOpc)) { - while (isUncondBranchOpcode(SecondLastOpc)) { - LastInst->eraseFromParent(); - LastInst = SecondLastInst; - LastOpc = LastInst->getOpcode(); - if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) { - // Return now the only terminator is an unconditional branch. - TBB = LastInst->getOperand(0).getMBB(); - return false; - } else { - SecondLastInst = &*I; - SecondLastOpc = SecondLastInst->getOpcode(); - } - } - } - - // If there are three terminators, we don't know what sort of block this is. - if (SecondLastInst && I != MBB.begin() && isUnpredicatedTerminator(*--I)) - return true; - - // If the block ends with a B and a Bcc, handle it. - if (isCondBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) { - parseCondBranch(SecondLastInst, TBB, Cond); - FBB = LastInst->getOperand(0).getMBB(); - return false; - } - - // If the block ends with two unconditional branches, handle it. The second - // one is not executed. - if (isUncondBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) { - TBB = SecondLastInst->getOperand(0).getMBB(); - return false; - } - - // ...likewise if it ends with an indirect branch followed by an unconditional - // branch. - if (isIndirectBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) { - I = LastInst; - if (AllowModify) - I->eraseFromParent(); - return true; - } - - // Otherwise, can't handle this. - return true; -} - -unsigned SparcInstrInfo::insertBranch(MachineBasicBlock &MBB, - MachineBasicBlock *TBB, - MachineBasicBlock *FBB, - ArrayRef Cond, - const DebugLoc &DL, - int *BytesAdded) const { - assert(TBB && "insertBranch must not be told to insert a fallthrough"); - assert((Cond.size() == 1 || Cond.size() == 0) && - "Sparc branch conditions should have one component!"); - assert(!BytesAdded && "code size not handled"); - - if (Cond.empty()) { - assert(!FBB && "Unconditional branch with multiple successors!"); - BuildMI(&MBB, DL, get(SP::BA)).addMBB(TBB); - return 1; - } - - // Conditional branch - unsigned CC = Cond[0].getImm(); - - if (IsIntegerCC(CC)) - BuildMI(&MBB, DL, get(SP::BCOND)).addMBB(TBB).addImm(CC); - else - BuildMI(&MBB, DL, get(SP::FBCOND)).addMBB(TBB).addImm(CC); - if (!FBB) - return 1; - - BuildMI(&MBB, DL, get(SP::BA)).addMBB(FBB); - return 2; -} - -unsigned SparcInstrInfo::removeBranch(MachineBasicBlock &MBB, - int *BytesRemoved) const { - assert(!BytesRemoved && "code size not handled"); - - MachineBasicBlock::iterator I = MBB.end(); - unsigned Count = 0; - while (I != MBB.begin()) { - --I; - - if (I->isDebugInstr()) - continue; - - if (I->getOpcode() != SP::BA - && I->getOpcode() != SP::BCOND - && I->getOpcode() != SP::FBCOND) - break; // Not a branch - - I->eraseFromParent(); - I = MBB.end(); - ++Count; - } - return Count; -} - -bool SparcInstrInfo::reverseBranchCondition( - SmallVectorImpl &Cond) const { - assert(Cond.size() == 1); - SPCC::CondCodes CC = static_cast(Cond[0].getImm()); - Cond[0].setImm(GetOppositeBranchCondition(CC)); - return false; -} - -void SparcInstrInfo::copyPhysReg(MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, - const DebugLoc &DL, unsigned DestReg, - unsigned SrcReg, bool KillSrc) const { - unsigned numSubRegs = 0; - unsigned movOpc = 0; - const unsigned *subRegIdx = nullptr; - bool ExtraG0 = false; - - const unsigned DW_SubRegsIdx[] = { SP::sub_even, SP::sub_odd }; - const unsigned DFP_FP_SubRegsIdx[] = { SP::sub_even, SP::sub_odd }; - const unsigned QFP_DFP_SubRegsIdx[] = { SP::sub_even64, SP::sub_odd64 }; - const unsigned QFP_FP_SubRegsIdx[] = { SP::sub_even, SP::sub_odd, - SP::sub_odd64_then_sub_even, - SP::sub_odd64_then_sub_odd }; - - if (SP::IntRegsRegClass.contains(DestReg, SrcReg)) - BuildMI(MBB, I, DL, get(SP::ORrr), DestReg).addReg(SP::G0) - .addReg(SrcReg, getKillRegState(KillSrc)); - else if (SP::IntPairRegClass.contains(DestReg, SrcReg)) { - subRegIdx = DW_SubRegsIdx; - numSubRegs = 2; - movOpc = SP::ORrr; - ExtraG0 = true; - } else if (SP::FPRegsRegClass.contains(DestReg, SrcReg)) - BuildMI(MBB, I, DL, get(SP::FMOVS), DestReg) - .addReg(SrcReg, getKillRegState(KillSrc)); - else if (SP::DFPRegsRegClass.contains(DestReg, SrcReg)) { - if (Subtarget.isV9()) { - BuildMI(MBB, I, DL, get(SP::FMOVD), DestReg) - .addReg(SrcReg, getKillRegState(KillSrc)); - } else { - // Use two FMOVS instructions. - subRegIdx = DFP_FP_SubRegsIdx; - numSubRegs = 2; - movOpc = SP::FMOVS; - } - } else if (SP::QFPRegsRegClass.contains(DestReg, SrcReg)) { - if (Subtarget.isV9()) { - if (Subtarget.hasHardQuad()) { - BuildMI(MBB, I, DL, get(SP::FMOVQ), DestReg) - .addReg(SrcReg, getKillRegState(KillSrc)); - } else { - // Use two FMOVD instructions. - subRegIdx = QFP_DFP_SubRegsIdx; - numSubRegs = 2; - movOpc = SP::FMOVD; - } - } else { - // Use four FMOVS instructions. - subRegIdx = QFP_FP_SubRegsIdx; - numSubRegs = 4; - movOpc = SP::FMOVS; - } - } else if (SP::ASRRegsRegClass.contains(DestReg) && - SP::IntRegsRegClass.contains(SrcReg)) { - BuildMI(MBB, I, DL, get(SP::WRASRrr), DestReg) - .addReg(SP::G0) - .addReg(SrcReg, getKillRegState(KillSrc)); - } else if (SP::IntRegsRegClass.contains(DestReg) && - SP::ASRRegsRegClass.contains(SrcReg)) { - BuildMI(MBB, I, DL, get(SP::RDASR), DestReg) - .addReg(SrcReg, getKillRegState(KillSrc)); - } else - llvm_unreachable("Impossible reg-to-reg copy"); - - if (numSubRegs == 0 || subRegIdx == nullptr || movOpc == 0) - return; - - const TargetRegisterInfo *TRI = &getRegisterInfo(); - MachineInstr *MovMI = nullptr; - - for (unsigned i = 0; i != numSubRegs; ++i) { - unsigned Dst = TRI->getSubReg(DestReg, subRegIdx[i]); - unsigned Src = TRI->getSubReg(SrcReg, subRegIdx[i]); - assert(Dst && Src && "Bad sub-register"); - - MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(movOpc), Dst); - if (ExtraG0) - MIB.addReg(SP::G0); - MIB.addReg(Src); - MovMI = MIB.getInstr(); - } - // Add implicit super-register defs and kills to the last MovMI. - MovMI->addRegisterDefined(DestReg, TRI); - if (KillSrc) - MovMI->addRegisterKilled(SrcReg, TRI); -} - -void SparcInstrInfo:: -storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, - unsigned SrcReg, bool isKill, int FI, - const TargetRegisterClass *RC, - const TargetRegisterInfo *TRI) const { - DebugLoc DL; - if (I != MBB.end()) DL = I->getDebugLoc(); - - MachineFunction *MF = MBB.getParent(); - const MachineFrameInfo &MFI = MF->getFrameInfo(); - MachineMemOperand *MMO = MF->getMachineMemOperand( - MachinePointerInfo::getFixedStack(*MF, FI), MachineMemOperand::MOStore, - MFI.getObjectSize(FI), MFI.getObjectAlignment(FI)); - - // On the order of operands here: think "[FrameIdx + 0] = SrcReg". - if (RC == &SP::I64RegsRegClass) - BuildMI(MBB, I, DL, get(SP::STXri)).addFrameIndex(FI).addImm(0) - .addReg(SrcReg, getKillRegState(isKill)).addMemOperand(MMO); - else if (RC == &SP::IntRegsRegClass) - BuildMI(MBB, I, DL, get(SP::STri)).addFrameIndex(FI).addImm(0) - .addReg(SrcReg, getKillRegState(isKill)).addMemOperand(MMO); - else if (RC == &SP::IntPairRegClass) - BuildMI(MBB, I, DL, get(SP::STDri)).addFrameIndex(FI).addImm(0) - .addReg(SrcReg, getKillRegState(isKill)).addMemOperand(MMO); - else if (RC == &SP::FPRegsRegClass) - BuildMI(MBB, I, DL, get(SP::STFri)).addFrameIndex(FI).addImm(0) - .addReg(SrcReg, getKillRegState(isKill)).addMemOperand(MMO); - else if (SP::DFPRegsRegClass.hasSubClassEq(RC)) - BuildMI(MBB, I, DL, get(SP::STDFri)).addFrameIndex(FI).addImm(0) - .addReg(SrcReg, getKillRegState(isKill)).addMemOperand(MMO); - else if (SP::QFPRegsRegClass.hasSubClassEq(RC)) - // Use STQFri irrespective of its legality. If STQ is not legal, it will be - // lowered into two STDs in eliminateFrameIndex. - BuildMI(MBB, I, DL, get(SP::STQFri)).addFrameIndex(FI).addImm(0) - .addReg(SrcReg, getKillRegState(isKill)).addMemOperand(MMO); - else - llvm_unreachable("Can't store this register to stack slot"); -} - -void SparcInstrInfo:: -loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, - unsigned DestReg, int FI, - const TargetRegisterClass *RC, - const TargetRegisterInfo *TRI) const { - DebugLoc DL; - if (I != MBB.end()) DL = I->getDebugLoc(); - - MachineFunction *MF = MBB.getParent(); - const MachineFrameInfo &MFI = MF->getFrameInfo(); - MachineMemOperand *MMO = MF->getMachineMemOperand( - MachinePointerInfo::getFixedStack(*MF, FI), MachineMemOperand::MOLoad, - MFI.getObjectSize(FI), MFI.getObjectAlignment(FI)); - - if (RC == &SP::I64RegsRegClass) - BuildMI(MBB, I, DL, get(SP::LDXri), DestReg).addFrameIndex(FI).addImm(0) - .addMemOperand(MMO); - else if (RC == &SP::IntRegsRegClass) - BuildMI(MBB, I, DL, get(SP::LDri), DestReg).addFrameIndex(FI).addImm(0) - .addMemOperand(MMO); - else if (RC == &SP::IntPairRegClass) - BuildMI(MBB, I, DL, get(SP::LDDri), DestReg).addFrameIndex(FI).addImm(0) - .addMemOperand(MMO); - else if (RC == &SP::FPRegsRegClass) - BuildMI(MBB, I, DL, get(SP::LDFri), DestReg).addFrameIndex(FI).addImm(0) - .addMemOperand(MMO); - else if (SP::DFPRegsRegClass.hasSubClassEq(RC)) - BuildMI(MBB, I, DL, get(SP::LDDFri), DestReg).addFrameIndex(FI).addImm(0) - .addMemOperand(MMO); - else if (SP::QFPRegsRegClass.hasSubClassEq(RC)) - // Use LDQFri irrespective of its legality. If LDQ is not legal, it will be - // lowered into two LDDs in eliminateFrameIndex. - BuildMI(MBB, I, DL, get(SP::LDQFri), DestReg).addFrameIndex(FI).addImm(0) - .addMemOperand(MMO); - else - llvm_unreachable("Can't load this register from stack slot"); -} - -unsigned SparcInstrInfo::getGlobalBaseReg(MachineFunction *MF) const -{ - SparcMachineFunctionInfo *SparcFI = MF->getInfo(); - unsigned GlobalBaseReg = SparcFI->getGlobalBaseReg(); - if (GlobalBaseReg != 0) - return GlobalBaseReg; - - // Insert the set of GlobalBaseReg into the first MBB of the function - MachineBasicBlock &FirstMBB = MF->front(); - MachineBasicBlock::iterator MBBI = FirstMBB.begin(); - MachineRegisterInfo &RegInfo = MF->getRegInfo(); - - const TargetRegisterClass *PtrRC = - Subtarget.is64Bit() ? &SP::I64RegsRegClass : &SP::IntRegsRegClass; - GlobalBaseReg = RegInfo.createVirtualRegister(PtrRC); - - DebugLoc dl; - - BuildMI(FirstMBB, MBBI, dl, get(SP::GETPCX), GlobalBaseReg); - SparcFI->setGlobalBaseReg(GlobalBaseReg); - return GlobalBaseReg; -} - -bool SparcInstrInfo::expandPostRAPseudo(MachineInstr &MI) const { - switch (MI.getOpcode()) { - case TargetOpcode::LOAD_STACK_GUARD: { - assert(Subtarget.isTargetLinux() && - "Only Linux target is expected to contain LOAD_STACK_GUARD"); - // offsetof(tcbhead_t, stack_guard) from sysdeps/sparc/nptl/tls.h in glibc. - const int64_t Offset = Subtarget.is64Bit() ? 0x28 : 0x14; - MI.setDesc(get(Subtarget.is64Bit() ? SP::LDXri : SP::LDri)); - MachineInstrBuilder(*MI.getParent()->getParent(), MI) - .addReg(SP::G7) - .addImm(Offset); - return true; - } - } - return false; -} diff --git a/contrib/llvm/lib/Target/Sparc/SparcInstrInfo.h b/contrib/llvm/lib/Target/Sparc/SparcInstrInfo.h deleted file mode 100644 index b587b28c25fc..000000000000 --- a/contrib/llvm/lib/Target/Sparc/SparcInstrInfo.h +++ /dev/null @@ -1,107 +0,0 @@ -//===-- SparcInstrInfo.h - Sparc 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 Sparc implementation of the TargetInstrInfo class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_SPARC_SPARCINSTRINFO_H -#define LLVM_LIB_TARGET_SPARC_SPARCINSTRINFO_H - -#include "SparcRegisterInfo.h" -#include "llvm/CodeGen/TargetInstrInfo.h" - -#define GET_INSTRINFO_HEADER -#include "SparcGenInstrInfo.inc" - -namespace llvm { - -class SparcSubtarget; - -/// SPII - This namespace holds all of the target specific flags that -/// instruction info tracks. -/// -namespace SPII { - enum { - Pseudo = (1<<0), - Load = (1<<1), - Store = (1<<2), - DelaySlot = (1<<3) - }; -} - -class SparcInstrInfo : public SparcGenInstrInfo { - const SparcRegisterInfo RI; - const SparcSubtarget& Subtarget; - virtual void anchor(); -public: - explicit SparcInstrInfo(SparcSubtarget &ST); - - /// 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). - /// - const SparcRegisterInfo &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 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; - - bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, - MachineBasicBlock *&FBB, - SmallVectorImpl &Cond, - bool AllowModify = false) const override; - - unsigned removeBranch(MachineBasicBlock &MBB, - int *BytesRemoved = nullptr) const override; - - unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, - MachineBasicBlock *FBB, ArrayRef Cond, - const DebugLoc &DL, - int *BytesAdded = nullptr) const override; - - bool - reverseBranchCondition(SmallVectorImpl &Cond) const override; - - void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, - const DebugLoc &DL, unsigned DestReg, unsigned SrcReg, - bool KillSrc) const override; - - void storeRegToStackSlot(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI, - unsigned SrcReg, bool isKill, int FrameIndex, - const TargetRegisterClass *RC, - const TargetRegisterInfo *TRI) const override; - - void loadRegFromStackSlot(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI, - unsigned DestReg, int FrameIndex, - const TargetRegisterClass *RC, - const TargetRegisterInfo *TRI) const override; - - unsigned getGlobalBaseReg(MachineFunction *MF) const; - - // Lower pseudo instructions after register allocation. - bool expandPostRAPseudo(MachineInstr &MI) const override; -}; - -} - -#endif diff --git a/contrib/llvm/lib/Target/Sparc/SparcInstrInfo.td b/contrib/llvm/lib/Target/Sparc/SparcInstrInfo.td deleted file mode 100644 index 8474c7abffb3..000000000000 --- a/contrib/llvm/lib/Target/Sparc/SparcInstrInfo.td +++ /dev/null @@ -1,1712 +0,0 @@ -//===-- SparcInstrInfo.td - Target Description for Sparc Target -----------===// -// -// Part of the LLVM Project, under the Apache 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 Sparc instructions in TableGen format. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// Instruction format superclass -//===----------------------------------------------------------------------===// - -include "SparcInstrFormats.td" - -//===----------------------------------------------------------------------===// -// Feature predicates. -//===----------------------------------------------------------------------===// - -// True when generating 32-bit code. -def Is32Bit : Predicate<"!Subtarget->is64Bit()">; - -// True when generating 64-bit code. This also implies HasV9. -def Is64Bit : Predicate<"Subtarget->is64Bit()">; - -def UseSoftMulDiv : Predicate<"Subtarget->useSoftMulDiv()">, - AssemblerPredicate<"FeatureSoftMulDiv">; - -// HasV9 - This predicate is true when the target processor supports V9 -// instructions. Note that the machine may be running in 32-bit mode. -def HasV9 : Predicate<"Subtarget->isV9()">, - AssemblerPredicate<"FeatureV9">; - -// HasNoV9 - This predicate is true when the target doesn't have V9 -// instructions. Use of this is just a hack for the isel not having proper -// costs for V8 instructions that are more expensive than their V9 ones. -def HasNoV9 : Predicate<"!Subtarget->isV9()">; - -// HasVIS - This is true when the target processor has VIS extensions. -def HasVIS : Predicate<"Subtarget->isVIS()">, - AssemblerPredicate<"FeatureVIS">; -def HasVIS2 : Predicate<"Subtarget->isVIS2()">, - AssemblerPredicate<"FeatureVIS2">; -def HasVIS3 : Predicate<"Subtarget->isVIS3()">, - AssemblerPredicate<"FeatureVIS3">; - -// HasHardQuad - This is true when the target processor supports quad floating -// point instructions. -def HasHardQuad : Predicate<"Subtarget->hasHardQuad()">; - -// HasLeonCASA - This is true when the target processor supports the CASA -// instruction -def HasLeonCASA : Predicate<"Subtarget->hasLeonCasa()">; - -// HasPWRPSR - This is true when the target processor supports partial -// writes to the PSR register that only affects the ET field. -def HasPWRPSR : Predicate<"Subtarget->hasPWRPSR()">, - AssemblerPredicate<"FeaturePWRPSR">; - -// HasUMAC_SMAC - This is true when the target processor supports the -// UMAC and SMAC instructions -def HasUMAC_SMAC : Predicate<"Subtarget->hasUmacSmac()">; - -def HasNoFdivSqrtFix : Predicate<"!Subtarget->fixAllFDIVSQRT()">; -def HasFMULS : Predicate<"!Subtarget->hasNoFMULS()">; -def HasFSMULD : Predicate<"!Subtarget->hasNoFSMULD()">; - -// UseDeprecatedInsts - This predicate is true when the target processor is a -// V8, or when it is V9 but the V8 deprecated instructions are efficient enough -// to use when appropriate. In either of these cases, the instruction selector -// will pick deprecated instructions. -def UseDeprecatedInsts : Predicate<"Subtarget->useDeprecatedV8Instructions()">; - -//===----------------------------------------------------------------------===// -// Instruction Pattern Stuff -//===----------------------------------------------------------------------===// - -def simm11 : PatLeaf<(imm), [{ return isInt<11>(N->getSExtValue()); }]>; - -def simm13 : PatLeaf<(imm), [{ return isInt<13>(N->getSExtValue()); }]>; - -def LO10 : SDNodeXFormgetTargetConstant((unsigned)N->getZExtValue() & 1023, SDLoc(N), - MVT::i32); -}]>; - -def HI22 : SDNodeXFormgetTargetConstant((unsigned)N->getZExtValue() >> 10, SDLoc(N), - MVT::i32); -}]>; - -// Return the complement of a HI22 immediate value. -def HI22_not : SDNodeXFormgetTargetConstant(~(unsigned)N->getZExtValue() >> 10, SDLoc(N), - MVT::i32); -}]>; - -def SETHIimm : PatLeaf<(imm), [{ - return isShiftedUInt<22, 10>(N->getZExtValue()); -}], HI22>; - -// The N->hasOneUse() prevents the immediate from being instantiated in both -// normal and complement form. -def SETHIimm_not : PatLeaf<(i32 imm), [{ - return N->hasOneUse() && isShiftedUInt<22, 10>(~(unsigned)N->getZExtValue()); -}], HI22_not>; - -// Addressing modes. -def ADDRrr : ComplexPattern; -def ADDRri : ComplexPattern; - -// Address operands -def SparcMEMrrAsmOperand : AsmOperandClass { - let Name = "MEMrr"; - let ParserMethod = "parseMEMOperand"; -} - -def SparcMEMriAsmOperand : AsmOperandClass { - let Name = "MEMri"; - let ParserMethod = "parseMEMOperand"; -} - -def MEMrr : Operand { - let PrintMethod = "printMemOperand"; - let MIOperandInfo = (ops ptr_rc, ptr_rc); - let ParserMatchClass = SparcMEMrrAsmOperand; -} -def MEMri : Operand { - let PrintMethod = "printMemOperand"; - let MIOperandInfo = (ops ptr_rc, i32imm); - let ParserMatchClass = SparcMEMriAsmOperand; -} - -def TLSSym : Operand; - -def SparcMembarTagAsmOperand : AsmOperandClass { - let Name = "MembarTag"; - let ParserMethod = "parseMembarTag"; -} - -def MembarTag : Operand { - let PrintMethod = "printMembarTag"; - let ParserMatchClass = SparcMembarTagAsmOperand; -} - -// Branch targets have OtherVT type. -def brtarget : Operand { - let EncoderMethod = "getBranchTargetOpValue"; -} - -def bprtarget : Operand { - let EncoderMethod = "getBranchPredTargetOpValue"; -} - -def bprtarget16 : Operand { - let EncoderMethod = "getBranchOnRegTargetOpValue"; -} - -def calltarget : Operand { - let EncoderMethod = "getCallTargetOpValue"; - let DecoderMethod = "DecodeCall"; -} - -def simm13Op : Operand { - let DecoderMethod = "DecodeSIMM13"; -} - -// Operand for printing out a condition code. -let PrintMethod = "printCCOperand" in - def CCOp : Operand; - -def SDTSPcmpicc : -SDTypeProfile<0, 2, [SDTCisInt<0>, SDTCisSameAs<0, 1>]>; -def SDTSPcmpfcc : -SDTypeProfile<0, 2, [SDTCisFP<0>, SDTCisSameAs<0, 1>]>; -def SDTSPbrcc : -SDTypeProfile<0, 2, [SDTCisVT<0, OtherVT>, SDTCisVT<1, i32>]>; -def SDTSPselectcc : -SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>, SDTCisVT<3, i32>]>; -def SDTSPFTOI : -SDTypeProfile<1, 1, [SDTCisVT<0, f32>, SDTCisFP<1>]>; -def SDTSPITOF : -SDTypeProfile<1, 1, [SDTCisFP<0>, SDTCisVT<1, f32>]>; -def SDTSPFTOX : -SDTypeProfile<1, 1, [SDTCisVT<0, f64>, SDTCisFP<1>]>; -def SDTSPXTOF : -SDTypeProfile<1, 1, [SDTCisFP<0>, SDTCisVT<1, f64>]>; - -def SDTSPtlsadd : -SDTypeProfile<1, 3, [SDTCisInt<0>, SDTCisSameAs<0, 1>, SDTCisPtrTy<2>]>; -def SDTSPtlsld : -SDTypeProfile<1, 2, [SDTCisPtrTy<0>, SDTCisPtrTy<1>]>; - -def SPcmpicc : SDNode<"SPISD::CMPICC", SDTSPcmpicc, [SDNPOutGlue]>; -def SPcmpfcc : SDNode<"SPISD::CMPFCC", SDTSPcmpfcc, [SDNPOutGlue]>; -def SPbricc : SDNode<"SPISD::BRICC", SDTSPbrcc, [SDNPHasChain, SDNPInGlue]>; -def SPbrxcc : SDNode<"SPISD::BRXCC", SDTSPbrcc, [SDNPHasChain, SDNPInGlue]>; -def SPbrfcc : SDNode<"SPISD::BRFCC", SDTSPbrcc, [SDNPHasChain, SDNPInGlue]>; - -def SPhi : SDNode<"SPISD::Hi", SDTIntUnaryOp>; -def SPlo : SDNode<"SPISD::Lo", SDTIntUnaryOp>; - -def SPftoi : SDNode<"SPISD::FTOI", SDTSPFTOI>; -def SPitof : SDNode<"SPISD::ITOF", SDTSPITOF>; -def SPftox : SDNode<"SPISD::FTOX", SDTSPFTOX>; -def SPxtof : SDNode<"SPISD::XTOF", SDTSPXTOF>; - -def SPselecticc : SDNode<"SPISD::SELECT_ICC", SDTSPselectcc, [SDNPInGlue]>; -def SPselectxcc : SDNode<"SPISD::SELECT_XCC", SDTSPselectcc, [SDNPInGlue]>; -def SPselectfcc : SDNode<"SPISD::SELECT_FCC", SDTSPselectcc, [SDNPInGlue]>; - -// These are target-independent nodes, but have target-specific formats. -def SDT_SPCallSeqStart : SDCallSeqStart<[ SDTCisVT<0, i32>, - SDTCisVT<1, i32> ]>; -def SDT_SPCallSeqEnd : SDCallSeqEnd<[ SDTCisVT<0, i32>, - SDTCisVT<1, i32> ]>; - -def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_SPCallSeqStart, - [SDNPHasChain, SDNPOutGlue]>; -def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_SPCallSeqEnd, - [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; - -def SDT_SPCall : SDTypeProfile<0, -1, [SDTCisVT<0, i32>]>; -def call : SDNode<"SPISD::CALL", SDT_SPCall, - [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, - SDNPVariadic]>; - -def SDT_SPRet : SDTypeProfile<0, 1, [SDTCisVT<0, i32>]>; -def retflag : SDNode<"SPISD::RET_FLAG", SDT_SPRet, - [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; - -def flushw : SDNode<"SPISD::FLUSHW", SDTNone, - [SDNPHasChain, SDNPSideEffect, SDNPMayStore]>; - -def tlsadd : SDNode<"SPISD::TLS_ADD", SDTSPtlsadd>; -def tlsld : SDNode<"SPISD::TLS_LD", SDTSPtlsld>; -def tlscall : SDNode<"SPISD::TLS_CALL", SDT_SPCall, - [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, - SDNPVariadic]>; - -def getPCX : Operand { - let PrintMethod = "printGetPCX"; -} - -//===----------------------------------------------------------------------===// -// SPARC Flag Conditions -//===----------------------------------------------------------------------===// - -// Note that these values must be kept in sync with the CCOp::CondCode enum -// values. -class ICC_VAL : PatLeaf<(i32 N)>; -def ICC_NE : ICC_VAL< 9>; // Not Equal -def ICC_E : ICC_VAL< 1>; // Equal -def ICC_G : ICC_VAL<10>; // Greater -def ICC_LE : ICC_VAL< 2>; // Less or Equal -def ICC_GE : ICC_VAL<11>; // Greater or Equal -def ICC_L : ICC_VAL< 3>; // Less -def ICC_GU : ICC_VAL<12>; // Greater Unsigned -def ICC_LEU : ICC_VAL< 4>; // Less or Equal Unsigned -def ICC_CC : ICC_VAL<13>; // Carry Clear/Great or Equal Unsigned -def ICC_CS : ICC_VAL< 5>; // Carry Set/Less Unsigned -def ICC_POS : ICC_VAL<14>; // Positive -def ICC_NEG : ICC_VAL< 6>; // Negative -def ICC_VC : ICC_VAL<15>; // Overflow Clear -def ICC_VS : ICC_VAL< 7>; // Overflow Set - -class FCC_VAL : PatLeaf<(i32 N)>; -def FCC_U : FCC_VAL<23>; // Unordered -def FCC_G : FCC_VAL<22>; // Greater -def FCC_UG : FCC_VAL<21>; // Unordered or Greater -def FCC_L : FCC_VAL<20>; // Less -def FCC_UL : FCC_VAL<19>; // Unordered or Less -def FCC_LG : FCC_VAL<18>; // Less or Greater -def FCC_NE : FCC_VAL<17>; // Not Equal -def FCC_E : FCC_VAL<25>; // Equal -def FCC_UE : FCC_VAL<26>; // Unordered or Equal -def FCC_GE : FCC_VAL<27>; // Greater or Equal -def FCC_UGE : FCC_VAL<28>; // Unordered or Greater or Equal -def FCC_LE : FCC_VAL<29>; // Less or Equal -def FCC_ULE : FCC_VAL<30>; // Unordered or Less or Equal -def FCC_O : FCC_VAL<31>; // Ordered - -class CPCC_VAL : PatLeaf<(i32 N)>; -def CPCC_3 : CPCC_VAL<39>; // 3 -def CPCC_2 : CPCC_VAL<38>; // 2 -def CPCC_23 : CPCC_VAL<37>; // 2 or 3 -def CPCC_1 : CPCC_VAL<36>; // 1 -def CPCC_13 : CPCC_VAL<35>; // 1 or 3 -def CPCC_12 : CPCC_VAL<34>; // 1 or 2 -def CPCC_123 : CPCC_VAL<33>; // 1 or 2 or 3 -def CPCC_0 : CPCC_VAL<41>; // 0 -def CPCC_03 : CPCC_VAL<42>; // 0 or 3 -def CPCC_02 : CPCC_VAL<43>; // 0 or 2 -def CPCC_023 : CPCC_VAL<44>; // 0 or 2 or 3 -def CPCC_01 : CPCC_VAL<45>; // 0 or 1 -def CPCC_013 : CPCC_VAL<46>; // 0 or 1 or 3 -def CPCC_012 : CPCC_VAL<47>; // 0 or 1 or 2 - -//===----------------------------------------------------------------------===// -// Instruction Class Templates -//===----------------------------------------------------------------------===// - -/// F3_12 multiclass - Define a normal F3_1/F3_2 pattern in one shot. -multiclass F3_12 Op3Val, SDNode OpNode, - RegisterClass RC, ValueType Ty, Operand immOp, - InstrItinClass itin = IIC_iu_instr> { - def rr : F3_1<2, Op3Val, - (outs RC:$rd), (ins RC:$rs1, RC:$rs2), - !strconcat(OpcStr, " $rs1, $rs2, $rd"), - [(set Ty:$rd, (OpNode Ty:$rs1, Ty:$rs2))], - itin>; - def ri : F3_2<2, Op3Val, - (outs RC:$rd), (ins RC:$rs1, immOp:$simm13), - !strconcat(OpcStr, " $rs1, $simm13, $rd"), - [(set Ty:$rd, (OpNode Ty:$rs1, (Ty simm13:$simm13)))], - itin>; -} - -/// F3_12np multiclass - Define a normal F3_1/F3_2 pattern in one shot, with no -/// pattern. -multiclass F3_12np Op3Val, InstrItinClass itin = IIC_iu_instr> { - def rr : F3_1<2, Op3Val, - (outs IntRegs:$rd), (ins IntRegs:$rs1, IntRegs:$rs2), - !strconcat(OpcStr, " $rs1, $rs2, $rd"), [], - itin>; - def ri : F3_2<2, Op3Val, - (outs IntRegs:$rd), (ins IntRegs:$rs1, simm13Op:$simm13), - !strconcat(OpcStr, " $rs1, $simm13, $rd"), [], - itin>; -} - -// Load multiclass - Define both Reg+Reg/Reg+Imm patterns in one shot. -multiclass Load Op3Val, SDPatternOperator OpNode, - RegisterClass RC, ValueType Ty, InstrItinClass itin = IIC_iu_instr> { - def rr : F3_1<3, Op3Val, - (outs RC:$dst), (ins MEMrr:$addr), - !strconcat(OpcStr, " [$addr], $dst"), - [(set Ty:$dst, (OpNode ADDRrr:$addr))], - itin>; - def ri : F3_2<3, Op3Val, - (outs RC:$dst), (ins MEMri:$addr), - !strconcat(OpcStr, " [$addr], $dst"), - [(set Ty:$dst, (OpNode ADDRri:$addr))], - itin>; -} - -// TODO: Instructions of the LoadASI class are currently asm only; hooking up -// CodeGen's address spaces to use these is a future task. -class LoadASI Op3Val, SDPatternOperator OpNode, - RegisterClass RC, ValueType Ty, InstrItinClass itin = NoItinerary> : - F3_1_asi<3, Op3Val, (outs RC:$dst), (ins MEMrr:$addr, i8imm:$asi), - !strconcat(OpcStr, "a [$addr] $asi, $dst"), - []>; - -// LoadA multiclass - As above, but also define alternate address space variant -multiclass LoadA Op3Val, bits<6> LoadAOp3Val, - SDPatternOperator OpNode, RegisterClass RC, ValueType Ty, - InstrItinClass itin = NoItinerary> : - Load { - def Arr : LoadASI; -} - -// The LDSTUB instruction is supported for asm only. -// It is unlikely that general-purpose code could make use of it. -// CAS is preferred for sparc v9. -def LDSTUBrr : F3_1<3, 0b001101, (outs IntRegs:$dst), (ins MEMrr:$addr), - "ldstub [$addr], $dst", []>; -def LDSTUBri : F3_2<3, 0b001101, (outs IntRegs:$dst), (ins MEMri:$addr), - "ldstub [$addr], $dst", []>; -def LDSTUBArr : F3_1_asi<3, 0b011101, (outs IntRegs:$dst), - (ins MEMrr:$addr, i8imm:$asi), - "ldstuba [$addr] $asi, $dst", []>; - -// Store multiclass - Define both Reg+Reg/Reg+Imm patterns in one shot. -multiclass Store Op3Val, SDPatternOperator OpNode, - RegisterClass RC, ValueType Ty, InstrItinClass itin = IIC_st> { - def rr : F3_1<3, Op3Val, - (outs), (ins MEMrr:$addr, RC:$rd), - !strconcat(OpcStr, " $rd, [$addr]"), - [(OpNode Ty:$rd, ADDRrr:$addr)], - itin>; - def ri : F3_2<3, Op3Val, - (outs), (ins MEMri:$addr, RC:$rd), - !strconcat(OpcStr, " $rd, [$addr]"), - [(OpNode Ty:$rd, ADDRri:$addr)], - itin>; -} - -// TODO: Instructions of the StoreASI class are currently asm only; hooking up -// CodeGen's address spaces to use these is a future task. -class StoreASI Op3Val, - SDPatternOperator OpNode, RegisterClass RC, ValueType Ty, - InstrItinClass itin = IIC_st> : - F3_1_asi<3, Op3Val, (outs), (ins MEMrr:$addr, RC:$rd, i8imm:$asi), - !strconcat(OpcStr, "a $rd, [$addr] $asi"), - [], - itin>; - -multiclass StoreA Op3Val, bits<6> StoreAOp3Val, - SDPatternOperator OpNode, RegisterClass RC, ValueType Ty, - InstrItinClass itin = IIC_st> : - Store { - def Arr : StoreASI; -} - -//===----------------------------------------------------------------------===// -// Instructions -//===----------------------------------------------------------------------===// - -// Pseudo instructions. -class Pseudo pattern> - : InstSP { - let isCodeGenOnly = 1; - let isPseudo = 1; -} - -// GETPCX for PIC -let Defs = [O7] in { - def GETPCX : Pseudo<(outs getPCX:$getpcseq), (ins), "$getpcseq", [] >; -} - -let Defs = [O6], Uses = [O6] in { -def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), - "!ADJCALLSTACKDOWN $amt1, $amt2", - [(callseq_start timm:$amt1, timm:$amt2)]>; -def ADJCALLSTACKUP : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), - "!ADJCALLSTACKUP $amt1", - [(callseq_end timm:$amt1, timm:$amt2)]>; -} - -let hasSideEffects = 1, mayStore = 1 in { - let rd = 0, rs1 = 0, rs2 = 0 in - def FLUSHW : F3_1<0b10, 0b101011, (outs), (ins), - "flushw", - [(flushw)]>, Requires<[HasV9]>; - let rd = 8, rs1 = 0, simm13 = 3 in - def TA3 : F3_2<0b10, 0b111010, (outs), (ins), - "ta 3", - [(flushw)]>; -} - -// SELECT_CC_* - Used to implement the SELECT_CC DAG operation. Expanded after -// instruction selection into a branch sequence. This has to handle all -// permutations of selection between i32/f32/f64 on ICC and FCC. -// Expanded after instruction selection. -let Uses = [ICC], usesCustomInserter = 1 in { - def SELECT_CC_Int_ICC - : Pseudo<(outs IntRegs:$dst), (ins IntRegs:$T, IntRegs:$F, i32imm:$Cond), - "; SELECT_CC_Int_ICC PSEUDO!", - [(set i32:$dst, (SPselecticc i32:$T, i32:$F, imm:$Cond))]>; - def SELECT_CC_FP_ICC - : Pseudo<(outs FPRegs:$dst), (ins FPRegs:$T, FPRegs:$F, i32imm:$Cond), - "; SELECT_CC_FP_ICC PSEUDO!", - [(set f32:$dst, (SPselecticc f32:$T, f32:$F, imm:$Cond))]>; - - def SELECT_CC_DFP_ICC - : Pseudo<(outs DFPRegs:$dst), (ins DFPRegs:$T, DFPRegs:$F, i32imm:$Cond), - "; SELECT_CC_DFP_ICC PSEUDO!", - [(set f64:$dst, (SPselecticc f64:$T, f64:$F, imm:$Cond))]>; - - def SELECT_CC_QFP_ICC - : Pseudo<(outs QFPRegs:$dst), (ins QFPRegs:$T, QFPRegs:$F, i32imm:$Cond), - "; SELECT_CC_QFP_ICC PSEUDO!", - [(set f128:$dst, (SPselecticc f128:$T, f128:$F, imm:$Cond))]>; -} - -let usesCustomInserter = 1, Uses = [FCC0] in { - - def SELECT_CC_Int_FCC - : Pseudo<(outs IntRegs:$dst), (ins IntRegs:$T, IntRegs:$F, i32imm:$Cond), - "; SELECT_CC_Int_FCC PSEUDO!", - [(set i32:$dst, (SPselectfcc i32:$T, i32:$F, imm:$Cond))]>; - - def SELECT_CC_FP_FCC - : Pseudo<(outs FPRegs:$dst), (ins FPRegs:$T, FPRegs:$F, i32imm:$Cond), - "; SELECT_CC_FP_FCC PSEUDO!", - [(set f32:$dst, (SPselectfcc f32:$T, f32:$F, imm:$Cond))]>; - def SELECT_CC_DFP_FCC - : Pseudo<(outs DFPRegs:$dst), (ins DFPRegs:$T, DFPRegs:$F, i32imm:$Cond), - "; SELECT_CC_DFP_FCC PSEUDO!", - [(set f64:$dst, (SPselectfcc f64:$T, f64:$F, imm:$Cond))]>; - def SELECT_CC_QFP_FCC - : Pseudo<(outs QFPRegs:$dst), (ins QFPRegs:$T, QFPRegs:$F, i32imm:$Cond), - "; SELECT_CC_QFP_FCC PSEUDO!", - [(set f128:$dst, (SPselectfcc f128:$T, f128:$F, imm:$Cond))]>; -} - -// Section B.1 - Load Integer Instructions, p. 90 -let DecoderMethod = "DecodeLoadInt" in { - defm LDSB : LoadA<"ldsb", 0b001001, 0b011001, sextloadi8, IntRegs, i32>; - defm LDSH : LoadA<"ldsh", 0b001010, 0b011010, sextloadi16, IntRegs, i32>; - defm LDUB : LoadA<"ldub", 0b000001, 0b010001, zextloadi8, IntRegs, i32>; - defm LDUH : LoadA<"lduh", 0b000010, 0b010010, zextloadi16, IntRegs, i32>; - defm LD : LoadA<"ld", 0b000000, 0b010000, load, IntRegs, i32>; -} - -let DecoderMethod = "DecodeLoadIntPair" in - defm LDD : LoadA<"ldd", 0b000011, 0b010011, load, IntPair, v2i32, IIC_ldd>; - -// Section B.2 - Load Floating-point Instructions, p. 92 -let DecoderMethod = "DecodeLoadFP" in { - defm LDF : Load<"ld", 0b100000, load, FPRegs, f32, IIC_iu_or_fpu_instr>; - def LDFArr : LoadASI<"ld", 0b110000, load, FPRegs, f32, IIC_iu_or_fpu_instr>, - Requires<[HasV9]>; -} -let DecoderMethod = "DecodeLoadDFP" in { - defm LDDF : Load<"ldd", 0b100011, load, DFPRegs, f64, IIC_ldd>; - def LDDFArr : LoadASI<"ldd", 0b110011, load, DFPRegs, f64>, - Requires<[HasV9]>; -} -let DecoderMethod = "DecodeLoadQFP" in - defm LDQF : LoadA<"ldq", 0b100010, 0b110010, load, QFPRegs, f128>, - Requires<[HasV9, HasHardQuad]>; - -let DecoderMethod = "DecodeLoadCP" in - defm LDC : Load<"ld", 0b110000, load, CoprocRegs, i32>; -let DecoderMethod = "DecodeLoadCPPair" in - defm LDDC : Load<"ldd", 0b110011, load, CoprocPair, v2i32, IIC_ldd>; - -let DecoderMethod = "DecodeLoadCP", Defs = [CPSR] in { - let rd = 0 in { - def LDCSRrr : F3_1<3, 0b110001, (outs), (ins MEMrr:$addr), - "ld [$addr], %csr", []>; - def LDCSRri : F3_2<3, 0b110001, (outs), (ins MEMri:$addr), - "ld [$addr], %csr", []>; - } -} - -let DecoderMethod = "DecodeLoadFP" in - let Defs = [FSR] in { - let rd = 0 in { - def LDFSRrr : F3_1<3, 0b100001, (outs), (ins MEMrr:$addr), - "ld [$addr], %fsr", [], IIC_iu_or_fpu_instr>; - def LDFSRri : F3_2<3, 0b100001, (outs), (ins MEMri:$addr), - "ld [$addr], %fsr", [], IIC_iu_or_fpu_instr>; - } - let rd = 1 in { - def LDXFSRrr : F3_1<3, 0b100001, (outs), (ins MEMrr:$addr), - "ldx [$addr], %fsr", []>, Requires<[HasV9]>; - def LDXFSRri : F3_2<3, 0b100001, (outs), (ins MEMri:$addr), - "ldx [$addr], %fsr", []>, Requires<[HasV9]>; - } - } - -// Section B.4 - Store Integer Instructions, p. 95 -let DecoderMethod = "DecodeStoreInt" in { - defm STB : StoreA<"stb", 0b000101, 0b010101, truncstorei8, IntRegs, i32>; - defm STH : StoreA<"sth", 0b000110, 0b010110, truncstorei16, IntRegs, i32>; - defm ST : StoreA<"st", 0b000100, 0b010100, store, IntRegs, i32>; -} - -let DecoderMethod = "DecodeStoreIntPair" in - defm STD : StoreA<"std", 0b000111, 0b010111, store, IntPair, v2i32, IIC_std>; - -// Section B.5 - Store Floating-point Instructions, p. 97 -let DecoderMethod = "DecodeStoreFP" in { - defm STF : Store<"st", 0b100100, store, FPRegs, f32>; - def STFArr : StoreASI<"st", 0b110100, store, FPRegs, f32>, - Requires<[HasV9]>; -} -let DecoderMethod = "DecodeStoreDFP" in { - defm STDF : Store<"std", 0b100111, store, DFPRegs, f64, IIC_std>; - def STDFArr : StoreASI<"std", 0b110111, store, DFPRegs, f64>, - Requires<[HasV9]>; -} -let DecoderMethod = "DecodeStoreQFP" in - defm STQF : StoreA<"stq", 0b100110, 0b110110, store, QFPRegs, f128>, - Requires<[HasV9, HasHardQuad]>; - -let DecoderMethod = "DecodeStoreCP" in - defm STC : Store<"st", 0b110100, store, CoprocRegs, i32>; - -let DecoderMethod = "DecodeStoreCPPair" in - defm STDC : Store<"std", 0b110111, store, CoprocPair, v2i32, IIC_std>; - -let DecoderMethod = "DecodeStoreCP", rd = 0 in { - let Defs = [CPSR] in { - def STCSRrr : F3_1<3, 0b110101, (outs MEMrr:$addr), (ins), - "st %csr, [$addr]", [], IIC_st>; - def STCSRri : F3_2<3, 0b110101, (outs MEMri:$addr), (ins), - "st %csr, [$addr]", [], IIC_st>; - } - let Defs = [CPQ] in { - def STDCQrr : F3_1<3, 0b110110, (outs MEMrr:$addr), (ins), - "std %cq, [$addr]", [], IIC_std>; - def STDCQri : F3_2<3, 0b110110, (outs MEMri:$addr), (ins), - "std %cq, [$addr]", [], IIC_std>; - } -} - -let DecoderMethod = "DecodeStoreFP" in { - let rd = 0 in { - let Defs = [FSR] in { - def STFSRrr : F3_1<3, 0b100101, (outs MEMrr:$addr), (ins), - "st %fsr, [$addr]", [], IIC_st>; - def STFSRri : F3_2<3, 0b100101, (outs MEMri:$addr), (ins), - "st %fsr, [$addr]", [], IIC_st>; - } - let Defs = [FQ] in { - def STDFQrr : F3_1<3, 0b100110, (outs MEMrr:$addr), (ins), - "std %fq, [$addr]", [], IIC_std>; - def STDFQri : F3_2<3, 0b100110, (outs MEMri:$addr), (ins), - "std %fq, [$addr]", [], IIC_std>; - } - } - let rd = 1, Defs = [FSR] in { - def STXFSRrr : F3_1<3, 0b100101, (outs MEMrr:$addr), (ins), - "stx %fsr, [$addr]", []>, Requires<[HasV9]>; - def STXFSRri : F3_2<3, 0b100101, (outs MEMri:$addr), (ins), - "stx %fsr, [$addr]", []>, Requires<[HasV9]>; - } -} - -// Section B.8 - SWAP Register with Memory Instruction -// (Atomic swap) -let Constraints = "$val = $dst", DecoderMethod = "DecodeSWAP" in { - def SWAPrr : F3_1<3, 0b001111, - (outs IntRegs:$dst), (ins MEMrr:$addr, IntRegs:$val), - "swap [$addr], $dst", - [(set i32:$dst, (atomic_swap_32 ADDRrr:$addr, i32:$val))]>; - def SWAPri : F3_2<3, 0b001111, - (outs IntRegs:$dst), (ins MEMri:$addr, IntRegs:$val), - "swap [$addr], $dst", - [(set i32:$dst, (atomic_swap_32 ADDRri:$addr, i32:$val))]>; - def SWAPArr : F3_1_asi<3, 0b011111, - (outs IntRegs:$dst), (ins MEMrr:$addr, i8imm:$asi, IntRegs:$val), - "swapa [$addr] $asi, $dst", - [/*FIXME: pattern?*/]>; -} - - -// Section B.9 - SETHI Instruction, p. 104 -def SETHIi: F2_1<0b100, - (outs IntRegs:$rd), (ins i32imm:$imm22), - "sethi $imm22, $rd", - [(set i32:$rd, SETHIimm:$imm22)], - IIC_iu_instr>; - -// Section B.10 - NOP Instruction, p. 105 -// (It's a special case of SETHI) -let rd = 0, imm22 = 0 in - def NOP : F2_1<0b100, (outs), (ins), "nop", []>; - -// Section B.11 - Logical Instructions, p. 106 -defm AND : F3_12<"and", 0b000001, and, IntRegs, i32, simm13Op>; - -def ANDNrr : F3_1<2, 0b000101, - (outs IntRegs:$rd), (ins IntRegs:$rs1, IntRegs:$rs2), - "andn $rs1, $rs2, $rd", - [(set i32:$rd, (and i32:$rs1, (not i32:$rs2)))]>; -def ANDNri : F3_2<2, 0b000101, - (outs IntRegs:$rd), (ins IntRegs:$rs1, simm13Op:$simm13), - "andn $rs1, $simm13, $rd", []>; - -defm OR : F3_12<"or", 0b000010, or, IntRegs, i32, simm13Op>; - -def ORNrr : F3_1<2, 0b000110, - (outs IntRegs:$rd), (ins IntRegs:$rs1, IntRegs:$rs2), - "orn $rs1, $rs2, $rd", - [(set i32:$rd, (or i32:$rs1, (not i32:$rs2)))]>; -def ORNri : F3_2<2, 0b000110, - (outs IntRegs:$rd), (ins IntRegs:$rs1, simm13Op:$simm13), - "orn $rs1, $simm13, $rd", []>; -defm XOR : F3_12<"xor", 0b000011, xor, IntRegs, i32, simm13Op>; - -def XNORrr : F3_1<2, 0b000111, - (outs IntRegs:$rd), (ins IntRegs:$rs1, IntRegs:$rs2), - "xnor $rs1, $rs2, $rd", - [(set i32:$rd, (not (xor i32:$rs1, i32:$rs2)))]>; -def XNORri : F3_2<2, 0b000111, - (outs IntRegs:$rd), (ins IntRegs:$rs1, simm13Op:$simm13), - "xnor $rs1, $simm13, $rd", []>; - -def : Pat<(and IntRegs:$rs1, SETHIimm_not:$rs2), - (ANDNrr i32:$rs1, (SETHIi SETHIimm_not:$rs2))>; - -def : Pat<(or IntRegs:$rs1, SETHIimm_not:$rs2), - (ORNrr i32:$rs1, (SETHIi SETHIimm_not:$rs2))>; - -let Defs = [ICC] in { - defm ANDCC : F3_12np<"andcc", 0b010001>; - defm ANDNCC : F3_12np<"andncc", 0b010101>; - defm ORCC : F3_12np<"orcc", 0b010010>; - defm ORNCC : F3_12np<"orncc", 0b010110>; - defm XORCC : F3_12np<"xorcc", 0b010011>; - defm XNORCC : F3_12np<"xnorcc", 0b010111>; -} - -// Section B.12 - Shift Instructions, p. 107 -defm SLL : F3_12<"sll", 0b100101, shl, IntRegs, i32, simm13Op>; -defm SRL : F3_12<"srl", 0b100110, srl, IntRegs, i32, simm13Op>; -defm SRA : F3_12<"sra", 0b100111, sra, IntRegs, i32, simm13Op>; - -// Section B.13 - Add Instructions, p. 108 -defm ADD : F3_12<"add", 0b000000, add, IntRegs, i32, simm13Op>; - -// "LEA" forms of add (patterns to make tblgen happy) -let Predicates = [Is32Bit], isCodeGenOnly = 1 in - def LEA_ADDri : F3_2<2, 0b000000, - (outs IntRegs:$dst), (ins MEMri:$addr), - "add ${addr:arith}, $dst", - [(set iPTR:$dst, ADDRri:$addr)]>; - -let Defs = [ICC] in - defm ADDCC : F3_12<"addcc", 0b010000, addc, IntRegs, i32, simm13Op>; - -let Uses = [ICC] in - defm ADDC : F3_12np<"addx", 0b001000>; - -let Uses = [ICC], Defs = [ICC] in - defm ADDE : F3_12<"addxcc", 0b011000, adde, IntRegs, i32, simm13Op>; - -// Section B.15 - Subtract Instructions, p. 110 -defm SUB : F3_12 <"sub" , 0b000100, sub, IntRegs, i32, simm13Op>; -let Uses = [ICC], Defs = [ICC] in - defm SUBE : F3_12 <"subxcc" , 0b011100, sube, IntRegs, i32, simm13Op>; - -let Defs = [ICC] in - defm SUBCC : F3_12 <"subcc", 0b010100, subc, IntRegs, i32, simm13Op>; - -let Uses = [ICC] in - defm SUBC : F3_12np <"subx", 0b001100>; - -// cmp (from Section A.3) is a specialized alias for subcc -let Defs = [ICC], rd = 0 in { - def CMPrr : F3_1<2, 0b010100, - (outs), (ins IntRegs:$rs1, IntRegs:$rs2), - "cmp $rs1, $rs2", - [(SPcmpicc i32:$rs1, i32:$rs2)]>; - def CMPri : F3_2<2, 0b010100, - (outs), (ins IntRegs:$rs1, simm13Op:$simm13), - "cmp $rs1, $simm13", - [(SPcmpicc i32:$rs1, (i32 simm13:$simm13))]>; -} - -// Section B.18 - Multiply Instructions, p. 113 -let Defs = [Y] in { - defm UMUL : F3_12<"umul", 0b001010, umullohi, IntRegs, i32, simm13Op, IIC_iu_umul>; - defm SMUL : F3_12<"smul", 0b001011, smullohi, IntRegs, i32, simm13Op, IIC_iu_smul>; -} - -let Defs = [Y, ICC] in { - defm UMULCC : F3_12np<"umulcc", 0b011010, IIC_iu_umul>; - defm SMULCC : F3_12np<"smulcc", 0b011011, IIC_iu_smul>; -} - -let Defs = [Y, ICC], Uses = [Y, ICC] in { - defm MULSCC : F3_12np<"mulscc", 0b100100>; -} - -// Section B.19 - Divide Instructions, p. 115 -let Uses = [Y], Defs = [Y] in { - defm UDIV : F3_12np<"udiv", 0b001110, IIC_iu_div>; - defm SDIV : F3_12np<"sdiv", 0b001111, IIC_iu_div>; -} - -let Uses = [Y], Defs = [Y, ICC] in { - defm UDIVCC : F3_12np<"udivcc", 0b011110, IIC_iu_div>; - defm SDIVCC : F3_12np<"sdivcc", 0b011111, IIC_iu_div>; -} - -// Section B.20 - SAVE and RESTORE, p. 117 -defm SAVE : F3_12np<"save" , 0b111100>; -defm RESTORE : F3_12np<"restore", 0b111101>; - -// Section B.21 - Branch on Integer Condition Codes Instructions, p. 119 - -// unconditional branch class. -class BranchAlways pattern> - : F2_2<0b010, 0, (outs), ins, asmstr, pattern> { - let isBranch = 1; - let isTerminator = 1; - let hasDelaySlot = 1; - let isBarrier = 1; -} - -let cond = 8 in - def BA : BranchAlways<(ins brtarget:$imm22), "ba $imm22", [(br bb:$imm22)]>; - - -let isBranch = 1, isTerminator = 1, hasDelaySlot = 1 in { - -// conditional branch class: -class BranchSP pattern> - : F2_2<0b010, 0, (outs), ins, asmstr, pattern, IIC_iu_instr>; - -// conditional branch with annul class: -class BranchSPA pattern> - : F2_2<0b010, 1, (outs), ins, asmstr, pattern, IIC_iu_instr>; - -// Conditional branch class on %icc|%xcc with predication: -multiclass IPredBranch CCPattern> { - def CC : F2_3<0b001, 0, 1, (outs), (ins bprtarget:$imm19, CCOp:$cond), - !strconcat("b$cond ", !strconcat(regstr, ", $imm19")), - CCPattern, - IIC_iu_instr>; - def CCA : F2_3<0b001, 1, 1, (outs), (ins bprtarget:$imm19, CCOp:$cond), - !strconcat("b$cond,a ", !strconcat(regstr, ", $imm19")), - [], - IIC_iu_instr>; - def CCNT : F2_3<0b001, 0, 0, (outs), (ins bprtarget:$imm19, CCOp:$cond), - !strconcat("b$cond,pn ", !strconcat(regstr, ", $imm19")), - [], - IIC_iu_instr>; - def CCANT : F2_3<0b001, 1, 0, (outs), (ins bprtarget:$imm19, CCOp:$cond), - !strconcat("b$cond,a,pn ", !strconcat(regstr, ", $imm19")), - [], - IIC_iu_instr>; -} - -} // let isBranch = 1, isTerminator = 1, hasDelaySlot = 1 - - -// Indirect branch instructions. -let isTerminator = 1, isBarrier = 1, hasDelaySlot = 1, isBranch =1, - isIndirectBranch = 1, rd = 0, isCodeGenOnly = 1 in { - def BINDrr : F3_1<2, 0b111000, - (outs), (ins MEMrr:$ptr), - "jmp $ptr", - [(brind ADDRrr:$ptr)]>; - def BINDri : F3_2<2, 0b111000, - (outs), (ins MEMri:$ptr), - "jmp $ptr", - [(brind ADDRri:$ptr)]>; -} - -let Uses = [ICC] in { - def BCOND : BranchSP<(ins brtarget:$imm22, CCOp:$cond), - "b$cond $imm22", - [(SPbricc bb:$imm22, imm:$cond)]>; - def BCONDA : BranchSPA<(ins brtarget:$imm22, CCOp:$cond), - "b$cond,a $imm22", []>; - - let Predicates = [HasV9], cc = 0b00 in - defm BPI : IPredBranch<"%icc", []>; -} - -// Section B.22 - Branch on Floating-point Condition Codes Instructions, p. 121 - -let isBranch = 1, isTerminator = 1, hasDelaySlot = 1 in { - -// floating-point conditional branch class: -class FPBranchSP pattern> - : F2_2<0b110, 0, (outs), ins, asmstr, pattern, IIC_fpu_normal_instr>; - -// floating-point conditional branch with annul class: -class FPBranchSPA pattern> - : F2_2<0b110, 1, (outs), ins, asmstr, pattern, IIC_fpu_normal_instr>; - -// Conditional branch class on %fcc0-%fcc3 with predication: -multiclass FPredBranch { - def CC : F2_3<0b101, 0, 1, (outs), (ins bprtarget:$imm19, CCOp:$cond, - FCCRegs:$cc), - "fb$cond $cc, $imm19", [], IIC_fpu_normal_instr>; - def CCA : F2_3<0b101, 1, 1, (outs), (ins bprtarget:$imm19, CCOp:$cond, - FCCRegs:$cc), - "fb$cond,a $cc, $imm19", [], IIC_fpu_normal_instr>; - def CCNT : F2_3<0b101, 0, 0, (outs), (ins bprtarget:$imm19, CCOp:$cond, - FCCRegs:$cc), - "fb$cond,pn $cc, $imm19", [], IIC_fpu_normal_instr>; - def CCANT : F2_3<0b101, 1, 0, (outs), (ins bprtarget:$imm19, CCOp:$cond, - FCCRegs:$cc), - "fb$cond,a,pn $cc, $imm19", [], IIC_fpu_normal_instr>; -} -} // let isBranch = 1, isTerminator = 1, hasDelaySlot = 1 - -let Uses = [FCC0] in { - def FBCOND : FPBranchSP<(ins brtarget:$imm22, CCOp:$cond), - "fb$cond $imm22", - [(SPbrfcc bb:$imm22, imm:$cond)]>; - def FBCONDA : FPBranchSPA<(ins brtarget:$imm22, CCOp:$cond), - "fb$cond,a $imm22", []>; -} - -let Predicates = [HasV9] in - defm BPF : FPredBranch; - -// Section B.22 - Branch on Co-processor Condition Codes Instructions, p. 123 -let isBranch = 1, isTerminator = 1, hasDelaySlot = 1 in { - -// co-processor conditional branch class: -class CPBranchSP pattern> - : F2_2<0b111, 0, (outs), ins, asmstr, pattern>; - -// co-processor conditional branch with annul class: -class CPBranchSPA pattern> - : F2_2<0b111, 1, (outs), ins, asmstr, pattern>; - -} // let isBranch = 1, isTerminator = 1, hasDelaySlot = 1 - -def CBCOND : CPBranchSP<(ins brtarget:$imm22, CCOp:$cond), - "cb$cond $imm22", - [(SPbrfcc bb:$imm22, imm:$cond)]>; -def CBCONDA : CPBranchSPA<(ins brtarget:$imm22, CCOp:$cond), - "cb$cond,a $imm22", []>; - -// Section B.24 - Call and Link Instruction, p. 125 -// This is the only Format 1 instruction -let Uses = [O6], - hasDelaySlot = 1, isCall = 1 in { - def CALL : InstSP<(outs), (ins calltarget:$disp, variable_ops), - "call $disp", - [], - IIC_jmp_or_call> { - bits<30> disp; - let op = 1; - let Inst{29-0} = disp; - } - - // indirect calls: special cases of JMPL. - let isCodeGenOnly = 1, rd = 15 in { - def CALLrr : F3_1<2, 0b111000, - (outs), (ins MEMrr:$ptr, variable_ops), - "call $ptr", - [(call ADDRrr:$ptr)], - IIC_jmp_or_call>; - def CALLri : F3_2<2, 0b111000, - (outs), (ins MEMri:$ptr, variable_ops), - "call $ptr", - [(call ADDRri:$ptr)], - IIC_jmp_or_call>; - } -} - -// Section B.25 - Jump and Link Instruction - -// JMPL Instruction. -let isTerminator = 1, hasDelaySlot = 1, isBarrier = 1, - DecoderMethod = "DecodeJMPL" in { - def JMPLrr: F3_1<2, 0b111000, - (outs IntRegs:$dst), (ins MEMrr:$addr), - "jmpl $addr, $dst", - [], - IIC_jmp_or_call>; - def JMPLri: F3_2<2, 0b111000, - (outs IntRegs:$dst), (ins MEMri:$addr), - "jmpl $addr, $dst", - [], - IIC_jmp_or_call>; -} - -// Section A.3 - Synthetic Instructions, p. 85 -// special cases of JMPL: -let isReturn = 1, isTerminator = 1, hasDelaySlot = 1, isBarrier = 1, - isCodeGenOnly = 1 in { - let rd = 0, rs1 = 15 in - def RETL: F3_2<2, 0b111000, - (outs), (ins i32imm:$val), - "jmp %o7+$val", - [(retflag simm13:$val)], - IIC_jmp_or_call>; - - let rd = 0, rs1 = 31 in - def RET: F3_2<2, 0b111000, - (outs), (ins i32imm:$val), - "jmp %i7+$val", - [], - IIC_jmp_or_call>; -} - -// Section B.26 - Return from Trap Instruction -let isReturn = 1, isTerminator = 1, hasDelaySlot = 1, - isBarrier = 1, rd = 0, DecoderMethod = "DecodeReturn" in { - def RETTrr : F3_1<2, 0b111001, - (outs), (ins MEMrr:$addr), - "rett $addr", - [], - IIC_jmp_or_call>; - def RETTri : F3_2<2, 0b111001, - (outs), (ins MEMri:$addr), - "rett $addr", - [], - IIC_jmp_or_call>; -} - - -// Section B.27 - Trap on Integer Condition Codes Instruction -// conditional branch class: -let DecoderNamespace = "SparcV8", DecoderMethod = "DecodeTRAP", hasSideEffects = 1, Uses = [ICC], cc = 0b00 in -{ - def TRAPrr : TRAPSPrr<0b111010, - (outs), (ins IntRegs:$rs1, IntRegs:$rs2, CCOp:$cond), - "t$cond $rs1 + $rs2", - []>; - def TRAPri : TRAPSPri<0b111010, - (outs), (ins IntRegs:$rs1, i32imm:$imm, CCOp:$cond), - "t$cond $rs1 + $imm", - []>; -} - -multiclass TRAP { - def rr : TRAPSPrr<0b111010, - (outs), (ins IntRegs:$rs1, IntRegs:$rs2, CCOp:$cond), - !strconcat(!strconcat("t$cond ", regStr), ", $rs1 + $rs2"), - []>; - def ri : TRAPSPri<0b111010, - (outs), (ins IntRegs:$rs1, i32imm:$imm, CCOp:$cond), - !strconcat(!strconcat("t$cond ", regStr), ", $rs1 + $imm"), - []>; -} - -let DecoderNamespace = "SparcV9", DecoderMethod = "DecodeTRAP", Predicates = [HasV9], hasSideEffects = 1, Uses = [ICC], cc = 0b00 in - defm TICC : TRAP<"%icc">; - - -let isBarrier = 1, isTerminator = 1, rd = 0b01000, rs1 = 0, simm13 = 5 in - def TA5 : F3_2<0b10, 0b111010, (outs), (ins), "ta 5", [(trap)]>; - -let hasSideEffects = 1, rd = 0b01000, rs1 = 0, simm13 = 1 in - def TA1 : F3_2<0b10, 0b111010, (outs), (ins), "ta 1", [(debugtrap)]>; - -// Section B.28 - Read State Register Instructions -let rs2 = 0 in - def RDASR : F3_1<2, 0b101000, - (outs IntRegs:$rd), (ins ASRRegs:$rs1), - "rd $rs1, $rd", []>; - -// PSR, WIM, and TBR don't exist on the SparcV9, only the V8. -let Predicates = [HasNoV9] in { - let rs2 = 0, rs1 = 0, Uses=[PSR] in - def RDPSR : F3_1<2, 0b101001, - (outs IntRegs:$rd), (ins), - "rd %psr, $rd", []>; - - let rs2 = 0, rs1 = 0, Uses=[WIM] in - def RDWIM : F3_1<2, 0b101010, - (outs IntRegs:$rd), (ins), - "rd %wim, $rd", []>; - - let rs2 = 0, rs1 = 0, Uses=[TBR] in - def RDTBR : F3_1<2, 0b101011, - (outs IntRegs:$rd), (ins), - "rd %tbr, $rd", []>; -} - -// Section B.29 - Write State Register Instructions -def WRASRrr : F3_1<2, 0b110000, - (outs ASRRegs:$rd), (ins IntRegs:$rs1, IntRegs:$rs2), - "wr $rs1, $rs2, $rd", []>; -def WRASRri : F3_2<2, 0b110000, - (outs ASRRegs:$rd), (ins IntRegs:$rs1, simm13Op:$simm13), - "wr $rs1, $simm13, $rd", []>; - -// PSR, WIM, and TBR don't exist on the SparcV9, only the V8. -let Predicates = [HasNoV9] in { - let Defs = [PSR], rd=0 in { - def WRPSRrr : F3_1<2, 0b110001, - (outs), (ins IntRegs:$rs1, IntRegs:$rs2), - "wr $rs1, $rs2, %psr", []>; - def WRPSRri : F3_2<2, 0b110001, - (outs), (ins IntRegs:$rs1, simm13Op:$simm13), - "wr $rs1, $simm13, %psr", []>; - } - - let Defs = [WIM], rd=0 in { - def WRWIMrr : F3_1<2, 0b110010, - (outs), (ins IntRegs:$rs1, IntRegs:$rs2), - "wr $rs1, $rs2, %wim", []>; - def WRWIMri : F3_2<2, 0b110010, - (outs), (ins IntRegs:$rs1, simm13Op:$simm13), - "wr $rs1, $simm13, %wim", []>; - } - - let Defs = [TBR], rd=0 in { - def WRTBRrr : F3_1<2, 0b110011, - (outs), (ins IntRegs:$rs1, IntRegs:$rs2), - "wr $rs1, $rs2, %tbr", []>; - def WRTBRri : F3_2<2, 0b110011, - (outs), (ins IntRegs:$rs1, simm13Op:$simm13), - "wr $rs1, $simm13, %tbr", []>; - } -} - -// Section B.30 - STBAR Instruction -let hasSideEffects = 1, rd = 0, rs1 = 0b01111, rs2 = 0 in - def STBAR : F3_1<2, 0b101000, (outs), (ins), "stbar", []>; - - -// Section B.31 - Unimplmented Instruction -let rd = 0 in - def UNIMP : F2_1<0b000, (outs), (ins i32imm:$imm22), - "unimp $imm22", []>; - -// Section B.32 - Flush Instruction Memory -let rd = 0 in { - def FLUSHrr : F3_1<2, 0b111011, (outs), (ins MEMrr:$addr), - "flush $addr", []>; - def FLUSHri : F3_2<2, 0b111011, (outs), (ins MEMri:$addr), - "flush $addr", []>; - - // The no-arg FLUSH is only here for the benefit of the InstAlias - // "flush", which cannot seem to use FLUSHrr, due to the inability - // to construct a MEMrr with fixed G0 registers. - let rs1 = 0, rs2 = 0 in - def FLUSH : F3_1<2, 0b111011, (outs), (ins), "flush %g0", []>; -} - -// Section B.33 - Floating-point Operate (FPop) Instructions - -// Convert Integer to Floating-point Instructions, p. 141 -def FITOS : F3_3u<2, 0b110100, 0b011000100, - (outs FPRegs:$rd), (ins FPRegs:$rs2), - "fitos $rs2, $rd", - [(set FPRegs:$rd, (SPitof FPRegs:$rs2))], - IIC_fpu_fast_instr>; -def FITOD : F3_3u<2, 0b110100, 0b011001000, - (outs DFPRegs:$rd), (ins FPRegs:$rs2), - "fitod $rs2, $rd", - [(set DFPRegs:$rd, (SPitof FPRegs:$rs2))], - IIC_fpu_fast_instr>; -def FITOQ : F3_3u<2, 0b110100, 0b011001100, - (outs QFPRegs:$rd), (ins FPRegs:$rs2), - "fitoq $rs2, $rd", - [(set QFPRegs:$rd, (SPitof FPRegs:$rs2))]>, - Requires<[HasHardQuad]>; - -// Convert Floating-point to Integer Instructions, p. 142 -def FSTOI : F3_3u<2, 0b110100, 0b011010001, - (outs FPRegs:$rd), (ins FPRegs:$rs2), - "fstoi $rs2, $rd", - [(set FPRegs:$rd, (SPftoi FPRegs:$rs2))], - IIC_fpu_fast_instr>; -def FDTOI : F3_3u<2, 0b110100, 0b011010010, - (outs FPRegs:$rd), (ins DFPRegs:$rs2), - "fdtoi $rs2, $rd", - [(set FPRegs:$rd, (SPftoi DFPRegs:$rs2))], - IIC_fpu_fast_instr>; -def FQTOI : F3_3u<2, 0b110100, 0b011010011, - (outs FPRegs:$rd), (ins QFPRegs:$rs2), - "fqtoi $rs2, $rd", - [(set FPRegs:$rd, (SPftoi QFPRegs:$rs2))]>, - Requires<[HasHardQuad]>; - -// Convert between Floating-point Formats Instructions, p. 143 -def FSTOD : F3_3u<2, 0b110100, 0b011001001, - (outs DFPRegs:$rd), (ins FPRegs:$rs2), - "fstod $rs2, $rd", - [(set f64:$rd, (fpextend f32:$rs2))], - IIC_fpu_stod>; -def FSTOQ : F3_3u<2, 0b110100, 0b011001101, - (outs QFPRegs:$rd), (ins FPRegs:$rs2), - "fstoq $rs2, $rd", - [(set f128:$rd, (fpextend f32:$rs2))]>, - Requires<[HasHardQuad]>; -def FDTOS : F3_3u<2, 0b110100, 0b011000110, - (outs FPRegs:$rd), (ins DFPRegs:$rs2), - "fdtos $rs2, $rd", - [(set f32:$rd, (fpround f64:$rs2))], - IIC_fpu_fast_instr>; -def FDTOQ : F3_3u<2, 0b110100, 0b011001110, - (outs QFPRegs:$rd), (ins DFPRegs:$rs2), - "fdtoq $rs2, $rd", - [(set f128:$rd, (fpextend f64:$rs2))]>, - Requires<[HasHardQuad]>; -def FQTOS : F3_3u<2, 0b110100, 0b011000111, - (outs FPRegs:$rd), (ins QFPRegs:$rs2), - "fqtos $rs2, $rd", - [(set f32:$rd, (fpround f128:$rs2))]>, - Requires<[HasHardQuad]>; -def FQTOD : F3_3u<2, 0b110100, 0b011001011, - (outs DFPRegs:$rd), (ins QFPRegs:$rs2), - "fqtod $rs2, $rd", - [(set f64:$rd, (fpround f128:$rs2))]>, - Requires<[HasHardQuad]>; - -// Floating-point Move Instructions, p. 144 -def FMOVS : F3_3u<2, 0b110100, 0b000000001, - (outs FPRegs:$rd), (ins FPRegs:$rs2), - "fmovs $rs2, $rd", []>; -def FNEGS : F3_3u<2, 0b110100, 0b000000101, - (outs FPRegs:$rd), (ins FPRegs:$rs2), - "fnegs $rs2, $rd", - [(set f32:$rd, (fneg f32:$rs2))], - IIC_fpu_negs>; -def FABSS : F3_3u<2, 0b110100, 0b000001001, - (outs FPRegs:$rd), (ins FPRegs:$rs2), - "fabss $rs2, $rd", - [(set f32:$rd, (fabs f32:$rs2))], - IIC_fpu_abs>; - - -// Floating-point Square Root Instructions, p.145 -// FSQRTS generates an erratum on LEON processors, so by disabling this instruction -// this will be promoted to use FSQRTD with doubles instead. -let Predicates = [HasNoFdivSqrtFix] in -def FSQRTS : F3_3u<2, 0b110100, 0b000101001, - (outs FPRegs:$rd), (ins FPRegs:$rs2), - "fsqrts $rs2, $rd", - [(set f32:$rd, (fsqrt f32:$rs2))], - IIC_fpu_sqrts>; -def FSQRTD : F3_3u<2, 0b110100, 0b000101010, - (outs DFPRegs:$rd), (ins DFPRegs:$rs2), - "fsqrtd $rs2, $rd", - [(set f64:$rd, (fsqrt f64:$rs2))], - IIC_fpu_sqrtd>; -def FSQRTQ : F3_3u<2, 0b110100, 0b000101011, - (outs QFPRegs:$rd), (ins QFPRegs:$rs2), - "fsqrtq $rs2, $rd", - [(set f128:$rd, (fsqrt f128:$rs2))]>, - Requires<[HasHardQuad]>; - - - -// Floating-point Add and Subtract Instructions, p. 146 -def FADDS : F3_3<2, 0b110100, 0b001000001, - (outs FPRegs:$rd), (ins FPRegs:$rs1, FPRegs:$rs2), - "fadds $rs1, $rs2, $rd", - [(set f32:$rd, (fadd f32:$rs1, f32:$rs2))], - IIC_fpu_fast_instr>; -def FADDD : F3_3<2, 0b110100, 0b001000010, - (outs DFPRegs:$rd), (ins DFPRegs:$rs1, DFPRegs:$rs2), - "faddd $rs1, $rs2, $rd", - [(set f64:$rd, (fadd f64:$rs1, f64:$rs2))], - IIC_fpu_fast_instr>; -def FADDQ : F3_3<2, 0b110100, 0b001000011, - (outs QFPRegs:$rd), (ins QFPRegs:$rs1, QFPRegs:$rs2), - "faddq $rs1, $rs2, $rd", - [(set f128:$rd, (fadd f128:$rs1, f128:$rs2))]>, - Requires<[HasHardQuad]>; - -def FSUBS : F3_3<2, 0b110100, 0b001000101, - (outs FPRegs:$rd), (ins FPRegs:$rs1, FPRegs:$rs2), - "fsubs $rs1, $rs2, $rd", - [(set f32:$rd, (fsub f32:$rs1, f32:$rs2))], - IIC_fpu_fast_instr>; -def FSUBD : F3_3<2, 0b110100, 0b001000110, - (outs DFPRegs:$rd), (ins DFPRegs:$rs1, DFPRegs:$rs2), - "fsubd $rs1, $rs2, $rd", - [(set f64:$rd, (fsub f64:$rs1, f64:$rs2))], - IIC_fpu_fast_instr>; -def FSUBQ : F3_3<2, 0b110100, 0b001000111, - (outs QFPRegs:$rd), (ins QFPRegs:$rs1, QFPRegs:$rs2), - "fsubq $rs1, $rs2, $rd", - [(set f128:$rd, (fsub f128:$rs1, f128:$rs2))]>, - Requires<[HasHardQuad]>; - - -// Floating-point Multiply and Divide Instructions, p. 147 -def FMULS : F3_3<2, 0b110100, 0b001001001, - (outs FPRegs:$rd), (ins FPRegs:$rs1, FPRegs:$rs2), - "fmuls $rs1, $rs2, $rd", - [(set f32:$rd, (fmul f32:$rs1, f32:$rs2))], - IIC_fpu_muls>, - Requires<[HasFMULS]>; -def FMULD : F3_3<2, 0b110100, 0b001001010, - (outs DFPRegs:$rd), (ins DFPRegs:$rs1, DFPRegs:$rs2), - "fmuld $rs1, $rs2, $rd", - [(set f64:$rd, (fmul f64:$rs1, f64:$rs2))], - IIC_fpu_muld>; -def FMULQ : F3_3<2, 0b110100, 0b001001011, - (outs QFPRegs:$rd), (ins QFPRegs:$rs1, QFPRegs:$rs2), - "fmulq $rs1, $rs2, $rd", - [(set f128:$rd, (fmul f128:$rs1, f128:$rs2))]>, - Requires<[HasHardQuad]>; - -def FSMULD : F3_3<2, 0b110100, 0b001101001, - (outs DFPRegs:$rd), (ins FPRegs:$rs1, FPRegs:$rs2), - "fsmuld $rs1, $rs2, $rd", - [(set f64:$rd, (fmul (fpextend f32:$rs1), - (fpextend f32:$rs2)))], - IIC_fpu_muld>, - Requires<[HasFSMULD]>; -def FDMULQ : F3_3<2, 0b110100, 0b001101110, - (outs QFPRegs:$rd), (ins DFPRegs:$rs1, DFPRegs:$rs2), - "fdmulq $rs1, $rs2, $rd", - [(set f128:$rd, (fmul (fpextend f64:$rs1), - (fpextend f64:$rs2)))]>, - Requires<[HasHardQuad]>; - -// FDIVS generates an erratum on LEON processors, so by disabling this instruction -// this will be promoted to use FDIVD with doubles instead. -def FDIVS : F3_3<2, 0b110100, 0b001001101, - (outs FPRegs:$rd), (ins FPRegs:$rs1, FPRegs:$rs2), - "fdivs $rs1, $rs2, $rd", - [(set f32:$rd, (fdiv f32:$rs1, f32:$rs2))], - IIC_fpu_divs>; -def FDIVD : F3_3<2, 0b110100, 0b001001110, - (outs DFPRegs:$rd), (ins DFPRegs:$rs1, DFPRegs:$rs2), - "fdivd $rs1, $rs2, $rd", - [(set f64:$rd, (fdiv f64:$rs1, f64:$rs2))], - IIC_fpu_divd>; -def FDIVQ : F3_3<2, 0b110100, 0b001001111, - (outs QFPRegs:$rd), (ins QFPRegs:$rs1, QFPRegs:$rs2), - "fdivq $rs1, $rs2, $rd", - [(set f128:$rd, (fdiv f128:$rs1, f128:$rs2))]>, - Requires<[HasHardQuad]>; - -// Floating-point Compare Instructions, p. 148 -// Note: the 2nd template arg is different for these guys. -// Note 2: the result of a FCMP is not available until the 2nd cycle -// after the instr is retired, but there is no interlock in Sparc V8. -// This behavior is modeled with a forced noop after the instruction in -// DelaySlotFiller. - -let Defs = [FCC0], rd = 0, isCodeGenOnly = 1 in { - def FCMPS : F3_3c<2, 0b110101, 0b001010001, - (outs), (ins FPRegs:$rs1, FPRegs:$rs2), - "fcmps $rs1, $rs2", - [(SPcmpfcc f32:$rs1, f32:$rs2)], - IIC_fpu_fast_instr>; - def FCMPD : F3_3c<2, 0b110101, 0b001010010, - (outs), (ins DFPRegs:$rs1, DFPRegs:$rs2), - "fcmpd $rs1, $rs2", - [(SPcmpfcc f64:$rs1, f64:$rs2)], - IIC_fpu_fast_instr>; - def FCMPQ : F3_3c<2, 0b110101, 0b001010011, - (outs), (ins QFPRegs:$rs1, QFPRegs:$rs2), - "fcmpq $rs1, $rs2", - [(SPcmpfcc f128:$rs1, f128:$rs2)]>, - Requires<[HasHardQuad]>; -} - -//===----------------------------------------------------------------------===// -// Instructions for Thread Local Storage(TLS). -//===----------------------------------------------------------------------===// -let isAsmParserOnly = 1 in { -def TLS_ADDrr : F3_1<2, 0b000000, - (outs IntRegs:$rd), - (ins IntRegs:$rs1, IntRegs:$rs2, TLSSym:$sym), - "add $rs1, $rs2, $rd, $sym", - [(set i32:$rd, - (tlsadd i32:$rs1, i32:$rs2, tglobaltlsaddr:$sym))]>; - -let mayLoad = 1 in - def TLS_LDrr : F3_1<3, 0b000000, - (outs IntRegs:$dst), (ins MEMrr:$addr, TLSSym:$sym), - "ld [$addr], $dst, $sym", - [(set i32:$dst, - (tlsld ADDRrr:$addr, tglobaltlsaddr:$sym))]>; - -let Uses = [O6], isCall = 1, hasDelaySlot = 1 in - def TLS_CALL : InstSP<(outs), - (ins calltarget:$disp, TLSSym:$sym, variable_ops), - "call $disp, $sym", - [(tlscall texternalsym:$disp, tglobaltlsaddr:$sym)], - IIC_jmp_or_call> { - bits<30> disp; - let op = 1; - let Inst{29-0} = disp; -} -} - -//===----------------------------------------------------------------------===// -// V9 Instructions -//===----------------------------------------------------------------------===// - -// V9 Conditional Moves. -let Predicates = [HasV9], Constraints = "$f = $rd" in { - // Move Integer Register on Condition (MOVcc) p. 194 of the V9 manual. - let Uses = [ICC], intcc = 1, cc = 0b00 in { - def MOVICCrr - : F4_1<0b101100, (outs IntRegs:$rd), - (ins IntRegs:$rs2, IntRegs:$f, CCOp:$cond), - "mov$cond %icc, $rs2, $rd", - [(set i32:$rd, (SPselecticc i32:$rs2, i32:$f, imm:$cond))]>; - - def MOVICCri - : F4_2<0b101100, (outs IntRegs:$rd), - (ins i32imm:$simm11, IntRegs:$f, CCOp:$cond), - "mov$cond %icc, $simm11, $rd", - [(set i32:$rd, - (SPselecticc simm11:$simm11, i32:$f, imm:$cond))]>; - } - - let Uses = [FCC0], intcc = 0, cc = 0b00 in { - def MOVFCCrr - : F4_1<0b101100, (outs IntRegs:$rd), - (ins IntRegs:$rs2, IntRegs:$f, CCOp:$cond), - "mov$cond %fcc0, $rs2, $rd", - [(set i32:$rd, (SPselectfcc i32:$rs2, i32:$f, imm:$cond))]>; - def MOVFCCri - : F4_2<0b101100, (outs IntRegs:$rd), - (ins i32imm:$simm11, IntRegs:$f, CCOp:$cond), - "mov$cond %fcc0, $simm11, $rd", - [(set i32:$rd, - (SPselectfcc simm11:$simm11, i32:$f, imm:$cond))]>; - } - - let Uses = [ICC], intcc = 1, opf_cc = 0b00 in { - def FMOVS_ICC - : F4_3<0b110101, 0b000001, (outs FPRegs:$rd), - (ins FPRegs:$rs2, FPRegs:$f, CCOp:$cond), - "fmovs$cond %icc, $rs2, $rd", - [(set f32:$rd, (SPselecticc f32:$rs2, f32:$f, imm:$cond))]>; - def FMOVD_ICC - : F4_3<0b110101, 0b000010, (outs DFPRegs:$rd), - (ins DFPRegs:$rs2, DFPRegs:$f, CCOp:$cond), - "fmovd$cond %icc, $rs2, $rd", - [(set f64:$rd, (SPselecticc f64:$rs2, f64:$f, imm:$cond))]>; - def FMOVQ_ICC - : F4_3<0b110101, 0b000011, (outs QFPRegs:$rd), - (ins QFPRegs:$rs2, QFPRegs:$f, CCOp:$cond), - "fmovq$cond %icc, $rs2, $rd", - [(set f128:$rd, (SPselecticc f128:$rs2, f128:$f, imm:$cond))]>, - Requires<[HasHardQuad]>; - } - - let Uses = [FCC0], intcc = 0, opf_cc = 0b00 in { - def FMOVS_FCC - : F4_3<0b110101, 0b000001, (outs FPRegs:$rd), - (ins FPRegs:$rs2, FPRegs:$f, CCOp:$cond), - "fmovs$cond %fcc0, $rs2, $rd", - [(set f32:$rd, (SPselectfcc f32:$rs2, f32:$f, imm:$cond))]>; - def FMOVD_FCC - : F4_3<0b110101, 0b000010, (outs DFPRegs:$rd), - (ins DFPRegs:$rs2, DFPRegs:$f, CCOp:$cond), - "fmovd$cond %fcc0, $rs2, $rd", - [(set f64:$rd, (SPselectfcc f64:$rs2, f64:$f, imm:$cond))]>; - def FMOVQ_FCC - : F4_3<0b110101, 0b000011, (outs QFPRegs:$rd), - (ins QFPRegs:$rs2, QFPRegs:$f, CCOp:$cond), - "fmovq$cond %fcc0, $rs2, $rd", - [(set f128:$rd, (SPselectfcc f128:$rs2, f128:$f, imm:$cond))]>, - Requires<[HasHardQuad]>; - } - -} - -// Floating-Point Move Instructions, p. 164 of the V9 manual. -let Predicates = [HasV9] in { - def FMOVD : F3_3u<2, 0b110100, 0b000000010, - (outs DFPRegs:$rd), (ins DFPRegs:$rs2), - "fmovd $rs2, $rd", []>; - def FMOVQ : F3_3u<2, 0b110100, 0b000000011, - (outs QFPRegs:$rd), (ins QFPRegs:$rs2), - "fmovq $rs2, $rd", []>, - Requires<[HasHardQuad]>; - def FNEGD : F3_3u<2, 0b110100, 0b000000110, - (outs DFPRegs:$rd), (ins DFPRegs:$rs2), - "fnegd $rs2, $rd", - [(set f64:$rd, (fneg f64:$rs2))]>; - def FNEGQ : F3_3u<2, 0b110100, 0b000000111, - (outs QFPRegs:$rd), (ins QFPRegs:$rs2), - "fnegq $rs2, $rd", - [(set f128:$rd, (fneg f128:$rs2))]>, - Requires<[HasHardQuad]>; - def FABSD : F3_3u<2, 0b110100, 0b000001010, - (outs DFPRegs:$rd), (ins DFPRegs:$rs2), - "fabsd $rs2, $rd", - [(set f64:$rd, (fabs f64:$rs2))]>; - def FABSQ : F3_3u<2, 0b110100, 0b000001011, - (outs QFPRegs:$rd), (ins QFPRegs:$rs2), - "fabsq $rs2, $rd", - [(set f128:$rd, (fabs f128:$rs2))]>, - Requires<[HasHardQuad]>; -} - -// Floating-point compare instruction with %fcc0-%fcc3. -def V9FCMPS : F3_3c<2, 0b110101, 0b001010001, - (outs FCCRegs:$rd), (ins FPRegs:$rs1, FPRegs:$rs2), - "fcmps $rd, $rs1, $rs2", []>; -def V9FCMPD : F3_3c<2, 0b110101, 0b001010010, - (outs FCCRegs:$rd), (ins DFPRegs:$rs1, DFPRegs:$rs2), - "fcmpd $rd, $rs1, $rs2", []>; -def V9FCMPQ : F3_3c<2, 0b110101, 0b001010011, - (outs FCCRegs:$rd), (ins QFPRegs:$rs1, QFPRegs:$rs2), - "fcmpq $rd, $rs1, $rs2", []>, - Requires<[HasHardQuad]>; - -let hasSideEffects = 1 in { - def V9FCMPES : F3_3c<2, 0b110101, 0b001010101, - (outs FCCRegs:$rd), (ins FPRegs:$rs1, FPRegs:$rs2), - "fcmpes $rd, $rs1, $rs2", []>; - def V9FCMPED : F3_3c<2, 0b110101, 0b001010110, - (outs FCCRegs:$rd), (ins DFPRegs:$rs1, DFPRegs:$rs2), - "fcmped $rd, $rs1, $rs2", []>; - def V9FCMPEQ : F3_3c<2, 0b110101, 0b001010111, - (outs FCCRegs:$rd), (ins QFPRegs:$rs1, QFPRegs:$rs2), - "fcmpeq $rd, $rs1, $rs2", []>, - Requires<[HasHardQuad]>; -} - -// Floating point conditional move instrucitons with %fcc0-%fcc3. -let Predicates = [HasV9] in { - let Constraints = "$f = $rd", intcc = 0 in { - def V9MOVFCCrr - : F4_1<0b101100, (outs IntRegs:$rd), - (ins FCCRegs:$cc, IntRegs:$rs2, IntRegs:$f, CCOp:$cond), - "mov$cond $cc, $rs2, $rd", []>; - def V9MOVFCCri - : F4_2<0b101100, (outs IntRegs:$rd), - (ins FCCRegs:$cc, i32imm:$simm11, IntRegs:$f, CCOp:$cond), - "mov$cond $cc, $simm11, $rd", []>; - def V9FMOVS_FCC - : F4_3<0b110101, 0b000001, (outs FPRegs:$rd), - (ins FCCRegs:$opf_cc, FPRegs:$rs2, FPRegs:$f, CCOp:$cond), - "fmovs$cond $opf_cc, $rs2, $rd", []>; - def V9FMOVD_FCC - : F4_3<0b110101, 0b000010, (outs DFPRegs:$rd), - (ins FCCRegs:$opf_cc, DFPRegs:$rs2, DFPRegs:$f, CCOp:$cond), - "fmovd$cond $opf_cc, $rs2, $rd", []>; - def V9FMOVQ_FCC - : F4_3<0b110101, 0b000011, (outs QFPRegs:$rd), - (ins FCCRegs:$opf_cc, QFPRegs:$rs2, QFPRegs:$f, CCOp:$cond), - "fmovq$cond $opf_cc, $rs2, $rd", []>, - Requires<[HasHardQuad]>; - } // Constraints = "$f = $rd", ... -} // let Predicates = [hasV9] - - -// POPCrr - This does a ctpop of a 64-bit register. As such, we have to clear -// the top 32-bits before using it. To do this clearing, we use a SRLri X,0. -let rs1 = 0 in - def POPCrr : F3_1<2, 0b101110, - (outs IntRegs:$rd), (ins IntRegs:$rs2), - "popc $rs2, $rd", []>, Requires<[HasV9]>; -def : Pat<(ctpop i32:$src), - (POPCrr (SRLri $src, 0))>; - -let Predicates = [HasV9], hasSideEffects = 1, rd = 0, rs1 = 0b01111 in - def MEMBARi : F3_2<2, 0b101000, (outs), (ins MembarTag:$simm13), - "membar $simm13", []>; - -// The CAS instruction, unlike other instructions, only comes in a -// form which requires an ASI be provided. The ASI value hardcoded -// here is ASI_PRIMARY, the default unprivileged ASI for SparcV9. -let Predicates = [HasV9], Constraints = "$swap = $rd", asi = 0b10000000 in - def CASrr: F3_1_asi<3, 0b111100, - (outs IntRegs:$rd), (ins IntRegs:$rs1, IntRegs:$rs2, - IntRegs:$swap), - "cas [$rs1], $rs2, $rd", - [(set i32:$rd, - (atomic_cmp_swap_32 iPTR:$rs1, i32:$rs2, i32:$swap))]>; - - -// CASA is supported as an instruction on some LEON3 and all LEON4 processors. -// This version can be automatically lowered from C code, selecting ASI 10 -let Predicates = [HasLeonCASA], Constraints = "$swap = $rd", asi = 0b00001010 in - def CASAasi10: F3_1_asi<3, 0b111100, - (outs IntRegs:$rd), (ins IntRegs:$rs1, IntRegs:$rs2, - IntRegs:$swap), - "casa [$rs1] 10, $rs2, $rd", - [(set i32:$rd, - (atomic_cmp_swap_32 iPTR:$rs1, i32:$rs2, i32:$swap))]>; - -// CASA supported on some LEON3 and all LEON4 processors. Same pattern as -// CASrr, above, but with a different ASI. This version is supported for -// inline assembly lowering only. -let Predicates = [HasLeonCASA], Constraints = "$swap = $rd" in - def CASArr: F3_1_asi<3, 0b111100, - (outs IntRegs:$rd), (ins IntRegs:$rs1, IntRegs:$rs2, - IntRegs:$swap, i8imm:$asi), - "casa [$rs1] $asi, $rs2, $rd", []>; - -// TODO: Add DAG sequence to lower these instructions. Currently, only provided -// as inline assembler-supported instructions. -let Predicates = [HasUMAC_SMAC], Defs = [Y, ASR18], Uses = [Y, ASR18] in { - def SMACrr : F3_1<2, 0b111111, - (outs IntRegs:$rd), (ins IntRegs:$rs1, IntRegs:$rs2, ASRRegs:$asr18), - "smac $rs1, $rs2, $rd", - [], IIC_smac_umac>; - - def SMACri : F3_2<2, 0b111111, - (outs IntRegs:$rd), (ins IntRegs:$rs1, simm13Op:$simm13, ASRRegs:$asr18), - "smac $rs1, $simm13, $rd", - [], IIC_smac_umac>; - - def UMACrr : F3_1<2, 0b111110, - (outs IntRegs:$rd), (ins IntRegs:$rs1, IntRegs:$rs2, ASRRegs:$asr18), - "umac $rs1, $rs2, $rd", - [], IIC_smac_umac>; - - def UMACri : F3_2<2, 0b111110, - (outs IntRegs:$rd), (ins IntRegs:$rs1, simm13Op:$simm13, ASRRegs:$asr18), - "umac $rs1, $simm13, $rd", - [], IIC_smac_umac>; -} - -// The partial write WRPSR instruction has a non-zero destination -// register value to separate it from the standard instruction. -let Predicates = [HasPWRPSR], Defs = [PSR], rd=1 in { - def PWRPSRrr : F3_1<2, 0b110001, - (outs), (ins IntRegs:$rs1, IntRegs:$rs2), - "pwr $rs1, $rs2, %psr", []>; - def PWRPSRri : F3_2<2, 0b110001, - (outs), (ins IntRegs:$rs1, simm13Op:$simm13), - "pwr $rs1, $simm13, %psr", []>; -} - -let Defs = [ICC] in { -defm TADDCC : F3_12np<"taddcc", 0b100000>; -defm TSUBCC : F3_12np<"tsubcc", 0b100001>; - -let hasSideEffects = 1 in { - defm TADDCCTV : F3_12np<"taddcctv", 0b100010>; - defm TSUBCCTV : F3_12np<"tsubcctv", 0b100011>; -} -} - - -// Section A.43 - Read Privileged Register Instructions -let Predicates = [HasV9] in { -let rs2 = 0 in - def RDPR : F3_1<2, 0b101010, - (outs IntRegs:$rd), (ins PRRegs:$rs1), - "rdpr $rs1, $rd", []>; -} - -// Section A.62 - Write Privileged Register Instructions -let Predicates = [HasV9] in { - def WRPRrr : F3_1<2, 0b110010, - (outs PRRegs:$rd), (ins IntRegs:$rs1, IntRegs:$rs2), - "wrpr $rs1, $rs2, $rd", []>; - def WRPRri : F3_2<2, 0b110010, - (outs PRRegs:$rd), (ins IntRegs:$rs1, simm13Op:$simm13), - "wrpr $rs1, $simm13, $rd", []>; -} - -//===----------------------------------------------------------------------===// -// Non-Instruction Patterns -//===----------------------------------------------------------------------===// - -// Zero immediate. -def : Pat<(i32 0), - (ORrr (i32 G0), (i32 G0))>; -// Small immediates. -def : Pat<(i32 simm13:$val), - (ORri (i32 G0), imm:$val)>; -// Arbitrary immediates. -def : Pat<(i32 imm:$val), - (ORri (SETHIi (HI22 imm:$val)), (LO10 imm:$val))>; - - -// Global addresses, constant pool entries -let Predicates = [Is32Bit] in { - -def : Pat<(SPhi tglobaladdr:$in), (SETHIi tglobaladdr:$in)>; -def : Pat<(SPlo tglobaladdr:$in), (ORri (i32 G0), tglobaladdr:$in)>; -def : Pat<(SPhi tconstpool:$in), (SETHIi tconstpool:$in)>; -def : Pat<(SPlo tconstpool:$in), (ORri (i32 G0), tconstpool:$in)>; - -// GlobalTLS addresses -def : Pat<(SPhi tglobaltlsaddr:$in), (SETHIi tglobaltlsaddr:$in)>; -def : Pat<(SPlo tglobaltlsaddr:$in), (ORri (i32 G0), tglobaltlsaddr:$in)>; -def : Pat<(add (SPhi tglobaltlsaddr:$in1), (SPlo tglobaltlsaddr:$in2)), - (ADDri (SETHIi tglobaltlsaddr:$in1), (tglobaltlsaddr:$in2))>; -def : Pat<(xor (SPhi tglobaltlsaddr:$in1), (SPlo tglobaltlsaddr:$in2)), - (XORri (SETHIi tglobaltlsaddr:$in1), (tglobaltlsaddr:$in2))>; - -// Blockaddress -def : Pat<(SPhi tblockaddress:$in), (SETHIi tblockaddress:$in)>; -def : Pat<(SPlo tblockaddress:$in), (ORri (i32 G0), tblockaddress:$in)>; - -// Add reg, lo. This is used when taking the addr of a global/constpool entry. -def : Pat<(add iPTR:$r, (SPlo tglobaladdr:$in)), (ADDri $r, tglobaladdr:$in)>; -def : Pat<(add iPTR:$r, (SPlo tconstpool:$in)), (ADDri $r, tconstpool:$in)>; -def : Pat<(add iPTR:$r, (SPlo tblockaddress:$in)), - (ADDri $r, tblockaddress:$in)>; -} - -// Calls: -def : Pat<(call tglobaladdr:$dst), - (CALL tglobaladdr:$dst)>; -def : Pat<(call texternalsym:$dst), - (CALL texternalsym:$dst)>; - -// Map integer extload's to zextloads. -def : Pat<(i32 (extloadi1 ADDRrr:$src)), (LDUBrr ADDRrr:$src)>; -def : Pat<(i32 (extloadi1 ADDRri:$src)), (LDUBri ADDRri:$src)>; -def : Pat<(i32 (extloadi8 ADDRrr:$src)), (LDUBrr ADDRrr:$src)>; -def : Pat<(i32 (extloadi8 ADDRri:$src)), (LDUBri ADDRri:$src)>; -def : Pat<(i32 (extloadi16 ADDRrr:$src)), (LDUHrr ADDRrr:$src)>; -def : Pat<(i32 (extloadi16 ADDRri:$src)), (LDUHri ADDRri:$src)>; - -// zextload bool -> zextload byte -def : Pat<(i32 (zextloadi1 ADDRrr:$src)), (LDUBrr ADDRrr:$src)>; -def : Pat<(i32 (zextloadi1 ADDRri:$src)), (LDUBri ADDRri:$src)>; - -// store 0, addr -> store %g0, addr -def : Pat<(store (i32 0), ADDRrr:$dst), (STrr ADDRrr:$dst, (i32 G0))>; -def : Pat<(store (i32 0), ADDRri:$dst), (STri ADDRri:$dst, (i32 G0))>; - -// store bar for all atomic_fence in V8. -let Predicates = [HasNoV9] in - def : Pat<(atomic_fence imm, imm), (STBAR)>; - -// atomic_load addr -> load addr -def : Pat<(i32 (atomic_load_8 ADDRrr:$src)), (LDUBrr ADDRrr:$src)>; -def : Pat<(i32 (atomic_load_8 ADDRri:$src)), (LDUBri ADDRri:$src)>; -def : Pat<(i32 (atomic_load_16 ADDRrr:$src)), (LDUHrr ADDRrr:$src)>; -def : Pat<(i32 (atomic_load_16 ADDRri:$src)), (LDUHri ADDRri:$src)>; -def : Pat<(i32 (atomic_load_32 ADDRrr:$src)), (LDrr ADDRrr:$src)>; -def : Pat<(i32 (atomic_load_32 ADDRri:$src)), (LDri ADDRri:$src)>; - -// atomic_store val, addr -> store val, addr -def : Pat<(atomic_store_8 ADDRrr:$dst, i32:$val), (STBrr ADDRrr:$dst, $val)>; -def : Pat<(atomic_store_8 ADDRri:$dst, i32:$val), (STBri ADDRri:$dst, $val)>; -def : Pat<(atomic_store_16 ADDRrr:$dst, i32:$val), (STHrr ADDRrr:$dst, $val)>; -def : Pat<(atomic_store_16 ADDRri:$dst, i32:$val), (STHri ADDRri:$dst, $val)>; -def : Pat<(atomic_store_32 ADDRrr:$dst, i32:$val), (STrr ADDRrr:$dst, $val)>; -def : Pat<(atomic_store_32 ADDRri:$dst, i32:$val), (STri ADDRri:$dst, $val)>; - -// extract_vector -def : Pat<(extractelt (v2i32 IntPair:$Rn), 0), - (i32 (EXTRACT_SUBREG IntPair:$Rn, sub_even))>; -def : Pat<(extractelt (v2i32 IntPair:$Rn), 1), - (i32 (EXTRACT_SUBREG IntPair:$Rn, sub_odd))>; - -// build_vector -def : Pat<(build_vector (i32 IntRegs:$a1), (i32 IntRegs:$a2)), - (INSERT_SUBREG - (INSERT_SUBREG (v2i32 (IMPLICIT_DEF)), (i32 IntRegs:$a1), sub_even), - (i32 IntRegs:$a2), sub_odd)>; - - -include "SparcInstr64Bit.td" -include "SparcInstrVIS.td" -include "SparcInstrAliases.td" diff --git a/contrib/llvm/lib/Target/Sparc/SparcInstrVIS.td b/contrib/llvm/lib/Target/Sparc/SparcInstrVIS.td deleted file mode 100644 index bdefc70869d7..000000000000 --- a/contrib/llvm/lib/Target/Sparc/SparcInstrVIS.td +++ /dev/null @@ -1,262 +0,0 @@ -//===---- SparcInstrVIS.td - Visual Instruction Set extensions (VIS) -----===// -// -// Part of the LLVM Project, under the Apache 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 instruction formats, definitions and patterns needed for -// VIS, VIS II, VIS II instructions on SPARC. -//===----------------------------------------------------------------------===// - -// VIS Instruction Format. -class VISInstFormat opfval, dag outs, dag ins, string asmstr, - list pattern> - : F3_3<0b10, 0b110110, opfval, outs, ins, asmstr, pattern>; - -class VISInst opfval, string OpcStr, RegisterClass RC = DFPRegs> - : VISInstFormat; - -// VIS Instruction with integer destination register. -class VISInstID opfval, string OpcStr> - : VISInstFormat; - -// For VIS Instructions with no operand. -let rd = 0, rs1 = 0, rs2 = 0 in -class VISInst0 opfval, string asmstr> - : VISInstFormat; - -// For VIS Instructions with only rs1, rd operands. -let rs2 = 0 in -class VISInst1 opfval, string OpcStr, RegisterClass RC = DFPRegs> - : VISInstFormat; - -// For VIS Instructions with only rs2, rd operands. -let rs1 = 0 in -class VISInst2 opfval, string OpcStr, RegisterClass RC = DFPRegs> - : VISInstFormat; - -// For VIS Instructions with only rd operand. -let Constraints = "$rd = $f", rs1 = 0, rs2 = 0 in -class VISInstD opfval, string OpcStr, RegisterClass RC = DFPRegs> - : VISInstFormat; - -// VIS 1 Instructions -let Predicates = [HasVIS] in { - -def FPADD16 : VISInst<0b001010000, "fpadd16">; -def FPADD16S : VISInst<0b001010001, "fpadd16s">; -def FPADD32 : VISInst<0b001010010, "fpadd32">; -def FPADD32S : VISInst<0b001010011, "fpadd32s">; -def FPSUB16 : VISInst<0b001010100, "fpsub16">; -def FPSUB16S : VISInst<0b001010101, "fpsub16S">; -def FPSUB32 : VISInst<0b001010110, "fpsub32">; -def FPSUB32S : VISInst<0b001010111, "fpsub32S">; - -def FPACK16 : VISInst2<0b000111011, "fpack16">; -def FPACK32 : VISInst <0b000111010, "fpack32">; -def FPACKFIX : VISInst2<0b000111101, "fpackfix">; -def FEXPAND : VISInst2<0b001001101, "fexpand">; -def FPMERGE : VISInst <0b001001011, "fpmerge">; - -def FMUL8X16 : VISInst<0b000110001, "fmul8x16">; -def FMUL8X16AU : VISInst<0b000110011, "fmul8x16au">; -def FMUL8X16AL : VISInst<0b000110101, "fmul8x16al">; -def FMUL8SUX16 : VISInst<0b000110110, "fmul8sux16">; -def FMUL8ULX16 : VISInst<0b000110111, "fmul8ulx16">; -def FMULD8SUX16 : VISInst<0b000111000, "fmuld8sux16">; -def FMULD8ULX16 : VISInst<0b000111001, "fmuld8ulx16">; - -def ALIGNADDR : VISInst<0b000011000, "alignaddr", I64Regs>; -def ALIGNADDRL : VISInst<0b000011010, "alignaddrl", I64Regs>; -def FALIGNADATA : VISInst<0b001001000, "faligndata">; - -def FZERO : VISInstD<0b001100000, "fzero">; -def FZEROS : VISInstD<0b001100001, "fzeros", FPRegs>; -def FONE : VISInstD<0b001111110, "fone">; -def FONES : VISInstD<0b001111111, "fones", FPRegs>; -def FSRC1 : VISInst1<0b001110100, "fsrc1">; -def FSRC1S : VISInst1<0b001110101, "fsrc1s", FPRegs>; -def FSRC2 : VISInst2<0b001111000, "fsrc2">; -def FSRC2S : VISInst2<0b001111001, "fsrc2s", FPRegs>; -def FNOT1 : VISInst1<0b001101010, "fnot1">; -def FNOT1S : VISInst1<0b001101011, "fnot1s", FPRegs>; -def FNOT2 : VISInst2<0b001100110, "fnot2">; -def FNOT2S : VISInst2<0b001100111, "fnot2s", FPRegs>; -def FOR : VISInst<0b001111100, "for">; -def FORS : VISInst<0b001111101, "fors", FPRegs>; -def FNOR : VISInst<0b001100010, "fnor">; -def FNORS : VISInst<0b001100011, "fnors", FPRegs>; -def FAND : VISInst<0b001110000, "fand">; -def FANDS : VISInst<0b001110001, "fands", FPRegs>; -def FNAND : VISInst<0b001101110, "fnand">; -def FNANDS : VISInst<0b001101111, "fnands", FPRegs>; -def FXOR : VISInst<0b001101100, "fxor">; -def FXORS : VISInst<0b001101101, "fxors", FPRegs>; -def FXNOR : VISInst<0b001110010, "fxnor">; -def FXNORS : VISInst<0b001110011, "fxnors", FPRegs>; - -def FORNOT1 : VISInst<0b001111010, "fornot1">; -def FORNOT1S : VISInst<0b001111011, "fornot1s", FPRegs>; -def FORNOT2 : VISInst<0b001110110, "fornot2">; -def FORNOT2S : VISInst<0b001110111, "fornot2s", FPRegs>; -def FANDNOT1 : VISInst<0b001101000, "fandnot1">; -def FANDNOT1S : VISInst<0b001101001, "fandnot1s", FPRegs>; -def FANDNOT2 : VISInst<0b001100100, "fandnot2">; -def FANDNOT2S : VISInst<0b001100101, "fandnot2s", FPRegs>; - -def FCMPGT16 : VISInstID<0b000101000, "fcmpgt16">; -def FCMPGT32 : VISInstID<0b000101100, "fcmpgt32">; -def FCMPLE16 : VISInstID<0b000100000, "fcmple16">; -def FCMPLE32 : VISInstID<0b000100100, "fcmple32">; -def FCMPNE16 : VISInstID<0b000100010, "fcmpne16">; -def FCMPNE32 : VISInstID<0b000100110, "fcmpne32">; -def FCMPEQ16 : VISInstID<0b000101010, "fcmpeq16">; -def FCMPEQ32 : VISInstID<0b000101110, "fcmpeq32">; - - -def EDGE8 : VISInst<0b000000000, "edge8", I64Regs>; -def EDGE8L : VISInst<0b000000010, "edge8l", I64Regs>; -def EDGE16 : VISInst<0b000000100, "edge16", I64Regs>; -def EDGE16L : VISInst<0b000000110, "edge16l", I64Regs>; -def EDGE32 : VISInst<0b000001000, "edge32", I64Regs>; -def EDGE32L : VISInst<0b000001010, "edge32l", I64Regs>; - -def PDIST : VISInst<0b000111110, "pdist">; - -def ARRAY8 : VISInst<0b000010000, "array8", I64Regs>; -def ARRAY16 : VISInst<0b000010010, "array16", I64Regs>; -def ARRAY32 : VISInst<0b000010100, "array32", I64Regs>; - -def SHUTDOWN : VISInst0<0b010000000, "shutdown">; - -} // Predicates = [HasVIS] - - -// VIS 2 Instructions. -let Predicates = [HasVIS2] in { - -def BMASK : VISInst<0b000011001, "bmask", I64Regs>; -def BSHUFFLE : VISInst<0b000011100, "bshuffle">; - -def SIAM : VISInst0<0b010000001, "siam">; - -def EDGE8N : VISInst<0b000000001, "edge8n", I64Regs>; -def EDGE8LN : VISInst<0b000000011, "edge8ln", I64Regs>; -def EDGE16N : VISInst<0b000000101, "edge16n", I64Regs>; -def EDGE16LN : VISInst<0b000000111, "edge16ln", I64Regs>; -def EDGE32N : VISInst<0b000001001, "edge32n", I64Regs>; -def EDGE32LN : VISInst<0b000001011, "edge32ln", I64Regs>; -} // Predicates = [HasVIS2] - - -// VIS 3 Instructions. -let Predicates = [HasVIS3] in { - -let Uses = [ICC] in -def ADDXC : VISInst<0b000010001, "addxc", I64Regs>; - -let Defs = [ICC], Uses = [ICC] in -def ADDXCCC : VISInst<0b000010011, "addxccc", I64Regs>; - -let rd = 0, rs1 = 0 in { -def CMASK8 : VISInstFormat<0b000011011, (outs), (ins I64Regs:$rs2), - "cmask8 $rs2", []>; -def CMASK16 : VISInstFormat<0b000011101, (outs), (ins I64Regs:$rs2), - "cmask16 $rs2", []>; -def CMASK32 : VISInstFormat<0b000011111, (outs), (ins I64Regs:$rs2), - "cmask32 $rs2", []>; - -} - -def FCHKSM16 : VISInst<0b001000100, "fchksm16">; - -def FHADDS : F3_3<0b10, 0b110100, 0b001100001, - (outs DFPRegs:$rd), (ins DFPRegs:$rs1, DFPRegs:$rs2), - "fhadds $rs1, $rs2, $rd", []>; -def FHADDD : F3_3<0b10, 0b110100, 0b001100010, - (outs DFPRegs:$rd), (ins DFPRegs:$rs1, DFPRegs:$rs2), - "fhaddd $rs1, $rs2, $rd", []>; -def FHSUBS : F3_3<0b10, 0b110100, 0b001100101, - (outs DFPRegs:$rd), (ins DFPRegs:$rs1, DFPRegs:$rs2), - "fhsubs $rs1, $rs2, $rd", []>; -def FHSUBD : F3_3<0b10, 0b110100, 0b001100110, - (outs DFPRegs:$rd), (ins DFPRegs:$rs1, DFPRegs:$rs2), - "fhsubd $rs1, $rs2, $rd", []>; -def FLCMPS : VISInstFormat<0b101010001, (outs FCCRegs:$rd), - (ins DFPRegs:$rs1, DFPRegs:$rs2), - "flcmps $rd, $rs1, $rs2", []>; -def FLCMPD : VISInstFormat<0b101010010, (outs FCCRegs:$rd), - (ins DFPRegs:$rs1, DFPRegs:$rs2), - "flcmpd $rd, $rs1, $rs2", []>; - -def FMEAN16 : VISInst<0b001000000, "fmean16">; - -def FNADDS : F3_3<0b10, 0b110100, 0b001010001, - (outs DFPRegs:$rd), (ins DFPRegs:$rs1, DFPRegs:$rs2), - "fnadds $rs1, $rs2, $rd", []>; -def FNADDD : F3_3<0b10, 0b110100, 0b001010010, - (outs DFPRegs:$rd), (ins DFPRegs:$rs1, DFPRegs:$rs2), - "fnaddd $rs1, $rs2, $rd", []>; -def FNHADDS : F3_3<0b10, 0b110100, 0b001110001, - (outs DFPRegs:$rd), (ins DFPRegs:$rs1, DFPRegs:$rs2), - "fnhadds $rs1, $rs2, $rd", []>; -def FNHADDD : F3_3<0b10, 0b110100, 0b001110010, - (outs DFPRegs:$rd), (ins DFPRegs:$rs1, DFPRegs:$rs2), - "fnhaddd $rs1, $rs2, $rd", []>; - -def FNMULS : F3_3<0b10, 0b110100, 0b001011001, - (outs DFPRegs:$rd), (ins DFPRegs:$rs1, DFPRegs:$rs2), - "fnhadds $rs1, $rs2, $rd", []>; -def FNMULD : F3_3<0b10, 0b110100, 0b001011010, - (outs DFPRegs:$rd), (ins DFPRegs:$rs1, DFPRegs:$rs2), - "fnhaddd $rs1, $rs2, $rd", []>; -def FNSMULD : F3_3<0b10, 0b110100, 0b001111001, - (outs DFPRegs:$rd), (ins DFPRegs:$rs1, DFPRegs:$rs2), - "fnhadds $rs1, $rs2, $rd", []>; - -def FPADD64 : VISInst<0b001000010, "fpadd64">; - -def FSLL16 : VISInst<0b000100001, "fsll16">; -def FSRL16 : VISInst<0b000100011, "fsrl16">; -def FSLL32 : VISInst<0b000100101, "fsll32">; -def FSRL32 : VISInst<0b000100111, "fsrl32">; -def FSLAS16 : VISInst<0b000101001, "fslas16">; -def FSRA16 : VISInst<0b000101011, "fsra16">; -def FSLAS32 : VISInst<0b000101101, "fslas32">; -def FSRA32 : VISInst<0b000101111, "fsra32">; - -let rs1 = 0 in -def LZCNT : VISInstFormat<0b000010111, (outs I64Regs:$rd), - (ins I64Regs:$rs2), "lzcnt $rs2, $rd", []>; - -let rs1 = 0 in { -def MOVSTOSW : VISInstFormat<0b100010011, (outs I64Regs:$rd), - (ins DFPRegs:$rs2), "movstosw $rs2, $rd", []>; -def MOVSTOUW : VISInstFormat<0b100010001, (outs I64Regs:$rd), - (ins DFPRegs:$rs2), "movstouw $rs2, $rd", []>; -def MOVDTOX : VISInstFormat<0b100010000, (outs I64Regs:$rd), - (ins DFPRegs:$rs2), "movdtox $rs2, $rd", []>; -def MOVWTOS : VISInstFormat<0b100011001, (outs DFPRegs:$rd), - (ins I64Regs:$rs2), "movdtox $rs2, $rd", []>; -def MOVXTOD : VISInstFormat<0b100011000, (outs DFPRegs:$rd), - (ins I64Regs:$rs2), "movdtox $rs2, $rd", []>; -} - -def PDISTN : VISInst<0b000111111, "pdistn">; - -def UMULXHI : VISInst<0b000010110, "umulxhi", I64Regs>; -def XMULX : VISInst<0b100010101, "xmulx", I64Regs>; -def XMULXHI : VISInst<0b100010111, "xmulxhi", I64Regs>; -} // Predicates = [IsVIS3] diff --git a/contrib/llvm/lib/Target/Sparc/SparcMCInstLower.cpp b/contrib/llvm/lib/Target/Sparc/SparcMCInstLower.cpp deleted file mode 100644 index 8ea317fdd453..000000000000 --- a/contrib/llvm/lib/Target/Sparc/SparcMCInstLower.cpp +++ /dev/null @@ -1,107 +0,0 @@ -//===-- SparcMCInstLower.cpp - Convert Sparc 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 Sparc MachineInstrs to their corresponding -// MCInst records. -// -//===----------------------------------------------------------------------===// - -#include "MCTargetDesc/SparcMCExpr.h" -#include "Sparc.h" -#include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/CodeGen/MachineOperand.h" -#include "llvm/IR/Mangler.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCInst.h" - -using namespace llvm; - - -static MCOperand LowerSymbolOperand(const MachineInstr *MI, - const MachineOperand &MO, - AsmPrinter &AP) { - - SparcMCExpr::VariantKind Kind = - (SparcMCExpr::VariantKind)MO.getTargetFlags(); - const MCSymbol *Symbol = nullptr; - - switch(MO.getType()) { - default: llvm_unreachable("Unknown type in LowerSymbolOperand"); - case MachineOperand::MO_MachineBasicBlock: - Symbol = MO.getMBB()->getSymbol(); - break; - - case MachineOperand::MO_GlobalAddress: - Symbol = AP.getSymbol(MO.getGlobal()); - break; - - case MachineOperand::MO_BlockAddress: - Symbol = AP.GetBlockAddressSymbol(MO.getBlockAddress()); - break; - - case MachineOperand::MO_ExternalSymbol: - Symbol = AP.GetExternalSymbolSymbol(MO.getSymbolName()); - break; - - case MachineOperand::MO_ConstantPoolIndex: - Symbol = AP.GetCPISymbol(MO.getIndex()); - break; - } - - const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::create(Symbol, - AP.OutContext); - const SparcMCExpr *expr = SparcMCExpr::create(Kind, MCSym, - AP.OutContext); - return MCOperand::createExpr(expr); -} - -static MCOperand LowerOperand(const MachineInstr *MI, - const MachineOperand &MO, - AsmPrinter &AP) { - switch(MO.getType()) { - default: llvm_unreachable("unknown operand type"); break; - case MachineOperand::MO_Register: - if (MO.isImplicit()) - break; - return MCOperand::createReg(MO.getReg()); - - case MachineOperand::MO_Immediate: - return MCOperand::createImm(MO.getImm()); - - case MachineOperand::MO_MachineBasicBlock: - case MachineOperand::MO_GlobalAddress: - case MachineOperand::MO_BlockAddress: - case MachineOperand::MO_ExternalSymbol: - case MachineOperand::MO_ConstantPoolIndex: - return LowerSymbolOperand(MI, MO, AP); - - case MachineOperand::MO_RegisterMask: break; - - } - return MCOperand(); -} - -void llvm::LowerSparcMachineInstrToMCInst(const MachineInstr *MI, - MCInst &OutMI, - AsmPrinter &AP) -{ - - OutMI.setOpcode(MI->getOpcode()); - - for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { - const MachineOperand &MO = MI->getOperand(i); - MCOperand MCOp = LowerOperand(MI, MO, AP); - - if (MCOp.isValid()) - OutMI.addOperand(MCOp); - } -} diff --git a/contrib/llvm/lib/Target/Sparc/SparcMachineFunctionInfo.cpp b/contrib/llvm/lib/Target/Sparc/SparcMachineFunctionInfo.cpp deleted file mode 100644 index 7c36c4ab865f..000000000000 --- a/contrib/llvm/lib/Target/Sparc/SparcMachineFunctionInfo.cpp +++ /dev/null @@ -1,13 +0,0 @@ -//===-- SparcMachineFunctionInfo.cpp - Sparc Machine Function Info --------===// -// -// Part of the LLVM Project, under the Apache 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 "SparcMachineFunctionInfo.h" - -using namespace llvm; - -void SparcMachineFunctionInfo::anchor() { } diff --git a/contrib/llvm/lib/Target/Sparc/SparcMachineFunctionInfo.h b/contrib/llvm/lib/Target/Sparc/SparcMachineFunctionInfo.h deleted file mode 100644 index fe5705878693..000000000000 --- a/contrib/llvm/lib/Target/Sparc/SparcMachineFunctionInfo.h +++ /dev/null @@ -1,55 +0,0 @@ -//===- SparcMachineFunctionInfo.h - Sparc Machine Function 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 declares Sparc specific per-machine-function information. -// -//===----------------------------------------------------------------------===// -#ifndef LLVM_LIB_TARGET_SPARC_SPARCMACHINEFUNCTIONINFO_H -#define LLVM_LIB_TARGET_SPARC_SPARCMACHINEFUNCTIONINFO_H - -#include "llvm/CodeGen/MachineFunction.h" - -namespace llvm { - - class SparcMachineFunctionInfo : public MachineFunctionInfo { - virtual void anchor(); - private: - unsigned GlobalBaseReg; - - /// VarArgsFrameOffset - Frame offset to start of varargs area. - int VarArgsFrameOffset; - - /// SRetReturnReg - Holds the virtual register into which the sret - /// argument is passed. - unsigned SRetReturnReg; - - /// IsLeafProc - True if the function is a leaf procedure. - bool IsLeafProc; - public: - SparcMachineFunctionInfo() - : GlobalBaseReg(0), VarArgsFrameOffset(0), SRetReturnReg(0), - IsLeafProc(false) {} - explicit SparcMachineFunctionInfo(MachineFunction &MF) - : GlobalBaseReg(0), VarArgsFrameOffset(0), SRetReturnReg(0), - IsLeafProc(false) {} - - unsigned getGlobalBaseReg() const { return GlobalBaseReg; } - void setGlobalBaseReg(unsigned Reg) { GlobalBaseReg = Reg; } - - int getVarArgsFrameOffset() const { return VarArgsFrameOffset; } - void setVarArgsFrameOffset(int Offset) { VarArgsFrameOffset = Offset; } - - unsigned getSRetReturnReg() const { return SRetReturnReg; } - void setSRetReturnReg(unsigned Reg) { SRetReturnReg = Reg; } - - void setLeafProc(bool rhs) { IsLeafProc = rhs; } - bool isLeafProc() const { return IsLeafProc; } - }; -} - -#endif diff --git a/contrib/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp b/contrib/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp deleted file mode 100644 index ce11a423d10e..000000000000 --- a/contrib/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp +++ /dev/null @@ -1,240 +0,0 @@ -//===-- SparcRegisterInfo.cpp - SPARC 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 SPARC implementation of the TargetRegisterInfo class. -// -//===----------------------------------------------------------------------===// - -#include "SparcRegisterInfo.h" -#include "Sparc.h" -#include "SparcMachineFunctionInfo.h" -#include "SparcSubtarget.h" -#include "llvm/ADT/BitVector.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/TargetInstrInfo.h" -#include "llvm/IR/Type.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/ErrorHandling.h" - -using namespace llvm; - -#define GET_REGINFO_TARGET_DESC -#include "SparcGenRegisterInfo.inc" - -static cl::opt -ReserveAppRegisters("sparc-reserve-app-registers", cl::Hidden, cl::init(false), - cl::desc("Reserve application registers (%g2-%g4)")); - -SparcRegisterInfo::SparcRegisterInfo() : SparcGenRegisterInfo(SP::O7) {} - -const MCPhysReg* -SparcRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { - return CSR_SaveList; -} - -const uint32_t * -SparcRegisterInfo::getCallPreservedMask(const MachineFunction &MF, - CallingConv::ID CC) const { - return CSR_RegMask; -} - -const uint32_t* -SparcRegisterInfo::getRTCallPreservedMask(CallingConv::ID CC) const { - return RTCSR_RegMask; -} - -BitVector SparcRegisterInfo::getReservedRegs(const MachineFunction &MF) const { - BitVector Reserved(getNumRegs()); - const SparcSubtarget &Subtarget = MF.getSubtarget(); - // FIXME: G1 reserved for now for large imm generation by frame code. - Reserved.set(SP::G1); - - // G1-G4 can be used in applications. - if (ReserveAppRegisters) { - Reserved.set(SP::G2); - Reserved.set(SP::G3); - Reserved.set(SP::G4); - } - // G5 is not reserved in 64 bit mode. - if (!Subtarget.is64Bit()) - Reserved.set(SP::G5); - - Reserved.set(SP::O6); - Reserved.set(SP::I6); - Reserved.set(SP::I7); - Reserved.set(SP::G0); - Reserved.set(SP::G6); - Reserved.set(SP::G7); - - // Also reserve the register pair aliases covering the above - // registers, with the same conditions. - Reserved.set(SP::G0_G1); - if (ReserveAppRegisters) - Reserved.set(SP::G2_G3); - if (ReserveAppRegisters || !Subtarget.is64Bit()) - Reserved.set(SP::G4_G5); - - Reserved.set(SP::O6_O7); - Reserved.set(SP::I6_I7); - Reserved.set(SP::G6_G7); - - // Unaliased double registers are not available in non-V9 targets. - if (!Subtarget.isV9()) { - for (unsigned n = 0; n != 16; ++n) { - for (MCRegAliasIterator AI(SP::D16 + n, this, true); AI.isValid(); ++AI) - Reserved.set(*AI); - } - } - - // Reserve ASR1-ASR31 - for (unsigned n = 0; n < 31; n++) - Reserved.set(SP::ASR1 + n); - - return Reserved; -} - -const TargetRegisterClass* -SparcRegisterInfo::getPointerRegClass(const MachineFunction &MF, - unsigned Kind) const { - const SparcSubtarget &Subtarget = MF.getSubtarget(); - return Subtarget.is64Bit() ? &SP::I64RegsRegClass : &SP::IntRegsRegClass; -} - -static void replaceFI(MachineFunction &MF, MachineBasicBlock::iterator II, - MachineInstr &MI, const DebugLoc &dl, - unsigned FIOperandNum, int Offset, unsigned FramePtr) { - // Replace frame index with a frame pointer reference. - if (Offset >= -4096 && Offset <= 4095) { - // If the offset is small enough to fit in the immediate field, directly - // encode it. - MI.getOperand(FIOperandNum).ChangeToRegister(FramePtr, false); - MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset); - return; - } - - const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); - - // FIXME: it would be better to scavenge a register here instead of - // reserving G1 all of the time. - if (Offset >= 0) { - // Emit nonnegaive immediates with sethi + or. - // sethi %hi(Offset), %g1 - // add %g1, %fp, %g1 - // Insert G1+%lo(offset) into the user. - BuildMI(*MI.getParent(), II, dl, TII.get(SP::SETHIi), SP::G1) - .addImm(HI22(Offset)); - - - // Emit G1 = G1 + I6 - BuildMI(*MI.getParent(), II, dl, TII.get(SP::ADDrr), SP::G1).addReg(SP::G1) - .addReg(FramePtr); - // Insert: G1+%lo(offset) into the user. - MI.getOperand(FIOperandNum).ChangeToRegister(SP::G1, false); - MI.getOperand(FIOperandNum + 1).ChangeToImmediate(LO10(Offset)); - return; - } - - // Emit Negative numbers with sethi + xor - // sethi %hix(Offset), %g1 - // xor %g1, %lox(offset), %g1 - // add %g1, %fp, %g1 - // Insert: G1 + 0 into the user. - BuildMI(*MI.getParent(), II, dl, TII.get(SP::SETHIi), SP::G1) - .addImm(HIX22(Offset)); - BuildMI(*MI.getParent(), II, dl, TII.get(SP::XORri), SP::G1) - .addReg(SP::G1).addImm(LOX10(Offset)); - - BuildMI(*MI.getParent(), II, dl, TII.get(SP::ADDrr), SP::G1).addReg(SP::G1) - .addReg(FramePtr); - // Insert: G1+%lo(offset) into the user. - MI.getOperand(FIOperandNum).ChangeToRegister(SP::G1, false); - MI.getOperand(FIOperandNum + 1).ChangeToImmediate(0); -} - - -void -SparcRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, - int SPAdj, unsigned FIOperandNum, - RegScavenger *RS) const { - assert(SPAdj == 0 && "Unexpected"); - - MachineInstr &MI = *II; - DebugLoc dl = MI.getDebugLoc(); - int FrameIndex = MI.getOperand(FIOperandNum).getIndex(); - MachineFunction &MF = *MI.getParent()->getParent(); - const SparcSubtarget &Subtarget = MF.getSubtarget(); - const SparcFrameLowering *TFI = getFrameLowering(MF); - - unsigned FrameReg; - int Offset; - Offset = TFI->getFrameIndexReference(MF, FrameIndex, FrameReg); - - Offset += MI.getOperand(FIOperandNum + 1).getImm(); - - if (!Subtarget.isV9() || !Subtarget.hasHardQuad()) { - if (MI.getOpcode() == SP::STQFri) { - const TargetInstrInfo &TII = *Subtarget.getInstrInfo(); - unsigned SrcReg = MI.getOperand(2).getReg(); - unsigned SrcEvenReg = getSubReg(SrcReg, SP::sub_even64); - unsigned SrcOddReg = getSubReg(SrcReg, SP::sub_odd64); - MachineInstr *StMI = - BuildMI(*MI.getParent(), II, dl, TII.get(SP::STDFri)) - .addReg(FrameReg).addImm(0).addReg(SrcEvenReg); - replaceFI(MF, *StMI, *StMI, dl, 0, Offset, FrameReg); - MI.setDesc(TII.get(SP::STDFri)); - MI.getOperand(2).setReg(SrcOddReg); - Offset += 8; - } else if (MI.getOpcode() == SP::LDQFri) { - const TargetInstrInfo &TII = *Subtarget.getInstrInfo(); - unsigned DestReg = MI.getOperand(0).getReg(); - unsigned DestEvenReg = getSubReg(DestReg, SP::sub_even64); - unsigned DestOddReg = getSubReg(DestReg, SP::sub_odd64); - MachineInstr *LdMI = - BuildMI(*MI.getParent(), II, dl, TII.get(SP::LDDFri), DestEvenReg) - .addReg(FrameReg).addImm(0); - replaceFI(MF, *LdMI, *LdMI, dl, 1, Offset, FrameReg); - - MI.setDesc(TII.get(SP::LDDFri)); - MI.getOperand(0).setReg(DestOddReg); - Offset += 8; - } - } - - replaceFI(MF, II, MI, dl, FIOperandNum, Offset, FrameReg); - -} - -Register SparcRegisterInfo::getFrameRegister(const MachineFunction &MF) const { - return SP::I6; -} - -// Sparc has no architectural need for stack realignment support, -// except that LLVM unfortunately currently implements overaligned -// stack objects by depending upon stack realignment support. -// If that ever changes, this can probably be deleted. -bool SparcRegisterInfo::canRealignStack(const MachineFunction &MF) const { - if (!TargetRegisterInfo::canRealignStack(MF)) - return false; - - // Sparc always has a fixed frame pointer register, so don't need to - // worry about needing to reserve it. [even if we don't have a frame - // pointer for our frame, it still cannot be used for other things, - // or register window traps will be SADNESS.] - - // If there's a reserved call frame, we can use SP to access locals. - if (getFrameLowering(MF)->hasReservedCallFrame(MF)) - return true; - - // Otherwise, we'd need a base pointer, but those aren't implemented - // for SPARC at the moment. - - return false; -} diff --git a/contrib/llvm/lib/Target/Sparc/SparcRegisterInfo.h b/contrib/llvm/lib/Target/Sparc/SparcRegisterInfo.h deleted file mode 100644 index 118ef9d80fae..000000000000 --- a/contrib/llvm/lib/Target/Sparc/SparcRegisterInfo.h +++ /dev/null @@ -1,49 +0,0 @@ -//===-- SparcRegisterInfo.h - Sparc 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 Sparc implementation of the TargetRegisterInfo class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_SPARC_SPARCREGISTERINFO_H -#define LLVM_LIB_TARGET_SPARC_SPARCREGISTERINFO_H - -#include "llvm/CodeGen/TargetRegisterInfo.h" - -#define GET_REGINFO_HEADER -#include "SparcGenRegisterInfo.inc" - -namespace llvm { -struct SparcRegisterInfo : public SparcGenRegisterInfo { - SparcRegisterInfo(); - - /// Code Generation virtual methods... - const MCPhysReg *getCalleeSavedRegs(const MachineFunction *MF) const override; - const uint32_t *getCallPreservedMask(const MachineFunction &MF, - CallingConv::ID CC) const override; - - const uint32_t* getRTCallPreservedMask(CallingConv::ID CC) const; - - BitVector getReservedRegs(const MachineFunction &MF) const override; - - const TargetRegisterClass *getPointerRegClass(const MachineFunction &MF, - unsigned Kind) const override; - - void eliminateFrameIndex(MachineBasicBlock::iterator II, - int SPAdj, unsigned FIOperandNum, - RegScavenger *RS = nullptr) const override; - - Register getFrameRegister(const MachineFunction &MF) const override; - - bool canRealignStack(const MachineFunction &MF) const override; - -}; - -} // end namespace llvm - -#endif diff --git a/contrib/llvm/lib/Target/Sparc/SparcRegisterInfo.td b/contrib/llvm/lib/Target/Sparc/SparcRegisterInfo.td deleted file mode 100644 index 98959d512955..000000000000 --- a/contrib/llvm/lib/Target/Sparc/SparcRegisterInfo.td +++ /dev/null @@ -1,378 +0,0 @@ -//===-- SparcRegisterInfo.td - Sparc 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 Sparc register file -//===----------------------------------------------------------------------===// - -class SparcReg Enc, string n> : Register { - let HWEncoding = Enc; - let Namespace = "SP"; -} - -class SparcCtrlReg Enc, string n>: Register { - let HWEncoding = Enc; - let Namespace = "SP"; -} - -let Namespace = "SP" in { -def sub_even : SubRegIndex<32>; -def sub_odd : SubRegIndex<32, 32>; -def sub_even64 : SubRegIndex<64>; -def sub_odd64 : SubRegIndex<64, 64>; -} - -// Registers are identified with 5-bit ID numbers. -// Ri - 32-bit integer registers -class Ri Enc, string n> : SparcReg; - -// Rdi - pairs of 32-bit integer registers -class Rdi Enc, string n, list subregs> : SparcReg { - let SubRegs = subregs; - let SubRegIndices = [sub_even, sub_odd]; - let CoveredBySubRegs = 1; -} -// Rf - 32-bit floating-point registers -class Rf Enc, string n> : SparcReg; - -// Rd - Slots in the FP register file for 64-bit floating-point values. -class Rd Enc, string n, list subregs> : SparcReg { - let SubRegs = subregs; - let SubRegIndices = [sub_even, sub_odd]; - let CoveredBySubRegs = 1; -} - -// Rq - Slots in the FP register file for 128-bit floating-point values. -class Rq Enc, string n, list subregs> : SparcReg { - let SubRegs = subregs; - let SubRegIndices = [sub_even64, sub_odd64]; - let CoveredBySubRegs = 1; -} - -// Control Registers -def ICC : SparcCtrlReg<0, "ICC">; // This represents icc and xcc in 64-bit code. -foreach I = 0-3 in - def FCC#I : SparcCtrlReg; - -def FSR : SparcCtrlReg<0, "FSR">; // Floating-point state register. - -def FQ : SparcCtrlReg<0, "FQ">; // Floating-point deferred-trap queue. - -def CPSR : SparcCtrlReg<0, "CPSR">; // Co-processor state register. - -def CPQ : SparcCtrlReg<0, "CPQ">; // Co-processor queue. - -// Y register -def Y : SparcCtrlReg<0, "Y">, DwarfRegNum<[64]>; -// Ancillary state registers (implementation defined) -def ASR1 : SparcCtrlReg<1, "ASR1">; -def ASR2 : SparcCtrlReg<2, "ASR2">; -def ASR3 : SparcCtrlReg<3, "ASR3">; -def ASR4 : SparcCtrlReg<4, "ASR4">; -def ASR5 : SparcCtrlReg<5, "ASR5">; -def ASR6 : SparcCtrlReg<6, "ASR6">; -def ASR7 : SparcCtrlReg<7, "ASR7">; -def ASR8 : SparcCtrlReg<8, "ASR8">; -def ASR9 : SparcCtrlReg<9, "ASR9">; -def ASR10 : SparcCtrlReg<10, "ASR10">; -def ASR11 : SparcCtrlReg<11, "ASR11">; -def ASR12 : SparcCtrlReg<12, "ASR12">; -def ASR13 : SparcCtrlReg<13, "ASR13">; -def ASR14 : SparcCtrlReg<14, "ASR14">; -def ASR15 : SparcCtrlReg<15, "ASR15">; -def ASR16 : SparcCtrlReg<16, "ASR16">; -def ASR17 : SparcCtrlReg<17, "ASR17">; -def ASR18 : SparcCtrlReg<18, "ASR18">; -def ASR19 : SparcCtrlReg<19, "ASR19">; -def ASR20 : SparcCtrlReg<20, "ASR20">; -def ASR21 : SparcCtrlReg<21, "ASR21">; -def ASR22 : SparcCtrlReg<22, "ASR22">; -def ASR23 : SparcCtrlReg<23, "ASR23">; -def ASR24 : SparcCtrlReg<24, "ASR24">; -def ASR25 : SparcCtrlReg<25, "ASR25">; -def ASR26 : SparcCtrlReg<26, "ASR26">; -def ASR27 : SparcCtrlReg<27, "ASR27">; -def ASR28 : SparcCtrlReg<28, "ASR28">; -def ASR29 : SparcCtrlReg<29, "ASR29">; -def ASR30 : SparcCtrlReg<30, "ASR30">; -def ASR31 : SparcCtrlReg<31, "ASR31">; - -// Note that PSR, WIM, and TBR don't exist on the SparcV9, only the V8. -def PSR : SparcCtrlReg<0, "PSR">; -def WIM : SparcCtrlReg<0, "WIM">; -def TBR : SparcCtrlReg<0, "TBR">; - -def TPC : SparcCtrlReg<0, "TPC">; -def TNPC : SparcCtrlReg<1, "TNPC">; -def TSTATE : SparcCtrlReg<2, "TSTATE">; -def TT : SparcCtrlReg<3, "TT">; -def TICK : SparcCtrlReg<4, "TICK">; -def TBA : SparcCtrlReg<5, "TBA">; -def PSTATE : SparcCtrlReg<6, "PSTATE">; -def TL : SparcCtrlReg<7, "TL">; -def PIL : SparcCtrlReg<8, "PIL">; -def CWP : SparcCtrlReg<9, "CWP">; -def CANSAVE : SparcCtrlReg<10, "CANSAVE">; -def CANRESTORE : SparcCtrlReg<11, "CANRESTORE">; -def CLEANWIN : SparcCtrlReg<12, "CLEANWIN">; -def OTHERWIN : SparcCtrlReg<13, "OTHERWIN">; -def WSTATE : SparcCtrlReg<14, "WSTATE">; - -// Integer registers -def G0 : Ri< 0, "G0">, DwarfRegNum<[0]>; -def G1 : Ri< 1, "G1">, DwarfRegNum<[1]>; -def G2 : Ri< 2, "G2">, DwarfRegNum<[2]>; -def G3 : Ri< 3, "G3">, DwarfRegNum<[3]>; -def G4 : Ri< 4, "G4">, DwarfRegNum<[4]>; -def G5 : Ri< 5, "G5">, DwarfRegNum<[5]>; -def G6 : Ri< 6, "G6">, DwarfRegNum<[6]>; -def G7 : Ri< 7, "G7">, DwarfRegNum<[7]>; -def O0 : Ri< 8, "O0">, DwarfRegNum<[8]>; -def O1 : Ri< 9, "O1">, DwarfRegNum<[9]>; -def O2 : Ri<10, "O2">, DwarfRegNum<[10]>; -def O3 : Ri<11, "O3">, DwarfRegNum<[11]>; -def O4 : Ri<12, "O4">, DwarfRegNum<[12]>; -def O5 : Ri<13, "O5">, DwarfRegNum<[13]>; -def O6 : Ri<14, "SP">, DwarfRegNum<[14]>; -def O7 : Ri<15, "O7">, DwarfRegNum<[15]>; -def L0 : Ri<16, "L0">, DwarfRegNum<[16]>; -def L1 : Ri<17, "L1">, DwarfRegNum<[17]>; -def L2 : Ri<18, "L2">, DwarfRegNum<[18]>; -def L3 : Ri<19, "L3">, DwarfRegNum<[19]>; -def L4 : Ri<20, "L4">, DwarfRegNum<[20]>; -def L5 : Ri<21, "L5">, DwarfRegNum<[21]>; -def L6 : Ri<22, "L6">, DwarfRegNum<[22]>; -def L7 : Ri<23, "L7">, DwarfRegNum<[23]>; -def I0 : Ri<24, "I0">, DwarfRegNum<[24]>; -def I1 : Ri<25, "I1">, DwarfRegNum<[25]>; -def I2 : Ri<26, "I2">, DwarfRegNum<[26]>; -def I3 : Ri<27, "I3">, DwarfRegNum<[27]>; -def I4 : Ri<28, "I4">, DwarfRegNum<[28]>; -def I5 : Ri<29, "I5">, DwarfRegNum<[29]>; -def I6 : Ri<30, "FP">, DwarfRegNum<[30]>; -def I7 : Ri<31, "I7">, DwarfRegNum<[31]>; - -// Floating-point registers -def F0 : Rf< 0, "F0">, DwarfRegNum<[32]>; -def F1 : Rf< 1, "F1">, DwarfRegNum<[33]>; -def F2 : Rf< 2, "F2">, DwarfRegNum<[34]>; -def F3 : Rf< 3, "F3">, DwarfRegNum<[35]>; -def F4 : Rf< 4, "F4">, DwarfRegNum<[36]>; -def F5 : Rf< 5, "F5">, DwarfRegNum<[37]>; -def F6 : Rf< 6, "F6">, DwarfRegNum<[38]>; -def F7 : Rf< 7, "F7">, DwarfRegNum<[39]>; -def F8 : Rf< 8, "F8">, DwarfRegNum<[40]>; -def F9 : Rf< 9, "F9">, DwarfRegNum<[41]>; -def F10 : Rf<10, "F10">, DwarfRegNum<[42]>; -def F11 : Rf<11, "F11">, DwarfRegNum<[43]>; -def F12 : Rf<12, "F12">, DwarfRegNum<[44]>; -def F13 : Rf<13, "F13">, DwarfRegNum<[45]>; -def F14 : Rf<14, "F14">, DwarfRegNum<[46]>; -def F15 : Rf<15, "F15">, DwarfRegNum<[47]>; -def F16 : Rf<16, "F16">, DwarfRegNum<[48]>; -def F17 : Rf<17, "F17">, DwarfRegNum<[49]>; -def F18 : Rf<18, "F18">, DwarfRegNum<[50]>; -def F19 : Rf<19, "F19">, DwarfRegNum<[51]>; -def F20 : Rf<20, "F20">, DwarfRegNum<[52]>; -def F21 : Rf<21, "F21">, DwarfRegNum<[53]>; -def F22 : Rf<22, "F22">, DwarfRegNum<[54]>; -def F23 : Rf<23, "F23">, DwarfRegNum<[55]>; -def F24 : Rf<24, "F24">, DwarfRegNum<[56]>; -def F25 : Rf<25, "F25">, DwarfRegNum<[57]>; -def F26 : Rf<26, "F26">, DwarfRegNum<[58]>; -def F27 : Rf<27, "F27">, DwarfRegNum<[59]>; -def F28 : Rf<28, "F28">, DwarfRegNum<[60]>; -def F29 : Rf<29, "F29">, DwarfRegNum<[61]>; -def F30 : Rf<30, "F30">, DwarfRegNum<[62]>; -def F31 : Rf<31, "F31">, DwarfRegNum<[63]>; - -// Aliases of the F* registers used to hold 64-bit fp values (doubles) -def D0 : Rd< 0, "F0", [F0, F1]>, DwarfRegNum<[72]>; -def D1 : Rd< 2, "F2", [F2, F3]>, DwarfRegNum<[73]>; -def D2 : Rd< 4, "F4", [F4, F5]>, DwarfRegNum<[74]>; -def D3 : Rd< 6, "F6", [F6, F7]>, DwarfRegNum<[75]>; -def D4 : Rd< 8, "F8", [F8, F9]>, DwarfRegNum<[76]>; -def D5 : Rd<10, "F10", [F10, F11]>, DwarfRegNum<[77]>; -def D6 : Rd<12, "F12", [F12, F13]>, DwarfRegNum<[78]>; -def D7 : Rd<14, "F14", [F14, F15]>, DwarfRegNum<[79]>; -def D8 : Rd<16, "F16", [F16, F17]>, DwarfRegNum<[80]>; -def D9 : Rd<18, "F18", [F18, F19]>, DwarfRegNum<[81]>; -def D10 : Rd<20, "F20", [F20, F21]>, DwarfRegNum<[82]>; -def D11 : Rd<22, "F22", [F22, F23]>, DwarfRegNum<[83]>; -def D12 : Rd<24, "F24", [F24, F25]>, DwarfRegNum<[84]>; -def D13 : Rd<26, "F26", [F26, F27]>, DwarfRegNum<[85]>; -def D14 : Rd<28, "F28", [F28, F29]>, DwarfRegNum<[86]>; -def D15 : Rd<30, "F30", [F30, F31]>, DwarfRegNum<[87]>; - -// Co-processor registers -def C0 : Ri< 0, "C0">; -def C1 : Ri< 1, "C1">; -def C2 : Ri< 2, "C2">; -def C3 : Ri< 3, "C3">; -def C4 : Ri< 4, "C4">; -def C5 : Ri< 5, "C5">; -def C6 : Ri< 6, "C6">; -def C7 : Ri< 7, "C7">; -def C8 : Ri< 8, "C8">; -def C9 : Ri< 9, "C9">; -def C10 : Ri< 10, "C10">; -def C11 : Ri< 11, "C11">; -def C12 : Ri< 12, "C12">; -def C13 : Ri< 13, "C13">; -def C14 : Ri< 14, "C14">; -def C15 : Ri< 15, "C15">; -def C16 : Ri< 16, "C16">; -def C17 : Ri< 17, "C17">; -def C18 : Ri< 18, "C18">; -def C19 : Ri< 19, "C19">; -def C20 : Ri< 20, "C20">; -def C21 : Ri< 21, "C21">; -def C22 : Ri< 22, "C22">; -def C23 : Ri< 23, "C23">; -def C24 : Ri< 24, "C24">; -def C25 : Ri< 25, "C25">; -def C26 : Ri< 26, "C26">; -def C27 : Ri< 27, "C27">; -def C28 : Ri< 28, "C28">; -def C29 : Ri< 29, "C29">; -def C30 : Ri< 30, "C30">; -def C31 : Ri< 31, "C31">; - -// Unaliased double precision floating point registers. -// FIXME: Define DwarfRegNum for these registers. -def D16 : SparcReg< 1, "F32">; -def D17 : SparcReg< 3, "F34">; -def D18 : SparcReg< 5, "F36">; -def D19 : SparcReg< 7, "F38">; -def D20 : SparcReg< 9, "F40">; -def D21 : SparcReg<11, "F42">; -def D22 : SparcReg<13, "F44">; -def D23 : SparcReg<15, "F46">; -def D24 : SparcReg<17, "F48">; -def D25 : SparcReg<19, "F50">; -def D26 : SparcReg<21, "F52">; -def D27 : SparcReg<23, "F54">; -def D28 : SparcReg<25, "F56">; -def D29 : SparcReg<27, "F58">; -def D30 : SparcReg<29, "F60">; -def D31 : SparcReg<31, "F62">; - -// Aliases of the F* registers used to hold 128-bit for values (long doubles). -def Q0 : Rq< 0, "F0", [D0, D1]>; -def Q1 : Rq< 4, "F4", [D2, D3]>; -def Q2 : Rq< 8, "F8", [D4, D5]>; -def Q3 : Rq<12, "F12", [D6, D7]>; -def Q4 : Rq<16, "F16", [D8, D9]>; -def Q5 : Rq<20, "F20", [D10, D11]>; -def Q6 : Rq<24, "F24", [D12, D13]>; -def Q7 : Rq<28, "F28", [D14, D15]>; -def Q8 : Rq< 1, "F32", [D16, D17]>; -def Q9 : Rq< 5, "F36", [D18, D19]>; -def Q10 : Rq< 9, "F40", [D20, D21]>; -def Q11 : Rq<13, "F44", [D22, D23]>; -def Q12 : Rq<17, "F48", [D24, D25]>; -def Q13 : Rq<21, "F52", [D26, D27]>; -def Q14 : Rq<25, "F56", [D28, D29]>; -def Q15 : Rq<29, "F60", [D30, D31]>; - -// Aliases of the integer registers used for LDD/STD double-word operations -def G0_G1 : Rdi<0, "G0", [G0, G1]>; -def G2_G3 : Rdi<2, "G2", [G2, G3]>; -def G4_G5 : Rdi<4, "G4", [G4, G5]>; -def G6_G7 : Rdi<6, "G6", [G6, G7]>; -def O0_O1 : Rdi<8, "O0", [O0, O1]>; -def O2_O3 : Rdi<10, "O2", [O2, O3]>; -def O4_O5 : Rdi<12, "O4", [O4, O5]>; -def O6_O7 : Rdi<14, "O6", [O6, O7]>; -def L0_L1 : Rdi<16, "L0", [L0, L1]>; -def L2_L3 : Rdi<18, "L2", [L2, L3]>; -def L4_L5 : Rdi<20, "L4", [L4, L5]>; -def L6_L7 : Rdi<22, "L6", [L6, L7]>; -def I0_I1 : Rdi<24, "I0", [I0, I1]>; -def I2_I3 : Rdi<26, "I2", [I2, I3]>; -def I4_I5 : Rdi<28, "I4", [I4, I5]>; -def I6_I7 : Rdi<30, "I6", [I6, I7]>; - -// Aliases of the co-processor registers used for LDD/STD double-word operations -def C0_C1 : Rdi<0, "C0", [C0, C1]>; -def C2_C3 : Rdi<2, "C2", [C2, C3]>; -def C4_C5 : Rdi<4, "C4", [C4, C5]>; -def C6_C7 : Rdi<6, "C6", [C6, C7]>; -def C8_C9 : Rdi<8, "C8", [C8, C9]>; -def C10_C11 : Rdi<10, "C10", [C10, C11]>; -def C12_C13 : Rdi<12, "C12", [C12, C13]>; -def C14_C15 : Rdi<14, "C14", [C14, C15]>; -def C16_C17 : Rdi<16, "C16", [C16, C17]>; -def C18_C19 : Rdi<18, "C18", [C18, C19]>; -def C20_C21 : Rdi<20, "C20", [C20, C21]>; -def C22_C23 : Rdi<22, "C22", [C22, C23]>; -def C24_C25 : Rdi<24, "C24", [C24, C25]>; -def C26_C27 : Rdi<26, "C26", [C26, C27]>; -def C28_C29 : Rdi<28, "C28", [C28, C29]>; -def C30_C31 : Rdi<30, "C30", [C30, C31]>; - -// Register classes. -// -// FIXME: the register order should be defined in terms of the preferred -// allocation order... -// -// This register class should not be used to hold i64 values, use the I64Regs -// register class for that. The i64 type is included here to allow i64 patterns -// using the integer instructions. -def IntRegs : RegisterClass<"SP", [i32, i64], 32, - (add (sequence "I%u", 0, 7), - (sequence "G%u", 0, 7), - (sequence "L%u", 0, 7), - (sequence "O%u", 0, 7))>; - -// Should be in the same order as IntRegs. -def IntPair : RegisterClass<"SP", [v2i32], 64, - (add I0_I1, I2_I3, I4_I5, I6_I7, - G0_G1, G2_G3, G4_G5, G6_G7, - L0_L1, L2_L3, L4_L5, L6_L7, - O0_O1, O2_O3, O4_O5, O6_O7)>; - -// Register class for 64-bit mode, with a 64-bit spill slot size. -// These are the same as the 32-bit registers, so TableGen will consider this -// to be a sub-class of IntRegs. That works out because requiring a 64-bit -// spill slot is a stricter constraint than only requiring a 32-bit spill slot. -def I64Regs : RegisterClass<"SP", [i64], 64, (add IntRegs)>; - -// Floating point register classes. -def FPRegs : RegisterClass<"SP", [f32], 32, (sequence "F%u", 0, 31)>; -def DFPRegs : RegisterClass<"SP", [f64], 64, (sequence "D%u", 0, 31)>; -def QFPRegs : RegisterClass<"SP", [f128], 128, (sequence "Q%u", 0, 15)>; - -// The Low?FPRegs classes are used only for inline-asm constraints. -def LowDFPRegs : RegisterClass<"SP", [f64], 64, (sequence "D%u", 0, 15)>; -def LowQFPRegs : RegisterClass<"SP", [f128], 128, (sequence "Q%u", 0, 7)>; - -// Floating point control register classes. -def FCCRegs : RegisterClass<"SP", [i1], 1, (sequence "FCC%u", 0, 3)>; - -let isAllocatable = 0 in { - // Ancillary state registers - def ASRRegs : RegisterClass<"SP", [i32], 32, - (add Y, (sequence "ASR%u", 1, 31))>; - - // This register class should not be used to hold i64 values. - def CoprocRegs : RegisterClass<"SP", [i32], 32, - (add (sequence "C%u", 0, 31))>; - - // Should be in the same order as CoprocRegs. - def CoprocPair : RegisterClass<"SP", [v2i32], 64, - (add C0_C1, C2_C3, C4_C5, C6_C7, - C8_C9, C10_C11, C12_C13, C14_C15, - C16_C17, C18_C19, C20_C21, C22_C23, - C24_C25, C26_C27, C28_C29, C30_C31)>; -} - -// Privileged Registers -def PRRegs : RegisterClass<"SP", [i64], 64, - (add TPC, TNPC, TSTATE, TT, TICK, TBA, PSTATE, TL, PIL, CWP, - CANSAVE, CANRESTORE, CLEANWIN, OTHERWIN, WSTATE)>; diff --git a/contrib/llvm/lib/Target/Sparc/SparcSchedule.td b/contrib/llvm/lib/Target/Sparc/SparcSchedule.td deleted file mode 100755 index 31e43c9bd95d..000000000000 --- a/contrib/llvm/lib/Target/Sparc/SparcSchedule.td +++ /dev/null @@ -1,123 +0,0 @@ -//===-- SparcSchedule.td - Describe the Sparc Itineries ----*- 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 IIC_iu_or_fpu_instr : InstrItinClass; -def IIC_iu_instr : InstrItinClass; -def IIC_fpu_normal_instr : InstrItinClass; -def IIC_fpu_fast_instr : InstrItinClass; -def IIC_jmp_or_call : InstrItinClass; -def IIC_ldd : InstrItinClass; -def IIC_st : InstrItinClass; -def IIC_std : InstrItinClass; -def IIC_iu_smul : InstrItinClass; -def IIC_iu_umul : InstrItinClass; -def IIC_iu_div : InstrItinClass; -def IIC_ticc : InstrItinClass; -def IIC_ldstub : InstrItinClass; -def IIC_fpu_muls : InstrItinClass; -def IIC_fpu_muld : InstrItinClass; -def IIC_fpu_divs : InstrItinClass; -def IIC_fpu_divd : InstrItinClass; -def IIC_fpu_sqrts : InstrItinClass; -def IIC_fpu_sqrtd : InstrItinClass; -def IIC_fpu_abs : InstrItinClass; -def IIC_fpu_movs : InstrItinClass; -def IIC_fpu_negs : InstrItinClass; -def IIC_smac_umac : InstrItinClass; -def IIC_fpu_stod : InstrItinClass; - -def LEONIU : FuncUnit; // integer unit -def LEONFPU : FuncUnit; // floating-point unit - -// Ref: http://www.atmel.com/Images/doc4226.pdf - -def LEON2Itineraries : ProcessorItineraries< -[LEONIU, LEONFPU], [], [ - InstrItinData], [1, 1]>, - InstrItinData], [1, 1]>, - InstrItinData], [7, 1]>, - InstrItinData], [7, 1]>, - InstrItinData], [2, 1]>, - InstrItinData], [2, 1]>, - InstrItinData], [2, 1]>, - InstrItinData], [3, 1]>, - InstrItinData], [5, 1]>, - InstrItinData], [5, 1]>, - InstrItinData], [35, 1]>, - InstrItinData], [4, 1]>, - InstrItinData], [3, 1]>, - InstrItinData], [16, 1]>, - InstrItinData], [21, 1]>, - InstrItinData], [20, 1]>, - InstrItinData], [36, 1]>, - InstrItinData], [37, 1]>, - InstrItinData], [65, 1]>, - InstrItinData], [2, 1]>, - InstrItinData], [2, 1]>, - InstrItinData], [2, 1]>, - InstrItinData], [2, 1]> -]>; - -def LEON3Itineraries : ProcessorItineraries< -[LEONIU, LEONFPU], [], [ - InstrItinData], [1, 1]>, - InstrItinData], [1, 1]>, - InstrItinData], [7, 1]>, - InstrItinData], [4, 1]>, - InstrItinData], [3, 1]>, - InstrItinData], [2, 1]>, - InstrItinData], [4, 1]>, - InstrItinData], [5, 1]>, - InstrItinData], [1, 1]>, - InstrItinData], [4, 1]>, - InstrItinData], [35, 1]>, - InstrItinData], [2, 1]>, - InstrItinData], [5, 1]>, - InstrItinData], [3, 1]>, - InstrItinData], [4, 1]>, - InstrItinData], [4, 1]>, - InstrItinData], [16, 1]>, - InstrItinData], [17, 1]>, - InstrItinData], [24, 1]>, - InstrItinData], [25, 1]>, - InstrItinData], [2, 1]>, - InstrItinData], [2, 1]>, - InstrItinData], [2, 1]>, - InstrItinData], [4, 1]> -]>; - -def LEON4Itineraries : ProcessorItineraries< -[LEONIU, LEONFPU], [], [ - InstrItinData], [1, 1]>, - InstrItinData], [1, 1]>, - InstrItinData], [7, 1]>, - InstrItinData], [4, 1]>, - InstrItinData], [3, 1]>, - InstrItinData], [1, 1]>, - InstrItinData], [1, 1]>, - InstrItinData], [1, 1]>, - InstrItinData], [1, 1]>, - InstrItinData], [4, 1]>, - InstrItinData], [35, 1]>, - InstrItinData], [2, 1]>, - InstrItinData], [5, 1]>, - InstrItinData], [3, 1]>, - InstrItinData], [4, 1]>, - InstrItinData], [4, 1]>, - InstrItinData], [16, 1]>, - InstrItinData], [17, 1]>, - InstrItinData], [24, 1]>, - InstrItinData], [25, 1]>, - InstrItinData], [2, 1]>, - InstrItinData], [2, 1]>, - InstrItinData], [2, 1]>, - InstrItinData], [4, 1]> -]>; diff --git a/contrib/llvm/lib/Target/Sparc/SparcSubtarget.cpp b/contrib/llvm/lib/Target/Sparc/SparcSubtarget.cpp deleted file mode 100644 index 075a002a358d..000000000000 --- a/contrib/llvm/lib/Target/Sparc/SparcSubtarget.cpp +++ /dev/null @@ -1,102 +0,0 @@ -//===-- SparcSubtarget.cpp - SPARC 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 SPARC specific subclass of TargetSubtargetInfo. -// -//===----------------------------------------------------------------------===// - -#include "SparcSubtarget.h" -#include "Sparc.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/TargetRegistry.h" - -using namespace llvm; - -#define DEBUG_TYPE "sparc-subtarget" - -#define GET_SUBTARGETINFO_TARGET_DESC -#define GET_SUBTARGETINFO_CTOR -#include "SparcGenSubtargetInfo.inc" - -void SparcSubtarget::anchor() { } - -SparcSubtarget &SparcSubtarget::initializeSubtargetDependencies(StringRef CPU, - StringRef FS) { - UseSoftMulDiv = false; - IsV9 = false; - IsLeon = false; - V8DeprecatedInsts = false; - IsVIS = false; - IsVIS2 = false; - IsVIS3 = false; - HasHardQuad = false; - UsePopc = false; - UseSoftFloat = false; - HasNoFSMULD = false; - HasNoFMULS = false; - - // Leon features - HasLeonCasa = false; - HasUmacSmac = false; - HasPWRPSR = false; - InsertNOPLoad = false; - FixAllFDIVSQRT = false; - DetectRoundChange = false; - HasLeonCycleCounter = false; - - // Determine default and user specified characteristics - std::string CPUName = CPU; - if (CPUName.empty()) - CPUName = (Is64Bit) ? "v9" : "v8"; - - // Parse features string. - ParseSubtargetFeatures(CPUName, FS); - - // Popc is a v9-only instruction. - if (!IsV9) - UsePopc = false; - - return *this; -} - -SparcSubtarget::SparcSubtarget(const Triple &TT, const std::string &CPU, - const std::string &FS, const TargetMachine &TM, - bool is64Bit) - : SparcGenSubtargetInfo(TT, CPU, FS), TargetTriple(TT), Is64Bit(is64Bit), - InstrInfo(initializeSubtargetDependencies(CPU, FS)), TLInfo(TM, *this), - FrameLowering(*this) {} - -int SparcSubtarget::getAdjustedFrameSize(int frameSize) const { - - if (is64Bit()) { - // All 64-bit stack frames must be 16-byte aligned, and must reserve space - // for spilling the 16 window registers at %sp+BIAS..%sp+BIAS+128. - frameSize += 128; - // Frames with calls must also reserve space for 6 outgoing arguments - // whether they are used or not. LowerCall_64 takes care of that. - frameSize = alignTo(frameSize, 16); - } else { - // Emit the correct save instruction based on the number of bytes in - // the frame. Minimum stack frame size according to V8 ABI is: - // 16 words for register window spill - // 1 word for address of returned aggregate-value - // + 6 words for passing parameters on the stack - // ---------- - // 23 words * 4 bytes per word = 92 bytes - frameSize += 92; - - // Round up to next doubleword boundary -- a double-word boundary - // is required by the ABI. - frameSize = alignTo(frameSize, 8); - } - return frameSize; -} - -bool SparcSubtarget::enableMachineScheduler() const { - return true; -} diff --git a/contrib/llvm/lib/Target/Sparc/SparcSubtarget.h b/contrib/llvm/lib/Target/Sparc/SparcSubtarget.h deleted file mode 100644 index db19f99e3c9c..000000000000 --- a/contrib/llvm/lib/Target/Sparc/SparcSubtarget.h +++ /dev/null @@ -1,125 +0,0 @@ -//===-- SparcSubtarget.h - Define Subtarget for the SPARC -------*- 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 SPARC specific subclass of TargetSubtargetInfo. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_SPARC_SPARCSUBTARGET_H -#define LLVM_LIB_TARGET_SPARC_SPARCSUBTARGET_H - -#include "SparcFrameLowering.h" -#include "SparcISelLowering.h" -#include "SparcInstrInfo.h" -#include "llvm/CodeGen/SelectionDAGTargetInfo.h" -#include "llvm/CodeGen/TargetFrameLowering.h" -#include "llvm/CodeGen/TargetSubtargetInfo.h" -#include "llvm/IR/DataLayout.h" -#include - -#define GET_SUBTARGETINFO_HEADER -#include "SparcGenSubtargetInfo.inc" - -namespace llvm { -class StringRef; - -class SparcSubtarget : public SparcGenSubtargetInfo { - Triple TargetTriple; - virtual void anchor(); - bool UseSoftMulDiv; - bool IsV9; - bool IsLeon; - bool V8DeprecatedInsts; - bool IsVIS, IsVIS2, IsVIS3; - bool Is64Bit; - bool HasHardQuad; - bool UsePopc; - bool UseSoftFloat; - bool HasNoFSMULD; - bool HasNoFMULS; - - // LEON features - bool HasUmacSmac; - bool HasLeonCasa; - bool HasPWRPSR; - bool InsertNOPLoad; - bool FixAllFDIVSQRT; - bool DetectRoundChange; - bool HasLeonCycleCounter; - - SparcInstrInfo InstrInfo; - SparcTargetLowering TLInfo; - SelectionDAGTargetInfo TSInfo; - SparcFrameLowering FrameLowering; - -public: - SparcSubtarget(const Triple &TT, const std::string &CPU, - const std::string &FS, const TargetMachine &TM, bool is64bit); - - const SparcInstrInfo *getInstrInfo() const override { return &InstrInfo; } - const TargetFrameLowering *getFrameLowering() const override { - return &FrameLowering; - } - const SparcRegisterInfo *getRegisterInfo() const override { - return &InstrInfo.getRegisterInfo(); - } - const SparcTargetLowering *getTargetLowering() const override { - return &TLInfo; - } - const SelectionDAGTargetInfo *getSelectionDAGInfo() const override { - return &TSInfo; - } - - bool enableMachineScheduler() const override; - - bool useSoftMulDiv() const { return UseSoftMulDiv; } - bool isV9() const { return IsV9; } - bool isLeon() const { return IsLeon; } - bool isVIS() const { return IsVIS; } - bool isVIS2() const { return IsVIS2; } - bool isVIS3() const { return IsVIS3; } - bool useDeprecatedV8Instructions() const { return V8DeprecatedInsts; } - bool hasHardQuad() const { return HasHardQuad; } - bool usePopc() const { return UsePopc; } - bool useSoftFloat() const { return UseSoftFloat; } - bool hasNoFSMULD() const { return HasNoFSMULD; } - bool hasNoFMULS() const { return HasNoFMULS; } - - // Leon options - bool hasUmacSmac() const { return HasUmacSmac; } - bool hasLeonCasa() const { return HasLeonCasa; } - bool hasPWRPSR() const { return HasPWRPSR; } - bool insertNOPLoad() const { return InsertNOPLoad; } - bool fixAllFDIVSQRT() const { return FixAllFDIVSQRT; } - bool detectRoundChange() const { return DetectRoundChange; } - bool hasLeonCycleCounter() const { return HasLeonCycleCounter; } - - /// ParseSubtargetFeatures - Parses features string setting specified - /// subtarget options. Definition of function is auto generated by tblgen. - void ParseSubtargetFeatures(StringRef CPU, StringRef FS); - SparcSubtarget &initializeSubtargetDependencies(StringRef CPU, StringRef FS); - - bool is64Bit() const { return Is64Bit; } - - /// The 64-bit ABI uses biased stack and frame pointers, so the stack frame - /// of the current function is the area from [%sp+BIAS] to [%fp+BIAS]. - int64_t getStackPointerBias() const { - return is64Bit() ? 2047 : 0; - } - - /// Given a actual stack size as determined by FrameInfo, this function - /// returns adjusted framesize which includes space for register window - /// spills and arguments. - int getAdjustedFrameSize(int stackSize) const; - - bool isTargetLinux() const { return TargetTriple.isOSLinux(); } -}; - -} // end namespace llvm - -#endif diff --git a/contrib/llvm/lib/Target/Sparc/SparcTargetMachine.cpp b/contrib/llvm/lib/Target/Sparc/SparcTargetMachine.cpp deleted file mode 100644 index 195cff79de03..000000000000 --- a/contrib/llvm/lib/Target/Sparc/SparcTargetMachine.cpp +++ /dev/null @@ -1,218 +0,0 @@ -//===-- SparcTargetMachine.cpp - Define TargetMachine for Sparc -----------===// -// -// Part of the LLVM Project, under the Apache 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 "SparcTargetMachine.h" -#include "LeonPasses.h" -#include "Sparc.h" -#include "SparcTargetObjectFile.h" -#include "TargetInfo/SparcTargetInfo.h" -#include "llvm/CodeGen/Passes.h" -#include "llvm/CodeGen/TargetPassConfig.h" -#include "llvm/IR/LegacyPassManager.h" -#include "llvm/Support/TargetRegistry.h" -using namespace llvm; - -extern "C" void LLVMInitializeSparcTarget() { - // Register the target. - RegisterTargetMachine X(getTheSparcTarget()); - RegisterTargetMachine Y(getTheSparcV9Target()); - RegisterTargetMachine Z(getTheSparcelTarget()); -} - -static std::string computeDataLayout(const Triple &T, bool is64Bit) { - // Sparc is typically big endian, but some are little. - std::string Ret = T.getArch() == Triple::sparcel ? "e" : "E"; - Ret += "-m:e"; - - // Some ABIs have 32bit pointers. - if (!is64Bit) - Ret += "-p:32:32"; - - // Alignments for 64 bit integers. - Ret += "-i64:64"; - - // On SparcV9 128 floats are aligned to 128 bits, on others only to 64. - // On SparcV9 registers can hold 64 or 32 bits, on others only 32. - if (is64Bit) - Ret += "-n32:64"; - else - Ret += "-f128:64-n32"; - - if (is64Bit) - Ret += "-S128"; - else - Ret += "-S64"; - - return Ret; -} - -static Reloc::Model getEffectiveRelocModel(Optional RM) { - if (!RM.hasValue()) - return Reloc::Static; - return *RM; -} - -// Code models. Some only make sense for 64-bit code. -// -// SunCC Reloc CodeModel Constraints -// abs32 Static Small text+data+bss linked below 2^32 bytes -// abs44 Static Medium text+data+bss linked below 2^44 bytes -// abs64 Static Large text smaller than 2^31 bytes -// pic13 PIC_ Small GOT < 2^13 bytes -// pic32 PIC_ Medium GOT < 2^32 bytes -// -// All code models require that the text segment is smaller than 2GB. -static CodeModel::Model -getEffectiveSparcCodeModel(Optional CM, Reloc::Model RM, - bool Is64Bit, bool JIT) { - if (CM) { - if (*CM == CodeModel::Tiny) - report_fatal_error("Target does not support the tiny CodeModel", false); - if (*CM == CodeModel::Kernel) - report_fatal_error("Target does not support the kernel CodeModel", false); - return *CM; - } - if (Is64Bit) { - if (JIT) - return CodeModel::Large; - return RM == Reloc::PIC_ ? CodeModel::Small : CodeModel::Medium; - } - return CodeModel::Small; -} - -/// Create an ILP32 architecture model -SparcTargetMachine::SparcTargetMachine( - const Target &T, const Triple &TT, StringRef CPU, StringRef FS, - const TargetOptions &Options, Optional RM, - Optional CM, CodeGenOpt::Level OL, bool JIT, bool is64bit) - : LLVMTargetMachine(T, computeDataLayout(TT, is64bit), TT, CPU, FS, Options, - getEffectiveRelocModel(RM), - getEffectiveSparcCodeModel( - CM, getEffectiveRelocModel(RM), is64bit, JIT), - OL), - TLOF(make_unique()), - Subtarget(TT, CPU, FS, *this, is64bit), is64Bit(is64bit) { - initAsmInfo(); -} - -SparcTargetMachine::~SparcTargetMachine() {} - -const SparcSubtarget * -SparcTargetMachine::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; - - // 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 (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(TargetTriple, CPU, FS, *this, - this->is64Bit); - } - return I.get(); -} - -namespace { -/// Sparc Code Generator Pass Configuration Options. -class SparcPassConfig : public TargetPassConfig { -public: - SparcPassConfig(SparcTargetMachine &TM, PassManagerBase &PM) - : TargetPassConfig(TM, PM) {} - - SparcTargetMachine &getSparcTargetMachine() const { - return getTM(); - } - - void addIRPasses() override; - bool addInstSelector() override; - void addPreEmitPass() override; -}; -} // namespace - -TargetPassConfig *SparcTargetMachine::createPassConfig(PassManagerBase &PM) { - return new SparcPassConfig(*this, PM); -} - -void SparcPassConfig::addIRPasses() { - addPass(createAtomicExpandPass()); - - TargetPassConfig::addIRPasses(); -} - -bool SparcPassConfig::addInstSelector() { - addPass(createSparcISelDag(getSparcTargetMachine())); - return false; -} - -void SparcPassConfig::addPreEmitPass(){ - addPass(createSparcDelaySlotFillerPass()); - - if (this->getSparcTargetMachine().getSubtargetImpl()->insertNOPLoad()) - { - addPass(new InsertNOPLoad()); - } - if (this->getSparcTargetMachine().getSubtargetImpl()->detectRoundChange()) { - addPass(new DetectRoundChange()); - } - if (this->getSparcTargetMachine().getSubtargetImpl()->fixAllFDIVSQRT()) - { - addPass(new FixAllFDIVSQRT()); - } -} - -void SparcV8TargetMachine::anchor() { } - -SparcV8TargetMachine::SparcV8TargetMachine(const Target &T, const Triple &TT, - StringRef CPU, StringRef FS, - const TargetOptions &Options, - Optional RM, - Optional CM, - CodeGenOpt::Level OL, bool JIT) - : SparcTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, JIT, false) {} - -void SparcV9TargetMachine::anchor() { } - -SparcV9TargetMachine::SparcV9TargetMachine(const Target &T, const Triple &TT, - StringRef CPU, StringRef FS, - const TargetOptions &Options, - Optional RM, - Optional CM, - CodeGenOpt::Level OL, bool JIT) - : SparcTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, JIT, true) {} - -void SparcelTargetMachine::anchor() {} - -SparcelTargetMachine::SparcelTargetMachine(const Target &T, const Triple &TT, - StringRef CPU, StringRef FS, - const TargetOptions &Options, - Optional RM, - Optional CM, - CodeGenOpt::Level OL, bool JIT) - : SparcTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, JIT, false) {} diff --git a/contrib/llvm/lib/Target/Sparc/SparcTargetMachine.h b/contrib/llvm/lib/Target/Sparc/SparcTargetMachine.h deleted file mode 100644 index 4083f61433b1..000000000000 --- a/contrib/llvm/lib/Target/Sparc/SparcTargetMachine.h +++ /dev/null @@ -1,78 +0,0 @@ -//===-- SparcTargetMachine.h - Define TargetMachine for Sparc ---*- 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 Sparc specific subclass of TargetMachine. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_SPARC_SPARCTARGETMACHINE_H -#define LLVM_LIB_TARGET_SPARC_SPARCTARGETMACHINE_H - -#include "SparcInstrInfo.h" -#include "SparcSubtarget.h" -#include "llvm/Target/TargetMachine.h" - -namespace llvm { - -class SparcTargetMachine : public LLVMTargetMachine { - std::unique_ptr TLOF; - SparcSubtarget Subtarget; - bool is64Bit; - mutable StringMap> SubtargetMap; -public: - SparcTargetMachine(const Target &T, const Triple &TT, StringRef CPU, - StringRef FS, const TargetOptions &Options, - Optional RM, Optional CM, - CodeGenOpt::Level OL, bool JIT, bool is64bit); - ~SparcTargetMachine() override; - - const SparcSubtarget *getSubtargetImpl() const { return &Subtarget; } - const SparcSubtarget *getSubtargetImpl(const Function &) const override; - - // Pass Pipeline Configuration - TargetPassConfig *createPassConfig(PassManagerBase &PM) override; - TargetLoweringObjectFile *getObjFileLowering() const override { - return TLOF.get(); - } -}; - -/// Sparc 32-bit target machine -/// -class SparcV8TargetMachine : public SparcTargetMachine { - virtual void anchor(); -public: - SparcV8TargetMachine(const Target &T, const Triple &TT, StringRef CPU, - StringRef FS, const TargetOptions &Options, - Optional RM, Optional CM, - CodeGenOpt::Level OL, bool JIT); -}; - -/// Sparc 64-bit target machine -/// -class SparcV9TargetMachine : public SparcTargetMachine { - virtual void anchor(); -public: - SparcV9TargetMachine(const Target &T, const Triple &TT, StringRef CPU, - StringRef FS, const TargetOptions &Options, - Optional RM, Optional CM, - CodeGenOpt::Level OL, bool JIT); -}; - -class SparcelTargetMachine : public SparcTargetMachine { - virtual void anchor(); - -public: - SparcelTargetMachine(const Target &T, const Triple &TT, StringRef CPU, - StringRef FS, const TargetOptions &Options, - Optional RM, Optional CM, - CodeGenOpt::Level OL, bool JIT); -}; - -} // end namespace llvm - -#endif diff --git a/contrib/llvm/lib/Target/Sparc/SparcTargetObjectFile.cpp b/contrib/llvm/lib/Target/Sparc/SparcTargetObjectFile.cpp deleted file mode 100644 index e6ad4d2d67aa..000000000000 --- a/contrib/llvm/lib/Target/Sparc/SparcTargetObjectFile.cpp +++ /dev/null @@ -1,47 +0,0 @@ -//===------- SparcTargetObjectFile.cpp - Sparc Object Info Impl -----------===// -// -// Part of the LLVM Project, under the Apache 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 "SparcTargetObjectFile.h" -#include "MCTargetDesc/SparcMCExpr.h" -#include "llvm/BinaryFormat/Dwarf.h" -#include "llvm/CodeGen/MachineModuleInfoImpls.h" -#include "llvm/CodeGen/TargetLowering.h" - -using namespace llvm; - -void SparcELFTargetObjectFile::Initialize(MCContext &Ctx, - const TargetMachine &TM) { - TargetLoweringObjectFileELF::Initialize(Ctx, TM); - InitializeELF(TM.Options.UseInitArray); -} - -const MCExpr *SparcELFTargetObjectFile::getTTypeGlobalReference( - const GlobalValue *GV, unsigned Encoding, const TargetMachine &TM, - MachineModuleInfo *MMI, MCStreamer &Streamer) const { - - if (Encoding & dwarf::DW_EH_PE_pcrel) { - MachineModuleInfoELF &ELFMMI = MMI->getObjFileInfo(); - - MCSymbol *SSym = getSymbolWithGlobalValueBase(GV, ".DW.stub", TM); - - // Add information about the stub reference to ELFMMI so that the stub - // gets emitted by the asmprinter. - MachineModuleInfoImpl::StubValueTy &StubSym = ELFMMI.getGVStubEntry(SSym); - if (!StubSym.getPointer()) { - MCSymbol *Sym = TM.getSymbol(GV); - StubSym = MachineModuleInfoImpl::StubValueTy(Sym, !GV->hasLocalLinkage()); - } - - MCContext &Ctx = getContext(); - return SparcMCExpr::create(SparcMCExpr::VK_Sparc_R_DISP32, - MCSymbolRefExpr::create(SSym, Ctx), Ctx); - } - - return TargetLoweringObjectFileELF::getTTypeGlobalReference(GV, Encoding, TM, - MMI, Streamer); -} diff --git a/contrib/llvm/lib/Target/Sparc/SparcTargetObjectFile.h b/contrib/llvm/lib/Target/Sparc/SparcTargetObjectFile.h deleted file mode 100644 index 9bbe602b32b3..000000000000 --- a/contrib/llvm/lib/Target/Sparc/SparcTargetObjectFile.h +++ /dev/null @@ -1,36 +0,0 @@ -//===-- SparcTargetObjectFile.h - Sparc 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_SPARC_SPARCTARGETOBJECTFILE_H -#define LLVM_LIB_TARGET_SPARC_SPARCTARGETOBJECTFILE_H - -#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" - -namespace llvm { - -class MCContext; -class TargetMachine; - -class SparcELFTargetObjectFile : public TargetLoweringObjectFileELF { -public: - SparcELFTargetObjectFile() : - TargetLoweringObjectFileELF() - {} - - void Initialize(MCContext &Ctx, const TargetMachine &TM) override; - - const MCExpr *getTTypeGlobalReference(const GlobalValue *GV, - unsigned Encoding, - const TargetMachine &TM, - MachineModuleInfo *MMI, - MCStreamer &Streamer) const override; -}; - -} // end namespace llvm - -#endif diff --git a/contrib/llvm/lib/Target/Sparc/TargetInfo/SparcTargetInfo.cpp b/contrib/llvm/lib/Target/Sparc/TargetInfo/SparcTargetInfo.cpp deleted file mode 100644 index eafa2b4b2f13..000000000000 --- a/contrib/llvm/lib/Target/Sparc/TargetInfo/SparcTargetInfo.cpp +++ /dev/null @@ -1,33 +0,0 @@ -//===-- SparcTargetInfo.cpp - Sparc 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/SparcTargetInfo.h" -#include "llvm/Support/TargetRegistry.h" -using namespace llvm; - -Target &llvm::getTheSparcTarget() { - static Target TheSparcTarget; - return TheSparcTarget; -} -Target &llvm::getTheSparcV9Target() { - static Target TheSparcV9Target; - return TheSparcV9Target; -} -Target &llvm::getTheSparcelTarget() { - static Target TheSparcelTarget; - return TheSparcelTarget; -} - -extern "C" void LLVMInitializeSparcTargetInfo() { - RegisterTarget X(getTheSparcTarget(), "sparc", - "Sparc", "Sparc"); - RegisterTarget Y( - getTheSparcV9Target(), "sparcv9", "Sparc V9", "Sparc"); - RegisterTarget Z( - getTheSparcelTarget(), "sparcel", "Sparc LE", "Sparc"); -} diff --git a/contrib/llvm/lib/Target/Sparc/TargetInfo/SparcTargetInfo.h b/contrib/llvm/lib/Target/Sparc/TargetInfo/SparcTargetInfo.h deleted file mode 100644 index e02ff59fdac3..000000000000 --- a/contrib/llvm/lib/Target/Sparc/TargetInfo/SparcTargetInfo.h +++ /dev/null @@ -1,22 +0,0 @@ -//===-- SparcTargetInfo.h - Sparc 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_SPARC_TARGETINFO_SPARCTARGETINFO_H -#define LLVM_LIB_TARGET_SPARC_TARGETINFO_SPARCTARGETINFO_H - -namespace llvm { - -class Target; - -Target &getTheSparcTarget(); -Target &getTheSparcV9Target(); -Target &getTheSparcelTarget(); - -} // namespace llvm - -#endif // LLVM_LIB_TARGET_SPARC_TARGETINFO_SPARCTARGETINFO_H -- cgit v1.2.3