diff options
Diffstat (limited to 'lib/Target/Mips')
48 files changed, 3475 insertions, 1542 deletions
diff --git a/lib/Target/Mips/AsmParser/CMakeLists.txt b/lib/Target/Mips/AsmParser/CMakeLists.txt index ac21c25..6c7343b 100644 --- a/lib/Target/Mips/AsmParser/CMakeLists.txt +++ b/lib/Target/Mips/AsmParser/CMakeLists.txt @@ -1,6 +1,5 @@ -include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. ) - add_llvm_library(LLVMMipsAsmParser MipsAsmParser.cpp ) +add_dependencies(LLVMMipsAsmParser MipsCommonTableGen) diff --git a/lib/Target/Mips/CMakeLists.txt b/lib/Target/Mips/CMakeLists.txt index 0500c5d..e9a228c 100644 --- a/lib/Target/Mips/CMakeLists.txt +++ b/lib/Target/Mips/CMakeLists.txt @@ -17,13 +17,12 @@ add_llvm_target(MipsCodeGen MipsAsmPrinter.cpp MipsCodeEmitter.cpp MipsDelaySlotFiller.cpp - MipsEmitGPRestore.cpp - MipsExpandPseudo.cpp MipsJITInfo.cpp MipsInstrInfo.cpp MipsISelDAGToDAG.cpp MipsISelLowering.cpp MipsFrameLowering.cpp + MipsLongBranch.cpp MipsMCInstLower.cpp MipsMachineFunction.cpp MipsRegisterInfo.cpp @@ -33,6 +32,8 @@ add_llvm_target(MipsCodeGen MipsSelectionDAGInfo.cpp ) +add_dependencies(LLVMMipsCodeGen intrinsics_gen) + add_subdirectory(InstPrinter) add_subdirectory(Disassembler) add_subdirectory(TargetInfo) diff --git a/lib/Target/Mips/Disassembler/MipsDisassembler.cpp b/lib/Target/Mips/Disassembler/MipsDisassembler.cpp index 78dbc06..042b456 100644 --- a/lib/Target/Mips/Disassembler/MipsDisassembler.cpp +++ b/lib/Target/Mips/Disassembler/MipsDisassembler.cpp @@ -13,136 +13,87 @@ #include "Mips.h" #include "MipsSubtarget.h" +#include "MipsRegisterInfo.h" #include "llvm/MC/EDInstInfo.h" #include "llvm/MC/MCDisassembler.h" #include "llvm/Support/MemoryObject.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCInst.h" -#include "llvm/MC/MCRegisterInfo.h" #include "llvm/Support/MathExtras.h" - #include "MipsGenEDInfo.inc" using namespace llvm; typedef MCDisassembler::DecodeStatus DecodeStatus; -/// MipsDisassembler - a disasembler class for Mips32. -class MipsDisassembler : public MCDisassembler { +namespace { + +/// MipsDisassemblerBase - a disasembler class for Mips. +class MipsDisassemblerBase : public MCDisassembler { public: /// Constructor - Initializes the disassembler. /// - MipsDisassembler(const MCSubtargetInfo &STI, bool bigEndian) : - MCDisassembler(STI), isBigEndian(bigEndian) { - } - - ~MipsDisassembler() { - } + MipsDisassemblerBase(const MCSubtargetInfo &STI, const MCRegisterInfo *Info, + bool bigEndian) : + MCDisassembler(STI), RegInfo(Info), isBigEndian(bigEndian) {} - /// getInstruction - See MCDisassembler. - DecodeStatus getInstruction(MCInst &instr, - uint64_t &size, - const MemoryObject ®ion, - uint64_t address, - raw_ostream &vStream, - raw_ostream &cStream) const; + virtual ~MipsDisassemblerBase() {} /// getEDInfo - See MCDisassembler. const EDInstInfo *getEDInfo() const; + const MCRegisterInfo *getRegInfo() const { return RegInfo; } + private: + const MCRegisterInfo *RegInfo; +protected: bool isBigEndian; }; - -/// Mips64Disassembler - a disasembler class for Mips64. -class Mips64Disassembler : public MCDisassembler { +/// MipsDisassembler - a disasembler class for Mips32. +class MipsDisassembler : public MipsDisassemblerBase { public: /// Constructor - Initializes the disassembler. /// - Mips64Disassembler(const MCSubtargetInfo &STI, bool bigEndian) : - MCDisassembler(STI), isBigEndian(bigEndian) { - } - - ~Mips64Disassembler() { - } + MipsDisassembler(const MCSubtargetInfo &STI, const MCRegisterInfo *Info, + bool bigEndian) : + MipsDisassemblerBase(STI, Info, bigEndian) {} /// getInstruction - See MCDisassembler. - DecodeStatus getInstruction(MCInst &instr, - uint64_t &size, - const MemoryObject ®ion, - uint64_t address, - raw_ostream &vStream, - raw_ostream &cStream) const; - - /// getEDInfo - See MCDisassembler. - const EDInstInfo *getEDInfo() const; - -private: - bool isBigEndian; + virtual DecodeStatus getInstruction(MCInst &instr, + uint64_t &size, + const MemoryObject ®ion, + uint64_t address, + raw_ostream &vStream, + raw_ostream &cStream) const; }; -const EDInstInfo *MipsDisassembler::getEDInfo() const { - return instInfoMips; -} - -const EDInstInfo *Mips64Disassembler::getEDInfo() const { - return instInfoMips; -} - -// Decoder tables for Mips register -static const unsigned CPURegsTable[] = { - Mips::ZERO, Mips::AT, Mips::V0, Mips::V1, - Mips::A0, Mips::A1, Mips::A2, Mips::A3, - Mips::T0, Mips::T1, Mips::T2, Mips::T3, - Mips::T4, Mips::T5, Mips::T6, Mips::T7, - Mips::S0, Mips::S1, Mips::S2, Mips::S3, - Mips::S4, Mips::S5, Mips::S6, Mips::S7, - Mips::T8, Mips::T9, Mips::K0, Mips::K1, - Mips::GP, Mips::SP, Mips::FP, Mips::RA -}; -static const unsigned FGR32RegsTable[] = { - Mips::F0, Mips::F1, Mips::F2, Mips::F3, - Mips::F4, Mips::F5, Mips::F6, Mips::F7, - Mips::F8, Mips::F9, Mips::F10, Mips::F11, - Mips::F12, Mips::F13, Mips::F14, Mips::F15, - Mips::F16, Mips::F17, Mips::F18, Mips::F18, - Mips::F20, Mips::F21, Mips::F22, Mips::F23, - Mips::F24, Mips::F25, Mips::F26, Mips::F27, - Mips::F28, Mips::F29, Mips::F30, Mips::F31 -}; +/// Mips64Disassembler - a disasembler class for Mips64. +class Mips64Disassembler : public MipsDisassemblerBase { +public: + /// Constructor - Initializes the disassembler. + /// + Mips64Disassembler(const MCSubtargetInfo &STI, const MCRegisterInfo *Info, + bool bigEndian) : + MipsDisassemblerBase(STI, Info, bigEndian) {} -static const unsigned CPU64RegsTable[] = { - Mips::ZERO_64, Mips::AT_64, Mips::V0_64, Mips::V1_64, - Mips::A0_64, Mips::A1_64, Mips::A2_64, Mips::A3_64, - Mips::T0_64, Mips::T1_64, Mips::T2_64, Mips::T3_64, - Mips::T4_64, Mips::T5_64, Mips::T6_64, Mips::T7_64, - Mips::S0_64, Mips::S1_64, Mips::S2_64, Mips::S3_64, - Mips::S4_64, Mips::S5_64, Mips::S6_64, Mips::S7_64, - Mips::T8_64, Mips::T9_64, Mips::K0_64, Mips::K1_64, - Mips::GP_64, Mips::SP_64, Mips::FP_64, Mips::RA_64 + /// getInstruction - See MCDisassembler. + virtual DecodeStatus getInstruction(MCInst &instr, + uint64_t &size, + const MemoryObject ®ion, + uint64_t address, + raw_ostream &vStream, + raw_ostream &cStream) const; }; -static const unsigned FGR64RegsTable[] = { - Mips::D0_64, Mips::D1_64, Mips::D2_64, Mips::D3_64, - Mips::D4_64, Mips::D5_64, Mips::D6_64, Mips::D7_64, - Mips::D8_64, Mips::D9_64, Mips::D10_64, Mips::D11_64, - Mips::D12_64, Mips::D13_64, Mips::D14_64, Mips::D15_64, - Mips::D16_64, Mips::D17_64, Mips::D18_64, Mips::D19_64, - Mips::D20_64, Mips::D21_64, Mips::D22_64, Mips::D23_64, - Mips::D24_64, Mips::D25_64, Mips::D26_64, Mips::D27_64, - Mips::D28_64, Mips::D29_64, Mips::D30_64, Mips::D31_64 -}; +} // end anonymous namespace -static const unsigned AFGR64RegsTable[] = { - Mips::D0, Mips::D1, Mips::D2, Mips::D3, - Mips::D4, Mips::D5, Mips::D6, Mips::D7, - Mips::D8, Mips::D9, Mips::D10, Mips::D11, - Mips::D12, Mips::D13, Mips::D14, Mips::D15 -}; +const EDInstInfo *MipsDisassemblerBase::getEDInfo() const { + return instInfoMips; +} // Forward declare these because the autogenerated code will reference them. // Definitions are further down. @@ -239,25 +190,25 @@ extern Target TheMipselTarget, TheMipsTarget, TheMips64Target, static MCDisassembler *createMipsDisassembler( const Target &T, const MCSubtargetInfo &STI) { - return new MipsDisassembler(STI,true); + return new MipsDisassembler(STI, T.createMCRegInfo(""), true); } static MCDisassembler *createMipselDisassembler( const Target &T, const MCSubtargetInfo &STI) { - return new MipsDisassembler(STI,false); + return new MipsDisassembler(STI, T.createMCRegInfo(""), false); } static MCDisassembler *createMips64Disassembler( const Target &T, const MCSubtargetInfo &STI) { - return new Mips64Disassembler(STI,true); + return new Mips64Disassembler(STI, T.createMCRegInfo(""), true); } static MCDisassembler *createMips64elDisassembler( const Target &T, const MCSubtargetInfo &STI) { - return new Mips64Disassembler(STI, false); + return new Mips64Disassembler(STI, T.createMCRegInfo(""), false); } extern "C" void LLVMInitializeMipsDisassembler() { @@ -362,6 +313,11 @@ Mips64Disassembler::getInstruction(MCInst &instr, return MCDisassembler::Fail; } +static unsigned getReg(const void *D, unsigned RC, unsigned RegNo) { + const MipsDisassemblerBase *Dis = static_cast<const MipsDisassemblerBase*>(D); + return *(Dis->getRegInfo()->getRegClass(RC).begin() + RegNo); +} + static DecodeStatus DecodeCPU64RegsRegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address, @@ -370,7 +326,8 @@ static DecodeStatus DecodeCPU64RegsRegisterClass(MCInst &Inst, if (RegNo > 31) return MCDisassembler::Fail; - Inst.addOperand(MCOperand::CreateReg(CPU64RegsTable[RegNo])); + unsigned Reg = getReg(Decoder, Mips::CPU64RegsRegClassID, RegNo); + Inst.addOperand(MCOperand::CreateReg(Reg)); return MCDisassembler::Success; } @@ -380,8 +337,8 @@ static DecodeStatus DecodeCPURegsRegisterClass(MCInst &Inst, const void *Decoder) { if (RegNo > 31) return MCDisassembler::Fail; - - Inst.addOperand(MCOperand::CreateReg(CPURegsTable[RegNo])); + unsigned Reg = getReg(Decoder, Mips::CPURegsRegClassID, RegNo); + Inst.addOperand(MCOperand::CreateReg(Reg)); return MCDisassembler::Success; } @@ -392,7 +349,8 @@ static DecodeStatus DecodeFGR64RegisterClass(MCInst &Inst, if (RegNo > 31) return MCDisassembler::Fail; - Inst.addOperand(MCOperand::CreateReg(FGR64RegsTable[RegNo])); + unsigned Reg = getReg(Decoder, Mips::FGR64RegClassID, RegNo); + Inst.addOperand(MCOperand::CreateReg(Reg)); return MCDisassembler::Success; } @@ -403,7 +361,8 @@ static DecodeStatus DecodeFGR32RegisterClass(MCInst &Inst, if (RegNo > 31) return MCDisassembler::Fail; - Inst.addOperand(MCOperand::CreateReg(FGR32RegsTable[RegNo])); + unsigned Reg = getReg(Decoder, Mips::FGR32RegClassID, RegNo); + Inst.addOperand(MCOperand::CreateReg(Reg)); return MCDisassembler::Success; } @@ -420,15 +379,18 @@ static DecodeStatus DecodeMem(MCInst &Inst, uint64_t Address, const void *Decoder) { int Offset = SignExtend32<16>(Insn & 0xffff); - int Reg = (int)fieldFromInstruction32(Insn, 16, 5); - int Base = (int)fieldFromInstruction32(Insn, 21, 5); + unsigned Reg = fieldFromInstruction32(Insn, 16, 5); + unsigned Base = fieldFromInstruction32(Insn, 21, 5); + + Reg = getReg(Decoder, Mips::CPURegsRegClassID, Reg); + Base = getReg(Decoder, Mips::CPURegsRegClassID, Base); if(Inst.getOpcode() == Mips::SC){ - Inst.addOperand(MCOperand::CreateReg(CPURegsTable[Reg])); + Inst.addOperand(MCOperand::CreateReg(Reg)); } - Inst.addOperand(MCOperand::CreateReg(CPURegsTable[Reg])); - Inst.addOperand(MCOperand::CreateReg(CPURegsTable[Base])); + Inst.addOperand(MCOperand::CreateReg(Reg)); + Inst.addOperand(MCOperand::CreateReg(Base)); Inst.addOperand(MCOperand::CreateImm(Offset)); return MCDisassembler::Success; @@ -439,11 +401,14 @@ static DecodeStatus DecodeFMem(MCInst &Inst, uint64_t Address, const void *Decoder) { int Offset = SignExtend32<16>(Insn & 0xffff); - int Reg = (int)fieldFromInstruction32(Insn, 16, 5); - int Base = (int)fieldFromInstruction32(Insn, 21, 5); + unsigned Reg = fieldFromInstruction32(Insn, 16, 5); + unsigned Base = fieldFromInstruction32(Insn, 21, 5); - Inst.addOperand(MCOperand::CreateReg(FGR64RegsTable[Reg])); - Inst.addOperand(MCOperand::CreateReg(CPURegsTable[Base])); + Reg = getReg(Decoder, Mips::FGR64RegClassID, Reg); + Base = getReg(Decoder, Mips::CPURegsRegClassID, Base); + + Inst.addOperand(MCOperand::CreateReg(Reg)); + Inst.addOperand(MCOperand::CreateReg(Base)); Inst.addOperand(MCOperand::CreateImm(Offset)); return MCDisassembler::Success; @@ -474,10 +439,12 @@ static DecodeStatus DecodeAFGR64RegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { - if (RegNo > 31) + if (RegNo > 30 || RegNo %2) return MCDisassembler::Fail; - Inst.addOperand(MCOperand::CreateReg(AFGR64RegsTable[RegNo])); + ; + unsigned Reg = getReg(Decoder, Mips::AFGR64RegClassID, RegNo /2); + Inst.addOperand(MCOperand::CreateReg(Reg)); return MCDisassembler::Success; } @@ -488,7 +455,7 @@ static DecodeStatus DecodeHWRegs64RegisterClass(MCInst &Inst, //Currently only hardware register 29 is supported if (RegNo != 29) return MCDisassembler::Fail; - Inst.addOperand(MCOperand::CreateReg(Mips::HWR29)); + Inst.addOperand(MCOperand::CreateReg(Mips::HWR29_64)); return MCDisassembler::Success; } diff --git a/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp b/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp index 6886b17..b38463d 100644 --- a/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp +++ b/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp @@ -13,6 +13,7 @@ #define DEBUG_TYPE "asm-printer" #include "MipsInstPrinter.h" +#include "MipsInstrInfo.h" #include "llvm/ADT/StringExtras.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" @@ -68,8 +69,25 @@ void MipsInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const { void MipsInstPrinter::printInst(const MCInst *MI, raw_ostream &O, StringRef Annot) { + switch (MI->getOpcode()) { + default: + break; + case Mips::RDHWR: + case Mips::RDHWR64: + O << "\t.set\tpush\n"; + O << "\t.set\tmips32r2\n"; + } + printInstruction(MI, O); printAnnotation(O, Annot); + + switch (MI->getOpcode()) { + default: + break; + case Mips::RDHWR: + case Mips::RDHWR64: + O << "\n\t.set\tpop"; + } } static void printExpr(const MCExpr *Expr, raw_ostream &OS) { @@ -108,6 +126,8 @@ static void printExpr(const MCExpr *Expr, raw_ostream &OS) { case MCSymbolRefExpr::VK_Mips_GOT_DISP: OS << "%got_disp("; break; case MCSymbolRefExpr::VK_Mips_GOT_PAGE: OS << "%got_page("; break; case MCSymbolRefExpr::VK_Mips_GOT_OFST: OS << "%got_ofst("; break; + case MCSymbolRefExpr::VK_Mips_HIGHER: OS << "%higher("; break; + case MCSymbolRefExpr::VK_Mips_HIGHEST: OS << "%highest("; break; } OS << SRE->getSymbol(); diff --git a/lib/Target/Mips/InstPrinter/MipsInstPrinter.h b/lib/Target/Mips/InstPrinter/MipsInstPrinter.h index 76b839b..3d8a6f9 100644 --- a/lib/Target/Mips/InstPrinter/MipsInstPrinter.h +++ b/lib/Target/Mips/InstPrinter/MipsInstPrinter.h @@ -16,7 +16,7 @@ #include "llvm/MC/MCInstPrinter.h" namespace llvm { -// These enumeration declarations were orignally in MipsInstrInfo.h but +// These enumeration declarations were originally in MipsInstrInfo.h but // had to be moved here to avoid circular dependencies between // LLVMMipsCodeGen and LLVMMipsAsmPrinter. namespace Mips { diff --git a/lib/Target/Mips/MCTargetDesc/Makefile b/lib/Target/Mips/MCTargetDesc/Makefile index 7fe2086..22a2721 100644 --- a/lib/Target/Mips/MCTargetDesc/Makefile +++ b/lib/Target/Mips/MCTargetDesc/Makefile @@ -14,3 +14,4 @@ LIBRARYNAME = LLVMMipsDesc CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. include $(LEVEL)/Makefile.common + diff --git a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp index 9b4caf6..6fe0c11 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp @@ -36,6 +36,11 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) { case FK_GPRel_4: case FK_Data_4: case Mips::fixup_Mips_LO16: + case Mips::fixup_Mips_GPOFF_HI: + case Mips::fixup_Mips_GPOFF_LO: + case Mips::fixup_Mips_GOT_PAGE: + case Mips::fixup_Mips_GOT_OFST: + case Mips::fixup_Mips_GOT_DISP: break; case Mips::fixup_Mips_PC16: // So far we are only using this type for branches. @@ -74,7 +79,8 @@ public: :MCAsmBackend(), OSType(_OSType), IsLittle(_isLittle), Is64Bit(_is64Bit) {} MCObjectWriter *createObjectWriter(raw_ostream &OS) const { - return createMipsELFObjectWriter(OS, OSType, IsLittle, Is64Bit); + return createMipsELFObjectWriter(OS, + MCELFObjectTargetWriter::getOSABI(OSType), IsLittle, Is64Bit); } /// ApplyFixup - Apply the \arg Value for given \arg Fixup into the provided @@ -115,7 +121,8 @@ public: CurVal |= (uint64_t)((uint8_t)Data[Offset + Idx]) << (i*8); } - uint64_t Mask = ((uint64_t)(-1) >> (64 - getFixupKindInfo(Kind).TargetSize)); + uint64_t Mask = ((uint64_t)(-1) >> + (64 - getFixupKindInfo(Kind).TargetSize)); CurVal |= Value & Mask; // Write out the fixed up bytes back to the code/data bits. @@ -156,7 +163,12 @@ public: { "fixup_Mips_TLSLDM", 0, 16, 0 }, { "fixup_Mips_DTPREL_HI", 0, 16, 0 }, { "fixup_Mips_DTPREL_LO", 0, 16, 0 }, - { "fixup_Mips_Branch_PCRel", 0, 16, MCFixupKindInfo::FKF_IsPCRel } + { "fixup_Mips_Branch_PCRel", 0, 16, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_Mips_GPOFF_HI", 0, 16, 0 }, + { "fixup_Mips_GPOFF_LO", 0, 16, 0 }, + { "fixup_Mips_GOT_PAGE", 0, 16, 0 }, + { "fixup_Mips_GOT_OFST", 0, 16, 0 }, + { "fixup_Mips_GOT_DISP", 0, 16, 0 } }; if (Kind < FirstTargetFixupKind) @@ -206,6 +218,14 @@ public: /// /// \return - True on success. bool writeNopData(uint64_t Count, MCObjectWriter *OW) const { + // Check for a less than instruction size number of bytes + // FIXME: 16 bit instructions are not handled yet here. + // We shouldn't be using a hard coded number for instruction size. + if (Count % 4) return false; + + uint64_t NumNops = Count / 4; + for (uint64_t i = 0; i != NumNops; ++i) + OW->Write32(0); return true; } }; // class MipsAsmBackend diff --git a/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h b/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h index fb1c5ce..234455e 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h +++ b/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h @@ -79,7 +79,12 @@ namespace MipsII { MO_GPOFF_LO, MO_GOT_DISP, MO_GOT_PAGE, - MO_GOT_OFST + MO_GOT_OFST, + + /// MO_HIGHER/HIGHEST - Represents the highest or higher half word of a + /// 64-bit symbol address. + MO_HIGHER, + MO_HIGHEST }; enum { diff --git a/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp b/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp index 2091bec..77c1524 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp @@ -34,7 +34,7 @@ namespace { class MipsELFObjectWriter : public MCELFObjectTargetWriter { public: - MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI); + MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI, bool _isN64); virtual ~MipsELFObjectWriter(); @@ -52,9 +52,11 @@ namespace { }; } -MipsELFObjectWriter::MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI) +MipsELFObjectWriter::MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI, + bool _isN64) : MCELFObjectTargetWriter(_is64Bit, OSABI, ELF::EM_MIPS, - /*HasRelocationAddend*/ false) {} + /*HasRelocationAddend*/ false, + /*IsN64*/ _isN64) {} MipsELFObjectWriter::~MipsELFObjectWriter() {} @@ -148,8 +150,26 @@ unsigned MipsELFObjectWriter::GetRelocType(const MCValue &Target, case Mips::fixup_Mips_PC16: Type = ELF::R_MIPS_PC16; break; + case Mips::fixup_Mips_GOT_PAGE: + Type = ELF::R_MIPS_GOT_PAGE; + break; + case Mips::fixup_Mips_GOT_OFST: + Type = ELF::R_MIPS_GOT_OFST; + break; + case Mips::fixup_Mips_GOT_DISP: + Type = ELF::R_MIPS_GOT_DISP; + break; + case Mips::fixup_Mips_GPOFF_HI: + Type = setRType((unsigned)ELF::R_MIPS_GPREL16, Type); + Type = setRType2((unsigned)ELF::R_MIPS_SUB, Type); + Type = setRType3((unsigned)ELF::R_MIPS_HI16, Type); + break; + case Mips::fixup_Mips_GPOFF_LO: + Type = setRType((unsigned)ELF::R_MIPS_GPREL16, Type); + Type = setRType2((unsigned)ELF::R_MIPS_SUB, Type); + Type = setRType3((unsigned)ELF::R_MIPS_LO16, Type); + break; } - return Type; } @@ -184,10 +204,10 @@ static int CompareOffset(const RelEntry &R0, const RelEntry &R1) { void MipsELFObjectWriter::sortRelocs(const MCAssembler &Asm, std::vector<ELFRelocationEntry> &Relocs) { - // Call the defualt function first. Relocations are sorted in descending + // Call the default function first. Relocations are sorted in descending // order of r_offset. MCELFObjectTargetWriter::sortRelocs(Asm, Relocs); - + RelLs RelocLs; std::vector<RelLsIter> Unmatched; @@ -244,6 +264,7 @@ MCObjectWriter *llvm::createMipsELFObjectWriter(raw_ostream &OS, uint8_t OSABI, bool IsLittleEndian, bool Is64Bit) { - MCELFObjectTargetWriter *MOTW = new MipsELFObjectWriter(Is64Bit, OSABI); + MCELFObjectTargetWriter *MOTW = new MipsELFObjectWriter(Is64Bit, OSABI, + (Is64Bit) ? true : false); return createELFObjectWriter(MOTW, OS, IsLittleEndian); } diff --git a/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h b/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h index 9b76eda..f5cbbd5 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h +++ b/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h @@ -95,6 +95,21 @@ namespace Mips { // PC relative branch fixup resulting in - R_MIPS_PC16 fixup_Mips_Branch_PCRel, + // resulting in - R_MIPS_GPREL16/R_MIPS_SUB/R_MIPS_HI16 + fixup_Mips_GPOFF_HI, + + // resulting in - R_MIPS_GPREL16/R_MIPS_SUB/R_MIPS_LO16 + fixup_Mips_GPOFF_LO, + + // resulting in - R_MIPS_PAGE + fixup_Mips_GOT_PAGE, + + // resulting in - R_MIPS_GOT_OFST + fixup_Mips_GOT_OFST, + + // resulting in - R_MIPS_GOT_DISP + fixup_Mips_GOT_DISP, + // Marker LastTargetFixupKind, NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp index 27954b1..ff3b3a7 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp @@ -91,6 +91,7 @@ public: } // namespace MCCodeEmitter *llvm::createMipsMCCodeEmitterEB(const MCInstrInfo &MCII, + const MCRegisterInfo &MRI, const MCSubtargetInfo &STI, MCContext &Ctx) { @@ -98,6 +99,7 @@ MCCodeEmitter *llvm::createMipsMCCodeEmitterEB(const MCInstrInfo &MCII, } MCCodeEmitter *llvm::createMipsMCCodeEmitterEL(const MCInstrInfo &MCII, + const MCRegisterInfo &MRI, const MCSubtargetInfo &STI, MCContext &Ctx) { @@ -179,7 +181,7 @@ getMachineOpValue(const MCInst &MI, const MCOperand &MO, } else if (MO.isFPImm()) { return static_cast<unsigned>(APFloat(MO.getFPImm()) .bitcastToAPInt().getHiBits(32).getLimitedValue()); - } + } // MO must be an Expr. assert(MO.isExpr()); @@ -193,10 +195,27 @@ getMachineOpValue(const MCInst &MI, const MCOperand &MO, } assert (Kind == MCExpr::SymbolRef); - - Mips::Fixups FixupKind; + + Mips::Fixups FixupKind = Mips::Fixups(0); switch(cast<MCSymbolRefExpr>(Expr)->getKind()) { + default: llvm_unreachable("Unknown fixup kind!"); + break; + case MCSymbolRefExpr::VK_Mips_GPOFF_HI : + FixupKind = Mips::fixup_Mips_GPOFF_HI; + break; + case MCSymbolRefExpr::VK_Mips_GPOFF_LO : + FixupKind = Mips::fixup_Mips_GPOFF_LO; + break; + case MCSymbolRefExpr::VK_Mips_GOT_PAGE : + FixupKind = Mips::fixup_Mips_GOT_PAGE; + break; + case MCSymbolRefExpr::VK_Mips_GOT_OFST : + FixupKind = Mips::fixup_Mips_GOT_OFST; + break; + case MCSymbolRefExpr::VK_Mips_GOT_DISP : + FixupKind = Mips::fixup_Mips_GOT_DISP; + break; case MCSymbolRefExpr::VK_Mips_GPREL: FixupKind = Mips::fixup_Mips_GPREL16; break; @@ -236,8 +255,6 @@ getMachineOpValue(const MCInst &MI, const MCOperand &MO, case MCSymbolRefExpr::VK_Mips_TPREL_LO: FixupKind = Mips::fixup_Mips_TPREL_LO; break; - default: - break; } // switch Fixups.push_back(MCFixup::Create(0, MO.getExpr(), MCFixupKind(FixupKind))); diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h b/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h index 547ccdd..bfcc2a2 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h +++ b/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h @@ -22,6 +22,7 @@ class MCCodeEmitter; class MCContext; class MCInstrInfo; class MCObjectWriter; +class MCRegisterInfo; class MCSubtargetInfo; class StringRef; class Target; @@ -33,9 +34,11 @@ extern Target TheMips64Target; extern Target TheMips64elTarget; MCCodeEmitter *createMipsMCCodeEmitterEB(const MCInstrInfo &MCII, + const MCRegisterInfo &MRI, const MCSubtargetInfo &STI, MCContext &Ctx); MCCodeEmitter *createMipsMCCodeEmitterEL(const MCInstrInfo &MCII, + const MCRegisterInfo &MRI, const MCSubtargetInfo &STI, MCContext &Ctx); diff --git a/lib/Target/Mips/Mips.h b/lib/Target/Mips/Mips.h index bafadc8..2963f7e 100644 --- a/lib/Target/Mips/Mips.h +++ b/lib/Target/Mips/Mips.h @@ -24,9 +24,7 @@ namespace llvm { FunctionPass *createMipsISelDag(MipsTargetMachine &TM); FunctionPass *createMipsDelaySlotFillerPass(MipsTargetMachine &TM); - FunctionPass *createMipsExpandPseudoPass(MipsTargetMachine &TM); - FunctionPass *createMipsEmitGPRestorePass(MipsTargetMachine &TM); - + FunctionPass *createMipsLongBranchPass(MipsTargetMachine &TM); FunctionPass *createMipsJITCodeEmitterPass(MipsTargetMachine &TM, JITCodeEmitter &JCE); diff --git a/lib/Target/Mips/Mips.td b/lib/Target/Mips/Mips.td index cbebe84..8548ae0 100644 --- a/lib/Target/Mips/Mips.td +++ b/lib/Target/Mips/Mips.td @@ -72,6 +72,9 @@ def FeatureMips64r2 : SubtargetFeature<"mips64r2", "MipsArchVersion", "Mips64r2", "Mips64r2 ISA Support", [FeatureMips64, FeatureMips32r2]>; +def FeatureMips16 : SubtargetFeature<"mips16", "InMips16Mode", "true", + "Mips16 mode">; + //===----------------------------------------------------------------------===// // Mips processors supported. //===----------------------------------------------------------------------===// @@ -83,6 +86,7 @@ def : Proc<"mips32", [FeatureMips32]>; def : Proc<"mips32r2", [FeatureMips32r2]>; def : Proc<"mips64", [FeatureMips64]>; def : Proc<"mips64r2", [FeatureMips64r2]>; +def : Proc<"mips16", [FeatureMips16]>; def MipsAsmWriter : AsmWriter { string AsmWriterClassName = "InstPrinter"; diff --git a/lib/Target/Mips/Mips16InstrFormats.td b/lib/Target/Mips/Mips16InstrFormats.td new file mode 100644 index 0000000..61602b6 --- /dev/null +++ b/lib/Target/Mips/Mips16InstrFormats.td @@ -0,0 +1,663 @@ +//===- Mips16InstrFormats.td - Mips Instruction Formats ----*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Describe MIPS instructions format +// +// CPU INSTRUCTION FORMATS +// +// funct or f Function field +// +// immediate 4-,5-,8- or 11-bit immediate, branch displacement, or +// or imm address displacement +// +// op 5-bit major operation code +// +// rx 3-bit source or destination register +// +// ry 3-bit source or destination register +// +// rz 3-bit source or destination register +// +// sa 3- or 5-bit shift amount +// +//===----------------------------------------------------------------------===// + +// Format specifies the encoding used by the instruction. This is part of the +// ad-hoc solution used to emit machine instruction encodings by our machine +// code emitter. +// +class Format16<bits<5> val> { + bits<5> Value = val; +} + +def Pseudo16 : Format16<0>; +def FrmI16 : Format16<1>; +def FrmRI16 : Format16<2>; +def FrmRR16 : Format16<3>; +def FrmRRI16 : Format16<4>; +def FrmRRR16 : Format16<5>; +def FrmRRI_A16 : Format16<6>; +def FrmSHIFT16 : Format16<7>; +def FrmI8_TYPE16 : Format16<8>; +def FrmI8_MOVR3216 : Format16<9>; +def FrmI8_MOV32R16 : Format16<10>; +def FrmI8_SVRS16 : Format16<11>; +def FrmJAL16 : Format16<12>; +def FrmJALX16 : Format16<13>; +def FrmEXT_I16 : Format16<14>; +def FrmASMACRO16 : Format16<15>; +def FrmEXT_RI16 : Format16<16>; +def FrmEXT_RRI16 : Format16<17>; +def FrmEXT_RRI_A16 : Format16<18>; +def FrmEXT_SHIFT16 : Format16<19>; +def FrmEXT_I816 : Format16<20>; +def FrmEXT_I8_SVRS16 : Format16<21>; +def FrmOther16 : Format16<22>; // Instruction w/ a custom format + +// Base class for Mips 16 Format +// This class does not depend on the instruction size +// +class MipsInst16_Base<dag outs, dag ins, string asmstr, list<dag> pattern, + InstrItinClass itin, Format16 f>: Instruction +{ + Format16 Form = f; + + let Namespace = "Mips"; + + let OutOperandList = outs; + let InOperandList = ins; + + let AsmString = asmstr; + let Pattern = pattern; + let Itinerary = itin; + + // + // Attributes specific to Mips instructions... + // + bits<5> FormBits = Form.Value; + + // TSFlags layout should be kept in sync with MipsInstrInfo.h. + let TSFlags{4-0} = FormBits; + + let Predicates = [InMips16Mode]; +} + +// +// Generic Mips 16 Format +// +class MipsInst16<dag outs, dag ins, string asmstr, list<dag> pattern, + InstrItinClass itin, Format16 f>: + MipsInst16_Base<outs, ins, asmstr, pattern, itin, f> +{ + field bits<16> Inst; + bits<5> Opcode = 0; + + // Top 5 bits are the 'opcode' field + let Inst{15-11} = Opcode; +} + +// +// For 32 bit extended instruction forms. +// +class MipsInst16_32<dag outs, dag ins, string asmstr, list<dag> pattern, + InstrItinClass itin, Format16 f>: + MipsInst16_Base<outs, ins, asmstr, pattern, itin, f> +{ + field bits<32> Inst; + +} + +class MipsInst16_EXTEND<dag outs, dag ins, string asmstr, list<dag> pattern, + InstrItinClass itin, Format16 f>: + MipsInst16_32<outs, ins, asmstr, pattern, itin, f> +{ + let Inst{31-27} = 0b11110; +} + + + +// Mips Pseudo Instructions Format +class MipsPseudo16<dag outs, dag ins, string asmstr, list<dag> pattern>: + MipsInst16<outs, ins, asmstr, pattern, IIPseudo, Pseudo16> { + let isCodeGenOnly = 1; + let isPseudo = 1; +} + + +//===----------------------------------------------------------------------===// +// Format I instruction class in Mips : <|opcode|imm11|> +//===----------------------------------------------------------------------===// + +class FI16<bits<5> op, dag outs, dag ins, string asmstr, list<dag> pattern, + InstrItinClass itin>: + MipsInst16<outs, ins, asmstr, pattern, itin, FrmI16> +{ + bits<11> imm11; + + let Opcode = op; + + let Inst{10-0} = imm11; +} + +//===----------------------------------------------------------------------===// +// Format RI instruction class in Mips : <|opcode|rx|imm8|> +//===----------------------------------------------------------------------===// + +class FRI16<bits<5> op, dag outs, dag ins, string asmstr, + list<dag> pattern, InstrItinClass itin>: + MipsInst16<outs, ins, asmstr, pattern, itin, FrmRI16> +{ + bits<3> rx; + bits<8> imm8; + + let Opcode = op; + + let Inst{10-8} = rx; + let Inst{7-0} = imm8; +} + +//===----------------------------------------------------------------------===// +// Format RR instruction class in Mips : <|opcode|rx|ry|funct|> +//===----------------------------------------------------------------------===// + +class FRR16<bits<5> _funct, dag outs, dag ins, string asmstr, + list<dag> pattern, InstrItinClass itin>: + MipsInst16<outs, ins, asmstr, pattern, itin, FrmRR16> +{ + bits<3> rx; + bits<3> ry; + bits<5> funct; + + let Opcode = 0b11101; + let funct = _funct; + + let Inst{10-8} = rx; + let Inst{7-5} = ry; + let Inst{4-0} = funct; +} + +// +// For conversion functions. +// +class FRR_SF16<bits<5> _funct, bits<3> _subfunct, dag outs, dag ins, + string asmstr, list<dag> pattern, InstrItinClass itin>: + MipsInst16<outs, ins, asmstr, pattern, itin, FrmRR16> +{ + bits<3> rx; + bits<3> subfunct; + bits<5> funct; + + let Opcode = 0b11101; // RR + let funct = _funct; + let subfunct = _subfunct; + + let Inst{10-8} = rx; + let Inst{7-5} = subfunct; + let Inst{4-0} = funct; +} + +// +// just used for breakpoint (hardware and software) instructions. +// +class FC16<bits<5> _funct, dag outs, dag ins, string asmstr, + list<dag> pattern, InstrItinClass itin>: + MipsInst16<outs, ins, asmstr, pattern, itin, FrmRR16> +{ + bits<6> _code; // code is a keyword in tablegen + bits<5> funct; + + let Opcode = 0b11101; // RR + let funct = _funct; + + let Inst{10-5} = _code; + let Inst{4-0} = funct; +} + +// +// J(AL)R(C) subformat +// +class FRR16_JALRC<bits<1> _nd, bits<1> _l, bits<1> r_a, + dag outs, dag ins, string asmstr, + list<dag> pattern, InstrItinClass itin>: + MipsInst16<outs, ins, asmstr, pattern, itin, FrmRR16> +{ + bits<3> rx; + bits<1> nd; + bits<1> l; + bits<1> ra; + + let nd = _nd; + let l = _l; + let ra = r_a; + + let Opcode = 0b11101; + + let Inst{10-8} = rx; + let Inst{7} = nd; + let Inst{6} = l; + let Inst{5} = ra; + let Inst{4-0} = 0; +} + +//===----------------------------------------------------------------------===// +// Format RRI instruction class in Mips : <|opcode|rx|ry|imm5|> +//===----------------------------------------------------------------------===// + +class FRRI16<bits<5> op, dag outs, dag ins, string asmstr, + list<dag> pattern, InstrItinClass itin>: + MipsInst16<outs, ins, asmstr, pattern, itin, FrmRRI16> +{ + bits<3> rx; + bits<3> ry; + bits<5> imm5; + + let Opcode = op; + + + let Inst{10-8} = rx; + let Inst{7-5} = ry; + let Inst{4-0} = imm5; +} + +//===----------------------------------------------------------------------===// +// Format RRR instruction class in Mips : <|opcode|rx|ry|rz|f|> +//===----------------------------------------------------------------------===// + +class FRRR16<bits<2> _f, dag outs, dag ins, string asmstr, + list<dag> pattern, InstrItinClass itin>: + MipsInst16<outs, ins, asmstr, pattern, itin, FrmRRR16> +{ + bits<3> rx; + bits<3> ry; + bits<3> rz; + bits<2> f; + + let Opcode = 0b11100; + let f = _f; + + let Inst{10-8} = rx; + let Inst{7-5} = ry; + let Inst{4-2} = rz; + let Inst{1-0} = f; +} + +//===----------------------------------------------------------------------===// +// Format RRI-A instruction class in Mips : <|opcode|rx|ry|f|imm4|> +//===----------------------------------------------------------------------===// + +class FRRI_A16<bits<1> _f, dag outs, dag ins, string asmstr, + list<dag> pattern, InstrItinClass itin>: + MipsInst16<outs, ins, asmstr, pattern, itin, FrmRRI_A16> +{ + bits<3> rx; + bits<3> ry; + bits<1> f; + bits<4> imm4; + + let Opcode = 0b01000; + let f = _f; + + let Inst{10-8} = rx; + let Inst{7-5} = ry; + let Inst{4} = f; + let Inst{3-0} = imm4; +} + +//===----------------------------------------------------------------------===// +// Format Shift instruction class in Mips : <|opcode|rx|ry|sa|f|> +//===----------------------------------------------------------------------===// + +class FSHIFT16<bits<2> _f, dag outs, dag ins, string asmstr, + list<dag> pattern, InstrItinClass itin>: + MipsInst16<outs, ins, asmstr, pattern, itin, FrmSHIFT16> +{ + bits<3> rx; + bits<3> ry; + bits<3> sa; + bits<2> f; + + let Opcode = 0b00110; + let f = _f; + + let Inst{10-8} = rx; + let Inst{7-5} = ry; + let Inst{4-2} = sa; + let Inst{1-0} = f; +} + +//===----------------------------------------------------------------------===// +// Format i8 instruction class in Mips : <|opcode|funct|imm8> +//===----------------------------------------------------------------------===// + +class FI816<bits<3> _func, dag outs, dag ins, string asmstr, + list<dag> pattern, InstrItinClass itin>: + MipsInst16<outs, ins, asmstr, pattern, itin, FrmI8_TYPE16> +{ + bits<3> func; + bits<8> imm8; + + let Opcode = 0b01100; + let func = _func; + + let Inst{10-8} = func; + let Inst{7-0} = imm8; +} + +//===----------------------------------------------------------------------===// +// Format i8_MOVR32 instruction class in Mips : <|opcode|func|ry|r32> +//===----------------------------------------------------------------------===// + +class FI8_MOVR3216<dag outs, dag ins, string asmstr, + list<dag> pattern, InstrItinClass itin>: + MipsInst16<outs, ins, asmstr, pattern, itin, FrmI8_MOVR3216> +{ + + bits<4> ry; + bits<4> r32; + + let Opcode = 0b01100; + + let Inst{10-8} = 0b111; + let Inst{7-4} = ry; + let Inst{3-0} = r32; + +} + + + +//===----------------------------------------------------------------------===// +// Format i8_MOV32R instruction class in Mips : <|opcode|func|r32|rz> +//===----------------------------------------------------------------------===// + +class FI8_MOV32R16<dag outs, dag ins, string asmstr, + list<dag> pattern, InstrItinClass itin>: + MipsInst16<outs, ins, asmstr, pattern, itin, FrmI8_MOV32R16> +{ + + bits<3> func; + bits<5> r32; + bits<3> rz; + + + let Opcode = 0b01100; + + let Inst{10-8} = 0b101; + let Inst{7-5} = r32{2-0}; + let Inst{4-3} = r32{4-3}; + let Inst{2-0} = rz; + +} + +//===----------------------------------------------------------------------===// +// Format i8_SVRS instruction class in Mips : +// <|opcode|svrs|s|ra|s0|s1|framesize> +//===----------------------------------------------------------------------===// + +class FI8_SVRS16<bits<1> _s, dag outs, dag ins, string asmstr, + list<dag> pattern, InstrItinClass itin>: + MipsInst16<outs, ins, asmstr, pattern, itin, FrmI8_SVRS16> +{ + bits<1> s; + bits<1> ra = 0; + bits<1> s0 = 0; + bits<1> s1 = 0; + bits<4> framesize = 0; + + let s =_s; + let Opcode = 0b01100; + + let Inst{10-8} = 0b100; + let Inst{7} = s; + let Inst{6} = ra; + let Inst{5} = s0; + let Inst{4} = s1; + let Inst{3-0} = framesize; + +} + +//===----------------------------------------------------------------------===// +// Format JAL instruction class in Mips16 : +// <|opcode|svrs|s|ra|s0|s1|framesize> +//===----------------------------------------------------------------------===// + +class FJAL16<bits<1> _X, dag outs, dag ins, string asmstr, + list<dag> pattern, InstrItinClass itin>: + MipsInst16_32<outs, ins, asmstr, pattern, itin, FrmJAL16> +{ + bits<1> X; + bits<26> imm26; + + + let X = _X; + + let Inst{31-27} = 0b00011; + let Inst{26} = X; + let Inst{25-21} = imm26{20-16}; + let Inst{20-16} = imm26{25-21}; + let Inst{15-0} = imm26{15-0}; + +} + +//===----------------------------------------------------------------------===// +// Format EXT-I instruction class in Mips16 : +// <|EXTEND|imm10:5|imm15:11|op|0|0|0|0|0|0|imm4:0> +//===----------------------------------------------------------------------===// + +class FEXT_I16<bits<5> _eop, dag outs, dag ins, string asmstr, + list<dag> pattern, InstrItinClass itin>: + MipsInst16_EXTEND<outs, ins, asmstr, pattern, itin, FrmEXT_I16> +{ + bits<16> imm16; + bits<5> eop; + + let eop = _eop; + + let Inst{26-21} = imm16{10-5}; + let Inst{20-16} = imm16{15-11}; + let Inst{15-11} = eop; + let Inst{10-5} = 0; + let Inst{4-0} = imm16{4-0}; + +} + +//===----------------------------------------------------------------------===// +// Format ASMACRO instruction class in Mips16 : +// <EXTEND|select|p4|p3|RRR|p2|p1|p0> +//===----------------------------------------------------------------------===// + +class FASMACRO16<dag outs, dag ins, string asmstr, + list<dag> pattern, InstrItinClass itin>: + MipsInst16_EXTEND<outs, ins, asmstr, pattern, itin, FrmASMACRO16> +{ + bits<3> select; + bits<3> p4; + bits<5> p3; + bits<5> RRR = 0b11100; + bits<3> p2; + bits<3> p1; + bits<5> p0; + + + let Inst{26-24} = select; + let Inst{23-21} = p4; + let Inst{20-16} = p3; + let Inst{15-11} = RRR; + let Inst{10-8} = p2; + let Inst{7-5} = p1; + let Inst{4-0} = p0; + +} + + +//===----------------------------------------------------------------------===// +// Format EXT-RI instruction class in Mips16 : +// <|EXTEND|imm10:5|imm15:11|op|rx|0|0|0|imm4:0> +//===----------------------------------------------------------------------===// + +class FEXT_RI16<bits<5> _op, dag outs, dag ins, string asmstr, + list<dag> pattern, InstrItinClass itin>: + MipsInst16_EXTEND<outs, ins, asmstr, pattern, itin, FrmEXT_RI16> +{ + bits<16> imm16; + bits<5> op; + bits<3> rx; + + let op = _op; + + let Inst{26-21} = imm16{10-5}; + let Inst{20-16} = imm16{15-11}; + let Inst{15-11} = op; + let Inst{10-8} = rx; + let Inst{7-5} = 0; + let Inst{4-0} = imm16{4-0}; + +} + +//===----------------------------------------------------------------------===// +// Format EXT-RRI instruction class in Mips16 : +// <|EXTEND|imm10:5|imm15:11|op|rx|ry|imm4:0> +//===----------------------------------------------------------------------===// + +class FEXT_RRI16<bits<5> _op, dag outs, dag ins, string asmstr, + list<dag> pattern, InstrItinClass itin>: + MipsInst16_EXTEND<outs, ins, asmstr, pattern, itin, FrmEXT_RRI16> +{ + bits<5> op; + bits<16> imm16; + bits<3> rx; + bits<3> ry; + + let op=_op; + + let Inst{26-21} = imm16{10-5}; + let Inst{20-16} = imm16{15-11}; + let Inst{15-11} = op; + let Inst{10-8} = rx; + let Inst{7-5} = ry; + let Inst{4-0} = imm16{4-0}; + +} + +//===----------------------------------------------------------------------===// +// Format EXT-RRI-A instruction class in Mips16 : +// <|EXTEND|imm10:4|imm14:11|RRI-A|rx|ry|f|imm3:0> +//===----------------------------------------------------------------------===// + +class FEXT_RRI_A16<bits<1> _f, dag outs, dag ins, string asmstr, + list<dag> pattern, InstrItinClass itin>: + MipsInst16_EXTEND<outs, ins, asmstr, pattern, itin, FrmEXT_RRI_A16> +{ + bits<15> imm15; + bits<3> rx; + bits<3> ry; + bits<1> f; + + let f = _f; + + let Inst{26-20} = imm15{10-4}; + let Inst{19-16} = imm15{14-11}; + let Inst{15-11} = 0b01000; + let Inst{10-8} = rx; + let Inst{7-5} = ry; + let Inst{4} = f; + let Inst{3-0} = imm15{3-0}; + +} + +//===----------------------------------------------------------------------===// +// Format EXT-SHIFT instruction class in Mips16 : +// <|EXTEND|sa 4:0|s5|0|SHIFT|rx|ry|0|f> +//===----------------------------------------------------------------------===// + +class FEXT_SHIFT16<bits<2> _f, dag outs, dag ins, string asmstr, + list<dag> pattern, InstrItinClass itin>: + MipsInst16_EXTEND<outs, ins, asmstr, pattern, itin, FrmEXT_SHIFT16> +{ + bits<6> sa6; + bits<3> rx; + bits<3> ry; + bits<2> f; + + let f = _f; + + let Inst{26-22} = sa6{4-0}; + let Inst{21} = sa6{5}; + let Inst{20-16} = 0; + let Inst{15-11} = 0b00110; + let Inst{10-8} = rx; + let Inst{7-5} = ry; + let Inst{4-2} = 0; + let Inst{1-0} = f; + +} + +//===----------------------------------------------------------------------===// +// Format EXT-I8 instruction class in Mips16 : +// <|EXTEND|imm10:5|imm15:11|I8|funct|0|imm4:0> +//===----------------------------------------------------------------------===// + +class FEXT_I816<bits<3> _funct, dag outs, dag ins, string asmstr, + list<dag> pattern, InstrItinClass itin>: + MipsInst16_EXTEND<outs, ins, asmstr, pattern, itin, FrmEXT_I816> +{ + bits<16> imm16; + bits<5> I8; + bits<3> funct; + + let funct = _funct; + let I8 = 0b0110; + + let Inst{26-21} = imm16{10-5}; + let Inst{20-16} = imm16{15-11}; + let Inst{15-11} = I8; + let Inst{10-8} = funct; + let Inst{7-5} = 0; + let Inst{4-0} = imm16{4-0}; + +} + +//===----------------------------------------------------------------------===// +// Format EXT-I8_SVRS instruction class in Mips16 : +// <|EXTEND|xsregs|framesize7:4|aregs|I8|SVRS|s|ra|s0|s1|framesize3:0> +//===----------------------------------------------------------------------===// + +class FEXT_I8_SVRS16<bits<1> s_, dag outs, dag ins, string asmstr, + list<dag> pattern, InstrItinClass itin>: + MipsInst16_EXTEND<outs, ins, asmstr, pattern, itin, FrmI8_SVRS16> +{ + bits<3> xsregs =0; + bits<8> framesize =0; + bits<3> aregs =0; + bits<5> I8 = 0b01100; + bits<3> SVRS = 0b100; + bits<1> s; + bits<1> ra = 0; + bits<1> s0 = 0; + bits<1> s1 = 0; + + let s= s_; + + let Inst{26-24} = xsregs; + let Inst{23-20} = framesize{7-4}; + let Inst{19} = 0; + let Inst{18-16} = aregs; + let Inst{15-11} = I8; + let Inst{10-8} = SVRS; + let Inst{7} = s; + let Inst{6} = ra; + let Inst{5} = s0; + let Inst{4} = s1; + let Inst{3-0} = framesize{3-0}; + + +} + + + diff --git a/lib/Target/Mips/Mips16InstrInfo.td b/lib/Target/Mips/Mips16InstrInfo.td new file mode 100644 index 0000000..c852042 --- /dev/null +++ b/lib/Target/Mips/Mips16InstrInfo.td @@ -0,0 +1,243 @@ +//===- Mips16InstrInfo.td - Target Description for Mips16 -*- tablegen -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes Mips16 instructions. +// +//===----------------------------------------------------------------------===// + +def uimm5 : Operand<i8> { + let DecoderMethod= "DecodeSimm16"; +} + +// +// RRR-type instruction format +// + +class FRRR16_ins<bits<2> _f, string asmstr, InstrItinClass itin> : + FRRR16<_f, (outs CPU16Regs:$rz), (ins CPU16Regs:$rx, CPU16Regs:$ry), + !strconcat(asmstr, "\t$rz, $rx, $ry"), [], itin>; + +// +// I8_MOV32R instruction format (used only by MOV32R instruction) +// +class FI8_MOV32R16_ins<string asmstr, InstrItinClass itin>: + FI8_MOV32R16<(outs CPURegs:$r32), (ins CPU16Regs:$rz), + !strconcat(asmstr, "\t$r32, $rz"), [], itin>; + +// +// EXT-RI instruction format +// + +class FEXT_RI16_ins_base<bits<5> _op, string asmstr, string asmstr2, + InstrItinClass itin>: + FEXT_RI16<_op, (outs CPU16Regs:$rx), (ins simm16:$imm), + !strconcat(asmstr, asmstr2), [], itin>; + +class FEXT_RI16_ins<bits<5> _op, string asmstr, + InstrItinClass itin>: + FEXT_RI16_ins_base<_op, asmstr, "\t$rx, $imm", itin>; + +class FEXT_RI16_PC_ins<bits<5> _op, string asmstr, InstrItinClass itin>: + FEXT_RI16_ins_base<_op, asmstr, "\t$rx, $$pc, $imm", itin>; + +// +// RR-type instruction format +// +let rx=0 in +class FRR16_JALRC_RA_only_ins<bits<1> nd_, bits<1> l_, + string asmstr, InstrItinClass itin>: + FRR16_JALRC<nd_, l_, 1, (outs), (ins), !strconcat(asmstr, "\t $$ra"), + [], itin> ; + +// +// EXT-RRI instruction format +// + +class FEXT_RRI16_mem_ins<bits<5> op, string asmstr, Operand MemOpnd, + InstrItinClass itin>: + FEXT_RRI16<op, (outs CPU16Regs:$ry), (ins MemOpnd:$addr), + !strconcat(asmstr, "\t$ry, $addr"), [], itin>; + +// +// EXT-SHIFT instruction format +// +class FEXT_SHIFT16_ins<bits<2> _f, string asmstr, InstrItinClass itin>: + FEXT_SHIFT16<_f, (outs CPU16Regs:$rx), (ins CPU16Regs:$ry, uimm5:$sa), + !strconcat(asmstr, "\t$rx, $ry, $sa"), [], itin>; + +// +// Address operand +def mem16 : Operand<i32> { + let PrintMethod = "printMemOperand"; + let MIOperandInfo = (ops CPU16Regs, simm16); + let EncoderMethod = "getMemEncoding"; +} + +// +// Format: ADDIU rx, pc, immediate MIPS16e +// Purpose: Add Immediate Unsigned Word (3-Operand, PC-Relative, Extended) +// To add a constant to the program counter. +// +class AddiuRxPcImmX16_base : FEXT_RI16_PC_ins<0b00001, "addiu", IIAlu>; +def AddiuRxPcImmX16 : AddiuRxPcImmX16_base; +// +// Format: ADDU rz, rx, ry MIPS16e +// Purpose: Add Unsigned Word (3-Operand) +// To add 32-bit integers. +// + +class AdduRxRyRz16_base: FRRR16_ins<01, "addu", IIAlu>; +def AdduRxRyRz16: AdduRxRyRz16_base; + +// +// Format: JR ra MIPS16e +// Purpose: Jump Register Through Register ra +// To execute a branch to the instruction address in the return +// address register. +// + +def JrRa16: FRR16_JALRC_RA_only_ins<0, 0, "jr", IIAlu>; + +// +// Format: LI rx, immediate MIPS16e +// Purpose: Load Immediate (Extended) +// To load a constant into a GPR. +// +def LiRxImmX16: FEXT_RI16_ins<0b01101, "li", IIAlu>; + +// +// Format: LW ry, offset(rx) MIPS16e +// Purpose: Load Word (Extended) +// To load a word from memory as a signed value. +// +class LwRxRyOffMemX16_base: FEXT_RRI16_mem_ins<0b10011, "lw", mem16, IIAlu>; +def LwRxRyOffMemX16: LwRxRyOffMemX16_base; + +// +// Format: MOVE r32, rz MIPS16e +// Purpose: Move +// To move the contents of a GPR to a GPR. +// +def Mov32R16: FI8_MOV32R16_ins<"move", IIAlu>; +// +// Format: RESTORE {ra,}{s0/s1/s0-1,}{framesize} +// (All args are optional) MIPS16e +// Purpose: Restore Registers and Deallocate Stack Frame +// To deallocate a stack frame before exit from a subroutine, +// restoring return address and static registers, and adjusting +// stack +// + +// fixed form for restoring RA and the frame +// for direct object emitter, encoding needs to be adjusted for the +// frame size +// +let ra=1, s=0,s0=0,s1=0 in +def RestoreRaF16: + FI8_SVRS16<0b1, (outs), (ins uimm16:$frame_size), + "restore \t$$ra, $frame_size", [], IILoad >; + +// +// Format: SAVE {ra,}{s0/s1/s0-1,}{framesize} (All arguments are optional) +// MIPS16e +// Purpose: Save Registers and Set Up Stack Frame +// To set up a stack frame on entry to a subroutine, +// saving return address and static registers, and adjusting stack +// +let ra=1, s=1,s0=0,s1=0 in +def SaveRaF16: + FI8_SVRS16<0b1, (outs), (ins uimm16:$frame_size), + "save \t$$ra, $frame_size", [], IILoad >; + +// +// Format: SLL rx, ry, sa MIPS16e +// Purpose: Shift Word Left Logical (Extended) +// To execute a left-shift of a word by a fixed number of bits—0 to 31 bits. +// +def SllX16: FEXT_SHIFT16_ins<0b00, "sll", IIAlu>; + +// +// Format: SW ry, offset(rx) MIPS16e +// Purpose: Store Word (Extended) +// To store a word to memory. +// +class SwRxRyOffMemX16_base: FEXT_RRI16_mem_ins<0b11011, "sw", mem16, IIAlu>; +def SwRxRyOffMemX16: SwRxRyOffMemX16_base; + +class Mips16Pat<dag pattern, dag result> : Pat<pattern, result> { + let Predicates = [InMips16Mode]; +} + +class ArithLogicR16Defs<SDNode OpNode, bit isComm = 0> { + dag OutOperandList = (outs CPU16Regs:$rz); + dag InOperandList = (ins CPU16Regs:$rx, CPU16Regs:$ry); + list<dag> Pattern = [(set CPU16Regs:$rz, + (OpNode CPU16Regs:$rx, CPU16Regs:$ry))]; +} + +multiclass ArithLogicR16_base { + def _add: AdduRxRyRz16_base, ArithLogicR16Defs<add, 1>; +} + +defm ArithLogicR16_patt : ArithLogicR16_base; + +class LoadM16Defs<PatFrag OpNode, Operand _MemOpnd, bit Pseudo=0> { + bit isPseudo = Pseudo; + Operand MemOpnd = _MemOpnd; + dag OutOperandList = (outs CPU16Regs:$ry); + dag InOperandList = (ins MemOpnd:$addr); + list<dag> Pattern = [(set CPU16Regs:$ry, (OpNode addr:$addr))]; +} + +multiclass LoadM16_base { + def _LwRxRyOffMemX16: LwRxRyOffMemX16_base, LoadM16Defs<load_a, mem16>; +} + +defm LoadM16: LoadM16_base; + +class StoreM16Defs<PatFrag OpNode, Operand _MemOpnd, bit Pseudo=0> { + bit isPseudo = Pseudo; + Operand MemOpnd = _MemOpnd; + dag OutOperandList = (outs ); + dag InOperandList = (ins CPU16Regs:$ry, MemOpnd:$addr); + list<dag> Pattern = [(OpNode CPU16Regs:$ry, addr:$addr)]; +} + +multiclass StoreM16_base { + def _SwRxRyOffMemX16: SwRxRyOffMemX16_base, StoreM16Defs<store_a, mem16>; +} + +defm StoreM16: StoreM16_base; + +// Jump and Link (Call) +let isCall=1, hasDelaySlot=1 in +def JumpLinkReg16: + FRR16_JALRC<0, 0, 0, (outs), (ins CPU16Regs:$rs), + "jalr \t$rs", [(MipsJmpLink CPU16Regs:$rs)], IIBranch>; + +// Mips16 pseudos +let isReturn=1, isTerminator=1, hasDelaySlot=1, isBarrier=1, hasCtrlDep=1, + hasExtraSrcRegAllocReq = 1 in +def RetRA16 : MipsPseudo16<(outs), (ins), "", [(MipsRet)]>; + +// As stack alignment is always done with addiu, we need a 16-bit immediate +// This is basically deprecated code but needs to be there for things +// to work. +let Defs = [SP], Uses = [SP] in { +def ADJCALLSTACKDOWN16 : MipsPseudo16<(outs), (ins uimm16:$amt), + ";", + [(callseq_start timm:$amt)]>; +def ADJCALLSTACKUP16 : MipsPseudo16<(outs), (ins uimm16:$amt1, uimm16:$amt2), + ";", + [(callseq_end timm:$amt1, timm:$amt2)]>; +} + +// Small immediates +def : Mips16Pat<(i32 immZExt16:$in), (LiRxImmX16 immZExt16:$in)>; +def : Mips16Pat<(MipsLo tglobaladdr:$in), (LiRxImmX16 tglobaladdr:$in)>; diff --git a/lib/Target/Mips/Mips64InstrInfo.td b/lib/Target/Mips/Mips64InstrInfo.td index 0382869..cceee24 100644 --- a/lib/Target/Mips/Mips64InstrInfo.td +++ b/lib/Target/Mips/Mips64InstrInfo.td @@ -49,21 +49,24 @@ class Div64<SDNode op, bits<6> func, string instr_asm, InstrItinClass itin>: Div<op, func, instr_asm, itin, CPU64Regs, [HI64, LO64]>; multiclass Atomic2Ops64<PatFrag Op, string Opstr> { - def #NAME# : Atomic2Ops<Op, Opstr, CPU64Regs, CPURegs>, Requires<[NotN64]>; - def _P8 : Atomic2Ops<Op, Opstr, CPU64Regs, CPU64Regs>, Requires<[IsN64]> { + def #NAME# : Atomic2Ops<Op, Opstr, CPU64Regs, CPURegs>, + Requires<[NotN64, HasStandardEncoding]>; + def _P8 : Atomic2Ops<Op, Opstr, CPU64Regs, CPU64Regs>, + Requires<[IsN64, HasStandardEncoding]> { let isCodeGenOnly = 1; } } multiclass AtomicCmpSwap64<PatFrag Op, string Width> { - def #NAME# : AtomicCmpSwap<Op, Width, CPU64Regs, CPURegs>, Requires<[NotN64]>; + def #NAME# : AtomicCmpSwap<Op, Width, CPU64Regs, CPURegs>, + Requires<[NotN64, HasStandardEncoding]>; def _P8 : AtomicCmpSwap<Op, Width, CPU64Regs, CPU64Regs>, - Requires<[IsN64]> { + Requires<[IsN64, HasStandardEncoding]> { let isCodeGenOnly = 1; } } } -let usesCustomInserter = 1, Predicates = [HasMips64], +let usesCustomInserter = 1, Predicates = [HasMips64, HasStandardEncoding], DecoderNamespace = "Mips64" in { defm ATOMIC_LOAD_ADD_I64 : Atomic2Ops64<atomic_load_add_64, "load_add_64">; defm ATOMIC_LOAD_SUB_I64 : Atomic2Ops64<atomic_load_sub_64, "load_sub_64">; @@ -106,9 +109,15 @@ def DSRA : shift_rotate_imm64<0x3b, 0x00, "dsra", sra>; def DSLLV : shift_rotate_reg<0x14, 0x00, "dsllv", shl, CPU64Regs>; def DSRLV : shift_rotate_reg<0x16, 0x00, "dsrlv", srl, CPU64Regs>; def DSRAV : shift_rotate_reg<0x17, 0x00, "dsrav", sra, CPU64Regs>; +let Pattern = []<dag> in { +def DSLL32 : shift_rotate_imm64<0x3c, 0x00, "dsll32", shl>; +def DSRL32 : shift_rotate_imm64<0x3e, 0x00, "dsrl32", srl>; +def DSRA32 : shift_rotate_imm64<0x3f, 0x00, "dsra32", sra>; +} } // Rotate Instructions -let Predicates = [HasMips64r2], DecoderNamespace = "Mips64" in { +let Predicates = [HasMips64r2, HasStandardEncoding], + DecoderNamespace = "Mips64" in { def DROTR : shift_rotate_imm64<0x3a, 0x01, "drotr", rotr>; def DROTRV : shift_rotate_reg<0x16, 0x01, "drotrv", rotr, CPU64Regs>; } @@ -137,18 +146,34 @@ defm USW64 : StoreM64<0x2b, "usw", truncstorei32_u, 1>; defm ULD : LoadM64<0x37, "uld", load_u, 1>; defm USD : StoreM64<0x3f, "usd", store_u, 1>; +/// load/store left/right +let isCodeGenOnly = 1 in { + defm LWL64 : LoadLeftRightM64<0x22, "lwl", MipsLWL>; + defm LWR64 : LoadLeftRightM64<0x26, "lwr", MipsLWR>; + defm SWL64 : StoreLeftRightM64<0x2a, "swl", MipsSWL>; + defm SWR64 : StoreLeftRightM64<0x2e, "swr", MipsSWR>; +} +defm LDL : LoadLeftRightM64<0x1a, "ldl", MipsLDL>; +defm LDR : LoadLeftRightM64<0x1b, "ldr", MipsLDR>; +defm SDL : StoreLeftRightM64<0x2c, "sdl", MipsSDL>; +defm SDR : StoreLeftRightM64<0x2d, "sdr", MipsSDR>; + /// Load-linked, Store-conditional -def LLD : LLBase<0x34, "lld", CPU64Regs, mem>, Requires<[NotN64]>; -def LLD_P8 : LLBase<0x34, "lld", CPU64Regs, mem64>, Requires<[IsN64]> { +def LLD : LLBase<0x34, "lld", CPU64Regs, mem>, + Requires<[NotN64, HasStandardEncoding]>; +def LLD_P8 : LLBase<0x34, "lld", CPU64Regs, mem64>, + Requires<[IsN64, HasStandardEncoding]> { let isCodeGenOnly = 1; } -def SCD : SCBase<0x3c, "scd", CPU64Regs, mem>, Requires<[NotN64]>; -def SCD_P8 : SCBase<0x3c, "scd", CPU64Regs, mem64>, Requires<[IsN64]> { +def SCD : SCBase<0x3c, "scd", CPU64Regs, mem>, + Requires<[NotN64, HasStandardEncoding]>; +def SCD_P8 : SCBase<0x3c, "scd", CPU64Regs, mem64>, + Requires<[IsN64, HasStandardEncoding]> { let isCodeGenOnly = 1; } /// Jump and Branch Instructions -def JR64 : JumpFR<0x00, 0x08, "jr", CPU64Regs>; +def JR64 : IndirectBranch<CPU64Regs>; def BEQ64 : CBranch<0x04, "beq", seteq, CPU64Regs>; def BNE64 : CBranch<0x05, "bne", setne, CPU64Regs>; def BGEZ64 : CBranchZero<0x01, 1, "bgez", setge, CPU64Regs>; @@ -187,7 +212,7 @@ def LEA_ADDiu64 : EffectiveAddress<"daddiu\t$rt, $addr", CPU64Regs, mem_ea_64>; } let Uses = [SP_64], DecoderNamespace = "Mips64" in def DynAlloc64 : EffectiveAddress<"daddiu\t$rt, $addr", CPU64Regs, mem_ea_64>, - Requires<[IsN64]> { + Requires<[IsN64, HasStandardEncoding]> { let isCodeGenOnly = 1; } let DecoderNamespace = "Mips64" in { @@ -209,48 +234,50 @@ def SLL64_64 : FR<0x0, 0x00, (outs CPU64Regs:$rd), (ins CPU64Regs:$rt), //===----------------------------------------------------------------------===// // extended loads -let Predicates = [NotN64] in { - def : Pat<(i64 (extloadi1 addr:$src)), (LB64 addr:$src)>; - def : Pat<(i64 (extloadi8 addr:$src)), (LB64 addr:$src)>; - def : Pat<(i64 (extloadi16_a addr:$src)), (LH64 addr:$src)>; - def : Pat<(i64 (extloadi16_u addr:$src)), (ULH64 addr:$src)>; - def : Pat<(i64 (extloadi32_a addr:$src)), (LW64 addr:$src)>; - def : Pat<(i64 (extloadi32_u addr:$src)), (ULW64 addr:$src)>; - def : Pat<(zextloadi32_u addr:$a), (DSRL (DSLL (ULW64 addr:$a), 32), 32)>; +let Predicates = [NotN64, HasStandardEncoding] in { + def : MipsPat<(i64 (extloadi1 addr:$src)), (LB64 addr:$src)>; + def : MipsPat<(i64 (extloadi8 addr:$src)), (LB64 addr:$src)>; + def : MipsPat<(i64 (extloadi16_a addr:$src)), (LH64 addr:$src)>; + def : MipsPat<(i64 (extloadi16_u addr:$src)), (ULH64 addr:$src)>; + def : MipsPat<(i64 (extloadi32_a addr:$src)), (LW64 addr:$src)>; + def : MipsPat<(i64 (extloadi32_u addr:$src)), (ULW64 addr:$src)>; + def : MipsPat<(zextloadi32_u addr:$a), (DSRL (DSLL (ULW64 addr:$a), 32), 32)>; } -let Predicates = [IsN64] in { - def : Pat<(i64 (extloadi1 addr:$src)), (LB64_P8 addr:$src)>; - def : Pat<(i64 (extloadi8 addr:$src)), (LB64_P8 addr:$src)>; - def : Pat<(i64 (extloadi16_a addr:$src)), (LH64_P8 addr:$src)>; - def : Pat<(i64 (extloadi16_u addr:$src)), (ULH64_P8 addr:$src)>; - def : Pat<(i64 (extloadi32_a addr:$src)), (LW64_P8 addr:$src)>; - def : Pat<(i64 (extloadi32_u addr:$src)), (ULW64_P8 addr:$src)>; - def : Pat<(zextloadi32_u addr:$a), (DSRL (DSLL (ULW64_P8 addr:$a), 32), 32)>; +let Predicates = [IsN64, HasStandardEncoding] in { + def : MipsPat<(i64 (extloadi1 addr:$src)), (LB64_P8 addr:$src)>; + def : MipsPat<(i64 (extloadi8 addr:$src)), (LB64_P8 addr:$src)>; + def : MipsPat<(i64 (extloadi16_a addr:$src)), (LH64_P8 addr:$src)>; + def : MipsPat<(i64 (extloadi16_u addr:$src)), (ULH64_P8 addr:$src)>; + def : MipsPat<(i64 (extloadi32_a addr:$src)), (LW64_P8 addr:$src)>; + def : MipsPat<(i64 (extloadi32_u addr:$src)), (ULW64_P8 addr:$src)>; + def : MipsPat<(zextloadi32_u addr:$a), + (DSRL (DSLL (ULW64_P8 addr:$a), 32), 32)>; } // hi/lo relocs -def : Pat<(MipsHi tglobaladdr:$in), (LUi64 tglobaladdr:$in)>; -def : Pat<(MipsHi tblockaddress:$in), (LUi64 tblockaddress:$in)>; -def : Pat<(MipsHi tjumptable:$in), (LUi64 tjumptable:$in)>; -def : Pat<(MipsHi tconstpool:$in), (LUi64 tconstpool:$in)>; -def : Pat<(MipsHi tglobaltlsaddr:$in), (LUi64 tglobaltlsaddr:$in)>; - -def : Pat<(MipsLo tglobaladdr:$in), (DADDiu ZERO_64, tglobaladdr:$in)>; -def : Pat<(MipsLo tblockaddress:$in), (DADDiu ZERO_64, tblockaddress:$in)>; -def : Pat<(MipsLo tjumptable:$in), (DADDiu ZERO_64, tjumptable:$in)>; -def : Pat<(MipsLo tconstpool:$in), (DADDiu ZERO_64, tconstpool:$in)>; -def : Pat<(MipsLo tglobaltlsaddr:$in), (DADDiu ZERO_64, tglobaltlsaddr:$in)>; - -def : Pat<(add CPU64Regs:$hi, (MipsLo tglobaladdr:$lo)), - (DADDiu CPU64Regs:$hi, tglobaladdr:$lo)>; -def : Pat<(add CPU64Regs:$hi, (MipsLo tblockaddress:$lo)), - (DADDiu CPU64Regs:$hi, tblockaddress:$lo)>; -def : Pat<(add CPU64Regs:$hi, (MipsLo tjumptable:$lo)), - (DADDiu CPU64Regs:$hi, tjumptable:$lo)>; -def : Pat<(add CPU64Regs:$hi, (MipsLo tconstpool:$lo)), - (DADDiu CPU64Regs:$hi, tconstpool:$lo)>; -def : Pat<(add CPU64Regs:$hi, (MipsLo tglobaltlsaddr:$lo)), - (DADDiu CPU64Regs:$hi, tglobaltlsaddr:$lo)>; +def : MipsPat<(MipsHi tglobaladdr:$in), (LUi64 tglobaladdr:$in)>; +def : MipsPat<(MipsHi tblockaddress:$in), (LUi64 tblockaddress:$in)>; +def : MipsPat<(MipsHi tjumptable:$in), (LUi64 tjumptable:$in)>; +def : MipsPat<(MipsHi tconstpool:$in), (LUi64 tconstpool:$in)>; +def : MipsPat<(MipsHi tglobaltlsaddr:$in), (LUi64 tglobaltlsaddr:$in)>; + +def : MipsPat<(MipsLo tglobaladdr:$in), (DADDiu ZERO_64, tglobaladdr:$in)>; +def : MipsPat<(MipsLo tblockaddress:$in), (DADDiu ZERO_64, tblockaddress:$in)>; +def : MipsPat<(MipsLo tjumptable:$in), (DADDiu ZERO_64, tjumptable:$in)>; +def : MipsPat<(MipsLo tconstpool:$in), (DADDiu ZERO_64, tconstpool:$in)>; +def : MipsPat<(MipsLo tglobaltlsaddr:$in), + (DADDiu ZERO_64, tglobaltlsaddr:$in)>; + +def : MipsPat<(add CPU64Regs:$hi, (MipsLo tglobaladdr:$lo)), + (DADDiu CPU64Regs:$hi, tglobaladdr:$lo)>; +def : MipsPat<(add CPU64Regs:$hi, (MipsLo tblockaddress:$lo)), + (DADDiu CPU64Regs:$hi, tblockaddress:$lo)>; +def : MipsPat<(add CPU64Regs:$hi, (MipsLo tjumptable:$lo)), + (DADDiu CPU64Regs:$hi, tjumptable:$lo)>; +def : MipsPat<(add CPU64Regs:$hi, (MipsLo tconstpool:$lo)), + (DADDiu CPU64Regs:$hi, tconstpool:$lo)>; +def : MipsPat<(add CPU64Regs:$hi, (MipsLo tglobaltlsaddr:$lo)), + (DADDiu CPU64Regs:$hi, tglobaltlsaddr:$lo)>; def : WrapperPat<tglobaladdr, DADDiu, CPU64Regs>; def : WrapperPat<tconstpool, DADDiu, CPU64Regs>; @@ -270,19 +297,22 @@ defm : SetgePats<CPU64Regs, SLT64, SLTu64>; defm : SetgeImmPats<CPU64Regs, SLTi64, SLTiu64>; // select MipsDynAlloc -def : Pat<(MipsDynAlloc addr:$f), (DynAlloc64 addr:$f)>, Requires<[IsN64]>; +def : MipsPat<(MipsDynAlloc addr:$f), (DynAlloc64 addr:$f)>, + Requires<[IsN64, HasStandardEncoding]>; // truncate -def : Pat<(i32 (trunc CPU64Regs:$src)), - (SLL (EXTRACT_SUBREG CPU64Regs:$src, sub_32), 0)>, Requires<[IsN64]>; +def : MipsPat<(i32 (trunc CPU64Regs:$src)), + (SLL (EXTRACT_SUBREG CPU64Regs:$src, sub_32), 0)>, + Requires<[IsN64, HasStandardEncoding]>; // 32-to-64-bit extension -def : Pat<(i64 (anyext CPURegs:$src)), (SLL64_32 CPURegs:$src)>; -def : Pat<(i64 (zext CPURegs:$src)), (DSRL (DSLL64_32 CPURegs:$src), 32)>; -def : Pat<(i64 (sext CPURegs:$src)), (SLL64_32 CPURegs:$src)>; +def : MipsPat<(i64 (anyext CPURegs:$src)), (SLL64_32 CPURegs:$src)>; +def : MipsPat<(i64 (zext CPURegs:$src)), (DSRL (DSLL64_32 CPURegs:$src), 32)>; +def : MipsPat<(i64 (sext CPURegs:$src)), (SLL64_32 CPURegs:$src)>; // Sign extend in register -def : Pat<(i64 (sext_inreg CPU64Regs:$src, i32)), (SLL64_64 CPU64Regs:$src)>; +def : MipsPat<(i64 (sext_inreg CPU64Regs:$src, i32)), + (SLL64_64 CPU64Regs:$src)>; -// bswap pattern -def : Pat<(bswap CPU64Regs:$rt), (DSHD (DSBH CPU64Regs:$rt))>; +// bswap MipsPattern +def : MipsPat<(bswap CPU64Regs:$rt), (DSHD (DSBH CPU64Regs:$rt))>; diff --git a/lib/Target/Mips/MipsAsmPrinter.cpp b/lib/Target/Mips/MipsAsmPrinter.cpp index 8206cfc..00ff754 100644 --- a/lib/Target/Mips/MipsAsmPrinter.cpp +++ b/lib/Target/Mips/MipsAsmPrinter.cpp @@ -13,29 +13,29 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "mips-asm-printer" -#include "MipsAsmPrinter.h" #include "Mips.h" +#include "MipsAsmPrinter.h" #include "MipsInstrInfo.h" +#include "MipsMCInstLower.h" #include "InstPrinter/MipsInstPrinter.h" #include "MCTargetDesc/MipsBaseInfo.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Twine.h" -#include "llvm/Analysis/DebugInfo.h" #include "llvm/BasicBlock.h" -#include "llvm/Instructions.h" -#include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineMemOperand.h" +#include "llvm/InlineAsm.h" #include "llvm/Instructions.h" -#include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCAsmInfo.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" +#include "llvm/Support/TargetRegistry.h" #include "llvm/Target/Mangler.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetLoweringObjectFile.h" @@ -43,19 +43,6 @@ using namespace llvm; -void MipsAsmPrinter::EmitInstrWithMacroNoAT(const MachineInstr *MI) { - MCInst TmpInst; - - MCInstLowering.Lower(MI, TmpInst); - OutStreamer.EmitRawText(StringRef("\t.set\tmacro")); - if (MipsFI->getEmitNOAT()) - OutStreamer.EmitRawText(StringRef("\t.set\tat")); - OutStreamer.EmitInstruction(TmpInst); - if (MipsFI->getEmitNOAT()) - OutStreamer.EmitRawText(StringRef("\t.set\tnoat")); - OutStreamer.EmitRawText(StringRef("\t.set\tnomacro")); -} - bool MipsAsmPrinter::runOnMachineFunction(MachineFunction &MF) { MipsFI = MF.getInfo<MipsFunctionInfo>(); AsmPrinter::runOnMachineFunction(MF); @@ -71,84 +58,33 @@ void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) { return; } - unsigned Opc = MI->getOpcode(); - MCInst TmpInst0; - SmallVector<MCInst, 4> MCInsts; - - switch (Opc) { - case Mips::ULW: - case Mips::ULH: - case Mips::ULHu: - case Mips::USW: - case Mips::USH: - case Mips::ULW_P8: - case Mips::ULH_P8: - case Mips::ULHu_P8: - case Mips::USW_P8: - case Mips::USH_P8: - case Mips::ULD: - case Mips::ULW64: - case Mips::ULH64: - case Mips::ULHu64: - case Mips::USD: - case Mips::USW64: - case Mips::USH64: - case Mips::ULD_P8: - case Mips::ULW64_P8: - case Mips::ULH64_P8: - case Mips::ULHu64_P8: - case Mips::USD_P8: - case Mips::USW64_P8: - case Mips::USH64_P8: { - if (OutStreamer.hasRawTextSupport()) { - EmitInstrWithMacroNoAT(MI); - return; - } - - MCInstLowering.LowerUnalignedLoadStore(MI, MCInsts); - for (SmallVector<MCInst, 4>::iterator I = MCInsts.begin(); I - != MCInsts.end(); ++I) - OutStreamer.EmitInstruction(*I); - - return; - } - case Mips::CPRESTORE: { - const MachineOperand &MO = MI->getOperand(0); - assert(MO.isImm() && "CPRESTORE's operand must be an immediate."); - int64_t Offset = MO.getImm(); - - if (OutStreamer.hasRawTextSupport()) { - if (!isInt<16>(Offset)) { - EmitInstrWithMacroNoAT(MI); + // Direct object specific instruction lowering + if (!OutStreamer.hasRawTextSupport()) + switch (MI->getOpcode()) { + case Mips::DSLL: + case Mips::DSRL: + case Mips::DSRA: + assert(MI->getNumOperands() == 3 && + "Invalid no. of machine operands for shift!"); + assert(MI->getOperand(2).isImm()); + int64_t Shift = MI->getOperand(2).getImm(); + if (Shift > 31) { + MCInst TmpInst0; + MCInstLowering.LowerLargeShift(MI, TmpInst0, Shift - 32); + OutStreamer.EmitInstruction(TmpInst0); return; } - } else { - MCInstLowering.LowerCPRESTORE(Offset, MCInsts); - - for (SmallVector<MCInst, 4>::iterator I = MCInsts.begin(); - I != MCInsts.end(); ++I) - OutStreamer.EmitInstruction(*I); - - return; + break; } - break; - } - case Mips::SETGP01: { - MCInstLowering.LowerSETGP01(MI, MCInsts); - - for (SmallVector<MCInst, 4>::iterator I = MCInsts.begin(); - I != MCInsts.end(); ++I) - OutStreamer.EmitInstruction(*I); - - return; - } - default: - break; - } + MachineBasicBlock::const_instr_iterator I = MI; + MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end(); - MCInstLowering.Lower(MI, TmpInst0); - OutStreamer.EmitInstruction(TmpInst0); + do { + MCInst TmpInst0; + MCInstLowering.Lower(I++, TmpInst0); + OutStreamer.EmitInstruction(TmpInst0); + } while ((I != E) && I->isInsideBundle()); } //===----------------------------------------------------------------------===// @@ -197,9 +133,9 @@ void MipsAsmPrinter::printSavedRegsBitmask(raw_ostream &O) { const MachineFrameInfo *MFI = MF->getFrameInfo(); const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); // size of stack area to which FP callee-saved regs are saved. - unsigned CPURegSize = Mips::CPURegsRegisterClass->getSize(); - unsigned FGR32RegSize = Mips::FGR32RegisterClass->getSize(); - unsigned AFGR64RegSize = Mips::AFGR64RegisterClass->getSize(); + unsigned CPURegSize = Mips::CPURegsRegClass.getSize(); + unsigned FGR32RegSize = Mips::FGR32RegClass.getSize(); + unsigned AFGR64RegSize = Mips::AFGR64RegClass.getSize(); bool HasAFGR64Reg = false; unsigned CSFPRegsSize = 0; unsigned i, e = CSI.size(); @@ -207,11 +143,11 @@ void MipsAsmPrinter::printSavedRegsBitmask(raw_ostream &O) { // Set FPU Bitmask. for (i = 0; i != e; ++i) { unsigned Reg = CSI[i].getReg(); - if (Mips::CPURegsRegisterClass->contains(Reg)) + if (Mips::CPURegsRegClass.contains(Reg)) break; unsigned RegNum = getMipsRegisterNumbering(Reg); - if (Mips::AFGR64RegisterClass->contains(Reg)) { + if (Mips::AFGR64RegClass.contains(Reg)) { FPUBitmask |= (3 << RegNum); CSFPRegsSize += AFGR64RegSize; HasAFGR64Reg = true; @@ -283,8 +219,15 @@ const char *MipsAsmPrinter::getCurrentABIString() const { } void MipsAsmPrinter::EmitFunctionEntryLabel() { - if (OutStreamer.hasRawTextSupport()) + if (OutStreamer.hasRawTextSupport()) { + if (Subtarget->inMips16Mode()) + OutStreamer.EmitRawText(StringRef("\t.set\tmips16")); + else + OutStreamer.EmitRawText(StringRef("\t.set\tnomips16")); + // leave out until FSF available gas has micromips changes + // OutStreamer.EmitRawText(StringRef("\t.set\tnomicromips")); OutStreamer.EmitRawText("\t.ent\t" + Twine(CurrentFnSym->getName())); + } OutStreamer.EmitLabel(CurrentFnSym); } @@ -295,10 +238,6 @@ void MipsAsmPrinter::EmitFunctionBodyStart() { emitFrameDirective(); - bool EmitCPLoad = (MF->getTarget().getRelocationModel() == Reloc::PIC_) && - Subtarget->isABI_O32() && MipsFI->globalBaseRegSet() && - MipsFI->globalBaseRegFixed(); - if (OutStreamer.hasRawTextSupport()) { SmallString<128> Str; raw_svector_ostream OS(Str); @@ -306,20 +245,9 @@ void MipsAsmPrinter::EmitFunctionBodyStart() { OutStreamer.EmitRawText(OS.str()); OutStreamer.EmitRawText(StringRef("\t.set\tnoreorder")); - - // Emit .cpload directive if needed. - if (EmitCPLoad) - OutStreamer.EmitRawText(StringRef("\t.cpload\t$25")); - OutStreamer.EmitRawText(StringRef("\t.set\tnomacro")); if (MipsFI->getEmitNOAT()) OutStreamer.EmitRawText(StringRef("\t.set\tnoat")); - } else if (EmitCPLoad) { - SmallVector<MCInst, 4> MCInsts; - MCInstLowering.LowerCPLOAD(MCInsts); - for (SmallVector<MCInst, 4>::iterator I = MCInsts.begin(); - I != MCInsts.end(); ++I) - OutStreamer.EmitInstruction(*I); } } @@ -382,14 +310,99 @@ bool MipsAsmPrinter::isBlockOnlyReachableByFallthrough(const MachineBasicBlock* } // Print out an operand for an inline asm expression. -bool MipsAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, +bool MipsAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, unsigned AsmVariant,const char *ExtraCode, raw_ostream &O) { // Does this asm operand have a single letter operand modifier? - if (ExtraCode && ExtraCode[0]) - return true; // Unknown modifier. + if (ExtraCode && ExtraCode[0]) { + if (ExtraCode[1] != 0) return true; // Unknown modifier. - printOperand(MI, OpNo, O); + const MachineOperand &MO = MI->getOperand(OpNum); + switch (ExtraCode[0]) { + default: + // See if this is a generic print operand + return AsmPrinter::PrintAsmOperand(MI,OpNum,AsmVariant,ExtraCode,O); + case 'X': // hex const int + if ((MO.getType()) != MachineOperand::MO_Immediate) + return true; + O << "0x" << StringRef(utohexstr(MO.getImm())).lower(); + return false; + case 'x': // hex const int (low 16 bits) + if ((MO.getType()) != MachineOperand::MO_Immediate) + return true; + O << "0x" << StringRef(utohexstr(MO.getImm() & 0xffff)).lower(); + return false; + case 'd': // decimal const int + if ((MO.getType()) != MachineOperand::MO_Immediate) + return true; + O << MO.getImm(); + return false; + case 'm': // decimal const int minus 1 + if ((MO.getType()) != MachineOperand::MO_Immediate) + return true; + O << MO.getImm() - 1; + return false; + case 'z': { + // $0 if zero, regular printing otherwise + if (MO.getType() != MachineOperand::MO_Immediate) + return true; + int64_t Val = MO.getImm(); + if (Val) + O << Val; + else + O << "$0"; + return false; + } + case 'D': // Second part of a double word register operand + case 'L': // Low order register of a double word register operand + case 'M': // High order register of a double word register operand + { + if (OpNum == 0) + return true; + const MachineOperand &FlagsOP = MI->getOperand(OpNum - 1); + if (!FlagsOP.isImm()) + return true; + unsigned Flags = FlagsOP.getImm(); + unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags); + // Number of registers represented by this operand. We are looking + // for 2 for 32 bit mode and 1 for 64 bit mode. + if (NumVals != 2) { + if (Subtarget->isGP64bit() && NumVals == 1 && MO.isReg()) { + unsigned Reg = MO.getReg(); + O << '$' << MipsInstPrinter::getRegisterName(Reg); + return false; + } + return true; + } + + unsigned RegOp = OpNum; + if (!Subtarget->isGP64bit()){ + // Endianess reverses which register holds the high or low value + // between M and L. + switch(ExtraCode[0]) { + case 'M': + RegOp = (Subtarget->isLittle()) ? OpNum + 1 : OpNum; + break; + case 'L': + RegOp = (Subtarget->isLittle()) ? OpNum : OpNum + 1; + break; + case 'D': // Always the second part + RegOp = OpNum + 1; + } + if (RegOp >= MI->getNumOperands()) + return true; + const MachineOperand &MO = MI->getOperand(RegOp); + if (!MO.isReg()) + return true; + unsigned Reg = MO.getReg(); + O << '$' << MipsInstPrinter::getRegisterName(Reg); + return false; + } + } + } + } + + printOperand(MI, OpNum, O); return false; } @@ -398,11 +411,12 @@ bool MipsAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, const char *ExtraCode, raw_ostream &O) { if (ExtraCode && ExtraCode[0]) - return true; // Unknown modifier. + return true; // Unknown modifier. const MachineOperand &MO = MI->getOperand(OpNum); assert(MO.isReg() && "unexpected inline asm memory operand"); O << "0($" << MipsInstPrinter::getRegisterName(MO.getReg()) << ")"; + return false; } @@ -450,7 +464,7 @@ void MipsAsmPrinter::printOperand(const MachineInstr *MI, int opNum, break; case MachineOperand::MO_BlockAddress: { - MCSymbol* BA = GetBlockAddressSymbol(MO.getBlockAddress()); + MCSymbol *BA = GetBlockAddressSymbol(MO.getBlockAddress()); O << BA->getName(); break; } @@ -511,7 +525,7 @@ printMemOperandEA(const MachineInstr *MI, int opNum, raw_ostream &O) { void MipsAsmPrinter:: printFCCOperand(const MachineInstr *MI, int opNum, raw_ostream &O, const char *Modifier) { - const MachineOperand& MO = MI->getOperand(opNum); + const MachineOperand &MO = MI->getOperand(opNum); O << Mips::MipsFCCToString((Mips::CondCode)MO.getImm()); } diff --git a/lib/Target/Mips/MipsCallingConv.td b/lib/Target/Mips/MipsCallingConv.td index 4b7e1d3..8aadefd 100644 --- a/lib/Target/Mips/MipsCallingConv.td +++ b/lib/Target/Mips/MipsCallingConv.td @@ -145,6 +145,58 @@ def RetCC_MipsEABI : CallingConv<[ ]>; //===----------------------------------------------------------------------===// +// Mips FastCC Calling Convention +//===----------------------------------------------------------------------===// +def CC_MipsO32_FastCC : CallingConv<[ + // f64 arguments are passed in double-precision floating pointer registers. + CCIfType<[f64], CCAssignToReg<[D0, D1, D2, D3, D4, D5, D6, D7, D8, D9]>>, + + // Stack parameter slots for f64 are 64-bit doublewords and 8-byte aligned. + CCIfType<[f64], CCAssignToStack<8, 8>> +]>; + +def CC_MipsN_FastCC : CallingConv<[ + // Integer arguments are passed in integer registers. + CCIfType<[i64], CCAssignToReg<[A0_64, A1_64, A2_64, A3_64, T0_64, T1_64, + T2_64, T3_64, T4_64, T5_64, T6_64, T7_64, + T8_64, V1_64]>>, + + // f64 arguments are passed in double-precision floating pointer registers. + CCIfType<[f64], CCAssignToReg<[D0_64, D1_64, D2_64, D3_64, D4_64, D5_64, + D6_64, D7_64, D8_64, D9_64, D10_64, D11_64, + D12_64, D13_64, D14_64, D15_64, D16_64, D17_64, + D18_64, D19_64]>>, + + // Stack parameter slots for i64 and f64 are 64-bit doublewords and + // 8-byte aligned. + CCIfType<[i64, f64], CCAssignToStack<8, 8>> +]>; + +def CC_Mips_FastCC : CallingConv<[ + // Handles byval parameters. + CCIfByVal<CCPassByVal<4, 4>>, + + // Promote i8/i16 arguments to i32. + CCIfType<[i8, i16], CCPromoteToType<i32>>, + + // Integer arguments are passed in integer registers. All scratch registers, + // except for AT, V0 and T9, are available to be used as argument registers. + CCIfType<[i32], CCAssignToReg<[A0, A1, A2, A3, T0, T1, T2, T3, T4, T5, T6, + T7, T8, V1]>>, + + // f32 arguments are passed in single-precision floating pointer registers. + CCIfType<[f32], CCAssignToReg<[F0, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, + F11, F12, F13, F14, F15, F16, F17, F18, F19]>>, + + // Stack parameter slots for i32 and f32 are 32-bit words and 4-byte aligned. + CCIfType<[i32, f32], CCAssignToStack<4, 4>>, + + CCIfSubtarget<"isABI_EABI()", CCDelegateTo<CC_MipsEABI>>, + CCIfSubtarget<"isABI_O32()", CCDelegateTo<CC_MipsO32_FastCC>>, + CCDelegateTo<CC_MipsN_FastCC> +]>; + +//===----------------------------------------------------------------------===// // Mips Calling Convention Dispatch //===----------------------------------------------------------------------===// diff --git a/lib/Target/Mips/MipsCodeEmitter.cpp b/lib/Target/Mips/MipsCodeEmitter.cpp index 7d81902..cb7022b 100644 --- a/lib/Target/Mips/MipsCodeEmitter.cpp +++ b/lib/Target/Mips/MipsCodeEmitter.cpp @@ -145,8 +145,8 @@ bool MipsCodeEmitter::runOnMachineFunction(MachineFunction &MF) { for (MachineFunction::iterator MBB = MF.begin(), E = MF.end(); MBB != E; ++MBB){ MCE.StartMachineBasicBlock(MBB); - for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); - I != E; ++I) + for (MachineBasicBlock::instr_iterator I = MBB->instr_begin(), + E = MBB->instr_end(); I != E; ++I) emitInstruction(*I); } } while (MCE.finishFunction(MF)); @@ -258,7 +258,7 @@ void MipsCodeEmitter::emitGlobalAddressUnaligned(const GlobalValue *GV, void MipsCodeEmitter:: emitExternalSymbolAddress(const char *ES, unsigned Reloc) const { MCE.addRelocation(MachineRelocation::getExtSym(MCE.getCurrentPCOffset(), - Reloc, ES, 0, 0, false)); + Reloc, ES, 0, 0)); } void MipsCodeEmitter::emitConstPoolAddress(unsigned CPI, unsigned Reloc) const { diff --git a/lib/Target/Mips/MipsCondMov.td b/lib/Target/Mips/MipsCondMov.td index da33680..b12b1f2 100644 --- a/lib/Target/Mips/MipsCondMov.td +++ b/lib/Target/Mips/MipsCondMov.td @@ -61,41 +61,54 @@ multiclass MovzPats0<RegisterClass CRC, RegisterClass DRC, Instruction MOVZInst, Instruction SLTOp, Instruction SLTuOp, Instruction SLTiOp, Instruction SLTiuOp> { - def : Pat<(select (i32 (setge CRC:$lhs, CRC:$rhs)), DRC:$T, DRC:$F), - (MOVZInst DRC:$T, (SLTOp CRC:$lhs, CRC:$rhs), DRC:$F)>; - def : Pat<(select (i32 (setuge CRC:$lhs, CRC:$rhs)), DRC:$T, DRC:$F), - (MOVZInst DRC:$T, (SLTuOp CRC:$lhs, CRC:$rhs), DRC:$F)>; - def : Pat<(select (i32 (setge CRC:$lhs, immSExt16:$rhs)), DRC:$T, DRC:$F), - (MOVZInst DRC:$T, (SLTiOp CRC:$lhs, immSExt16:$rhs), DRC:$F)>; - def : Pat<(select (i32 (setuge CRC:$lh, immSExt16:$rh)), DRC:$T, DRC:$F), - (MOVZInst DRC:$T, (SLTiuOp CRC:$lh, immSExt16:$rh), DRC:$F)>; - def : Pat<(select (i32 (setle CRC:$lhs, CRC:$rhs)), DRC:$T, DRC:$F), - (MOVZInst DRC:$T, (SLTOp CRC:$rhs, CRC:$lhs), DRC:$F)>; - def : Pat<(select (i32 (setule CRC:$lhs, CRC:$rhs)), DRC:$T, DRC:$F), - (MOVZInst DRC:$T, (SLTuOp CRC:$rhs, CRC:$lhs), DRC:$F)>; + def : MipsPat<(select (i32 (setge CRC:$lhs, CRC:$rhs)), DRC:$T, DRC:$F), + (MOVZInst DRC:$T, (SLTOp CRC:$lhs, CRC:$rhs), DRC:$F)>; + def : MipsPat< + (select (i32 (setuge CRC:$lhs, CRC:$rhs)), DRC:$T, DRC:$F), + (MOVZInst DRC:$T, (SLTuOp CRC:$lhs, CRC:$rhs), DRC:$F)>; + def : MipsPat< + (select (i32 (setge CRC:$lhs, immSExt16:$rhs)), DRC:$T, DRC:$F), + (MOVZInst DRC:$T, (SLTiOp CRC:$lhs, immSExt16:$rhs), DRC:$F)>; + def : MipsPat< + (select (i32 (setuge CRC:$lh, immSExt16:$rh)), DRC:$T, DRC:$F), + (MOVZInst DRC:$T, (SLTiuOp CRC:$lh, immSExt16:$rh), DRC:$F)>; + def : MipsPat< + (select (i32 (setle CRC:$lhs, CRC:$rhs)), DRC:$T, DRC:$F), + (MOVZInst DRC:$T, (SLTOp CRC:$rhs, CRC:$lhs), DRC:$F)>; + def : MipsPat< + (select (i32 (setule CRC:$lhs, CRC:$rhs)), DRC:$T, DRC:$F), + (MOVZInst DRC:$T, (SLTuOp CRC:$rhs, CRC:$lhs), DRC:$F)>; } multiclass MovzPats1<RegisterClass CRC, RegisterClass DRC, Instruction MOVZInst, Instruction XOROp> { - def : Pat<(select (i32 (seteq CRC:$lhs, CRC:$rhs)), DRC:$T, DRC:$F), - (MOVZInst DRC:$T, (XOROp CRC:$lhs, CRC:$rhs), DRC:$F)>; - def : Pat<(select (i32 (seteq CRC:$lhs, 0)), DRC:$T, DRC:$F), - (MOVZInst DRC:$T, CRC:$lhs, DRC:$F)>; + def : MipsPat<(select (i32 (seteq CRC:$lhs, CRC:$rhs)), DRC:$T, DRC:$F), + (MOVZInst DRC:$T, (XOROp CRC:$lhs, CRC:$rhs), DRC:$F)>; + def : MipsPat<(select (i32 (seteq CRC:$lhs, 0)), DRC:$T, DRC:$F), + (MOVZInst DRC:$T, CRC:$lhs, DRC:$F)>; +} + +multiclass MovzPats2<RegisterClass CRC, RegisterClass DRC, + Instruction MOVZInst, Instruction XORiOp> { + def : MipsPat< + (select (i32 (seteq CRC:$lhs, immZExt16:$uimm16)), DRC:$T, DRC:$F), + (MOVZInst DRC:$T, (XORiOp CRC:$lhs, immZExt16:$uimm16), DRC:$F)>; } multiclass MovnPats<RegisterClass CRC, RegisterClass DRC, Instruction MOVNInst, Instruction XOROp> { - def : Pat<(select (i32 (setne CRC:$lhs, CRC:$rhs)), DRC:$T, DRC:$F), - (MOVNInst DRC:$T, (XOROp CRC:$lhs, CRC:$rhs), DRC:$F)>; - def : Pat<(select CRC:$cond, DRC:$T, DRC:$F), - (MOVNInst DRC:$T, CRC:$cond, DRC:$F)>; - def : Pat<(select (i32 (setne CRC:$lhs, 0)),DRC:$T, DRC:$F), - (MOVNInst DRC:$T, CRC:$lhs, DRC:$F)>; + def : MipsPat<(select (i32 (setne CRC:$lhs, CRC:$rhs)), DRC:$T, DRC:$F), + (MOVNInst DRC:$T, (XOROp CRC:$lhs, CRC:$rhs), DRC:$F)>; + def : MipsPat<(select CRC:$cond, DRC:$T, DRC:$F), + (MOVNInst DRC:$T, CRC:$cond, DRC:$F)>; + def : MipsPat<(select (i32 (setne CRC:$lhs, 0)),DRC:$T, DRC:$F), + (MOVNInst DRC:$T, CRC:$lhs, DRC:$F)>; } // Instantiation of instructions. def MOVZ_I_I : CondMovIntInt<CPURegs, CPURegs, 0x0a, "movz">; -let Predicates = [HasMips64],DecoderNamespace = "Mips64" in { +let Predicates = [HasMips64, HasStandardEncoding], + DecoderNamespace = "Mips64" in { def MOVZ_I_I64 : CondMovIntInt<CPURegs, CPU64Regs, 0x0a, "movz">; def MOVZ_I64_I : CondMovIntInt<CPU64Regs, CPURegs, 0x0a, "movz"> { let isCodeGenOnly = 1; @@ -106,7 +119,8 @@ let Predicates = [HasMips64],DecoderNamespace = "Mips64" in { } def MOVN_I_I : CondMovIntInt<CPURegs, CPURegs, 0x0b, "movn">; -let Predicates = [HasMips64],DecoderNamespace = "Mips64" in { +let Predicates = [HasMips64, HasStandardEncoding], + DecoderNamespace = "Mips64" in { def MOVN_I_I64 : CondMovIntInt<CPURegs, CPU64Regs, 0x0b, "movn">; def MOVN_I64_I : CondMovIntInt<CPU64Regs, CPURegs, 0x0b, "movn"> { let isCodeGenOnly = 1; @@ -118,21 +132,22 @@ let Predicates = [HasMips64],DecoderNamespace = "Mips64" in { def MOVZ_I_S : CondMovIntFP<CPURegs, FGR32, 16, 18, "movz.s">; def MOVZ_I64_S : CondMovIntFP<CPU64Regs, FGR32, 16, 18, "movz.s">, - Requires<[HasMips64]> { + Requires<[HasMips64, HasStandardEncoding]> { let DecoderNamespace = "Mips64"; } def MOVN_I_S : CondMovIntFP<CPURegs, FGR32, 16, 19, "movn.s">; def MOVN_I64_S : CondMovIntFP<CPU64Regs, FGR32, 16, 19, "movn.s">, - Requires<[HasMips64]> { + Requires<[HasMips64, HasStandardEncoding]> { let DecoderNamespace = "Mips64"; } -let Predicates = [NotFP64bit] in { +let Predicates = [NotFP64bit, HasStandardEncoding] in { def MOVZ_I_D32 : CondMovIntFP<CPURegs, AFGR64, 17, 18, "movz.d">; def MOVN_I_D32 : CondMovIntFP<CPURegs, AFGR64, 17, 19, "movn.d">; } -let Predicates = [IsFP64bit],DecoderNamespace = "Mips64" in { +let Predicates = [IsFP64bit, HasStandardEncoding], + DecoderNamespace = "Mips64" in { def MOVZ_I_D64 : CondMovIntFP<CPURegs, FGR64, 17, 18, "movz.d">; def MOVZ_I64_D64 : CondMovIntFP<CPU64Regs, FGR64, 17, 18, "movz.d"> { let isCodeGenOnly = 1; @@ -145,24 +160,25 @@ let Predicates = [IsFP64bit],DecoderNamespace = "Mips64" in { def MOVT_I : CondMovFPInt<CPURegs, MipsCMovFP_T, 1, "movt">; def MOVT_I64 : CondMovFPInt<CPU64Regs, MipsCMovFP_T, 1, "movt">, - Requires<[HasMips64]> { + Requires<[HasMips64, HasStandardEncoding]> { let DecoderNamespace = "Mips64"; } def MOVF_I : CondMovFPInt<CPURegs, MipsCMovFP_F, 0, "movf">; def MOVF_I64 : CondMovFPInt<CPU64Regs, MipsCMovFP_F, 0, "movf">, - Requires<[HasMips64]> { + Requires<[HasMips64, HasStandardEncoding]> { let DecoderNamespace = "Mips64"; } def MOVT_S : CondMovFPFP<FGR32, MipsCMovFP_T, 16, 1, "movt.s">; def MOVF_S : CondMovFPFP<FGR32, MipsCMovFP_F, 16, 0, "movf.s">; -let Predicates = [NotFP64bit] in { +let Predicates = [NotFP64bit, HasStandardEncoding] in { def MOVT_D32 : CondMovFPFP<AFGR64, MipsCMovFP_T, 17, 1, "movt.d">; def MOVF_D32 : CondMovFPFP<AFGR64, MipsCMovFP_F, 17, 0, "movf.d">; } -let Predicates = [IsFP64bit], DecoderNamespace = "Mips64" in { +let Predicates = [IsFP64bit, HasStandardEncoding], + DecoderNamespace = "Mips64" in { def MOVT_D64 : CondMovFPFP<FGR64, MipsCMovFP_T, 17, 1, "movt.d">; def MOVF_D64 : CondMovFPFP<FGR64, MipsCMovFP_F, 17, 0, "movf.d">; } @@ -170,7 +186,8 @@ let Predicates = [IsFP64bit], DecoderNamespace = "Mips64" in { // Instantiation of conditional move patterns. defm : MovzPats0<CPURegs, CPURegs, MOVZ_I_I, SLT, SLTu, SLTi, SLTiu>; defm : MovzPats1<CPURegs, CPURegs, MOVZ_I_I, XOR>; -let Predicates = [HasMips64] in { +defm : MovzPats2<CPURegs, CPURegs, MOVZ_I_I, XORi>; +let Predicates = [HasMips64, HasStandardEncoding] in { defm : MovzPats0<CPURegs, CPU64Regs, MOVZ_I_I64, SLT, SLTu, SLTi, SLTiu>; defm : MovzPats0<CPU64Regs, CPURegs, MOVZ_I_I, SLT64, SLTu64, SLTi64, SLTiu64>; @@ -179,10 +196,13 @@ let Predicates = [HasMips64] in { defm : MovzPats1<CPURegs, CPU64Regs, MOVZ_I_I64, XOR>; defm : MovzPats1<CPU64Regs, CPURegs, MOVZ_I64_I, XOR64>; defm : MovzPats1<CPU64Regs, CPU64Regs, MOVZ_I64_I64, XOR64>; + defm : MovzPats2<CPURegs, CPU64Regs, MOVZ_I_I64, XORi>; + defm : MovzPats2<CPU64Regs, CPURegs, MOVZ_I64_I, XORi64>; + defm : MovzPats2<CPU64Regs, CPU64Regs, MOVZ_I64_I64, XORi64>; } defm : MovnPats<CPURegs, CPURegs, MOVN_I_I, XOR>; -let Predicates = [HasMips64] in { +let Predicates = [HasMips64, HasStandardEncoding] in { defm : MovnPats<CPURegs, CPU64Regs, MOVN_I_I64, XOR>; defm : MovnPats<CPU64Regs, CPURegs, MOVN_I64_I, XOR64>; defm : MovnPats<CPU64Regs, CPU64Regs, MOVN_I64_I64, XOR64>; @@ -191,19 +211,19 @@ let Predicates = [HasMips64] in { defm : MovzPats0<CPURegs, FGR32, MOVZ_I_S, SLT, SLTu, SLTi, SLTiu>; defm : MovzPats1<CPURegs, FGR32, MOVZ_I_S, XOR>; defm : MovnPats<CPURegs, FGR32, MOVN_I_S, XOR>; -let Predicates = [HasMips64] in { +let Predicates = [HasMips64, HasStandardEncoding] in { defm : MovzPats0<CPU64Regs, FGR32, MOVZ_I_S, SLT64, SLTu64, SLTi64, SLTiu64>; defm : MovzPats1<CPU64Regs, FGR32, MOVZ_I64_S, XOR64>; defm : MovnPats<CPU64Regs, FGR32, MOVN_I64_S, XOR64>; } -let Predicates = [NotFP64bit] in { +let Predicates = [NotFP64bit, HasStandardEncoding] in { defm : MovzPats0<CPURegs, AFGR64, MOVZ_I_D32, SLT, SLTu, SLTi, SLTiu>; defm : MovzPats1<CPURegs, AFGR64, MOVZ_I_D32, XOR>; defm : MovnPats<CPURegs, AFGR64, MOVN_I_D32, XOR>; } -let Predicates = [IsFP64bit] in { +let Predicates = [IsFP64bit, HasStandardEncoding] in { defm : MovzPats0<CPURegs, FGR64, MOVZ_I_D64, SLT, SLTu, SLTi, SLTiu>; defm : MovzPats0<CPU64Regs, FGR64, MOVZ_I_D64, SLT64, SLTu64, SLTi64, SLTiu64>; diff --git a/lib/Target/Mips/MipsDelaySlotFiller.cpp b/lib/Target/Mips/MipsDelaySlotFiller.cpp index debf2f1..2bba8a3 100644 --- a/lib/Target/Mips/MipsDelaySlotFiller.cpp +++ b/lib/Target/Mips/MipsDelaySlotFiller.cpp @@ -36,12 +36,21 @@ static cl::opt<bool> EnableDelaySlotFiller( cl::desc("Fill the Mips delay slots useful instructions."), cl::Hidden); +// This option can be used to silence complaints by machine verifier passes. +static cl::opt<bool> SkipDelaySlotFiller( + "skip-mips-delay-filler", + cl::init(false), + cl::desc("Skip MIPS' delay slot filling pass."), + cl::Hidden); + namespace { struct Filler : public MachineFunctionPass { + typedef MachineBasicBlock::instr_iterator InstrIter; + typedef MachineBasicBlock::reverse_instr_iterator ReverseInstrIter; TargetMachine &TM; const TargetInstrInfo *TII; - MachineBasicBlock::iterator LastFiller; + InstrIter LastFiller; static char ID; Filler(TargetMachine &tm) @@ -53,6 +62,9 @@ namespace { bool runOnMachineBasicBlock(MachineBasicBlock &MBB); bool runOnMachineFunction(MachineFunction &F) { + if (SkipDelaySlotFiller) + return false; + bool Changed = false; for (MachineFunction::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI) @@ -61,27 +73,27 @@ namespace { } bool isDelayFiller(MachineBasicBlock &MBB, - MachineBasicBlock::iterator candidate); + InstrIter candidate); - void insertCallUses(MachineBasicBlock::iterator MI, - SmallSet<unsigned, 32>& RegDefs, - SmallSet<unsigned, 32>& RegUses); + void insertCallUses(InstrIter MI, + SmallSet<unsigned, 32> &RegDefs, + SmallSet<unsigned, 32> &RegUses); - void insertDefsUses(MachineBasicBlock::iterator MI, - SmallSet<unsigned, 32>& RegDefs, - SmallSet<unsigned, 32>& RegUses); + void insertDefsUses(InstrIter MI, + SmallSet<unsigned, 32> &RegDefs, + SmallSet<unsigned, 32> &RegUses); - bool IsRegInSet(SmallSet<unsigned, 32>& RegSet, + bool IsRegInSet(SmallSet<unsigned, 32> &RegSet, unsigned Reg); - bool delayHasHazard(MachineBasicBlock::iterator candidate, + bool delayHasHazard(InstrIter candidate, bool &sawLoad, bool &sawStore, SmallSet<unsigned, 32> &RegDefs, SmallSet<unsigned, 32> &RegUses); bool - findDelayInstr(MachineBasicBlock &MBB, MachineBasicBlock::iterator slot, - MachineBasicBlock::iterator &Filler); + findDelayInstr(MachineBasicBlock &MBB, InstrIter slot, + InstrIter &Filler); }; @@ -93,14 +105,14 @@ namespace { bool Filler:: runOnMachineBasicBlock(MachineBasicBlock &MBB) { bool Changed = false; - LastFiller = MBB.end(); + LastFiller = MBB.instr_end(); - for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I) + for (InstrIter I = MBB.instr_begin(); I != MBB.instr_end(); ++I) if (I->hasDelaySlot()) { ++FilledSlots; Changed = true; - MachineBasicBlock::iterator D; + InstrIter D; if (EnableDelaySlotFiller && findDelayInstr(MBB, I, D)) { MBB.splice(llvm::next(I), &MBB, D); @@ -111,6 +123,10 @@ runOnMachineBasicBlock(MachineBasicBlock &MBB) { // Record the filler instruction that filled the delay slot. // The instruction after it will be visited in the next iteration. LastFiller = ++I; + + // Set InsideBundle bit so that the machine verifier doesn't expect this + // instruction to be a terminator. + LastFiller->setIsInsideBundle(); } return Changed; @@ -123,8 +139,8 @@ FunctionPass *llvm::createMipsDelaySlotFillerPass(MipsTargetMachine &tm) { } bool Filler::findDelayInstr(MachineBasicBlock &MBB, - MachineBasicBlock::iterator slot, - MachineBasicBlock::iterator &Filler) { + InstrIter slot, + InstrIter &Filler) { SmallSet<unsigned, 32> RegDefs; SmallSet<unsigned, 32> RegUses; @@ -133,13 +149,13 @@ bool Filler::findDelayInstr(MachineBasicBlock &MBB, bool sawLoad = false; bool sawStore = false; - for (MachineBasicBlock::reverse_iterator I(slot); I != MBB.rend(); ++I) { + for (ReverseInstrIter I(slot); I != MBB.instr_rend(); ++I) { // skip debug value if (I->isDebugValue()) continue; // Convert to forward iterator. - MachineBasicBlock::iterator FI(llvm::next(I).base()); + InstrIter FI(llvm::next(I).base()); if (I->hasUnmodeledSideEffects() || I->isInlineAsm() @@ -165,7 +181,7 @@ bool Filler::findDelayInstr(MachineBasicBlock &MBB, return false; } -bool Filler::delayHasHazard(MachineBasicBlock::iterator candidate, +bool Filler::delayHasHazard(InstrIter candidate, bool &sawLoad, bool &sawStore, SmallSet<unsigned, 32> &RegDefs, SmallSet<unsigned, 32> &RegUses) { @@ -213,9 +229,9 @@ bool Filler::delayHasHazard(MachineBasicBlock::iterator candidate, } // Insert Defs and Uses of MI into the sets RegDefs and RegUses. -void Filler::insertDefsUses(MachineBasicBlock::iterator MI, - SmallSet<unsigned, 32>& RegDefs, - SmallSet<unsigned, 32>& RegUses) { +void Filler::insertDefsUses(InstrIter MI, + SmallSet<unsigned, 32> &RegDefs, + SmallSet<unsigned, 32> &RegUses) { // If MI is a call or return, just examine the explicit non-variadic operands. MCInstrDesc MCID = MI->getDesc(); unsigned e = MI->isCall() || MI->isReturn() ? MCID.getNumOperands() : @@ -240,14 +256,11 @@ void Filler::insertDefsUses(MachineBasicBlock::iterator MI, } //returns true if the Reg or its alias is in the RegSet. -bool Filler::IsRegInSet(SmallSet<unsigned, 32>& RegSet, unsigned Reg) { - if (RegSet.count(Reg)) - return true; - // check Aliased Registers - for (const uint16_t *Alias = TM.getRegisterInfo()->getAliasSet(Reg); - *Alias; ++Alias) - if (RegSet.count(*Alias)) +bool Filler::IsRegInSet(SmallSet<unsigned, 32> &RegSet, unsigned Reg) { + // Check Reg and all aliased Registers. + for (MCRegAliasIterator AI(Reg, TM.getRegisterInfo(), true); + AI.isValid(); ++AI) + if (RegSet.count(*AI)) return true; - return false; } diff --git a/lib/Target/Mips/MipsEmitGPRestore.cpp b/lib/Target/Mips/MipsEmitGPRestore.cpp deleted file mode 100644 index 119d1a8..0000000 --- a/lib/Target/Mips/MipsEmitGPRestore.cpp +++ /dev/null @@ -1,97 +0,0 @@ -//===-- MipsEmitGPRestore.cpp - Emit GP Restore Instruction ---------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This pass emits instructions that restore $gp right -// after jalr instructions. -// -//===----------------------------------------------------------------------===// - -#define DEBUG_TYPE "emit-gp-restore" - -#include "Mips.h" -#include "MipsTargetMachine.h" -#include "MipsMachineFunction.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/Target/TargetInstrInfo.h" -#include "llvm/ADT/Statistic.h" - -using namespace llvm; - -namespace { - struct Inserter : public MachineFunctionPass { - - TargetMachine &TM; - const TargetInstrInfo *TII; - - static char ID; - Inserter(TargetMachine &tm) - : MachineFunctionPass(ID), TM(tm), TII(tm.getInstrInfo()) { } - - virtual const char *getPassName() const { - return "Mips Emit GP Restore"; - } - - bool runOnMachineFunction(MachineFunction &F); - }; - char Inserter::ID = 0; -} // end of anonymous namespace - -bool Inserter::runOnMachineFunction(MachineFunction &F) { - MipsFunctionInfo *MipsFI = F.getInfo<MipsFunctionInfo>(); - - if ((TM.getRelocationModel() != Reloc::PIC_) || - (!MipsFI->globalBaseRegFixed())) - return false; - - bool Changed = false; - int FI = MipsFI->getGPFI(); - - for (MachineFunction::iterator MFI = F.begin(), MFE = F.end(); - MFI != MFE; ++MFI) { - MachineBasicBlock& MBB = *MFI; - MachineBasicBlock::iterator I = MFI->begin(); - - // If MBB is a landing pad, insert instruction that restores $gp after - // EH_LABEL. - if (MBB.isLandingPad()) { - // Find EH_LABEL first. - for (; I->getOpcode() != TargetOpcode::EH_LABEL; ++I) ; - - // Insert lw. - ++I; - DebugLoc dl = I != MBB.end() ? I->getDebugLoc() : DebugLoc(); - BuildMI(MBB, I, dl, TII->get(Mips::LW), Mips::GP).addFrameIndex(FI) - .addImm(0); - Changed = true; - } - - while (I != MFI->end()) { - if (I->getOpcode() != Mips::JALR) { - ++I; - continue; - } - - DebugLoc dl = I->getDebugLoc(); - // emit lw $gp, ($gp save slot on stack) after jalr - BuildMI(MBB, ++I, dl, TII->get(Mips::LW), Mips::GP).addFrameIndex(FI) - .addImm(0); - Changed = true; - } - } - - return Changed; -} - -/// createMipsEmitGPRestorePass - Returns a pass that emits instructions that -/// restores $gp clobbered by jalr instructions. -FunctionPass *llvm::createMipsEmitGPRestorePass(MipsTargetMachine &tm) { - return new Inserter(tm); -} - diff --git a/lib/Target/Mips/MipsExpandPseudo.cpp b/lib/Target/Mips/MipsExpandPseudo.cpp deleted file mode 100644 index baeae97..0000000 --- a/lib/Target/Mips/MipsExpandPseudo.cpp +++ /dev/null @@ -1,123 +0,0 @@ -//===-- MipsExpandPseudo.cpp - Expand Pseudo Instructions ----------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This pass expands pseudo instructions into target instructions after register -// allocation but before post-RA scheduling. -// -//===----------------------------------------------------------------------===// - -#define DEBUG_TYPE "mips-expand-pseudo" - -#include "Mips.h" -#include "MipsTargetMachine.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/Target/TargetInstrInfo.h" -#include "llvm/ADT/Statistic.h" - -using namespace llvm; - -namespace { - struct MipsExpandPseudo : public MachineFunctionPass { - - TargetMachine &TM; - const TargetInstrInfo *TII; - - static char ID; - MipsExpandPseudo(TargetMachine &tm) - : MachineFunctionPass(ID), TM(tm), TII(tm.getInstrInfo()) { } - - virtual const char *getPassName() const { - return "Mips PseudoInstrs Expansion"; - } - - bool runOnMachineFunction(MachineFunction &F); - bool runOnMachineBasicBlock(MachineBasicBlock &MBB); - - private: - void ExpandBuildPairF64(MachineBasicBlock&, MachineBasicBlock::iterator); - void ExpandExtractElementF64(MachineBasicBlock&, - MachineBasicBlock::iterator); - }; - char MipsExpandPseudo::ID = 0; -} // end of anonymous namespace - -bool MipsExpandPseudo::runOnMachineFunction(MachineFunction& F) { - bool Changed = false; - - for (MachineFunction::iterator I = F.begin(); I != F.end(); ++I) - Changed |= runOnMachineBasicBlock(*I); - - return Changed; -} - -bool MipsExpandPseudo::runOnMachineBasicBlock(MachineBasicBlock& MBB) { - - bool Changed = false; - for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end();) { - const MCInstrDesc& MCid = I->getDesc(); - - switch(MCid.getOpcode()) { - default: - ++I; - continue; - case Mips::SETGP2: - // Convert "setgp2 $globalreg, $t9" to "addu $globalreg, $v0, $t9" - BuildMI(MBB, I, I->getDebugLoc(), TII->get(Mips::ADDu), - I->getOperand(0).getReg()) - .addReg(Mips::V0).addReg(I->getOperand(1).getReg()); - break; - case Mips::BuildPairF64: - ExpandBuildPairF64(MBB, I); - break; - case Mips::ExtractElementF64: - ExpandExtractElementF64(MBB, I); - break; - } - - // delete original instr - MBB.erase(I++); - Changed = true; - } - - return Changed; -} - -void MipsExpandPseudo::ExpandBuildPairF64(MachineBasicBlock& MBB, - MachineBasicBlock::iterator I) { - unsigned DstReg = I->getOperand(0).getReg(); - unsigned LoReg = I->getOperand(1).getReg(), HiReg = I->getOperand(2).getReg(); - const MCInstrDesc& Mtc1Tdd = TII->get(Mips::MTC1); - DebugLoc dl = I->getDebugLoc(); - const uint16_t* SubReg = - TM.getRegisterInfo()->getSubRegisters(DstReg); - - // mtc1 Lo, $fp - // mtc1 Hi, $fp + 1 - BuildMI(MBB, I, dl, Mtc1Tdd, *SubReg).addReg(LoReg); - BuildMI(MBB, I, dl, Mtc1Tdd, *(SubReg + 1)).addReg(HiReg); -} - -void MipsExpandPseudo::ExpandExtractElementF64(MachineBasicBlock& MBB, - MachineBasicBlock::iterator I) { - unsigned DstReg = I->getOperand(0).getReg(); - unsigned SrcReg = I->getOperand(1).getReg(); - unsigned N = I->getOperand(2).getImm(); - const MCInstrDesc& Mfc1Tdd = TII->get(Mips::MFC1); - DebugLoc dl = I->getDebugLoc(); - const uint16_t* SubReg = TM.getRegisterInfo()->getSubRegisters(SrcReg); - - BuildMI(MBB, I, dl, Mfc1Tdd, DstReg).addReg(*(SubReg + N)); -} - -/// createMipsMipsExpandPseudoPass - Returns a pass that expands pseudo -/// instrs into real instrs -FunctionPass *llvm::createMipsExpandPseudoPass(MipsTargetMachine &tm) { - return new MipsExpandPseudo(tm); -} diff --git a/lib/Target/Mips/MipsFrameLowering.cpp b/lib/Target/Mips/MipsFrameLowering.cpp index f8ea3d0..6338f3c 100644 --- a/lib/Target/Mips/MipsFrameLowering.cpp +++ b/lib/Target/Mips/MipsFrameLowering.cpp @@ -94,38 +94,6 @@ bool MipsFrameLowering::targetHandlesStackFrameRounding() const { return true; } -// Build an instruction sequence to load an immediate that is too large to fit -// in 16-bit and add the result to Reg. -static void expandLargeImm(unsigned Reg, int64_t Imm, bool IsN64, - const MipsInstrInfo &TII, MachineBasicBlock& MBB, - MachineBasicBlock::iterator II, DebugLoc DL) { - unsigned LUi = IsN64 ? Mips::LUi64 : Mips::LUi; - unsigned ADDu = IsN64 ? Mips::DADDu : Mips::ADDu; - unsigned ZEROReg = IsN64 ? Mips::ZERO_64 : Mips::ZERO; - unsigned ATReg = IsN64 ? Mips::AT_64 : Mips::AT; - MipsAnalyzeImmediate AnalyzeImm; - const MipsAnalyzeImmediate::InstSeq &Seq = - AnalyzeImm.Analyze(Imm, IsN64 ? 64 : 32, false /* LastInstrIsADDiu */); - MipsAnalyzeImmediate::InstSeq::const_iterator Inst = Seq.begin(); - - // The first instruction can be a LUi, which is different from other - // instructions (ADDiu, ORI and SLL) in that it does not have a register - // operand. - if (Inst->Opc == LUi) - BuildMI(MBB, II, DL, TII.get(LUi), ATReg) - .addImm(SignExtend64<16>(Inst->ImmOpnd)); - else - BuildMI(MBB, II, DL, TII.get(Inst->Opc), ATReg).addReg(ZEROReg) - .addImm(SignExtend64<16>(Inst->ImmOpnd)); - - // Build the remaining instructions in Seq. - for (++Inst; Inst != Seq.end(); ++Inst) - BuildMI(MBB, II, DL, TII.get(Inst->Opc), ATReg).addReg(ATReg) - .addImm(SignExtend64<16>(Inst->ImmOpnd)); - - BuildMI(MBB, II, DL, TII.get(ADDu), Reg).addReg(Reg).addReg(ATReg); -} - void MipsFrameLowering::emitPrologue(MachineFunction &MF) const { MachineBasicBlock &MBB = MF.front(); MachineFrameInfo *MFI = MF.getFrameInfo(); @@ -136,7 +104,6 @@ void MipsFrameLowering::emitPrologue(MachineFunction &MF) const { *static_cast<const MipsInstrInfo*>(MF.getTarget().getInstrInfo()); MachineBasicBlock::iterator MBBI = MBB.begin(); DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); - bool isPIC = (MF.getTarget().getRelocationModel() == Reloc::PIC_); unsigned SP = STI.isABI_N64() ? Mips::SP_64 : Mips::SP; unsigned FP = STI.isABI_N64() ? Mips::FP_64 : Mips::FP; unsigned ZERO = STI.isABI_N64() ? Mips::ZERO_64 : Mips::ZERO; @@ -144,35 +111,17 @@ void MipsFrameLowering::emitPrologue(MachineFunction &MF) const { unsigned ADDiu = STI.isABI_N64() ? Mips::DADDiu : Mips::ADDiu; // First, compute final stack size. - unsigned RegSize = STI.isGP32bit() ? 4 : 8; unsigned StackAlign = getStackAlignment(); - unsigned LocalVarAreaOffset = MipsFI->needGPSaveRestore() ? - (MFI->getObjectOffset(MipsFI->getGPFI()) + RegSize) : - MipsFI->getMaxCallFrameSize(); - uint64_t StackSize = RoundUpToAlignment(LocalVarAreaOffset, StackAlign) + - RoundUpToAlignment(MFI->getStackSize(), StackAlign); + uint64_t StackSize = RoundUpToAlignment(MFI->getStackSize(), StackAlign); + + if (MipsFI->globalBaseRegSet()) + StackSize += MFI->getObjectOffset(MipsFI->getGlobalRegFI()) + StackAlign; + else + StackSize += RoundUpToAlignment(MipsFI->getMaxCallFrameSize(), StackAlign); // Update stack size MFI->setStackSize(StackSize); - // Emit instructions that set the global base register if the target ABI is - // O32. - if (isPIC && MipsFI->globalBaseRegSet() && STI.isABI_O32() && - !MipsFI->globalBaseRegFixed()) { - // See MipsInstrInfo.td for explanation. - MachineBasicBlock *NewEntry = MF.CreateMachineBasicBlock(); - MF.insert(&MBB, NewEntry); - NewEntry->addSuccessor(&MBB); - - // Copy live in registers. - for (MachineBasicBlock::livein_iterator R = MBB.livein_begin(); - R != MBB.livein_end(); ++R) - NewEntry->addLiveIn(*R); - - BuildMI(*NewEntry, NewEntry->begin(), dl, TII.get(Mips:: SETGP01), - Mips::V0); - } - // No need to allocate space on the stack. if (StackSize == 0 && !MFI->adjustsStack()) return; @@ -181,11 +130,20 @@ void MipsFrameLowering::emitPrologue(MachineFunction &MF) const { MachineLocation DstML, SrcML; // Adjust stack. - if (isInt<16>(-StackSize)) // addi sp, sp, (-stacksize) - BuildMI(MBB, MBBI, dl, TII.get(ADDiu), SP).addReg(SP).addImm(-StackSize); + if (isInt<16>(-StackSize)) {// addi sp, sp, (-stacksize) + if (STI.inMips16Mode()) + BuildMI(MBB, MBBI, dl, + TII.get(Mips::SaveRaF16)).addImm(StackSize); // cleanup + else + BuildMI(MBB, MBBI, dl, TII.get(ADDiu), SP).addReg(SP).addImm(-StackSize); + } else { // Expand immediate that doesn't fit in 16-bit. - MipsFI->setEmitNOAT(); - expandLargeImm(SP, -StackSize, STI.isABI_N64(), TII, MBB, MBBI, dl); + unsigned ATReg = STI.isABI_N64() ? Mips::AT_64 : Mips::AT; + + MF.getInfo<MipsFunctionInfo>()->setEmitNOAT(); + Mips::loadImmediate(-StackSize, STI.isABI_N64(), TII, MBB, MBBI, dl, false, + 0); + BuildMI(MBB, MBBI, dl, TII.get(ADDu), SP).addReg(SP).addReg(ATReg); } // emit ".cfi_def_cfa_offset StackSize" @@ -217,20 +175,18 @@ void MipsFrameLowering::emitPrologue(MachineFunction &MF) const { // If Reg is a double precision register, emit two cfa_offsets, // one for each of the paired single precision registers. - if (Mips::AFGR64RegisterClass->contains(Reg)) { - const uint16_t *SubRegs = RegInfo->getSubRegisters(Reg); + if (Mips::AFGR64RegClass.contains(Reg)) { MachineLocation DstML0(MachineLocation::VirtualFP, Offset); MachineLocation DstML1(MachineLocation::VirtualFP, Offset + 4); - MachineLocation SrcML0(*SubRegs); - MachineLocation SrcML1(*(SubRegs + 1)); + MachineLocation SrcML0(RegInfo->getSubReg(Reg, Mips::sub_fpeven)); + MachineLocation SrcML1(RegInfo->getSubReg(Reg, Mips::sub_fpodd)); if (!STI.isLittle()) std::swap(SrcML0, SrcML1); Moves.push_back(MachineMove(CSLabel, DstML0, SrcML0)); Moves.push_back(MachineMove(CSLabel, DstML1, SrcML1)); - } - else { + } else { // Reg is either in CPURegs or FGR32. DstML = MachineLocation(MachineLocation::VirtualFP, Offset); SrcML = MachineLocation(Reg); @@ -252,13 +208,6 @@ void MipsFrameLowering::emitPrologue(MachineFunction &MF) const { SrcML = MachineLocation(MachineLocation::VirtualFP); Moves.push_back(MachineMove(SetFPLabel, DstML, SrcML)); } - - // Restore GP from the saved stack location - if (MipsFI->needGPSaveRestore()) { - unsigned Offset = MFI->getObjectOffset(MipsFI->getGPFI()); - BuildMI(MBB, MBBI, dl, TII.get(Mips::CPRESTORE)).addImm(Offset) - .addReg(Mips::GP); - } } void MipsFrameLowering::emitEpilogue(MachineFunction &MF, @@ -293,16 +242,28 @@ void MipsFrameLowering::emitEpilogue(MachineFunction &MF, return; // Adjust stack. - if (isInt<16>(StackSize)) // addi sp, sp, (-stacksize) - BuildMI(MBB, MBBI, dl, TII.get(ADDiu), SP).addReg(SP).addImm(StackSize); - else // Expand immediate that doesn't fit in 16-bit. - expandLargeImm(SP, StackSize, STI.isABI_N64(), TII, MBB, MBBI, dl); + if (isInt<16>(StackSize)) { // addi sp, sp, (-stacksize) + if (STI.inMips16Mode()) + // assumes stacksize multiple of 8 + BuildMI(MBB, MBBI, dl, + TII.get(Mips::RestoreRaF16)).addImm(StackSize); + else + BuildMI(MBB, MBBI, dl, TII.get(ADDiu), SP).addReg(SP).addImm(StackSize); + } + else { // Expand immediate that doesn't fit in 16-bit. + unsigned ATReg = STI.isABI_N64() ? Mips::AT_64 : Mips::AT; + + MF.getInfo<MipsFunctionInfo>()->setEmitNOAT(); + Mips::loadImmediate(StackSize, STI.isABI_N64(), TII, MBB, MBBI, dl, false, + 0); + BuildMI(MBB, MBBI, dl, TII.get(ADDu), SP).addReg(SP).addReg(ATReg); + } } void MipsFrameLowering:: processFunctionBeforeCalleeSavedScan(MachineFunction &MF, RegScavenger *RS) const { - MachineRegisterInfo& MRI = MF.getRegInfo(); + MachineRegisterInfo &MRI = MF.getRegInfo(); unsigned FP = STI.isABI_N64() ? Mips::FP_64 : Mips::FP; // FIXME: remove this code if register allocator can correctly mark @@ -311,16 +272,35 @@ processFunctionBeforeCalleeSavedScan(MachineFunction &MF, // Mark $fp and $ra as used or unused. if (hasFP(MF)) MRI.setPhysRegUsed(FP); +} - // The register allocator might determine $ra is used after seeing - // instruction "jr $ra", but we do not want PrologEpilogInserter to insert - // instructions to save/restore $ra unless there is a function call. - // To correct this, $ra is explicitly marked unused if there is no - // function call. - if (MF.getFrameInfo()->hasCalls()) - MRI.setPhysRegUsed(Mips::RA); - else { - MRI.setPhysRegUnused(Mips::RA); - MRI.setPhysRegUnused(Mips::RA_64); +bool MipsFrameLowering:: +spillCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector<CalleeSavedInfo> &CSI, + const TargetRegisterInfo *TRI) const { + MachineFunction *MF = MBB.getParent(); + MachineBasicBlock *EntryBlock = MF->begin(); + const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo(); + + for (unsigned i = 0, e = CSI.size(); i != e; ++i) { + // Add the callee-saved register as live-in. Do not add if the register is + // RA and return address is taken, because it has already been added in + // method MipsTargetLowering::LowerRETURNADDR. + // It's killed at the spill, unless the register is RA and return address + // is taken. + unsigned Reg = CSI[i].getReg(); + bool IsRAAndRetAddrIsTaken = (Reg == Mips::RA || Reg == Mips::RA_64) + && MF->getFrameInfo()->isReturnAddressTaken(); + if (!IsRAAndRetAddrIsTaken) + EntryBlock->addLiveIn(Reg); + + // Insert the spill to the stack frame. + bool IsKill = !IsRAAndRetAddrIsTaken; + const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); + TII.storeRegToStackSlot(*EntryBlock, MI, Reg, IsKill, + CSI[i].getFrameIdx(), RC, TRI); } + + return true; } diff --git a/lib/Target/Mips/MipsFrameLowering.h b/lib/Target/Mips/MipsFrameLowering.h index bd1d89f..e364ded 100644 --- a/lib/Target/Mips/MipsFrameLowering.h +++ b/lib/Target/Mips/MipsFrameLowering.h @@ -38,6 +38,11 @@ public: void emitPrologue(MachineFunction &MF) const; void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const; + bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector<CalleeSavedInfo> &CSI, + const TargetRegisterInfo *TRI) const; + bool hasFP(const MachineFunction &MF) const; void processFunctionBeforeCalleeSavedScan(MachineFunction &MF, diff --git a/lib/Target/Mips/MipsISelDAGToDAG.cpp b/lib/Target/Mips/MipsISelDAGToDAG.cpp index f0651c6..ea33b74 100644 --- a/lib/Target/Mips/MipsISelDAGToDAG.cpp +++ b/lib/Target/Mips/MipsISelDAGToDAG.cpp @@ -117,28 +117,32 @@ private: void MipsDAGToDAGISel::InitGlobalBaseReg(MachineFunction &MF) { MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); - if (!MipsFI->globalBaseRegSet()) + if (((MF.getTarget().getRelocationModel() == Reloc::Static) || + Subtarget.inMips16Mode()) && !MipsFI->globalBaseRegSet()) return; MachineBasicBlock &MBB = MF.front(); MachineBasicBlock::iterator I = MBB.begin(); MachineRegisterInfo &RegInfo = MF.getRegInfo(); + const MipsRegisterInfo *TargetRegInfo = TM.getRegisterInfo(); + const MipsInstrInfo *MII = TM.getInstrInfo(); const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc(); - unsigned V0, V1, GlobalBaseReg = MipsFI->getGlobalBaseReg(); - bool FixGlobalBaseReg = MipsFI->globalBaseRegFixed(); - - if (Subtarget.isABI_O32() && FixGlobalBaseReg) - // $gp is the global base register. - V0 = V1 = GlobalBaseReg; - else { - const TargetRegisterClass *RC; - RC = Subtarget.isABI_N64() ? - Mips::CPU64RegsRegisterClass : Mips::CPURegsRegisterClass; - - V0 = RegInfo.createVirtualRegister(RC); - V1 = RegInfo.createVirtualRegister(RC); - } + unsigned V0, V1, V2, GlobalBaseReg = MipsFI->getGlobalBaseReg(); + int FI = 0; + + FI= MipsFI->initGlobalRegFI(); + + const TargetRegisterClass *RC = Subtarget.isABI_N64() ? + (const TargetRegisterClass*)&Mips::CPU64RegsRegClass : + (const TargetRegisterClass*)&Mips::CPURegsRegClass; + + if (Subtarget.inMips16Mode()) + RC=(const TargetRegisterClass*)&Mips::CPU16RegsRegClass; + + V0 = RegInfo.createVirtualRegister(RC); + V1 = RegInfo.createVirtualRegister(RC); + V2 = RegInfo.createVirtualRegister(RC); if (Subtarget.isABI_N64()) { MF.getRegInfo().addLiveIn(Mips::T9_64); @@ -150,10 +154,31 @@ void MipsDAGToDAGISel::InitGlobalBaseReg(MachineFunction &MF) { const GlobalValue *FName = MF.getFunction(); BuildMI(MBB, I, DL, TII.get(Mips::LUi64), V0) .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_HI); - BuildMI(MBB, I, DL, TII.get(Mips::DADDu), V1).addReg(V0).addReg(Mips::T9_64); + BuildMI(MBB, I, DL, TII.get(Mips::DADDu), V1).addReg(V0) + .addReg(Mips::T9_64); BuildMI(MBB, I, DL, TII.get(Mips::DADDiu), GlobalBaseReg).addReg(V1) .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_LO); - } else if (MF.getTarget().getRelocationModel() == Reloc::Static) { + MII->storeRegToStackSlot(MBB, I, GlobalBaseReg, false, FI, RC, + TargetRegInfo); + return; + } + + if (Subtarget.inMips16Mode()) { + BuildMI(MBB, I, DL, TII.get(Mips::LiRxImmX16), V0) + .addExternalSymbol("_gp_disp", MipsII::MO_ABS_HI); + BuildMI(MBB, I, DL, TII.get(Mips::AddiuRxPcImmX16), + V1) + .addExternalSymbol("_gp_disp", MipsII::MO_ABS_LO); + BuildMI(MBB, I, DL, TII.get(Mips::SllX16), + V2 ).addReg(V0).addImm(16); + BuildMI(MBB, I, DL, TII.get(Mips::AdduRxRyRz16), GlobalBaseReg) + .addReg(V1).addReg(V2); + + + return; + } + + if (MF.getTarget().getRelocationModel() == Reloc::Static) { // Set global register to __gnu_local_gp. // // lui $v0, %hi(__gnu_local_gp) @@ -162,27 +187,57 @@ void MipsDAGToDAGISel::InitGlobalBaseReg(MachineFunction &MF) { .addExternalSymbol("__gnu_local_gp", MipsII::MO_ABS_HI); BuildMI(MBB, I, DL, TII.get(Mips::ADDiu), GlobalBaseReg).addReg(V0) .addExternalSymbol("__gnu_local_gp", MipsII::MO_ABS_LO); - } else { - MF.getRegInfo().addLiveIn(Mips::T9); - MBB.addLiveIn(Mips::T9); - - if (Subtarget.isABI_N32()) { - // lui $v0, %hi(%neg(%gp_rel(fname))) - // addu $v1, $v0, $t9 - // addiu $globalbasereg, $v1, %lo(%neg(%gp_rel(fname))) - const GlobalValue *FName = MF.getFunction(); - BuildMI(MBB, I, DL, TII.get(Mips::LUi), V0) - .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_HI); - BuildMI(MBB, I, DL, TII.get(Mips::ADDu), V1).addReg(V0).addReg(Mips::T9); - BuildMI(MBB, I, DL, TII.get(Mips::ADDiu), GlobalBaseReg).addReg(V1) - .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_LO); - } else if (!MipsFI->globalBaseRegFixed()) { - assert(Subtarget.isABI_O32()); - - BuildMI(MBB, I, DL, TII.get(Mips::SETGP2), GlobalBaseReg) - .addReg(Mips::T9); - } + return; + } + + MF.getRegInfo().addLiveIn(Mips::T9); + MBB.addLiveIn(Mips::T9); + + if (Subtarget.isABI_N32()) { + // lui $v0, %hi(%neg(%gp_rel(fname))) + // addu $v1, $v0, $t9 + // addiu $globalbasereg, $v1, %lo(%neg(%gp_rel(fname))) + const GlobalValue *FName = MF.getFunction(); + BuildMI(MBB, I, DL, TII.get(Mips::LUi), V0) + .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_HI); + BuildMI(MBB, I, DL, TII.get(Mips::ADDu), V1).addReg(V0).addReg(Mips::T9); + BuildMI(MBB, I, DL, TII.get(Mips::ADDiu), GlobalBaseReg).addReg(V1) + .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_LO); + MII->storeRegToStackSlot(MBB, I, GlobalBaseReg, false, FI, RC, + TargetRegInfo); + return; } + + assert(Subtarget.isABI_O32()); + + + //if (Subtarget.inMips16Mode()) + // return; // no need to load GP. It can be calculated anywhere + + + + // For O32 ABI, the following instruction sequence is emitted to initialize + // the global base register: + // + // 0. lui $2, %hi(_gp_disp) + // 1. addiu $2, $2, %lo(_gp_disp) + // 2. addu $globalbasereg, $2, $t9 + // + // We emit only the last instruction here. + // + // GNU linker requires that the first two instructions appear at the beginning + // of a function and no instructions be inserted before or between them. + // The two instructions are emitted during lowering to MC layer in order to + // avoid any reordering. + // + // Register $2 (Mips::V0) is added to the list of live-in registers to ensure + // the value instruction 1 (addiu) defines is valid when instruction 2 (addu) + // reads it. + MF.getRegInfo().addLiveIn(Mips::V0); + MBB.addLiveIn(Mips::V0); + BuildMI(MBB, I, DL, TII.get(Mips::ADDu), GlobalBaseReg) + .addReg(Mips::V0).addReg(Mips::T9); + MII->storeRegToStackSlot(MBB, I, GlobalBaseReg, false, FI, RC, TargetRegInfo); } bool MipsDAGToDAGISel::ReplaceUsesWithZeroReg(MachineRegisterInfo *MRI, @@ -212,7 +267,8 @@ bool MipsDAGToDAGISel::ReplaceUsesWithZeroReg(MachineRegisterInfo *MRI, MachineInstr *MI = MO.getParent(); // Do not replace if it is a phi's operand or is tied to def operand. - if (MI->isPHI() || MI->isRegTiedToDefOperand(U.getOperandNo())) + if (MI->isPHI() || MI->isRegTiedToDefOperand(U.getOperandNo()) || + MI->isPseudo()) continue; MO.setReg(ZeroReg); @@ -255,7 +311,7 @@ SelectAddr(SDNode *Parent, SDValue Addr, SDValue &Base, SDValue &Offset) { // If Parent is an unaligned f32 load or store, select a (base + index) // floating point load/store instruction (luxc1 or suxc1). - const LSBaseSDNode* LS = 0; + const LSBaseSDNode *LS = 0; if (Parent && (LS = dyn_cast<LSBaseSDNode>(Parent))) { EVT VT = LS->getMemoryVT(); @@ -316,17 +372,18 @@ SelectAddr(SDNode *Parent, SDValue Addr, SDValue &Base, SDValue &Offset) { // lui $2, %hi($CPI1_0) // lwc1 $f0, %lo($CPI1_0)($2) if (Addr.getOperand(1).getOpcode() == MipsISD::Lo) { - SDValue LoVal = Addr.getOperand(1); - if (isa<ConstantPoolSDNode>(LoVal.getOperand(0)) || - isa<GlobalAddressSDNode>(LoVal.getOperand(0))) { + SDValue LoVal = Addr.getOperand(1), Opnd0 = LoVal.getOperand(0); + if (isa<ConstantPoolSDNode>(Opnd0) || isa<GlobalAddressSDNode>(Opnd0) || + isa<JumpTableSDNode>(Opnd0)) { Base = Addr.getOperand(0); - Offset = LoVal.getOperand(0); + Offset = Opnd0; return true; } } // If an indexed floating point load/store can be emitted, return false. - if (LS && (LS->getMemoryVT() == MVT::f32 || LS->getMemoryVT() == MVT::f64) && + if (LS && + (LS->getMemoryVT() == MVT::f32 || LS->getMemoryVT() == MVT::f64) && Subtarget.hasMips32r2Or64()) return false; } diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index 6a23bc3..7741f9f 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -34,6 +34,8 @@ #include "llvm/CodeGen/ValueTypes.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" + using namespace llvm; // If I is a shifted mask, set the size (Size) and the first bit of the @@ -79,6 +81,14 @@ const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const { case MipsISD::Sync: return "MipsISD::Sync"; case MipsISD::Ext: return "MipsISD::Ext"; case MipsISD::Ins: return "MipsISD::Ins"; + case MipsISD::LWL: return "MipsISD::LWL"; + case MipsISD::LWR: return "MipsISD::LWR"; + case MipsISD::SWL: return "MipsISD::SWL"; + case MipsISD::SWR: return "MipsISD::SWR"; + case MipsISD::LDL: return "MipsISD::LDL"; + case MipsISD::LDR: return "MipsISD::LDR"; + case MipsISD::SDL: return "MipsISD::SDL"; + case MipsISD::SDR: return "MipsISD::SDR"; default: return NULL; } } @@ -96,20 +106,25 @@ MipsTargetLowering(MipsTargetMachine &TM) setBooleanVectorContents(ZeroOrOneBooleanContent); // FIXME: Is this correct? // Set up the register classes - addRegisterClass(MVT::i32, Mips::CPURegsRegisterClass); + addRegisterClass(MVT::i32, &Mips::CPURegsRegClass); if (HasMips64) - addRegisterClass(MVT::i64, Mips::CPU64RegsRegisterClass); + addRegisterClass(MVT::i64, &Mips::CPU64RegsRegClass); + + if (Subtarget->inMips16Mode()) { + addRegisterClass(MVT::i32, &Mips::CPU16RegsRegClass); + addRegisterClass(MVT::i32, &Mips::CPURARegRegClass); + } if (!TM.Options.UseSoftFloat) { - addRegisterClass(MVT::f32, Mips::FGR32RegisterClass); + addRegisterClass(MVT::f32, &Mips::FGR32RegClass); // When dealing with single precision only, use libcalls if (!Subtarget->isSingleFloat()) { if (HasMips64) - addRegisterClass(MVT::f64, Mips::FGR64RegisterClass); + addRegisterClass(MVT::f64, &Mips::FGR64RegClass); else - addRegisterClass(MVT::f64, Mips::AFGR64RegisterClass); + addRegisterClass(MVT::f64, &Mips::AFGR64RegClass); } } @@ -137,6 +152,8 @@ MipsTargetLowering(MipsTargetMachine &TM) setOperationAction(ISD::SELECT, MVT::f32, Custom); setOperationAction(ISD::SELECT, MVT::f64, Custom); setOperationAction(ISD::SELECT, MVT::i32, Custom); + setOperationAction(ISD::SELECT_CC, MVT::f32, Custom); + setOperationAction(ISD::SELECT_CC, MVT::f64, Custom); setOperationAction(ISD::SETCC, MVT::f32, Custom); setOperationAction(ISD::SETCC, MVT::f64, Custom); setOperationAction(ISD::BRCOND, MVT::Other, Custom); @@ -146,6 +163,8 @@ MipsTargetLowering(MipsTargetMachine &TM) setOperationAction(ISD::FCOPYSIGN, MVT::f64, Custom); setOperationAction(ISD::MEMBARRIER, MVT::Other, Custom); setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom); + setOperationAction(ISD::LOAD, MVT::i32, Custom); + setOperationAction(ISD::STORE, MVT::i32, Custom); if (!TM.Options.NoNaNsFPMath) { setOperationAction(ISD::FABS, MVT::f32, Custom); @@ -160,6 +179,14 @@ MipsTargetLowering(MipsTargetMachine &TM) setOperationAction(ISD::ConstantPool, MVT::i64, Custom); setOperationAction(ISD::SELECT, MVT::i64, Custom); setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64, Custom); + setOperationAction(ISD::LOAD, MVT::i64, Custom); + setOperationAction(ISD::STORE, MVT::i64, Custom); + } + + if (!HasMips64) { + setOperationAction(ISD::SHL_PARTS, MVT::i32, Custom); + setOperationAction(ISD::SRA_PARTS, MVT::i32, Custom); + setOperationAction(ISD::SRL_PARTS, MVT::i32, Custom); } setOperationAction(ISD::SDIV, MVT::i32, Expand); @@ -197,9 +224,6 @@ MipsTargetLowering(MipsTargetMachine &TM) if (!Subtarget->hasMips64r2()) setOperationAction(ISD::ROTR, MVT::i64, Expand); - setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand); - setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand); - setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand); setOperationAction(ISD::FSIN, MVT::f32, Expand); setOperationAction(ISD::FSIN, MVT::f64, Expand); setOperationAction(ISD::FCOS, MVT::f32, Expand); @@ -241,9 +265,6 @@ MipsTargetLowering(MipsTargetMachine &TM) setInsertFencesForAtomic(true); - if (Subtarget->isSingleFloat()) - setOperationAction(ISD::SELECT_CC, MVT::f64, Expand); - if (!Subtarget->hasSEInReg()) { setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8, Expand); setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16, Expand); @@ -259,6 +280,13 @@ MipsTargetLowering(MipsTargetMachine &TM) setOperationAction(ISD::BSWAP, MVT::i64, Expand); } + if (HasMips64) { + setLoadExtAction(ISD::SEXTLOAD, MVT::i32, Custom); + setLoadExtAction(ISD::ZEXTLOAD, MVT::i32, Custom); + setLoadExtAction(ISD::EXTLOAD, MVT::i32, Custom); + setTruncStoreAction(MVT::i64, MVT::i32, Custom); + } + setTargetDAGCombine(ISD::ADDE); setTargetDAGCombine(ISD::SUBE); setTargetDAGCombine(ISD::SDIVREM); @@ -266,6 +294,7 @@ MipsTargetLowering(MipsTargetMachine &TM) setTargetDAGCombine(ISD::SELECT); setTargetDAGCombine(ISD::AND); setTargetDAGCombine(ISD::OR); + setTargetDAGCombine(ISD::ADD); setMinFunctionAlignment(HasMips64 ? 3 : 2); @@ -274,6 +303,8 @@ MipsTargetLowering(MipsTargetMachine &TM) setExceptionPointerRegister(IsN64 ? Mips::A0_64 : Mips::A0); setExceptionSelectorRegister(IsN64 ? Mips::A1_64 : Mips::A1); + + maxStoresPerMemcpy = 16; } bool MipsTargetLowering::allowsUnalignedMemoryAccesses(EVT VT) const { @@ -282,7 +313,6 @@ bool MipsTargetLowering::allowsUnalignedMemoryAccesses(EVT VT) const { switch (SVT) { case MVT::i64: case MVT::i32: - case MVT::i16: return true; case MVT::f32: return Subtarget->hasMips32r2Or64(); @@ -303,17 +333,17 @@ EVT MipsTargetLowering::getSetCCResultType(EVT VT) const { // Lo0: initial value of Lo register // Hi0: initial value of Hi register // Return true if pattern matching was successful. -static bool SelectMadd(SDNode* ADDENode, SelectionDAG* CurDAG) { +static bool SelectMadd(SDNode *ADDENode, SelectionDAG *CurDAG) { // ADDENode's second operand must be a flag output of an ADDC node in order // for the matching to be successful. - SDNode* ADDCNode = ADDENode->getOperand(2).getNode(); + SDNode *ADDCNode = ADDENode->getOperand(2).getNode(); if (ADDCNode->getOpcode() != ISD::ADDC) return false; SDValue MultHi = ADDENode->getOperand(0); SDValue MultLo = ADDCNode->getOperand(0); - SDNode* MultNode = MultHi.getNode(); + SDNode *MultNode = MultHi.getNode(); unsigned MultOpc = MultHi.getOpcode(); // MultHi and MultLo must be generated by the same node, @@ -376,17 +406,17 @@ static bool SelectMadd(SDNode* ADDENode, SelectionDAG* CurDAG) { // Lo0: initial value of Lo register // Hi0: initial value of Hi register // Return true if pattern matching was successful. -static bool SelectMsub(SDNode* SUBENode, SelectionDAG* CurDAG) { +static bool SelectMsub(SDNode *SUBENode, SelectionDAG *CurDAG) { // SUBENode's second operand must be a flag output of an SUBC node in order // for the matching to be successful. - SDNode* SUBCNode = SUBENode->getOperand(2).getNode(); + SDNode *SUBCNode = SUBENode->getOperand(2).getNode(); if (SUBCNode->getOpcode() != ISD::SUBC) return false; SDValue MultHi = SUBENode->getOperand(1); SDValue MultLo = SUBCNode->getOperand(1); - SDNode* MultNode = MultHi.getNode(); + SDNode *MultNode = MultHi.getNode(); unsigned MultOpc = MultHi.getOpcode(); // MultHi and MultLo must be generated by the same node, @@ -441,9 +471,9 @@ static bool SelectMsub(SDNode* SUBENode, SelectionDAG* CurDAG) { return true; } -static SDValue PerformADDECombine(SDNode *N, SelectionDAG& DAG, +static SDValue PerformADDECombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, - const MipsSubtarget* Subtarget) { + const MipsSubtarget *Subtarget) { if (DCI.isBeforeLegalize()) return SDValue(); @@ -454,9 +484,9 @@ static SDValue PerformADDECombine(SDNode *N, SelectionDAG& DAG, return SDValue(); } -static SDValue PerformSUBECombine(SDNode *N, SelectionDAG& DAG, +static SDValue PerformSUBECombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, - const MipsSubtarget* Subtarget) { + const MipsSubtarget *Subtarget) { if (DCI.isBeforeLegalize()) return SDValue(); @@ -467,9 +497,9 @@ static SDValue PerformSUBECombine(SDNode *N, SelectionDAG& DAG, return SDValue(); } -static SDValue PerformDivRemCombine(SDNode *N, SelectionDAG& DAG, +static SDValue PerformDivRemCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, - const MipsSubtarget* Subtarget) { + const MipsSubtarget *Subtarget) { if (DCI.isBeforeLegalizeOps()) return SDValue(); @@ -544,7 +574,7 @@ static bool InvertFPCondCode(Mips::CondCode CC) { // Creates and returns an FPCmp node from a setcc node. // Returns Op if setcc is not a floating point comparison. -static SDValue CreateFPCmp(SelectionDAG& DAG, const SDValue& Op) { +static SDValue CreateFPCmp(SelectionDAG &DAG, const SDValue &Op) { // must be a SETCC node if (Op.getOpcode() != ISD::SETCC) return Op; @@ -566,7 +596,7 @@ static SDValue CreateFPCmp(SelectionDAG& DAG, const SDValue& Op) { } // Creates and returns a CMovFPT/F node. -static SDValue CreateCMovFP(SelectionDAG& DAG, SDValue Cond, SDValue True, +static SDValue CreateCMovFP(SelectionDAG &DAG, SDValue Cond, SDValue True, SDValue False, DebugLoc DL) { bool invert = InvertFPCondCode((Mips::CondCode) cast<ConstantSDNode>(Cond.getOperand(2)) @@ -576,9 +606,9 @@ static SDValue CreateCMovFP(SelectionDAG& DAG, SDValue Cond, SDValue True, True.getValueType(), True, False, Cond); } -static SDValue PerformSELECTCombine(SDNode *N, SelectionDAG& DAG, +static SDValue PerformSELECTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, - const MipsSubtarget* Subtarget) { + const MipsSubtarget *Subtarget) { if (DCI.isBeforeLegalizeOps()) return SDValue(); @@ -602,16 +632,16 @@ static SDValue PerformSELECTCombine(SDNode *N, SelectionDAG& DAG, const DebugLoc DL = N->getDebugLoc(); ISD::CondCode CC = cast<CondCodeSDNode>(SetCC.getOperand(2))->get(); SDValue True = N->getOperand(1); - + SetCC = DAG.getSetCC(DL, SetCC.getValueType(), SetCC.getOperand(0), SetCC.getOperand(1), ISD::getSetCCInverse(CC, true)); - + return DAG.getNode(ISD::SELECT, DL, FalseTy, SetCC, False, True); } -static SDValue PerformANDCombine(SDNode *N, SelectionDAG& DAG, +static SDValue PerformANDCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, - const MipsSubtarget* Subtarget) { + const MipsSubtarget *Subtarget) { // Pattern match EXT. // $dst = and ((sra or srl) $src , pos), (2**size - 1) // => ext $dst, $src, size, pos @@ -649,9 +679,9 @@ static SDValue PerformANDCombine(SDNode *N, SelectionDAG& DAG, DAG.getConstant(SMSize, MVT::i32)); } -static SDValue PerformORCombine(SDNode *N, SelectionDAG& DAG, +static SDValue PerformORCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, - const MipsSubtarget* Subtarget) { + const MipsSubtarget *Subtarget) { // Pattern match INS. // $dst = or (and $src1 , mask0), (and (shl $src, pos), mask1), // where mask1 = (2**size - 1) << pos, mask0 = ~mask1 @@ -703,6 +733,33 @@ static SDValue PerformORCombine(SDNode *N, SelectionDAG& DAG, DAG.getConstant(SMSize0, MVT::i32), And0.getOperand(0)); } +static SDValue PerformADDCombine(SDNode *N, SelectionDAG &DAG, + TargetLowering::DAGCombinerInfo &DCI, + const MipsSubtarget *Subtarget) { + // (add v0, (add v1, abs_lo(tjt))) => (add (add v0, v1), abs_lo(tjt)) + + if (DCI.isBeforeLegalizeOps()) + return SDValue(); + + SDValue Add = N->getOperand(1); + + if (Add.getOpcode() != ISD::ADD) + return SDValue(); + + SDValue Lo = Add.getOperand(1); + + if ((Lo.getOpcode() != MipsISD::Lo) || + (Lo.getOperand(0).getOpcode() != ISD::TargetJumpTable)) + return SDValue(); + + EVT ValTy = N->getValueType(0); + DebugLoc DL = N->getDebugLoc(); + + SDValue Add1 = DAG.getNode(ISD::ADD, DL, ValTy, N->getOperand(0), + Add.getOperand(0)); + return DAG.getNode(ISD::ADD, DL, ValTy, Add1, Lo); +} + SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const { SelectionDAG &DAG = DCI.DAG; @@ -718,11 +775,13 @@ SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) case ISD::UDIVREM: return PerformDivRemCombine(N, DAG, DCI, Subtarget); case ISD::SELECT: - return PerformSELECTCombine(N, DAG, DCI, Subtarget); + return PerformSELECTCombine(N, DAG, DCI, Subtarget); case ISD::AND: return PerformANDCombine(N, DAG, DCI, Subtarget); case ISD::OR: return PerformORCombine(N, DAG, DCI, Subtarget); + case ISD::ADD: + return PerformADDCombine(N, DAG, DCI, Subtarget); } return SDValue(); @@ -741,13 +800,20 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG); case ISD::JumpTable: return LowerJumpTable(Op, DAG); case ISD::SELECT: return LowerSELECT(Op, DAG); + case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG); case ISD::SETCC: return LowerSETCC(Op, DAG); case ISD::VASTART: return LowerVASTART(Op, DAG); case ISD::FCOPYSIGN: return LowerFCOPYSIGN(Op, DAG); case ISD::FABS: return LowerFABS(Op, DAG); case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG); + case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG); case ISD::MEMBARRIER: return LowerMEMBARRIER(Op, DAG); case ISD::ATOMIC_FENCE: return LowerATOMIC_FENCE(Op, DAG); + case ISD::SHL_PARTS: return LowerShiftLeftParts(Op, DAG); + case ISD::SRA_PARTS: return LowerShiftRightParts(Op, DAG, true); + case ISD::SRL_PARTS: return LowerShiftRightParts(Op, DAG, false); + case ISD::LOAD: return LowerLOAD(Op, DAG); + case ISD::STORE: return LowerSTORE(Op, DAG); } return SDValue(); } @@ -782,7 +848,7 @@ static Mips::FPBranchCode GetFPBranchCodeFromCond(Mips::CondCode CC) { /* static MachineBasicBlock* ExpandCondMov(MachineInstr *MI, MachineBasicBlock *BB, DebugLoc dl, - const MipsSubtarget* Subtarget, + const MipsSubtarget *Subtarget, const TargetInstrInfo *TII, bool isFPCmp, unsigned Opc) { // There is no need to expand CMov instructions if target has @@ -1510,6 +1576,19 @@ LowerSELECT(SDValue Op, SelectionDAG &DAG) const Op.getDebugLoc()); } +SDValue MipsTargetLowering:: +LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const +{ + DebugLoc DL = Op.getDebugLoc(); + EVT Ty = Op.getOperand(0).getValueType(); + SDValue Cond = DAG.getNode(ISD::SETCC, DL, getSetCCResultType(Ty), + Op.getOperand(0), Op.getOperand(1), + Op.getOperand(4)); + + return DAG.getNode(ISD::SELECT, DL, Op.getValueType(), Cond, Op.getOperand(2), + Op.getOperand(3)); +} + SDValue MipsTargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const { SDValue Cond = CreateFPCmp(DAG, Op); @@ -1612,10 +1691,13 @@ LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const const GlobalValue *GV = GA->getGlobal(); EVT PtrVT = getPointerTy(); - if (getTargetMachine().getRelocationModel() == Reloc::PIC_) { - // General Dynamic TLS Model - bool LocalDynamic = GV->hasInternalLinkage(); - unsigned Flag = LocalDynamic ? MipsII::MO_TLSLDM :MipsII::MO_TLSGD; + TLSModel::Model model = getTargetMachine().getTLSModel(GV); + + if (model == TLSModel::GeneralDynamic || model == TLSModel::LocalDynamic) { + // General Dynamic and Local Dynamic TLS Model. + unsigned Flag = (model == TLSModel::LocalDynamic) ? MipsII::MO_TLSLDM + : MipsII::MO_TLSGD; + SDValue TGA = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, Flag); SDValue Argument = DAG.getNode(MipsISD::Wrapper, dl, PtrVT, GetGlobalReg(DAG, PtrVT), TGA); @@ -1630,16 +1712,16 @@ LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const Entry.Ty = PtrTy; Args.push_back(Entry); - std::pair<SDValue, SDValue> CallResult = - LowerCallTo(DAG.getEntryNode(), PtrTy, + TargetLowering::CallLoweringInfo CLI(DAG.getEntryNode(), PtrTy, false, false, false, false, 0, CallingConv::C, /*isTailCall=*/false, /*doesNotRet=*/false, /*isReturnValueUsed=*/true, TlsGetAddr, Args, DAG, dl); + std::pair<SDValue, SDValue> CallResult = LowerCallTo(CLI); SDValue Ret = CallResult.first; - if (!LocalDynamic) + if (model != TLSModel::LocalDynamic) return Ret; SDValue TGAHi = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, @@ -1653,7 +1735,7 @@ LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const } SDValue Offset; - if (GV->isDeclaration()) { + if (model == TLSModel::InitialExec) { // Initial Exec TLS Model SDValue TGA = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, MipsII::MO_GOTTPREL); @@ -1664,6 +1746,7 @@ LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const false, false, false, 0); } else { // Local Exec TLS Model + assert(model == TLSModel::LocalExec); SDValue TGAHi = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, MipsII::MO_TPREL_HI); SDValue TGALo = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, @@ -1940,9 +2023,26 @@ LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const { return FrameAddr; } +SDValue MipsTargetLowering::LowerRETURNADDR(SDValue Op, + SelectionDAG &DAG) const { + // check the depth + assert((cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() == 0) && + "Return address can be determined only for current frame."); + + MachineFunction &MF = DAG.getMachineFunction(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + EVT VT = Op.getValueType(); + unsigned RA = IsN64 ? Mips::RA_64 : Mips::RA; + MFI->setReturnAddressIsTaken(true); + + // Return RA, which contains the return address. Mark it an implicit live-in. + unsigned Reg = MF.addLiveIn(RA, getRegClassFor(VT)); + return DAG.getCopyFromReg(DAG.getEntryNode(), Op.getDebugLoc(), Reg, VT); +} + // TODO: set SType according to the desired memory barrier behavior. SDValue -MipsTargetLowering::LowerMEMBARRIER(SDValue Op, SelectionDAG& DAG) const { +MipsTargetLowering::LowerMEMBARRIER(SDValue Op, SelectionDAG &DAG) const { unsigned SType = 0; DebugLoc dl = Op.getDebugLoc(); return DAG.getNode(MipsISD::Sync, dl, MVT::Other, Op.getOperand(0), @@ -1950,7 +2050,7 @@ MipsTargetLowering::LowerMEMBARRIER(SDValue Op, SelectionDAG& DAG) const { } SDValue MipsTargetLowering::LowerATOMIC_FENCE(SDValue Op, - SelectionDAG& DAG) const { + SelectionDAG &DAG) const { // FIXME: Need pseudo-fence for 'singlethread' fences // FIXME: Set SType for weaker fences where supported/appropriate. unsigned SType = 0; @@ -1959,6 +2059,210 @@ SDValue MipsTargetLowering::LowerATOMIC_FENCE(SDValue Op, DAG.getConstant(SType, MVT::i32)); } +SDValue MipsTargetLowering::LowerShiftLeftParts(SDValue Op, + SelectionDAG &DAG) const { + DebugLoc DL = Op.getDebugLoc(); + SDValue Lo = Op.getOperand(0), Hi = Op.getOperand(1); + SDValue Shamt = Op.getOperand(2); + + // if shamt < 32: + // lo = (shl lo, shamt) + // hi = (or (shl hi, shamt) (srl (srl lo, 1), ~shamt)) + // else: + // lo = 0 + // hi = (shl lo, shamt[4:0]) + SDValue Not = DAG.getNode(ISD::XOR, DL, MVT::i32, Shamt, + DAG.getConstant(-1, MVT::i32)); + SDValue ShiftRight1Lo = DAG.getNode(ISD::SRL, DL, MVT::i32, Lo, + DAG.getConstant(1, MVT::i32)); + SDValue ShiftRightLo = DAG.getNode(ISD::SRL, DL, MVT::i32, ShiftRight1Lo, + Not); + SDValue ShiftLeftHi = DAG.getNode(ISD::SHL, DL, MVT::i32, Hi, Shamt); + SDValue Or = DAG.getNode(ISD::OR, DL, MVT::i32, ShiftLeftHi, ShiftRightLo); + SDValue ShiftLeftLo = DAG.getNode(ISD::SHL, DL, MVT::i32, Lo, Shamt); + SDValue Cond = DAG.getNode(ISD::AND, DL, MVT::i32, Shamt, + DAG.getConstant(0x20, MVT::i32)); + Lo = DAG.getNode(ISD::SELECT, DL, MVT::i32, Cond, + DAG.getConstant(0, MVT::i32), ShiftLeftLo); + Hi = DAG.getNode(ISD::SELECT, DL, MVT::i32, Cond, ShiftLeftLo, Or); + + SDValue Ops[2] = {Lo, Hi}; + return DAG.getMergeValues(Ops, 2, DL); +} + +SDValue MipsTargetLowering::LowerShiftRightParts(SDValue Op, SelectionDAG &DAG, + bool IsSRA) const { + DebugLoc DL = Op.getDebugLoc(); + SDValue Lo = Op.getOperand(0), Hi = Op.getOperand(1); + SDValue Shamt = Op.getOperand(2); + + // if shamt < 32: + // lo = (or (shl (shl hi, 1), ~shamt) (srl lo, shamt)) + // if isSRA: + // hi = (sra hi, shamt) + // else: + // hi = (srl hi, shamt) + // else: + // if isSRA: + // lo = (sra hi, shamt[4:0]) + // hi = (sra hi, 31) + // else: + // lo = (srl hi, shamt[4:0]) + // hi = 0 + SDValue Not = DAG.getNode(ISD::XOR, DL, MVT::i32, Shamt, + DAG.getConstant(-1, MVT::i32)); + SDValue ShiftLeft1Hi = DAG.getNode(ISD::SHL, DL, MVT::i32, Hi, + DAG.getConstant(1, MVT::i32)); + SDValue ShiftLeftHi = DAG.getNode(ISD::SHL, DL, MVT::i32, ShiftLeft1Hi, Not); + SDValue ShiftRightLo = DAG.getNode(ISD::SRL, DL, MVT::i32, Lo, Shamt); + SDValue Or = DAG.getNode(ISD::OR, DL, MVT::i32, ShiftLeftHi, ShiftRightLo); + SDValue ShiftRightHi = DAG.getNode(IsSRA ? ISD::SRA : ISD::SRL, DL, MVT::i32, + Hi, Shamt); + SDValue Cond = DAG.getNode(ISD::AND, DL, MVT::i32, Shamt, + DAG.getConstant(0x20, MVT::i32)); + SDValue Shift31 = DAG.getNode(ISD::SRA, DL, MVT::i32, Hi, + DAG.getConstant(31, MVT::i32)); + Lo = DAG.getNode(ISD::SELECT, DL, MVT::i32, Cond, ShiftRightHi, Or); + Hi = DAG.getNode(ISD::SELECT, DL, MVT::i32, Cond, + IsSRA ? Shift31 : DAG.getConstant(0, MVT::i32), + ShiftRightHi); + + SDValue Ops[2] = {Lo, Hi}; + return DAG.getMergeValues(Ops, 2, DL); +} + +static SDValue CreateLoadLR(unsigned Opc, SelectionDAG &DAG, LoadSDNode *LD, + SDValue Chain, SDValue Src, unsigned Offset) { + SDValue Ptr = LD->getBasePtr(); + EVT VT = LD->getValueType(0), MemVT = LD->getMemoryVT(); + EVT BasePtrVT = Ptr.getValueType(); + DebugLoc DL = LD->getDebugLoc(); + SDVTList VTList = DAG.getVTList(VT, MVT::Other); + + if (Offset) + Ptr = DAG.getNode(ISD::ADD, DL, BasePtrVT, Ptr, + DAG.getConstant(Offset, BasePtrVT)); + + SDValue Ops[] = { Chain, Ptr, Src }; + return DAG.getMemIntrinsicNode(Opc, DL, VTList, Ops, 3, MemVT, + LD->getMemOperand()); +} + +// Expand an unaligned 32 or 64-bit integer load node. +SDValue MipsTargetLowering::LowerLOAD(SDValue Op, SelectionDAG &DAG) const { + LoadSDNode *LD = cast<LoadSDNode>(Op); + EVT MemVT = LD->getMemoryVT(); + + // Return if load is aligned or if MemVT is neither i32 nor i64. + if ((LD->getAlignment() >= MemVT.getSizeInBits() / 8) || + ((MemVT != MVT::i32) && (MemVT != MVT::i64))) + return SDValue(); + + bool IsLittle = Subtarget->isLittle(); + EVT VT = Op.getValueType(); + ISD::LoadExtType ExtType = LD->getExtensionType(); + SDValue Chain = LD->getChain(), Undef = DAG.getUNDEF(VT); + + assert((VT == MVT::i32) || (VT == MVT::i64)); + + // Expand + // (set dst, (i64 (load baseptr))) + // to + // (set tmp, (ldl (add baseptr, 7), undef)) + // (set dst, (ldr baseptr, tmp)) + if ((VT == MVT::i64) && (ExtType == ISD::NON_EXTLOAD)) { + SDValue LDL = CreateLoadLR(MipsISD::LDL, DAG, LD, Chain, Undef, + IsLittle ? 7 : 0); + return CreateLoadLR(MipsISD::LDR, DAG, LD, LDL.getValue(1), LDL, + IsLittle ? 0 : 7); + } + + SDValue LWL = CreateLoadLR(MipsISD::LWL, DAG, LD, Chain, Undef, + IsLittle ? 3 : 0); + SDValue LWR = CreateLoadLR(MipsISD::LWR, DAG, LD, LWL.getValue(1), LWL, + IsLittle ? 0 : 3); + + // Expand + // (set dst, (i32 (load baseptr))) or + // (set dst, (i64 (sextload baseptr))) or + // (set dst, (i64 (extload baseptr))) + // to + // (set tmp, (lwl (add baseptr, 3), undef)) + // (set dst, (lwr baseptr, tmp)) + if ((VT == MVT::i32) || (ExtType == ISD::SEXTLOAD) || + (ExtType == ISD::EXTLOAD)) + return LWR; + + assert((VT == MVT::i64) && (ExtType == ISD::ZEXTLOAD)); + + // Expand + // (set dst, (i64 (zextload baseptr))) + // to + // (set tmp0, (lwl (add baseptr, 3), undef)) + // (set tmp1, (lwr baseptr, tmp0)) + // (set tmp2, (shl tmp1, 32)) + // (set dst, (srl tmp2, 32)) + DebugLoc DL = LD->getDebugLoc(); + SDValue Const32 = DAG.getConstant(32, MVT::i32); + SDValue SLL = DAG.getNode(ISD::SHL, DL, MVT::i64, LWR, Const32); + SDValue SRL = DAG.getNode(ISD::SRL, DL, MVT::i64, SLL, Const32); + SDValue Ops[] = { SRL, LWR.getValue(1) }; + return DAG.getMergeValues(Ops, 2, DL); +} + +static SDValue CreateStoreLR(unsigned Opc, SelectionDAG &DAG, StoreSDNode *SD, + SDValue Chain, unsigned Offset) { + SDValue Ptr = SD->getBasePtr(), Value = SD->getValue(); + EVT MemVT = SD->getMemoryVT(), BasePtrVT = Ptr.getValueType(); + DebugLoc DL = SD->getDebugLoc(); + SDVTList VTList = DAG.getVTList(MVT::Other); + + if (Offset) + Ptr = DAG.getNode(ISD::ADD, DL, BasePtrVT, Ptr, + DAG.getConstant(Offset, BasePtrVT)); + + SDValue Ops[] = { Chain, Value, Ptr }; + return DAG.getMemIntrinsicNode(Opc, DL, VTList, Ops, 3, MemVT, + SD->getMemOperand()); +} + +// Expand an unaligned 32 or 64-bit integer store node. +SDValue MipsTargetLowering::LowerSTORE(SDValue Op, SelectionDAG &DAG) const { + StoreSDNode *SD = cast<StoreSDNode>(Op); + EVT MemVT = SD->getMemoryVT(); + + // Return if store is aligned or if MemVT is neither i32 nor i64. + if ((SD->getAlignment() >= MemVT.getSizeInBits() / 8) || + ((MemVT != MVT::i32) && (MemVT != MVT::i64))) + return SDValue(); + + bool IsLittle = Subtarget->isLittle(); + SDValue Value = SD->getValue(), Chain = SD->getChain(); + EVT VT = Value.getValueType(); + + // Expand + // (store val, baseptr) or + // (truncstore val, baseptr) + // to + // (swl val, (add baseptr, 3)) + // (swr val, baseptr) + if ((VT == MVT::i32) || SD->isTruncatingStore()) { + SDValue SWL = CreateStoreLR(MipsISD::SWL, DAG, SD, Chain, + IsLittle ? 3 : 0); + return CreateStoreLR(MipsISD::SWR, DAG, SD, SWL, IsLittle ? 0 : 3); + } + + assert(VT == MVT::i64); + + // Expand + // (store val, baseptr) + // to + // (sdl val, (add baseptr, 7)) + // (sdr val, baseptr) + SDValue SDL = CreateStoreLR(MipsISD::SDL, DAG, SD, Chain, IsLittle ? 7 : 0); + return CreateStoreLR(MipsISD::SDR, DAG, SD, SDL, IsLittle ? 0 : 7); +} + //===----------------------------------------------------------------------===// // Calling Convention Implementation //===----------------------------------------------------------------------===// @@ -2152,10 +2456,10 @@ static unsigned getNextIntArgReg(unsigned Reg) { // Write ByVal Arg to arg registers and stack. static void WriteByValArg(SDValue& ByValChain, SDValue Chain, DebugLoc dl, - SmallVector<std::pair<unsigned, SDValue>, 16>& RegsToPass, - SmallVector<SDValue, 8>& MemOpChains, int& LastFI, + SmallVector<std::pair<unsigned, SDValue>, 16> &RegsToPass, + SmallVector<SDValue, 8> &MemOpChains, int &LastFI, MachineFrameInfo *MFI, SelectionDAG &DAG, SDValue Arg, - const CCValAssign &VA, const ISD::ArgFlagsTy& Flags, + const CCValAssign &VA, const ISD::ArgFlagsTy &Flags, MVT PtrType, bool isLittle) { unsigned LocMemOffset = VA.getLocMemOffset(); unsigned Offset = 0; @@ -2243,10 +2547,10 @@ WriteByValArg(SDValue& ByValChain, SDValue Chain, DebugLoc dl, // Copy Mips64 byVal arg to registers and stack. void static PassByValArg64(SDValue& ByValChain, SDValue Chain, DebugLoc dl, - SmallVector<std::pair<unsigned, SDValue>, 16>& RegsToPass, - SmallVector<SDValue, 8>& MemOpChains, int& LastFI, + SmallVector<std::pair<unsigned, SDValue>, 16> &RegsToPass, + SmallVector<SDValue, 8> &MemOpChains, int &LastFI, MachineFrameInfo *MFI, SelectionDAG &DAG, SDValue Arg, - const CCValAssign &VA, const ISD::ArgFlagsTy& Flags, + const CCValAssign &VA, const ISD::ArgFlagsTy &Flags, EVT PtrTy, bool isLittle) { unsigned ByValSize = Flags.getByValSize(); unsigned Alignment = std::min(Flags.getByValAlign(), (unsigned)8); @@ -2332,14 +2636,20 @@ PassByValArg64(SDValue& ByValChain, SDValue Chain, DebugLoc dl, /// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted. /// TODO: isTailCall. SDValue -MipsTargetLowering::LowerCall(SDValue InChain, SDValue Callee, - CallingConv::ID CallConv, bool isVarArg, - bool doesNotRet, bool &isTailCall, - const SmallVectorImpl<ISD::OutputArg> &Outs, - const SmallVectorImpl<SDValue> &OutVals, - const SmallVectorImpl<ISD::InputArg> &Ins, - DebugLoc dl, SelectionDAG &DAG, +MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, SmallVectorImpl<SDValue> &InVals) const { + SelectionDAG &DAG = CLI.DAG; + DebugLoc &dl = CLI.DL; + SmallVector<ISD::OutputArg, 32> &Outs = CLI.Outs; + SmallVector<SDValue, 32> &OutVals = CLI.OutVals; + SmallVector<ISD::InputArg, 32> &Ins = CLI.Ins; + SDValue InChain = CLI.Chain; + SDValue Callee = CLI.Callee; + SDValue CalleeSave = CLI.Callee; + bool &isTailCall = CLI.IsTailCall; + CallingConv::ID CallConv = CLI.CallConv; + bool isVarArg = CLI.IsVarArg; + // MIPs target does not yet support tail call optimization. isTailCall = false; @@ -2354,7 +2664,9 @@ MipsTargetLowering::LowerCall(SDValue InChain, SDValue Callee, CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), getTargetMachine(), ArgLocs, *DAG.getContext()); - if (IsO32) + if (CallConv == CallingConv::Fast) + CCInfo.AnalyzeCallOperands(Outs, CC_Mips_FastCC); + else if (IsO32) CCInfo.AnalyzeCallOperands(Outs, CC_MipsO32); else if (HasMips64) AnalyzeMips64CallOperands(CCInfo, Outs); @@ -2372,11 +2684,6 @@ MipsTargetLowering::LowerCall(SDValue InChain, SDValue Callee, Chain = CallSeqStart = DAG.getCALLSEQ_START(InChain, NextStackOffsetVal); ByValChain = InChain; - // If this is the first call, create a stack frame object that points to - // a location to which .cprestore saves $gp. - if (IsO32 && IsPIC && MipsFI->globalBaseRegFixed() && !MipsFI->getGPFI()) - MipsFI->setGPFI(MFI->CreateFixedObject(4, 0, true)); - // Get the frame index of the stack frame object that points to the location // of dynamically allocated area on the stack. int DynAllocFI = MipsFI->getDynAllocFI(); @@ -2384,7 +2691,7 @@ MipsTargetLowering::LowerCall(SDValue InChain, SDValue Callee, // Update size of the maximum argument space. // For O32, a minimum of four words (16 bytes) of argument space is // allocated. - if (IsO32) + if (IsO32 && (CallConv != CallingConv::Fast)) NextStackOffset = std::max(NextStackOffset, (unsigned)16); unsigned MaxCallFrameSize = MipsFI->getMaxCallFrameSize(); @@ -2399,9 +2706,6 @@ MipsTargetLowering::LowerCall(SDValue InChain, SDValue Callee, NextStackOffset = (NextStackOffset + StackAlignment - 1) / StackAlignment * StackAlignment; - if (MipsFI->needGPSaveRestore()) - MFI->setObjectOffset(MipsFI->getGPFI(), NextStackOffset); - MFI->setObjectOffset(DynAllocFI, NextStackOffset); } @@ -2573,6 +2877,14 @@ MipsTargetLowering::LowerCall(SDValue InChain, SDValue Callee, Callee = DAG.getRegister(T9Reg, getPointerTy()); } + // Insert node "GP copy globalreg" before call to function. + // Lazy-binding stubs require GP to point to the GOT. + if (IsPICCall) { + unsigned GPReg = IsN64 ? Mips::GP_64 : Mips::GP; + EVT Ty = IsN64 ? MVT::i64 : MVT::i32; + RegsToPass.push_back(std::make_pair(GPReg, GetGlobalReg(DAG, Ty))); + } + // Build a sequence of copy-to-reg nodes chained together with token // chain and flag operands which copy the outgoing args into registers. // The InFlag in necessary since all emitted instructions must be @@ -2590,7 +2902,7 @@ MipsTargetLowering::LowerCall(SDValue InChain, SDValue Callee, SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); SmallVector<SDValue, 8> Ops; Ops.push_back(Chain); - Ops.push_back(Callee); + Ops.push_back(Subtarget->inMips16Mode()? CalleeSave: Callee); // Add argument registers to the end of the list so that they are // known live into the call. @@ -2598,6 +2910,8 @@ MipsTargetLowering::LowerCall(SDValue InChain, SDValue Callee, Ops.push_back(DAG.getRegister(RegsToPass[i].first, RegsToPass[i].second.getValueType())); + if (Subtarget->inMips16Mode()) + Ops.push_back(Callee); // Add a register mask operand representing the call-preserved registers. const TargetRegisterInfo *TRI = getTargetMachine().getRegisterInfo(); const uint32_t *Mask = TRI->getCallPreservedMask(CallConv); @@ -2633,7 +2947,7 @@ MipsTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag, // Assign locations to each value returned by this call. SmallVector<CCValAssign, 16> RVLocs; CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), - getTargetMachine(), RVLocs, *DAG.getContext()); + getTargetMachine(), RVLocs, *DAG.getContext()); CCInfo.AnalyzeCallResult(Ins, RetCC_Mips); @@ -2652,9 +2966,9 @@ MipsTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag, // Formal Arguments Calling Convention Implementation //===----------------------------------------------------------------------===// static void ReadByValArg(MachineFunction &MF, SDValue Chain, DebugLoc dl, - std::vector<SDValue>& OutChains, + std::vector<SDValue> &OutChains, SelectionDAG &DAG, unsigned NumWords, SDValue FIN, - const CCValAssign &VA, const ISD::ArgFlagsTy& Flags, + const CCValAssign &VA, const ISD::ArgFlagsTy &Flags, const Argument *FuncArg) { unsigned LocMem = VA.getLocMemOffset(); unsigned FirstWord = LocMem / 4; @@ -2666,7 +2980,7 @@ static void ReadByValArg(MachineFunction &MF, SDValue Chain, DebugLoc dl, break; unsigned SrcReg = O32IntRegs[CurWord]; - unsigned Reg = AddLiveIn(MF, SrcReg, Mips::CPURegsRegisterClass); + unsigned Reg = AddLiveIn(MF, SrcReg, &Mips::CPURegsRegClass); SDValue StorePtr = DAG.getNode(ISD::ADD, dl, MVT::i32, FIN, DAG.getConstant(i * 4, MVT::i32)); SDValue Store = DAG.getStore(Chain, dl, DAG.getRegister(Reg, MVT::i32), @@ -2679,8 +2993,8 @@ static void ReadByValArg(MachineFunction &MF, SDValue Chain, DebugLoc dl, // Create frame object on stack and copy registers used for byval passing to it. static unsigned CopyMips64ByValRegs(MachineFunction &MF, SDValue Chain, DebugLoc dl, - std::vector<SDValue>& OutChains, SelectionDAG &DAG, - const CCValAssign &VA, const ISD::ArgFlagsTy& Flags, + std::vector<SDValue> &OutChains, SelectionDAG &DAG, + const CCValAssign &VA, const ISD::ArgFlagsTy &Flags, MachineFrameInfo *MFI, bool IsRegLoc, SmallVectorImpl<SDValue> &InVals, MipsFunctionInfo *MipsFI, EVT PtrTy, const Argument *FuncArg) { @@ -2703,7 +3017,7 @@ CopyMips64ByValRegs(MachineFunction &MF, SDValue Chain, DebugLoc dl, // Copy arg registers. for (unsigned I = 0; (Reg != Mips64IntRegs + 8) && (I < NumRegs); ++Reg, ++I) { - unsigned VReg = AddLiveIn(MF, *Reg, Mips::CPU64RegsRegisterClass); + unsigned VReg = AddLiveIn(MF, *Reg, &Mips::CPU64RegsRegClass); SDValue StorePtr = DAG.getNode(ISD::ADD, dl, PtrTy, FIN, DAG.getConstant(I * 8, PtrTy)); SDValue Store = DAG.getStore(Chain, dl, DAG.getRegister(VReg, MVT::i64), @@ -2739,7 +3053,9 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), getTargetMachine(), ArgLocs, *DAG.getContext()); - if (IsO32) + if (CallConv == CallingConv::Fast) + CCInfo.AnalyzeFormalArguments(Ins, CC_Mips_FastCC); + else if (IsO32) CCInfo.AnalyzeFormalArguments(Ins, CC_MipsO32); else CCInfo.AnalyzeFormalArguments(Ins, CC_Mips); @@ -2779,13 +3095,13 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, const TargetRegisterClass *RC; if (RegVT == MVT::i32) - RC = Mips::CPURegsRegisterClass; + RC = &Mips::CPURegsRegClass; else if (RegVT == MVT::i64) - RC = Mips::CPU64RegsRegisterClass; + RC = &Mips::CPU64RegsRegClass; else if (RegVT == MVT::f32) - RC = Mips::FGR32RegisterClass; + RC = &Mips::FGR32RegClass; else if (RegVT == MVT::f64) - RC = HasMips64 ? Mips::FGR64RegisterClass : Mips::AFGR64RegisterClass; + RC = HasMips64 ? &Mips::FGR64RegClass : &Mips::AFGR64RegClass; else llvm_unreachable("RegVT not supported by FormalArguments Lowering"); @@ -2859,8 +3175,9 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, const uint16_t *ArgRegs = IsO32 ? O32IntRegs : Mips64IntRegs; unsigned Idx = CCInfo.getFirstUnallocated(ArgRegs, NumOfRegs); int FirstRegSlotOffset = IsO32 ? 0 : -64 ; // offset of $a0's slot. - const TargetRegisterClass *RC - = IsO32 ? Mips::CPURegsRegisterClass : Mips::CPU64RegsRegisterClass; + const TargetRegisterClass *RC = IsO32 ? + (const TargetRegisterClass*)&Mips::CPURegsRegClass : + (const TargetRegisterClass*)&Mips::CPU64RegsRegClass; unsigned RegSize = RC->getSize(); int RegSlotOffset = FirstRegSlotOffset + Idx * RegSize; @@ -2924,7 +3241,7 @@ MipsTargetLowering::LowerReturn(SDValue Chain, // CCState - Info about the registers and stack slot. CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), - getTargetMachine(), RVLocs, *DAG.getContext()); + getTargetMachine(), RVLocs, *DAG.getContext()); // Analize return values. CCInfo.AnalyzeReturn(Outs, RetCC_Mips); @@ -2970,11 +3287,10 @@ MipsTargetLowering::LowerReturn(SDValue Chain, // Return on Mips is always a "jr $ra" if (Flag.getNode()) - return DAG.getNode(MipsISD::Ret, dl, MVT::Other, - Chain, DAG.getRegister(Mips::RA, MVT::i32), Flag); - else // Return Void - return DAG.getNode(MipsISD::Ret, dl, MVT::Other, - Chain, DAG.getRegister(Mips::RA, MVT::i32)); + return DAG.getNode(MipsISD::Ret, dl, MVT::Other, Chain, Flag); + + // Return Void + return DAG.getNode(MipsISD::Ret, dl, MVT::Other, Chain); } //===----------------------------------------------------------------------===// @@ -2993,13 +3309,19 @@ getConstraintType(const std::string &Constraint) const // unless generating MIPS16 code. // 'y' : Equivalent to r; retained for // backwards compatibility. - // 'f' : Floating Point registers. + // 'c' : A register suitable for use in an indirect + // jump. This will always be $25 for -mabicalls. + // 'l' : The lo register. 1 word storage. + // 'x' : The hilo register pair. Double word storage. if (Constraint.size() == 1) { switch (Constraint[0]) { default : break; case 'd': case 'y': case 'f': + case 'c': + case 'l': + case 'x': return C_RegisterClass; } } @@ -3033,6 +3355,22 @@ MipsTargetLowering::getSingleConstraintMatchWeight( if (type->isFloatTy()) weight = CW_Register; break; + case 'c': // $25 for indirect jumps + case 'l': // lo register + case 'x': // hilo register pair + if (type->isIntegerTy()) + weight = CW_SpecificReg; + break; + case 'I': // signed 16 bit immediate + case 'J': // integer zero + case 'K': // unsigned 16 bit immediate + case 'L': // signed 32 bit immediate where lower 16 bits are 0 + case 'N': // immediate in the range of -65535 to -1 (inclusive) + case 'O': // signed 15 bit immediate (+- 16383) + case 'P': // immediate in the range of 65535 to 1 (inclusive) + if (isa<ConstantInt>(CallOperandVal)) + weight = CW_Constant; + break; } return weight; } @@ -3048,30 +3386,152 @@ getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const case 'd': // Address register. Same as 'r' unless generating MIPS16 code. case 'y': // Same as 'r'. Exists for compatibility. case 'r': - if (VT == MVT::i32) - return std::make_pair(0U, Mips::CPURegsRegisterClass); - assert(VT == MVT::i64 && "Unexpected type."); - return std::make_pair(0U, Mips::CPU64RegsRegisterClass); + if (VT == MVT::i32 || VT == MVT::i16 || VT == MVT::i8) + return std::make_pair(0U, &Mips::CPURegsRegClass); + if (VT == MVT::i64 && !HasMips64) + return std::make_pair(0U, &Mips::CPURegsRegClass); + if (VT == MVT::i64 && HasMips64) + return std::make_pair(0U, &Mips::CPU64RegsRegClass); + // This will generate an error message + return std::make_pair(0u, static_cast<const TargetRegisterClass*>(0)); case 'f': if (VT == MVT::f32) - return std::make_pair(0U, Mips::FGR32RegisterClass); + return std::make_pair(0U, &Mips::FGR32RegClass); if ((VT == MVT::f64) && (!Subtarget->isSingleFloat())) { if (Subtarget->isFP64bit()) - return std::make_pair(0U, Mips::FGR64RegisterClass); - else - return std::make_pair(0U, Mips::AFGR64RegisterClass); + return std::make_pair(0U, &Mips::FGR64RegClass); + return std::make_pair(0U, &Mips::AFGR64RegClass); } + break; + case 'c': // register suitable for indirect jump + if (VT == MVT::i32) + return std::make_pair((unsigned)Mips::T9, &Mips::CPURegsRegClass); + assert(VT == MVT::i64 && "Unexpected type."); + return std::make_pair((unsigned)Mips::T9_64, &Mips::CPU64RegsRegClass); + case 'l': // register suitable for indirect jump + if (VT == MVT::i32) + return std::make_pair((unsigned)Mips::LO, &Mips::HILORegClass); + return std::make_pair((unsigned)Mips::LO64, &Mips::HILO64RegClass); + case 'x': // register suitable for indirect jump + // Fixme: Not triggering the use of both hi and low + // This will generate an error message + return std::make_pair(0u, static_cast<const TargetRegisterClass*>(0)); } } return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT); } +/// LowerAsmOperandForConstraint - Lower the specified operand into the Ops +/// vector. If it is invalid, don't add anything to Ops. +void MipsTargetLowering::LowerAsmOperandForConstraint(SDValue Op, + std::string &Constraint, + std::vector<SDValue>&Ops, + SelectionDAG &DAG) const { + SDValue Result(0, 0); + + // Only support length 1 constraints for now. + if (Constraint.length() > 1) return; + + char ConstraintLetter = Constraint[0]; + switch (ConstraintLetter) { + default: break; // This will fall through to the generic implementation + case 'I': // Signed 16 bit constant + // If this fails, the parent routine will give an error + if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) { + EVT Type = Op.getValueType(); + int64_t Val = C->getSExtValue(); + if (isInt<16>(Val)) { + Result = DAG.getTargetConstant(Val, Type); + break; + } + } + return; + case 'J': // integer zero + if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) { + EVT Type = Op.getValueType(); + int64_t Val = C->getZExtValue(); + if (Val == 0) { + Result = DAG.getTargetConstant(0, Type); + break; + } + } + return; + case 'K': // unsigned 16 bit immediate + if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) { + EVT Type = Op.getValueType(); + uint64_t Val = (uint64_t)C->getZExtValue(); + if (isUInt<16>(Val)) { + Result = DAG.getTargetConstant(Val, Type); + break; + } + } + return; + case 'L': // signed 32 bit immediate where lower 16 bits are 0 + if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) { + EVT Type = Op.getValueType(); + int64_t Val = C->getSExtValue(); + if ((isInt<32>(Val)) && ((Val & 0xffff) == 0)){ + Result = DAG.getTargetConstant(Val, Type); + break; + } + } + return; + case 'N': // immediate in the range of -65535 to -1 (inclusive) + if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) { + EVT Type = Op.getValueType(); + int64_t Val = C->getSExtValue(); + if ((Val >= -65535) && (Val <= -1)) { + Result = DAG.getTargetConstant(Val, Type); + break; + } + } + return; + case 'O': // signed 15 bit immediate + if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) { + EVT Type = Op.getValueType(); + int64_t Val = C->getSExtValue(); + if ((isInt<15>(Val))) { + Result = DAG.getTargetConstant(Val, Type); + break; + } + } + return; + case 'P': // immediate in the range of 1 to 65535 (inclusive) + if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) { + EVT Type = Op.getValueType(); + int64_t Val = C->getSExtValue(); + if ((Val <= 65535) && (Val >= 1)) { + Result = DAG.getTargetConstant(Val, Type); + break; + } + } + return; + } + + if (Result.getNode()) { + Ops.push_back(Result); + return; + } + + TargetLowering::LowerAsmOperandForConstraint(Op, Constraint, Ops, DAG); +} + bool MipsTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const { // The Mips target isn't yet aware of offsets. return false; } +EVT MipsTargetLowering::getOptimalMemOpType(uint64_t Size, unsigned DstAlign, + unsigned SrcAlign, bool IsZeroVal, + bool MemcpyStrSrc, + MachineFunction &MF) const { + if (Subtarget->hasMips64()) + return MVT::i64; + + return MVT::i32; +} + bool MipsTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT) const { if (VT != MVT::f32 && VT != MVT::f64) return false; diff --git a/lib/Target/Mips/MipsISelLowering.h b/lib/Target/Mips/MipsISelLowering.h index c36f40f..edab03c 100644 --- a/lib/Target/Mips/MipsISelLowering.h +++ b/lib/Target/Mips/MipsISelLowering.h @@ -79,7 +79,17 @@ namespace llvm { Sync, Ext, - Ins + Ins, + + // Load/Store Left/Right nodes. + LWL = ISD::FIRST_TARGET_MEMORY_OPCODE, + LWR, + SWL, + SWR, + LDL, + LDR, + SDL, + SDR }; } @@ -128,13 +138,20 @@ namespace llvm { SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const; SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG) const; SDValue LowerSELECT(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const; SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) const; SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const; SDValue LowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const; SDValue LowerFABS(SDValue Op, SelectionDAG &DAG) const; SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const; SDValue LowerMEMBARRIER(SDValue Op, SelectionDAG& DAG) const; SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG& DAG) const; + SDValue LowerShiftLeftParts(SDValue Op, SelectionDAG& DAG) const; + SDValue LowerShiftRightParts(SDValue Op, SelectionDAG& DAG, + bool IsSRA) const; + SDValue LowerLOAD(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerSTORE(SDValue Op, SelectionDAG &DAG) const; virtual SDValue LowerFormalArguments(SDValue Chain, @@ -144,13 +161,7 @@ namespace llvm { SmallVectorImpl<SDValue> &InVals) const; virtual SDValue - LowerCall(SDValue Chain, SDValue Callee, - CallingConv::ID CallConv, bool isVarArg, - bool doesNotRet, bool &isTailCall, - const SmallVectorImpl<ISD::OutputArg> &Outs, - const SmallVectorImpl<SDValue> &OutVals, - const SmallVectorImpl<ISD::InputArg> &Ins, - DebugLoc dl, SelectionDAG &DAG, + LowerCall(TargetLowering::CallLoweringInfo &CLI, SmallVectorImpl<SDValue> &InVals) const; virtual SDValue @@ -176,8 +187,22 @@ namespace llvm { getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const; + /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops + /// vector. If it is invalid, don't add anything to Ops. If hasMemory is + /// true it means one of the asm constraint of the inline asm instruction + /// being processed is 'm'. + virtual void LowerAsmOperandForConstraint(SDValue Op, + std::string &Constraint, + std::vector<SDValue> &Ops, + SelectionDAG &DAG) const; + virtual bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const; + virtual EVT getOptimalMemOpType(uint64_t Size, unsigned DstAlign, + unsigned SrcAlign, bool IsZeroVal, + bool MemcpyStrSrc, + MachineFunction &MF) const; + /// isFPImmLegal - Returns true if the target can instruction select the /// specified FP immediate natively. If false, the legalizer will /// materialize the FP immediate as a load from a constant pool. diff --git a/lib/Target/Mips/MipsInstrFPU.td b/lib/Target/Mips/MipsInstrFPU.td index 14d8f1e..9654b86 100644 --- a/lib/Target/Mips/MipsInstrFPU.td +++ b/lib/Target/Mips/MipsInstrFPU.td @@ -54,10 +54,14 @@ let PrintMethod = "printFCCOperand", DecoderMethod = "DecodeCondCode" in // Feature predicates. //===----------------------------------------------------------------------===// -def IsFP64bit : Predicate<"Subtarget.isFP64bit()">, AssemblerPredicate<"FeatureFP64Bit">; -def NotFP64bit : Predicate<"!Subtarget.isFP64bit()">, AssemblerPredicate<"!FeatureFP64Bit">; -def IsSingleFloat : Predicate<"Subtarget.isSingleFloat()">, AssemblerPredicate<"FeatureSingleFloat">; -def IsNotSingleFloat : Predicate<"!Subtarget.isSingleFloat()">, AssemblerPredicate<"!FeatureSingleFloat">; +def IsFP64bit : Predicate<"Subtarget.isFP64bit()">, + AssemblerPredicate<"FeatureFP64Bit">; +def NotFP64bit : Predicate<"!Subtarget.isFP64bit()">, + AssemblerPredicate<"!FeatureFP64Bit">; +def IsSingleFloat : Predicate<"Subtarget.isSingleFloat()">, + AssemblerPredicate<"FeatureSingleFloat">; +def IsNotSingleFloat : Predicate<"!Subtarget.isSingleFloat()">, + AssemblerPredicate<"!FeatureSingleFloat">; // FP immediate patterns. def fpimm0 : PatLeaf<(fpimm), [{ @@ -117,15 +121,15 @@ class FPIdxStore<bits<6> funct, string opstr, RegisterClass DRC, multiclass FFR1_W_M<bits<6> funct, string opstr> { def _S : FFR1<funct, 16, opstr, "w.s", FGR32, FGR32>; def _D32 : FFR1<funct, 17, opstr, "w.d", FGR32, AFGR64>, - Requires<[NotFP64bit]>; + Requires<[NotFP64bit, HasStandardEncoding]>; def _D64 : FFR1<funct, 17, opstr, "w.d", FGR32, FGR64>, - Requires<[IsFP64bit]> { + Requires<[IsFP64bit, HasStandardEncoding]> { let DecoderNamespace = "Mips64"; } } // Instructions that convert an FP value to 64-bit fixed point. -let Predicates = [IsFP64bit], DecoderNamespace = "Mips64" in +let Predicates = [IsFP64bit, HasStandardEncoding], DecoderNamespace = "Mips64" in multiclass FFR1_L_M<bits<6> funct, string opstr> { def _S : FFR1<funct, 16, opstr, "l.s", FGR64, FGR32>; def _D64 : FFR1<funct, 17, opstr, "l.d", FGR64, FGR64>; @@ -135,9 +139,9 @@ multiclass FFR1_L_M<bits<6> funct, string opstr> { multiclass FFR1P_M<bits<6> funct, string opstr, SDNode OpNode> { def _S : FFR1P<funct, 16, opstr, "s", FGR32, FGR32, OpNode>; def _D32 : FFR1P<funct, 17, opstr, "d", AFGR64, AFGR64, OpNode>, - Requires<[NotFP64bit]>; + Requires<[NotFP64bit, HasStandardEncoding]>; def _D64 : FFR1P<funct, 17, opstr, "d", FGR64, FGR64, OpNode>, - Requires<[IsFP64bit]> { + Requires<[IsFP64bit, HasStandardEncoding]> { let DecoderNamespace = "Mips64"; } } @@ -146,9 +150,9 @@ multiclass FFR2P_M<bits<6> funct, string opstr, SDNode OpNode, bit isComm = 0> { let isCommutable = isComm in { def _S : FFR2P<funct, 16, opstr, "s", FGR32, OpNode>; def _D32 : FFR2P<funct, 17, opstr, "d", AFGR64, OpNode>, - Requires<[NotFP64bit]>; + Requires<[NotFP64bit, HasStandardEncoding]>; def _D64 : FFR2P<funct, 17, opstr, "d", FGR64, OpNode>, - Requires<[IsFP64bit]> { + Requires<[IsFP64bit, HasStandardEncoding]> { let DecoderNamespace = "Mips64"; } } @@ -185,13 +189,13 @@ def CVT_S_W : FFR1<0x20, 20, "cvt", "s.w", FGR32, FGR32>; def CVT_L_S : FFR1<0x25, 16, "cvt", "l.s", FGR64, FGR32>; def CVT_L_D64: FFR1<0x25, 17, "cvt", "l.d", FGR64, FGR64>; -let Predicates = [NotFP64bit] in { +let Predicates = [NotFP64bit, HasStandardEncoding] in { def CVT_S_D32 : FFR1<0x20, 17, "cvt", "s.d", FGR32, AFGR64>; def CVT_D32_W : FFR1<0x21, 20, "cvt", "d.w", AFGR64, FGR32>; def CVT_D32_S : FFR1<0x21, 16, "cvt", "d.s", AFGR64, FGR32>; } -let Predicates = [IsFP64bit], DecoderNamespace = "Mips64" in { +let Predicates = [IsFP64bit, HasStandardEncoding], DecoderNamespace = "Mips64" in { def CVT_S_D64 : FFR1<0x20, 17, "cvt", "s.d", FGR32, FGR64>; def CVT_S_L : FFR1<0x20, 21, "cvt", "s.l", FGR32, FGR64>; def CVT_D64_W : FFR1<0x21, 20, "cvt", "d.w", FGR64, FGR32>; @@ -199,7 +203,7 @@ let Predicates = [IsFP64bit], DecoderNamespace = "Mips64" in { def CVT_D64_L : FFR1<0x21, 21, "cvt", "d.l", FGR64, FGR64>; } -let Predicates = [NoNaNsFPMath] in { +let Predicates = [NoNaNsFPMath, HasStandardEncoding] in { defm FABS : FFR1P_M<0x5, "abs", fabs>; defm FNEG : FFR1P_M<0x7, "neg", fneg>; } @@ -242,14 +246,14 @@ def DMTC1 : FFRGPR<0x05, (outs FGR64:$fs), (ins CPU64Regs:$rt), def FMOV_S : FFR1<0x6, 16, "mov", "s", FGR32, FGR32>; def FMOV_D32 : FFR1<0x6, 17, "mov", "d", AFGR64, AFGR64>, - Requires<[NotFP64bit]>; + Requires<[NotFP64bit, HasStandardEncoding]>; def FMOV_D64 : FFR1<0x6, 17, "mov", "d", FGR64, FGR64>, - Requires<[IsFP64bit]> { + Requires<[IsFP64bit, HasStandardEncoding]> { let DecoderNamespace = "Mips64"; } /// Floating Point Memory Instructions -let Predicates = [IsN64], DecoderNamespace = "Mips64" in { +let Predicates = [IsN64, HasStandardEncoding], DecoderNamespace = "Mips64" in { def LWC1_P8 : FPLoad<0x31, "lwc1", FGR32, mem64>; def SWC1_P8 : FPStore<0x39, "swc1", FGR32, mem64>; def LDC164_P8 : FPLoad<0x35, "ldc1", FGR64, mem64> { @@ -260,41 +264,42 @@ let Predicates = [IsN64], DecoderNamespace = "Mips64" in { } } -let Predicates = [NotN64] in { +let Predicates = [NotN64, HasStandardEncoding] in { def LWC1 : FPLoad<0x31, "lwc1", FGR32, mem>; def SWC1 : FPStore<0x39, "swc1", FGR32, mem>; } -let Predicates = [NotN64, HasMips64], DecoderNamespace = "Mips64" in { +let Predicates = [NotN64, HasMips64, HasStandardEncoding], + DecoderNamespace = "Mips64" in { def LDC164 : FPLoad<0x35, "ldc1", FGR64, mem>; def SDC164 : FPStore<0x3d, "sdc1", FGR64, mem>; } -let Predicates = [NotN64, NotMips64] in { +let Predicates = [NotN64, NotMips64, HasStandardEncoding] in { def LDC1 : FPLoad<0x35, "ldc1", AFGR64, mem>; def SDC1 : FPStore<0x3d, "sdc1", AFGR64, mem>; } // Indexed loads and stores. -let Predicates = [HasMips32r2Or64] in { +let Predicates = [HasMips32r2Or64, HasStandardEncoding] in { def LWXC1 : FPIdxLoad<0x0, "lwxc1", FGR32, CPURegs, load_a>; def LUXC1 : FPIdxLoad<0x5, "luxc1", FGR32, CPURegs, load_u>; def SWXC1 : FPIdxStore<0x8, "swxc1", FGR32, CPURegs, store_a>; def SUXC1 : FPIdxStore<0xd, "suxc1", FGR32, CPURegs, store_u>; } -let Predicates = [HasMips32r2, NotMips64] in { +let Predicates = [HasMips32r2, NotMips64, HasStandardEncoding] in { def LDXC1 : FPIdxLoad<0x1, "ldxc1", AFGR64, CPURegs, load_a>; def SDXC1 : FPIdxStore<0x9, "sdxc1", AFGR64, CPURegs, store_a>; } -let Predicates = [HasMips64, NotN64], DecoderNamespace="Mips64" in { +let Predicates = [HasMips64, NotN64, HasStandardEncoding], DecoderNamespace="Mips64" in { def LDXC164 : FPIdxLoad<0x1, "ldxc1", FGR64, CPURegs, load_a>; def SDXC164 : FPIdxStore<0x9, "sdxc1", FGR64, CPURegs, store_a>; } // n64 -let Predicates = [IsN64], isCodeGenOnly=1 in { +let Predicates = [IsN64, HasStandardEncoding], isCodeGenOnly=1 in { def LWXC1_P8 : FPIdxLoad<0x0, "lwxc1", FGR32, CPU64Regs, load_a>; def LUXC1_P8 : FPIdxLoad<0x5, "luxc1", FGR32, CPU64Regs, load_u>; def LDXC164_P8 : FPIdxLoad<0x1, "ldxc1", FGR64, CPU64Regs, load_a>; @@ -309,32 +314,33 @@ defm FDIV : FFR2P_M<0x03, "div", fdiv>; defm FMUL : FFR2P_M<0x02, "mul", fmul, 1>; defm FSUB : FFR2P_M<0x01, "sub", fsub>; -let Predicates = [HasMips32r2] in { +let Predicates = [HasMips32r2, HasStandardEncoding] in { def MADD_S : FMADDSUB<0x4, 0, "madd", "s", fadd, FGR32>; def MSUB_S : FMADDSUB<0x5, 0, "msub", "s", fsub, FGR32>; } -let Predicates = [HasMips32r2, NoNaNsFPMath] in { +let Predicates = [HasMips32r2, NoNaNsFPMath, HasStandardEncoding] in { def NMADD_S : FNMADDSUB<0x6, 0, "nmadd", "s", fadd, FGR32>; def NMSUB_S : FNMADDSUB<0x7, 0, "nmsub", "s", fsub, FGR32>; } -let Predicates = [HasMips32r2, NotFP64bit] in { +let Predicates = [HasMips32r2, NotFP64bit, HasStandardEncoding] in { def MADD_D32 : FMADDSUB<0x4, 1, "madd", "d", fadd, AFGR64>; def MSUB_D32 : FMADDSUB<0x5, 1, "msub", "d", fsub, AFGR64>; } -let Predicates = [HasMips32r2, NotFP64bit, NoNaNsFPMath] in { +let Predicates = [HasMips32r2, NotFP64bit, NoNaNsFPMath, HasStandardEncoding] in { def NMADD_D32 : FNMADDSUB<0x6, 1, "nmadd", "d", fadd, AFGR64>; def NMSUB_D32 : FNMADDSUB<0x7, 1, "nmsub", "d", fsub, AFGR64>; } -let Predicates = [HasMips32r2, IsFP64bit], isCodeGenOnly=1 in { +let Predicates = [HasMips32r2, IsFP64bit, HasStandardEncoding], isCodeGenOnly=1 in { def MADD_D64 : FMADDSUB<0x4, 1, "madd", "d", fadd, FGR64>; def MSUB_D64 : FMADDSUB<0x5, 1, "msub", "d", fsub, FGR64>; } -let Predicates = [HasMips32r2, IsFP64bit, NoNaNsFPMath], isCodeGenOnly=1 in { +let Predicates = [HasMips32r2, IsFP64bit, NoNaNsFPMath, HasStandardEncoding], + isCodeGenOnly=1 in { def NMADD_D64 : FNMADDSUB<0x6, 1, "nmadd", "d", fadd, FGR64>; def NMSUB_D64 : FNMADDSUB<0x7, 1, "nmsub", "d", fsub, FGR64>; } @@ -391,8 +397,10 @@ class FCMP<bits<5> fmt, RegisterClass RC, string typestr> : /// Floating Point Compare let Defs=[FCR31] in { def FCMP_S32 : FCMP<0x10, FGR32, "s">; - def FCMP_D32 : FCMP<0x11, AFGR64, "d">, Requires<[NotFP64bit]>; - def FCMP_D64 : FCMP<0x11, FGR64, "d">, Requires<[IsFP64bit]> { + def FCMP_D32 : FCMP<0x11, AFGR64, "d">, + Requires<[NotFP64bit, HasStandardEncoding]>; + def FCMP_D64 : FCMP<0x11, FGR64, "d">, + Requires<[IsFP64bit, HasStandardEncoding]> { let DecoderNamespace = "Mips64"; } } @@ -423,46 +431,52 @@ def ExtractElementF64 : //===----------------------------------------------------------------------===// // Floating Point Patterns //===----------------------------------------------------------------------===// -def : Pat<(f32 fpimm0), (MTC1 ZERO)>; -def : Pat<(f32 fpimm0neg), (FNEG_S (MTC1 ZERO))>; +def : MipsPat<(f32 fpimm0), (MTC1 ZERO)>; +def : MipsPat<(f32 fpimm0neg), (FNEG_S (MTC1 ZERO))>; -def : Pat<(f32 (sint_to_fp CPURegs:$src)), (CVT_S_W (MTC1 CPURegs:$src))>; -def : Pat<(i32 (fp_to_sint FGR32:$src)), (MFC1 (TRUNC_W_S FGR32:$src))>; +def : MipsPat<(f32 (sint_to_fp CPURegs:$src)), (CVT_S_W (MTC1 CPURegs:$src))>; +def : MipsPat<(i32 (fp_to_sint FGR32:$src)), (MFC1 (TRUNC_W_S FGR32:$src))>; -let Predicates = [NotFP64bit] in { - def : Pat<(f64 (sint_to_fp CPURegs:$src)), (CVT_D32_W (MTC1 CPURegs:$src))>; - def : Pat<(i32 (fp_to_sint AFGR64:$src)), (MFC1 (TRUNC_W_D32 AFGR64:$src))>; - def : Pat<(f32 (fround AFGR64:$src)), (CVT_S_D32 AFGR64:$src)>; - def : Pat<(f64 (fextend FGR32:$src)), (CVT_D32_S FGR32:$src)>; +let Predicates = [NotFP64bit, HasStandardEncoding] in { + def : MipsPat<(f64 (sint_to_fp CPURegs:$src)), + (CVT_D32_W (MTC1 CPURegs:$src))>; + def : MipsPat<(i32 (fp_to_sint AFGR64:$src)), + (MFC1 (TRUNC_W_D32 AFGR64:$src))>; + def : MipsPat<(f32 (fround AFGR64:$src)), (CVT_S_D32 AFGR64:$src)>; + def : MipsPat<(f64 (fextend FGR32:$src)), (CVT_D32_S FGR32:$src)>; } -let Predicates = [IsFP64bit] in { - def : Pat<(f64 fpimm0), (DMTC1 ZERO_64)>; - def : Pat<(f64 fpimm0neg), (FNEG_D64 (DMTC1 ZERO_64))>; +let Predicates = [IsFP64bit, HasStandardEncoding] in { + def : MipsPat<(f64 fpimm0), (DMTC1 ZERO_64)>; + def : MipsPat<(f64 fpimm0neg), (FNEG_D64 (DMTC1 ZERO_64))>; - def : Pat<(f64 (sint_to_fp CPURegs:$src)), (CVT_D64_W (MTC1 CPURegs:$src))>; - def : Pat<(f32 (sint_to_fp CPU64Regs:$src)), - (CVT_S_L (DMTC1 CPU64Regs:$src))>; - def : Pat<(f64 (sint_to_fp CPU64Regs:$src)), - (CVT_D64_L (DMTC1 CPU64Regs:$src))>; + def : MipsPat<(f64 (sint_to_fp CPURegs:$src)), + (CVT_D64_W (MTC1 CPURegs:$src))>; + def : MipsPat<(f32 (sint_to_fp CPU64Regs:$src)), + (CVT_S_L (DMTC1 CPU64Regs:$src))>; + def : MipsPat<(f64 (sint_to_fp CPU64Regs:$src)), + (CVT_D64_L (DMTC1 CPU64Regs:$src))>; - def : Pat<(i32 (fp_to_sint FGR64:$src)), (MFC1 (TRUNC_W_D64 FGR64:$src))>; - def : Pat<(i64 (fp_to_sint FGR32:$src)), (DMFC1 (TRUNC_L_S FGR32:$src))>; - def : Pat<(i64 (fp_to_sint FGR64:$src)), (DMFC1 (TRUNC_L_D64 FGR64:$src))>; + def : MipsPat<(i32 (fp_to_sint FGR64:$src)), + (MFC1 (TRUNC_W_D64 FGR64:$src))>; + def : MipsPat<(i64 (fp_to_sint FGR32:$src)), (DMFC1 (TRUNC_L_S FGR32:$src))>; + def : MipsPat<(i64 (fp_to_sint FGR64:$src)), + (DMFC1 (TRUNC_L_D64 FGR64:$src))>; - def : Pat<(f32 (fround FGR64:$src)), (CVT_S_D64 FGR64:$src)>; - def : Pat<(f64 (fextend FGR32:$src)), (CVT_D64_S FGR32:$src)>; + def : MipsPat<(f32 (fround FGR64:$src)), (CVT_S_D64 FGR64:$src)>; + def : MipsPat<(f64 (fextend FGR32:$src)), (CVT_D64_S FGR32:$src)>; } // Patterns for unaligned floating point loads and stores. -let Predicates = [HasMips32r2Or64, NotN64] in { - def : Pat<(f32 (load_u CPURegs:$addr)), (LUXC1 CPURegs:$addr, ZERO)>; - def : Pat<(store_u FGR32:$src, CPURegs:$addr), - (SUXC1 FGR32:$src, CPURegs:$addr, ZERO)>; +let Predicates = [HasMips32r2Or64, NotN64, HasStandardEncoding] in { + def : MipsPat<(f32 (load_u CPURegs:$addr)), (LUXC1 CPURegs:$addr, ZERO)>; + def : MipsPat<(store_u FGR32:$src, CPURegs:$addr), + (SUXC1 FGR32:$src, CPURegs:$addr, ZERO)>; } -let Predicates = [IsN64] in { - def : Pat<(f32 (load_u CPU64Regs:$addr)), (LUXC1_P8 CPU64Regs:$addr, ZERO_64)>; - def : Pat<(store_u FGR32:$src, CPU64Regs:$addr), - (SUXC1_P8 FGR32:$src, CPU64Regs:$addr, ZERO_64)>; +let Predicates = [IsN64, HasStandardEncoding] in { + def : MipsPat<(f32 (load_u CPU64Regs:$addr)), + (LUXC1_P8 CPU64Regs:$addr, ZERO_64)>; + def : MipsPat<(store_u FGR32:$src, CPU64Regs:$addr), + (SUXC1_P8 FGR32:$src, CPU64Regs:$addr, ZERO_64)>; } diff --git a/lib/Target/Mips/MipsInstrFormats.td b/lib/Target/Mips/MipsInstrFormats.td index 841eba0..15a77fb 100644 --- a/lib/Target/Mips/MipsInstrFormats.td +++ b/lib/Target/Mips/MipsInstrFormats.td @@ -70,6 +70,9 @@ class MipsInst<dag outs, dag ins, string asmstr, list<dag> pattern, let DecoderNamespace = "Mips"; field bits<32> SoftFail = 0; + + let Predicates = [HasStandardEncoding]; + } // Mips Pseudo Instructions Format diff --git a/lib/Target/Mips/MipsInstrInfo.cpp b/lib/Target/Mips/MipsInstrInfo.cpp index a3a18bf..458e4f7 100644 --- a/lib/Target/Mips/MipsInstrInfo.cpp +++ b/lib/Target/Mips/MipsInstrInfo.cpp @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +#include "MipsAnalyzeImmediate.h" #include "MipsInstrInfo.h" #include "MipsTargetMachine.h" #include "MipsMachineFunction.h" @@ -29,6 +30,7 @@ using namespace llvm; MipsInstrInfo::MipsInstrInfo(MipsTargetMachine &tm) : MipsGenInstrInfo(Mips::ADJCALLSTACKDOWN, Mips::ADJCALLSTACKUP), TM(tm), IsN64(TM.getSubtarget<MipsSubtarget>().isABI_N64()), + InMips16Mode(TM.getSubtarget<MipsSubtarget>().inMips16Mode()), RI(*TM.getSubtargetImpl(), *this), UncondBrOpc(TM.getRelocationModel() == Reloc::PIC_ ? Mips::B : Mips::J) {} @@ -106,8 +108,13 @@ copyPhysReg(MachineBasicBlock &MBB, unsigned Opc = 0, ZeroReg = 0; if (Mips::CPURegsRegClass.contains(DestReg)) { // Copy to CPU Reg. - if (Mips::CPURegsRegClass.contains(SrcReg)) - Opc = Mips::ADDu, ZeroReg = Mips::ZERO; + if (Mips::CPURegsRegClass.contains(SrcReg)) { + if (InMips16Mode) + Opc=Mips::Mov32R16; + else { + Opc = Mips::ADDu, ZeroReg = Mips::ZERO; + } + } else if (Mips::CCRRegClass.contains(SrcReg)) Opc = Mips::CFC1; else if (Mips::FGR32RegClass.contains(SrcReg)) @@ -189,15 +196,15 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, unsigned Opc = 0; - if (RC == Mips::CPURegsRegisterClass) + if (Mips::CPURegsRegClass.hasSubClassEq(RC)) Opc = IsN64 ? Mips::SW_P8 : Mips::SW; - else if (RC == Mips::CPU64RegsRegisterClass) + else if (Mips::CPU64RegsRegClass.hasSubClassEq(RC)) Opc = IsN64 ? Mips::SD_P8 : Mips::SD; - else if (RC == Mips::FGR32RegisterClass) + else if (Mips::FGR32RegClass.hasSubClassEq(RC)) Opc = IsN64 ? Mips::SWC1_P8 : Mips::SWC1; - else if (RC == Mips::AFGR64RegisterClass) + else if (Mips::AFGR64RegClass.hasSubClassEq(RC)) Opc = Mips::SDC1; - else if (RC == Mips::FGR64RegisterClass) + else if (Mips::FGR64RegClass.hasSubClassEq(RC)) Opc = IsN64 ? Mips::SDC164_P8 : Mips::SDC164; assert(Opc && "Register class not handled!"); @@ -216,15 +223,15 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, MachineMemOperand *MMO = GetMemOperand(MBB, FI, MachineMemOperand::MOLoad); unsigned Opc = 0; - if (RC == Mips::CPURegsRegisterClass) + if (Mips::CPURegsRegClass.hasSubClassEq(RC)) Opc = IsN64 ? Mips::LW_P8 : Mips::LW; - else if (RC == Mips::CPU64RegsRegisterClass) + else if (Mips::CPU64RegsRegClass.hasSubClassEq(RC)) Opc = IsN64 ? Mips::LD_P8 : Mips::LD; - else if (RC == Mips::FGR32RegisterClass) + else if (Mips::FGR32RegClass.hasSubClassEq(RC)) Opc = IsN64 ? Mips::LWC1_P8 : Mips::LWC1; - else if (RC == Mips::AFGR64RegisterClass) + else if (Mips::AFGR64RegClass.hasSubClassEq(RC)) Opc = Mips::LDC1; - else if (RC == Mips::FGR64RegisterClass) + else if (Mips::FGR64RegClass.hasSubClassEq(RC)) Opc = IsN64 ? Mips::LDC164_P8 : Mips::LDC164; assert(Opc && "Register class not handled!"); @@ -232,6 +239,76 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, .addMemOperand(MMO); } +void MipsInstrInfo::ExpandRetRA(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + unsigned Opc) const { + BuildMI(MBB, I, I->getDebugLoc(), TM.getInstrInfo()->get(Opc)) + .addReg(Mips::RA); +} + +void MipsInstrInfo::ExpandRetRA16(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + unsigned Opc) const { + BuildMI(MBB, I, I->getDebugLoc(), TM.getInstrInfo()->get(Opc)); +} + +void MipsInstrInfo::ExpandExtractElementF64(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const { + const TargetInstrInfo *TII = TM.getInstrInfo(); + unsigned DstReg = I->getOperand(0).getReg(); + unsigned SrcReg = I->getOperand(1).getReg(); + unsigned N = I->getOperand(2).getImm(); + const MCInstrDesc& Mfc1Tdd = TII->get(Mips::MFC1); + DebugLoc dl = I->getDebugLoc(); + + assert(N < 2 && "Invalid immediate"); + unsigned SubIdx = N ? Mips::sub_fpodd : Mips::sub_fpeven; + unsigned SubReg = TM.getRegisterInfo()->getSubReg(SrcReg, SubIdx); + + BuildMI(MBB, I, dl, Mfc1Tdd, DstReg).addReg(SubReg); +} + +void MipsInstrInfo::ExpandBuildPairF64(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const { + const TargetInstrInfo *TII = TM.getInstrInfo(); + unsigned DstReg = I->getOperand(0).getReg(); + unsigned LoReg = I->getOperand(1).getReg(), HiReg = I->getOperand(2).getReg(); + const MCInstrDesc& Mtc1Tdd = TII->get(Mips::MTC1); + DebugLoc dl = I->getDebugLoc(); + const TargetRegisterInfo *TRI = TM.getRegisterInfo(); + + // mtc1 Lo, $fp + // mtc1 Hi, $fp + 1 + BuildMI(MBB, I, dl, Mtc1Tdd, TRI->getSubReg(DstReg, Mips::sub_fpeven)) + .addReg(LoReg); + BuildMI(MBB, I, dl, Mtc1Tdd, TRI->getSubReg(DstReg, Mips::sub_fpodd)) + .addReg(HiReg); +} + +bool MipsInstrInfo::expandPostRAPseudo(MachineBasicBlock::iterator MI) const { + MachineBasicBlock &MBB = *MI->getParent(); + + switch(MI->getDesc().getOpcode()) { + default: + return false; + case Mips::RetRA: + ExpandRetRA(MBB, MI, Mips::RET); + break; + case Mips::RetRA16: + ExpandRetRA16(MBB, MI, Mips::JrRa16); + break; + case Mips::BuildPairF64: + ExpandBuildPairF64(MBB, MI); + break; + case Mips::ExtractElementF64: + ExpandExtractElementF64(MBB, MI); + break; + } + + MBB.erase(MI); + return true; +} + MachineInstr* MipsInstrInfo::emitFrameIndexDebugValue(MachineFunction &MF, int FrameIx, uint64_t Offset, const MDNode *MDPtr, @@ -278,9 +355,9 @@ unsigned Mips::GetOppositeBranchOpc(unsigned Opc) } } -static void AnalyzeCondBr(const MachineInstr* Inst, unsigned Opc, +static void AnalyzeCondBr(const MachineInstr *Inst, unsigned Opc, MachineBasicBlock *&BB, - SmallVectorImpl<MachineOperand>& Cond) { + SmallVectorImpl<MachineOperand> &Cond) { assert(GetAnalyzableBrOpc(Opc) && "Not an analyzable branch"); int NumOp = Inst->getNumExplicitOperands(); @@ -454,3 +531,58 @@ ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const return false; } +/// Return the number of bytes of code the specified instruction may be. +unsigned MipsInstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const { + switch (MI->getOpcode()) { + default: + return MI->getDesc().getSize(); + case TargetOpcode::INLINEASM: { // Inline Asm: Variable size. + const MachineFunction *MF = MI->getParent()->getParent(); + const char *AsmStr = MI->getOperand(0).getSymbolName(); + return getInlineAsmLength(AsmStr, *MF->getTarget().getMCAsmInfo()); + } + } +} + +unsigned +llvm::Mips::loadImmediate(int64_t Imm, bool IsN64, const TargetInstrInfo &TII, + MachineBasicBlock& MBB, + MachineBasicBlock::iterator II, DebugLoc DL, + bool LastInstrIsADDiu, + MipsAnalyzeImmediate::Inst *LastInst) { + MipsAnalyzeImmediate AnalyzeImm; + unsigned Size = IsN64 ? 64 : 32; + unsigned LUi = IsN64 ? Mips::LUi64 : Mips::LUi; + unsigned ZEROReg = IsN64 ? Mips::ZERO_64 : Mips::ZERO; + unsigned ATReg = IsN64 ? Mips::AT_64 : Mips::AT; + + const MipsAnalyzeImmediate::InstSeq &Seq = + AnalyzeImm.Analyze(Imm, Size, LastInstrIsADDiu); + MipsAnalyzeImmediate::InstSeq::const_iterator Inst = Seq.begin(); + + if (LastInst && (Seq.size() == 1)) { + *LastInst = *Inst; + return 0; + } + + // The first instruction can be a LUi, which is different from other + // instructions (ADDiu, ORI and SLL) in that it does not have a register + // operand. + if (Inst->Opc == LUi) + BuildMI(MBB, II, DL, TII.get(LUi), ATReg) + .addImm(SignExtend64<16>(Inst->ImmOpnd)); + else + BuildMI(MBB, II, DL, TII.get(Inst->Opc), ATReg).addReg(ZEROReg) + .addImm(SignExtend64<16>(Inst->ImmOpnd)); + + // Build the remaining instructions in Seq. Skip the last instruction if + // LastInst is not 0. + for (++Inst; Inst != Seq.end() - !!LastInst; ++Inst) + BuildMI(MBB, II, DL, TII.get(Inst->Opc), ATReg).addReg(ATReg) + .addImm(SignExtend64<16>(Inst->ImmOpnd)); + + if (LastInst) + *LastInst = *Inst; + + return Seq.size() - !!LastInst; +} diff --git a/lib/Target/Mips/MipsInstrInfo.h b/lib/Target/Mips/MipsInstrInfo.h index 4be727d..358f817 100644 --- a/lib/Target/Mips/MipsInstrInfo.h +++ b/lib/Target/Mips/MipsInstrInfo.h @@ -15,6 +15,7 @@ #define MIPSINSTRUCTIONINFO_H #include "Mips.h" +#include "MipsAnalyzeImmediate.h" #include "MipsRegisterInfo.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Target/TargetInstrInfo.h" @@ -24,15 +25,9 @@ namespace llvm { -namespace Mips { - /// GetOppositeBranchOpc - Return the inverse of the specified - /// opcode, e.g. turning BEQ to BNE. - unsigned GetOppositeBranchOpc(unsigned Opc); -} - class MipsInstrInfo : public MipsGenInstrInfo { MipsTargetMachine &TM; - bool IsN64; + bool IsN64; bool InMips16Mode; const MipsRegisterInfo RI; unsigned UncondBrOpc; public: @@ -68,8 +63,17 @@ public: virtual unsigned RemoveBranch(MachineBasicBlock &MBB) const; private: + void ExpandRetRA(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, + unsigned Opc) const; + void ExpandRetRA16(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, + unsigned Opc) const; + void BuildCondBr(MachineBasicBlock &MBB, MachineBasicBlock *TBB, DebugLoc DL, const SmallVectorImpl<MachineOperand>& Cond) const; + void ExpandExtractElementF64(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const; + void ExpandBuildPairF64(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const; public: virtual unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, @@ -92,6 +96,8 @@ public: const TargetRegisterClass *RC, const TargetRegisterInfo *TRI) const; + virtual bool expandPostRAPseudo(MachineBasicBlock::iterator MI) const; + virtual MachineInstr* emitFrameIndexDebugValue(MachineFunction &MF, int FrameIx, uint64_t Offset, const MDNode *MDPtr, @@ -103,8 +109,27 @@ public: /// Insert nop instruction when hazard condition is found virtual void insertNoop(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const; + + /// Return the number of bytes of code the specified instruction may be. + unsigned GetInstSizeInBytes(const MachineInstr *MI) const; }; +namespace Mips { + /// GetOppositeBranchOpc - Return the inverse of the specified + /// opcode, e.g. turning BEQ to BNE. + unsigned GetOppositeBranchOpc(unsigned Opc); + + /// Emit a series of instructions to load an immediate. All instructions + /// except for the last one are emitted. The function returns the number of + /// MachineInstrs generated. The opcode-immediate pair of the last + /// instruction is returned in LastInst, if it is not 0. + unsigned + loadImmediate(int64_t Imm, bool IsN64, const TargetInstrInfo &TII, + MachineBasicBlock& MBB, MachineBasicBlock::iterator II, + DebugLoc DL, bool LastInstrIsADDiu, + MipsAnalyzeImmediate::Inst *LastInst); +} + } #endif diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td index 873d2bd..f1aada4 100644 --- a/lib/Target/Mips/MipsInstrInfo.td +++ b/lib/Target/Mips/MipsInstrInfo.td @@ -11,17 +11,11 @@ // //===----------------------------------------------------------------------===// -//===----------------------------------------------------------------------===// -// Instruction format superclass -//===----------------------------------------------------------------------===// - -include "MipsInstrFormats.td" //===----------------------------------------------------------------------===// // Mips profiles and nodes //===----------------------------------------------------------------------===// -def SDT_MipsRet : SDTypeProfile<0, 1, [SDTCisInt<0>]>; def SDT_MipsJmpLink : SDTypeProfile<0, 1, [SDTCisVT<0, iPTR>]>; def SDT_MipsCMov : SDTypeProfile<1, 4, [SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>, @@ -49,6 +43,10 @@ def SDT_Ins : SDTypeProfile<1, 4, [SDTCisInt<0>, SDTCisSameAs<0, 1>, SDTCisVT<2, i32>, SDTCisSameAs<2, 3>, SDTCisSameAs<0, 4>]>; +def SDTMipsLoadLR : SDTypeProfile<1, 2, + [SDTCisInt<0>, SDTCisPtrTy<1>, + SDTCisSameAs<0, 2>]>; + // Call def MipsJmpLink : SDNode<"MipsISD::JmpLink",SDT_MipsJmpLink, [SDNPHasChain, SDNPOutGlue, SDNPOptInGlue, @@ -72,8 +70,7 @@ def MipsTprelLo : SDNode<"MipsISD::TprelLo", SDTIntUnaryOp>; def MipsThreadPointer: SDNode<"MipsISD::ThreadPointer", SDT_MipsThreadPointer>; // Return -def MipsRet : SDNode<"MipsISD::Ret", SDT_MipsRet, [SDNPHasChain, - SDNPOptInGlue]>; +def MipsRet : SDNode<"MipsISD::Ret", SDTNone, [SDNPHasChain, SDNPOptInGlue]>; // These are target-independent nodes, but have target-specific formats. def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_MipsCallSeqStart, @@ -118,6 +115,23 @@ def MipsSync : SDNode<"MipsISD::Sync", SDT_Sync, [SDNPHasChain]>; def MipsExt : SDNode<"MipsISD::Ext", SDT_Ext>; def MipsIns : SDNode<"MipsISD::Ins", SDT_Ins>; +def MipsLWL : SDNode<"MipsISD::LWL", SDTMipsLoadLR, + [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; +def MipsLWR : SDNode<"MipsISD::LWR", SDTMipsLoadLR, + [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; +def MipsSWL : SDNode<"MipsISD::SWL", SDTStore, + [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; +def MipsSWR : SDNode<"MipsISD::SWR", SDTStore, + [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; +def MipsLDL : SDNode<"MipsISD::LDL", SDTMipsLoadLR, + [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; +def MipsLDR : SDNode<"MipsISD::LDR", SDTMipsLoadLR, + [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; +def MipsSDL : SDNode<"MipsISD::SDL", SDTStore, + [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; +def MipsSDR : SDNode<"MipsISD::SDR", SDTStore, + [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; + //===----------------------------------------------------------------------===// // Mips Instruction Predicate Definitions. //===----------------------------------------------------------------------===// @@ -145,12 +159,26 @@ def IsN64 : Predicate<"Subtarget.isABI_N64()">, AssemblerPredicate<"FeatureN64">; def NotN64 : Predicate<"!Subtarget.isABI_N64()">, AssemblerPredicate<"!FeatureN64">; +def InMips16Mode : Predicate<"Subtarget.inMips16Mode()">, + AssemblerPredicate<"FeatureMips16">; def RelocStatic : Predicate<"TM.getRelocationModel() == Reloc::Static">, AssemblerPredicate<"FeatureMips32">; def RelocPIC : Predicate<"TM.getRelocationModel() == Reloc::PIC_">, AssemblerPredicate<"FeatureMips32">; def NoNaNsFPMath : Predicate<"TM.Options.NoNaNsFPMath">, AssemblerPredicate<"FeatureMips32">; +def HasStandardEncoding : Predicate<"Subtarget.hasStandardEncoding()">, + AssemblerPredicate<"!FeatureMips16">; + +class MipsPat<dag pattern, dag result> : Pat<pattern, result> { + let Predicates = [HasStandardEncoding]; +} + +//===----------------------------------------------------------------------===// +// Instruction format superclass +//===----------------------------------------------------------------------===// + +include "MipsInstrFormats.td" //===----------------------------------------------------------------------===// // Mips Operand, Complex Patterns and Transformations Definitions. @@ -190,6 +218,7 @@ def mem : Operand<i32> { def mem64 : Operand<i64> { let PrintMethod = "printMemOperand"; let MIOperandInfo = (ops CPU64Regs, simm16_64); + let EncoderMethod = "getMemEncoding"; } def mem_ea : Operand<i32> { @@ -252,7 +281,8 @@ def immZExt5 : ImmLeaf<i32, [{return Imm == (Imm & 0x1f);}]>; // Mips Address Mode! SDNode frameindex could possibily be a match // since load and store instructions from stack used it. -def addr : ComplexPattern<iPTR, 2, "SelectAddr", [frameindex], [SDNPWantParent]>; +def addr : + ComplexPattern<iPTR, 2, "SelectAddr", [frameindex], [SDNPWantParent]>; //===----------------------------------------------------------------------===// // Pattern fragment for load/store @@ -418,21 +448,13 @@ class StoreM<bits<6> op, string instr_asm, PatFrag OpNode, RegisterClass RC, let isPseudo = Pseudo; } -// Unaligned Memory Load/Store -let canFoldAsLoad = 1 in -class LoadUnAlign<bits<6> op, RegisterClass RC, Operand MemOpnd>: - FMem<op, (outs RC:$rt), (ins MemOpnd:$addr), "", [], IILoad> {} - -class StoreUnAlign<bits<6> op, RegisterClass RC, Operand MemOpnd>: - FMem<op, (outs), (ins RC:$rt, MemOpnd:$addr), "", [], IIStore> {} - // 32-bit load. multiclass LoadM32<bits<6> op, string instr_asm, PatFrag OpNode, bit Pseudo = 0> { def #NAME# : LoadM<op, instr_asm, OpNode, CPURegs, mem, Pseudo>, - Requires<[NotN64]>; + Requires<[NotN64, HasStandardEncoding]>; def _P8 : LoadM<op, instr_asm, OpNode, CPURegs, mem64, Pseudo>, - Requires<[IsN64]> { + Requires<[IsN64, HasStandardEncoding]> { let DecoderNamespace = "Mips64"; let isCodeGenOnly = 1; } @@ -442,31 +464,21 @@ multiclass LoadM32<bits<6> op, string instr_asm, PatFrag OpNode, multiclass LoadM64<bits<6> op, string instr_asm, PatFrag OpNode, bit Pseudo = 0> { def #NAME# : LoadM<op, instr_asm, OpNode, CPU64Regs, mem, Pseudo>, - Requires<[NotN64]>; + Requires<[NotN64, HasStandardEncoding]>; def _P8 : LoadM<op, instr_asm, OpNode, CPU64Regs, mem64, Pseudo>, - Requires<[IsN64]> { + Requires<[IsN64, HasStandardEncoding]> { let DecoderNamespace = "Mips64"; let isCodeGenOnly = 1; } } -// 32-bit load. -multiclass LoadUnAlign32<bits<6> op> { - def #NAME# : LoadUnAlign<op, CPURegs, mem>, - Requires<[NotN64]>; - def _P8 : LoadUnAlign<op, CPURegs, mem64>, - Requires<[IsN64]> { - let DecoderNamespace = "Mips64"; - let isCodeGenOnly = 1; - } -} // 32-bit store. multiclass StoreM32<bits<6> op, string instr_asm, PatFrag OpNode, bit Pseudo = 0> { def #NAME# : StoreM<op, instr_asm, OpNode, CPURegs, mem, Pseudo>, - Requires<[NotN64]>; + Requires<[NotN64, HasStandardEncoding]>; def _P8 : StoreM<op, instr_asm, OpNode, CPURegs, mem64, Pseudo>, - Requires<[IsN64]> { + Requires<[IsN64, HasStandardEncoding]> { let DecoderNamespace = "Mips64"; let isCodeGenOnly = 1; } @@ -476,20 +488,69 @@ multiclass StoreM32<bits<6> op, string instr_asm, PatFrag OpNode, multiclass StoreM64<bits<6> op, string instr_asm, PatFrag OpNode, bit Pseudo = 0> { def #NAME# : StoreM<op, instr_asm, OpNode, CPU64Regs, mem, Pseudo>, - Requires<[NotN64]>; + Requires<[NotN64, HasStandardEncoding]>; def _P8 : StoreM<op, instr_asm, OpNode, CPU64Regs, mem64, Pseudo>, - Requires<[IsN64]> { + Requires<[IsN64, HasStandardEncoding]> { let DecoderNamespace = "Mips64"; let isCodeGenOnly = 1; } } -// 32-bit store. -multiclass StoreUnAlign32<bits<6> op> { - def #NAME# : StoreUnAlign<op, CPURegs, mem>, - Requires<[NotN64]>; - def _P8 : StoreUnAlign<op, CPURegs, mem64>, - Requires<[IsN64]> { +// Load/Store Left/Right +let canFoldAsLoad = 1 in +class LoadLeftRight<bits<6> op, string instr_asm, SDNode OpNode, + RegisterClass RC, Operand MemOpnd> : + FMem<op, (outs RC:$rt), (ins MemOpnd:$addr, RC:$src), + !strconcat(instr_asm, "\t$rt, $addr"), + [(set RC:$rt, (OpNode addr:$addr, RC:$src))], IILoad> { + string Constraints = "$src = $rt"; +} + +class StoreLeftRight<bits<6> op, string instr_asm, SDNode OpNode, + RegisterClass RC, Operand MemOpnd>: + FMem<op, (outs), (ins RC:$rt, MemOpnd:$addr), + !strconcat(instr_asm, "\t$rt, $addr"), [(OpNode RC:$rt, addr:$addr)], + IIStore>; + +// 32-bit load left/right. +multiclass LoadLeftRightM32<bits<6> op, string instr_asm, SDNode OpNode> { + def #NAME# : LoadLeftRight<op, instr_asm, OpNode, CPURegs, mem>, + Requires<[NotN64, HasStandardEncoding]>; + def _P8 : LoadLeftRight<op, instr_asm, OpNode, CPURegs, mem64>, + Requires<[IsN64, HasStandardEncoding]> { + let DecoderNamespace = "Mips64"; + let isCodeGenOnly = 1; + } +} + +// 64-bit load left/right. +multiclass LoadLeftRightM64<bits<6> op, string instr_asm, SDNode OpNode> { + def #NAME# : LoadLeftRight<op, instr_asm, OpNode, CPU64Regs, mem>, + Requires<[NotN64, HasStandardEncoding]>; + def _P8 : LoadLeftRight<op, instr_asm, OpNode, CPU64Regs, mem64>, + Requires<[IsN64, HasStandardEncoding]> { + let DecoderNamespace = "Mips64"; + let isCodeGenOnly = 1; + } +} + +// 32-bit store left/right. +multiclass StoreLeftRightM32<bits<6> op, string instr_asm, SDNode OpNode> { + def #NAME# : StoreLeftRight<op, instr_asm, OpNode, CPURegs, mem>, + Requires<[NotN64, HasStandardEncoding]>; + def _P8 : StoreLeftRight<op, instr_asm, OpNode, CPURegs, mem64>, + Requires<[IsN64, HasStandardEncoding]> { + let DecoderNamespace = "Mips64"; + let isCodeGenOnly = 1; + } +} + +// 64-bit store left/right. +multiclass StoreLeftRightM64<bits<6> op, string instr_asm, SDNode OpNode> { + def #NAME# : StoreLeftRight<op, instr_asm, OpNode, CPU64Regs, mem>, + Requires<[NotN64, HasStandardEncoding]>; + def _P8 : StoreLeftRight<op, instr_asm, OpNode, CPU64Regs, mem64>, + Requires<[IsN64, HasStandardEncoding]> { let DecoderNamespace = "Mips64"; let isCodeGenOnly = 1; } @@ -503,6 +564,7 @@ class CBranch<bits<6> op, string instr_asm, PatFrag cond_op, RegisterClass RC>: let isBranch = 1; let isTerminator = 1; let hasDelaySlot = 1; + let Defs = [AT]; } class CBranchZero<bits<6> op, bits<5> _rt, string instr_asm, PatFrag cond_op, @@ -514,6 +576,7 @@ class CBranchZero<bits<6> op, bits<5> _rt, string instr_asm, PatFrag cond_op, let isBranch = 1; let isTerminator = 1; let hasDelaySlot = 1; + let Defs = [AT]; } // SetCC @@ -541,8 +604,9 @@ class JumpFJ<bits<6> op, string instr_asm>: let isTerminator=1; let isBarrier=1; let hasDelaySlot = 1; - let Predicates = [RelocStatic]; + let Predicates = [RelocStatic, HasStandardEncoding]; let DecoderMethod = "DecodeJumpTarget"; + let Defs = [AT]; } // Unconditional branch @@ -555,23 +619,37 @@ class UncondBranch<bits<6> op, string instr_asm>: let isTerminator = 1; let isBarrier = 1; let hasDelaySlot = 1; - let Predicates = [RelocPIC]; + let Predicates = [RelocPIC, HasStandardEncoding]; + let Defs = [AT]; } -let isBranch=1, isTerminator=1, isBarrier=1, rd=0, hasDelaySlot = 1, - isIndirectBranch = 1 in -class JumpFR<bits<6> op, bits<6> func, string instr_asm, RegisterClass RC>: - FR<op, func, (outs), (ins RC:$rs), - !strconcat(instr_asm, "\t$rs"), [(brind RC:$rs)], IIBranch> { +// Base class for indirect branch and return instruction classes. +let isTerminator=1, isBarrier=1, hasDelaySlot = 1 in +class JumpFR<RegisterClass RC, list<dag> pattern>: + FR<0, 0x8, (outs), (ins RC:$rs), "jr\t$rs", pattern, IIBranch> { let rt = 0; let rd = 0; let shamt = 0; } +// Indirect branch +class IndirectBranch<RegisterClass RC>: JumpFR<RC, [(brind RC:$rs)]> { + let isBranch = 1; + let isIndirectBranch = 1; +} + +// Return instruction +class RetBase<RegisterClass RC>: JumpFR<RC, []> { + let isReturn = 1; + let isCodeGenOnly = 1; + let hasCtrlDep = 1; + let hasExtraSrcRegAllocReq = 1; +} + // Jump and Link (Call) -let isCall=1, hasDelaySlot=1 in { +let isCall=1, hasDelaySlot=1, Defs = [RA] in { class JumpLink<bits<6> op, string instr_asm>: - FJ<op, (outs), (ins calltarget:$target, variable_ops), + FJ<op, (outs), (ins calltarget:$target), !strconcat(instr_asm, "\t$target"), [(MipsJmpLink imm:$target)], IIBranch> { let DecoderMethod = "DecodeJumpTarget"; @@ -579,7 +657,7 @@ let isCall=1, hasDelaySlot=1 in { class JumpLinkReg<bits<6> op, bits<6> func, string instr_asm, RegisterClass RC>: - FR<op, func, (outs), (ins RC:$rs, variable_ops), + FR<op, func, (outs), (ins RC:$rs), !strconcat(instr_asm, "\t$rs"), [(MipsJmpLink RC:$rs)], IIBranch> { let rt = 0; let rd = 31; @@ -587,7 +665,7 @@ let isCall=1, hasDelaySlot=1 in { } class BranchLink<string instr_asm, bits<5> _rt, RegisterClass RC>: - FI<0x1, (outs), (ins RC:$rs, brtarget:$imm16, variable_ops), + FI<0x1, (outs), (ins RC:$rs, brtarget:$imm16), !strconcat(instr_asm, "\t$rs, $imm16"), [], IIBranch> { let rt = _rt; } @@ -653,7 +731,7 @@ class CountLeading0<bits<6> func, string instr_asm, RegisterClass RC>: FR<0x1c, func, (outs RC:$rd), (ins RC:$rs), !strconcat(instr_asm, "\t$rd, $rs"), [(set RC:$rd, (ctlz RC:$rs))], IIAlu>, - Requires<[HasBitCount]> { + Requires<[HasBitCount, HasStandardEncoding]> { let shamt = 0; let rt = rd; } @@ -662,7 +740,7 @@ class CountLeading1<bits<6> func, string instr_asm, RegisterClass RC>: FR<0x1c, func, (outs RC:$rd), (ins RC:$rs), !strconcat(instr_asm, "\t$rd, $rs"), [(set RC:$rd, (ctlz (not RC:$rs)))], IIAlu>, - Requires<[HasBitCount]> { + Requires<[HasBitCount, HasStandardEncoding]> { let shamt = 0; let rt = rd; } @@ -675,7 +753,7 @@ class SignExtInReg<bits<5> sa, string instr_asm, ValueType vt, [(set RC:$rd, (sext_inreg RC:$rt, vt))], NoItinerary> { let rs = 0; let shamt = sa; - let Predicates = [HasSEInReg]; + let Predicates = [HasSEInReg, HasStandardEncoding]; } // Subword Swap @@ -684,7 +762,7 @@ class SubwordSwap<bits<6> func, bits<5> sa, string instr_asm, RegisterClass RC>: !strconcat(instr_asm, "\t$rd, $rt"), [], NoItinerary> { let rs = 0; let shamt = sa; - let Predicates = [HasSwap]; + let Predicates = [HasSwap, HasStandardEncoding]; let neverHasSideEffects = 1; } @@ -705,7 +783,7 @@ class ExtBase<bits<6> _funct, string instr_asm, RegisterClass RC>: bits<5> sz; let rd = sz; let shamt = pos; - let Predicates = [HasMips32r2]; + let Predicates = [HasMips32r2, HasStandardEncoding]; } class InsBase<bits<6> _funct, string instr_asm, RegisterClass RC>: @@ -718,7 +796,7 @@ class InsBase<bits<6> _funct, string instr_asm, RegisterClass RC>: bits<5> sz; let rd = sz; let shamt = pos; - let Predicates = [HasMips32r2]; + let Predicates = [HasMips32r2, HasStandardEncoding]; let Constraints = "$src = $rt"; } @@ -730,8 +808,10 @@ class Atomic2Ops<PatFrag Op, string Opstr, RegisterClass DRC, [(set DRC:$dst, (Op PRC:$ptr, DRC:$incr))]>; multiclass Atomic2Ops32<PatFrag Op, string Opstr> { - def #NAME# : Atomic2Ops<Op, Opstr, CPURegs, CPURegs>, Requires<[NotN64]>; - def _P8 : Atomic2Ops<Op, Opstr, CPURegs, CPU64Regs>, Requires<[IsN64]> { + def #NAME# : Atomic2Ops<Op, Opstr, CPURegs, CPURegs>, + Requires<[NotN64, HasStandardEncoding]>; + def _P8 : Atomic2Ops<Op, Opstr, CPURegs, CPU64Regs>, + Requires<[IsN64, HasStandardEncoding]> { let DecoderNamespace = "Mips64"; } } @@ -744,8 +824,10 @@ class AtomicCmpSwap<PatFrag Op, string Width, RegisterClass DRC, [(set DRC:$dst, (Op PRC:$ptr, DRC:$cmp, DRC:$swap))]>; multiclass AtomicCmpSwap32<PatFrag Op, string Width> { - def #NAME# : AtomicCmpSwap<Op, Width, CPURegs, CPURegs>, Requires<[NotN64]>; - def _P8 : AtomicCmpSwap<Op, Width, CPURegs, CPU64Regs>, Requires<[IsN64]> { + def #NAME# : AtomicCmpSwap<Op, Width, CPURegs, CPURegs>, + Requires<[NotN64, HasStandardEncoding]>; + def _P8 : AtomicCmpSwap<Op, Width, CPURegs, CPU64Regs>, + Requires<[IsN64, HasStandardEncoding]> { let DecoderNamespace = "Mips64"; } } @@ -767,6 +849,10 @@ class SCBase<bits<6> Opc, string opstring, RegisterClass RC, Operand Mem> : // Pseudo instructions //===----------------------------------------------------------------------===// +// Return RA. +let isReturn=1, isTerminator=1, hasDelaySlot=1, isBarrier=1, hasCtrlDep=1 in +def RetRA : MipsPseudo<(outs), (ins), "", [(MipsRet)]>; + // As stack alignment is always done with addiu, we need a 16-bit immediate let Defs = [SP], Uses = [SP] in { def ADJCALLSTACKDOWN : MipsPseudo<(outs), (ins uimm16:$amt), @@ -785,29 +871,6 @@ let neverHasSideEffects = 1 in def CPRESTORE : MipsPseudo<(outs), (ins i32imm:$loc, CPURegs:$gp), ".cprestore\t$loc", []>; -// For O32 ABI & PIC & non-fixed global base register, the following instruction -// seqeunce is emitted to set the global base register: -// -// 0. lui $2, %hi(_gp_disp) -// 1. addiu $2, $2, %lo(_gp_disp) -// 2. addu $globalbasereg, $2, $t9 -// -// SETGP01 is emitted during Prologue/Epilogue insertion and then converted to -// instructions 0 and 1 in the sequence above during MC lowering. -// SETGP2 is emitted just before register allocation and converted to -// instruction 2 just prior to post-RA scheduling. -// -// These pseudo instructions are needed to ensure no instructions are inserted -// before or between instructions 0 and 1, which is a limitation imposed by -// GNU linker. - -let isTerminator = 1, isBarrier = 1 in -def SETGP01 : MipsPseudo<(outs CPURegs:$dst), (ins), "", []>; - -let neverHasSideEffects = 1 in -def SETGP2 : MipsPseudo<(outs CPURegs:$globalreg), (ins CPURegs:$picreg), "", - []>; - let usesCustomInserter = 1 in { defm ATOMIC_LOAD_ADD_I8 : Atomic2Ops32<atomic_load_add_8, "load_add_8">; defm ATOMIC_LOAD_ADD_I16 : Atomic2Ops32<atomic_load_add_16, "load_add_16">; @@ -876,7 +939,7 @@ def SRLV : shift_rotate_reg<0x06, 0x00, "srlv", srl, CPURegs>; def SRAV : shift_rotate_reg<0x07, 0x00, "srav", sra, CPURegs>; // Rotate Instructions -let Predicates = [HasMips32r2] in { +let Predicates = [HasMips32r2, HasStandardEncoding] in { def ROTR : shift_rotate_imm32<0x02, 0x01, "rotr", rotr>; def ROTRV : shift_rotate_reg<0x06, 0x01, "rotrv", rotr, CPURegs>; } @@ -899,11 +962,11 @@ defm ULW : LoadM32<0x23, "ulw", load_u, 1>; defm USH : StoreM32<0x29, "ush", truncstorei16_u, 1>; defm USW : StoreM32<0x2b, "usw", store_u, 1>; -/// Primitives for unaligned -defm LWL : LoadUnAlign32<0x22>; -defm LWR : LoadUnAlign32<0x26>; -defm SWL : StoreUnAlign32<0x2A>; -defm SWR : StoreUnAlign32<0x2E>; +/// load/store left/right +defm LWL : LoadLeftRightM32<0x22, "lwl", MipsLWL>; +defm LWR : LoadLeftRightM32<0x26, "lwr", MipsLWR>; +defm SWL : StoreLeftRightM32<0x2a, "swl", MipsSWL>; +defm SWR : StoreLeftRightM32<0x2e, "swr", MipsSWR>; let hasSideEffects = 1 in def SYNC : MipsInst<(outs), (ins i32imm:$stype), "sync $stype", @@ -917,19 +980,23 @@ def SYNC : MipsInst<(outs), (ins i32imm:$stype), "sync $stype", } /// Load-linked, Store-conditional -def LL : LLBase<0x30, "ll", CPURegs, mem>, Requires<[NotN64]>; -def LL_P8 : LLBase<0x30, "ll", CPURegs, mem64>, Requires<[IsN64]> { +def LL : LLBase<0x30, "ll", CPURegs, mem>, + Requires<[NotN64, HasStandardEncoding]>; +def LL_P8 : LLBase<0x30, "ll", CPURegs, mem64>, + Requires<[IsN64, HasStandardEncoding]> { let DecoderNamespace = "Mips64"; } -def SC : SCBase<0x38, "sc", CPURegs, mem>, Requires<[NotN64]>; -def SC_P8 : SCBase<0x38, "sc", CPURegs, mem64>, Requires<[IsN64]> { +def SC : SCBase<0x38, "sc", CPURegs, mem>, + Requires<[NotN64, HasStandardEncoding]>; +def SC_P8 : SCBase<0x38, "sc", CPURegs, mem64>, + Requires<[IsN64, HasStandardEncoding]> { let DecoderNamespace = "Mips64"; } /// Jump and Branch Instructions def J : JumpFJ<0x02, "j">; -def JR : JumpFR<0x00, 0x08, "jr", CPURegs>; +def JR : IndirectBranch<CPURegs>; def B : UncondBranch<0x04, "b">; def BEQ : CBranch<0x04, "beq", seteq, CPURegs>; def BNE : CBranch<0x05, "bne", setne, CPURegs>; @@ -938,15 +1005,16 @@ def BGTZ : CBranchZero<0x07, 0, "bgtz", setgt, CPURegs>; def BLEZ : CBranchZero<0x06, 0, "blez", setle, CPURegs>; def BLTZ : CBranchZero<0x01, 0, "bltz", setlt, CPURegs>; +let rt = 0, rs = 0, isBranch = 1, isTerminator = 1, isBarrier = 1, + hasDelaySlot = 1, Defs = [RA] in +def BAL_BR: FI<0x1, (outs), (ins brtarget:$imm16), "bal\t$imm16", [], IIBranch>; + def JAL : JumpLink<0x03, "jal">; def JALR : JumpLinkReg<0x00, 0x09, "jalr", CPURegs>; def BGEZAL : BranchLink<"bgezal", 0x11, CPURegs>; def BLTZAL : BranchLink<"bltzal", 0x10, CPURegs>; -let isReturn=1, isTerminator=1, hasDelaySlot=1, isCodeGenOnly=1, - isBarrier=1, hasCtrlDep=1, rd=0, rt=0, shamt=0 in - def RET : FR <0x00, 0x08, (outs), (ins CPURegs:$target), - "jr\t$target", [(MipsRet CPURegs:$target)], IIBranch>; +def RET : RetBase<CPURegs>; /// Multiply and Divide Instructions. def MULT : Mult32<0x18, "mult", IIImul>; @@ -999,7 +1067,7 @@ def MSUBU : MArithR<5, "msubu", MipsMSubu>; // MUL is a assembly macro in the current used ISAs. In recent ISA's // it is a real instruction. def MUL : ArithLogicR<0x1c, 0x02, "mul", mul, IIImul, CPURegs, 1>, - Requires<[HasMips32]>; + Requires<[HasMips32, HasStandardEncoding]>; def RDHWR : ReadHardware<CPURegs, HWRegs>; @@ -1011,67 +1079,67 @@ def INS : InsBase<4, "ins", CPURegs>; //===----------------------------------------------------------------------===// // Small immediates -def : Pat<(i32 immSExt16:$in), - (ADDiu ZERO, imm:$in)>; -def : Pat<(i32 immZExt16:$in), - (ORi ZERO, imm:$in)>; -def : Pat<(i32 immLow16Zero:$in), - (LUi (HI16 imm:$in))>; +def : MipsPat<(i32 immSExt16:$in), + (ADDiu ZERO, imm:$in)>; +def : MipsPat<(i32 immZExt16:$in), + (ORi ZERO, imm:$in)>; +def : MipsPat<(i32 immLow16Zero:$in), + (LUi (HI16 imm:$in))>; // Arbitrary immediates -def : Pat<(i32 imm:$imm), +def : MipsPat<(i32 imm:$imm), (ORi (LUi (HI16 imm:$imm)), (LO16 imm:$imm))>; -// Carry patterns -def : Pat<(subc CPURegs:$lhs, CPURegs:$rhs), - (SUBu CPURegs:$lhs, CPURegs:$rhs)>; -def : Pat<(addc CPURegs:$lhs, CPURegs:$rhs), - (ADDu CPURegs:$lhs, CPURegs:$rhs)>; -def : Pat<(addc CPURegs:$src, immSExt16:$imm), - (ADDiu CPURegs:$src, imm:$imm)>; +// Carry MipsPatterns +def : MipsPat<(subc CPURegs:$lhs, CPURegs:$rhs), + (SUBu CPURegs:$lhs, CPURegs:$rhs)>; +def : MipsPat<(addc CPURegs:$lhs, CPURegs:$rhs), + (ADDu CPURegs:$lhs, CPURegs:$rhs)>; +def : MipsPat<(addc CPURegs:$src, immSExt16:$imm), + (ADDiu CPURegs:$src, imm:$imm)>; // Call -def : Pat<(MipsJmpLink (i32 tglobaladdr:$dst)), - (JAL tglobaladdr:$dst)>; -def : Pat<(MipsJmpLink (i32 texternalsym:$dst)), - (JAL texternalsym:$dst)>; -//def : Pat<(MipsJmpLink CPURegs:$dst), -// (JALR CPURegs:$dst)>; +def : MipsPat<(MipsJmpLink (i32 tglobaladdr:$dst)), + (JAL tglobaladdr:$dst)>; +def : MipsPat<(MipsJmpLink (i32 texternalsym:$dst)), + (JAL texternalsym:$dst)>; +//def : MipsPat<(MipsJmpLink CPURegs:$dst), +// (JALR CPURegs:$dst)>; // hi/lo relocs -def : Pat<(MipsHi tglobaladdr:$in), (LUi tglobaladdr:$in)>; -def : Pat<(MipsHi tblockaddress:$in), (LUi tblockaddress:$in)>; -def : Pat<(MipsHi tjumptable:$in), (LUi tjumptable:$in)>; -def : Pat<(MipsHi tconstpool:$in), (LUi tconstpool:$in)>; -def : Pat<(MipsHi tglobaltlsaddr:$in), (LUi tglobaltlsaddr:$in)>; - -def : Pat<(MipsLo tglobaladdr:$in), (ADDiu ZERO, tglobaladdr:$in)>; -def : Pat<(MipsLo tblockaddress:$in), (ADDiu ZERO, tblockaddress:$in)>; -def : Pat<(MipsLo tjumptable:$in), (ADDiu ZERO, tjumptable:$in)>; -def : Pat<(MipsLo tconstpool:$in), (ADDiu ZERO, tconstpool:$in)>; -def : Pat<(MipsLo tglobaltlsaddr:$in), (ADDiu ZERO, tglobaltlsaddr:$in)>; - -def : Pat<(add CPURegs:$hi, (MipsLo tglobaladdr:$lo)), - (ADDiu CPURegs:$hi, tglobaladdr:$lo)>; -def : Pat<(add CPURegs:$hi, (MipsLo tblockaddress:$lo)), - (ADDiu CPURegs:$hi, tblockaddress:$lo)>; -def : Pat<(add CPURegs:$hi, (MipsLo tjumptable:$lo)), - (ADDiu CPURegs:$hi, tjumptable:$lo)>; -def : Pat<(add CPURegs:$hi, (MipsLo tconstpool:$lo)), - (ADDiu CPURegs:$hi, tconstpool:$lo)>; -def : Pat<(add CPURegs:$hi, (MipsLo tglobaltlsaddr:$lo)), - (ADDiu CPURegs:$hi, tglobaltlsaddr:$lo)>; +def : MipsPat<(MipsHi tglobaladdr:$in), (LUi tglobaladdr:$in)>; +def : MipsPat<(MipsHi tblockaddress:$in), (LUi tblockaddress:$in)>; +def : MipsPat<(MipsHi tjumptable:$in), (LUi tjumptable:$in)>; +def : MipsPat<(MipsHi tconstpool:$in), (LUi tconstpool:$in)>; +def : MipsPat<(MipsHi tglobaltlsaddr:$in), (LUi tglobaltlsaddr:$in)>; + +def : MipsPat<(MipsLo tglobaladdr:$in), (ADDiu ZERO, tglobaladdr:$in)>; +def : MipsPat<(MipsLo tblockaddress:$in), (ADDiu ZERO, tblockaddress:$in)>; +def : MipsPat<(MipsLo tjumptable:$in), (ADDiu ZERO, tjumptable:$in)>; +def : MipsPat<(MipsLo tconstpool:$in), (ADDiu ZERO, tconstpool:$in)>; +def : MipsPat<(MipsLo tglobaltlsaddr:$in), (ADDiu ZERO, tglobaltlsaddr:$in)>; + +def : MipsPat<(add CPURegs:$hi, (MipsLo tglobaladdr:$lo)), + (ADDiu CPURegs:$hi, tglobaladdr:$lo)>; +def : MipsPat<(add CPURegs:$hi, (MipsLo tblockaddress:$lo)), + (ADDiu CPURegs:$hi, tblockaddress:$lo)>; +def : MipsPat<(add CPURegs:$hi, (MipsLo tjumptable:$lo)), + (ADDiu CPURegs:$hi, tjumptable:$lo)>; +def : MipsPat<(add CPURegs:$hi, (MipsLo tconstpool:$lo)), + (ADDiu CPURegs:$hi, tconstpool:$lo)>; +def : MipsPat<(add CPURegs:$hi, (MipsLo tglobaltlsaddr:$lo)), + (ADDiu CPURegs:$hi, tglobaltlsaddr:$lo)>; // gp_rel relocs -def : Pat<(add CPURegs:$gp, (MipsGPRel tglobaladdr:$in)), - (ADDiu CPURegs:$gp, tglobaladdr:$in)>; -def : Pat<(add CPURegs:$gp, (MipsGPRel tconstpool:$in)), - (ADDiu CPURegs:$gp, tconstpool:$in)>; +def : MipsPat<(add CPURegs:$gp, (MipsGPRel tglobaladdr:$in)), + (ADDiu CPURegs:$gp, tglobaladdr:$in)>; +def : MipsPat<(add CPURegs:$gp, (MipsGPRel tconstpool:$in)), + (ADDiu CPURegs:$gp, tconstpool:$in)>; // wrapper_pic class WrapperPat<SDNode node, Instruction ADDiuOp, RegisterClass RC>: - Pat<(MipsWrapper RC:$gp, node:$in), - (ADDiuOp RC:$gp, node:$in)>; + MipsPat<(MipsWrapper RC:$gp, node:$in), + (ADDiuOp RC:$gp, node:$in)>; def : WrapperPat<tglobaladdr, ADDiu, CPURegs>; def : WrapperPat<tconstpool, ADDiu, CPURegs>; @@ -1081,58 +1149,58 @@ def : WrapperPat<tjumptable, ADDiu, CPURegs>; def : WrapperPat<tglobaltlsaddr, ADDiu, CPURegs>; // Mips does not have "not", so we expand our way -def : Pat<(not CPURegs:$in), - (NOR CPURegs:$in, ZERO)>; +def : MipsPat<(not CPURegs:$in), + (NOR CPURegs:$in, ZERO)>; // extended loads -let Predicates = [NotN64] in { - def : Pat<(i32 (extloadi1 addr:$src)), (LBu addr:$src)>; - def : Pat<(i32 (extloadi8 addr:$src)), (LBu addr:$src)>; - def : Pat<(i32 (extloadi16_a addr:$src)), (LHu addr:$src)>; - def : Pat<(i32 (extloadi16_u addr:$src)), (ULHu addr:$src)>; +let Predicates = [NotN64, HasStandardEncoding] in { + def : MipsPat<(i32 (extloadi1 addr:$src)), (LBu addr:$src)>; + def : MipsPat<(i32 (extloadi8 addr:$src)), (LBu addr:$src)>; + def : MipsPat<(i32 (extloadi16_a addr:$src)), (LHu addr:$src)>; + def : MipsPat<(i32 (extloadi16_u addr:$src)), (ULHu addr:$src)>; } -let Predicates = [IsN64] in { - def : Pat<(i32 (extloadi1 addr:$src)), (LBu_P8 addr:$src)>; - def : Pat<(i32 (extloadi8 addr:$src)), (LBu_P8 addr:$src)>; - def : Pat<(i32 (extloadi16_a addr:$src)), (LHu_P8 addr:$src)>; - def : Pat<(i32 (extloadi16_u addr:$src)), (ULHu_P8 addr:$src)>; +let Predicates = [IsN64, HasStandardEncoding] in { + def : MipsPat<(i32 (extloadi1 addr:$src)), (LBu_P8 addr:$src)>; + def : MipsPat<(i32 (extloadi8 addr:$src)), (LBu_P8 addr:$src)>; + def : MipsPat<(i32 (extloadi16_a addr:$src)), (LHu_P8 addr:$src)>; + def : MipsPat<(i32 (extloadi16_u addr:$src)), (ULHu_P8 addr:$src)>; } // peepholes -let Predicates = [NotN64] in { - def : Pat<(store_a (i32 0), addr:$dst), (SW ZERO, addr:$dst)>; - def : Pat<(store_u (i32 0), addr:$dst), (USW ZERO, addr:$dst)>; +let Predicates = [NotN64, HasStandardEncoding] in { + def : MipsPat<(store_a (i32 0), addr:$dst), (SW ZERO, addr:$dst)>; + def : MipsPat<(store_u (i32 0), addr:$dst), (USW ZERO, addr:$dst)>; } -let Predicates = [IsN64] in { - def : Pat<(store_a (i32 0), addr:$dst), (SW_P8 ZERO, addr:$dst)>; - def : Pat<(store_u (i32 0), addr:$dst), (USW_P8 ZERO, addr:$dst)>; +let Predicates = [IsN64, HasStandardEncoding] in { + def : MipsPat<(store_a (i32 0), addr:$dst), (SW_P8 ZERO, addr:$dst)>; + def : MipsPat<(store_u (i32 0), addr:$dst), (USW_P8 ZERO, addr:$dst)>; } // brcond patterns multiclass BrcondPats<RegisterClass RC, Instruction BEQOp, Instruction BNEOp, Instruction SLTOp, Instruction SLTuOp, Instruction SLTiOp, Instruction SLTiuOp, Register ZEROReg> { -def : Pat<(brcond (i32 (setne RC:$lhs, 0)), bb:$dst), - (BNEOp RC:$lhs, ZEROReg, bb:$dst)>; -def : Pat<(brcond (i32 (seteq RC:$lhs, 0)), bb:$dst), - (BEQOp RC:$lhs, ZEROReg, bb:$dst)>; +def : MipsPat<(brcond (i32 (setne RC:$lhs, 0)), bb:$dst), + (BNEOp RC:$lhs, ZEROReg, bb:$dst)>; +def : MipsPat<(brcond (i32 (seteq RC:$lhs, 0)), bb:$dst), + (BEQOp RC:$lhs, ZEROReg, bb:$dst)>; -def : Pat<(brcond (i32 (setge RC:$lhs, RC:$rhs)), bb:$dst), - (BEQ (SLTOp RC:$lhs, RC:$rhs), ZERO, bb:$dst)>; -def : Pat<(brcond (i32 (setuge RC:$lhs, RC:$rhs)), bb:$dst), - (BEQ (SLTuOp RC:$lhs, RC:$rhs), ZERO, bb:$dst)>; -def : Pat<(brcond (i32 (setge RC:$lhs, immSExt16:$rhs)), bb:$dst), - (BEQ (SLTiOp RC:$lhs, immSExt16:$rhs), ZERO, bb:$dst)>; -def : Pat<(brcond (i32 (setuge RC:$lhs, immSExt16:$rhs)), bb:$dst), - (BEQ (SLTiuOp RC:$lhs, immSExt16:$rhs), ZERO, bb:$dst)>; +def : MipsPat<(brcond (i32 (setge RC:$lhs, RC:$rhs)), bb:$dst), + (BEQ (SLTOp RC:$lhs, RC:$rhs), ZERO, bb:$dst)>; +def : MipsPat<(brcond (i32 (setuge RC:$lhs, RC:$rhs)), bb:$dst), + (BEQ (SLTuOp RC:$lhs, RC:$rhs), ZERO, bb:$dst)>; +def : MipsPat<(brcond (i32 (setge RC:$lhs, immSExt16:$rhs)), bb:$dst), + (BEQ (SLTiOp RC:$lhs, immSExt16:$rhs), ZERO, bb:$dst)>; +def : MipsPat<(brcond (i32 (setuge RC:$lhs, immSExt16:$rhs)), bb:$dst), + (BEQ (SLTiuOp RC:$lhs, immSExt16:$rhs), ZERO, bb:$dst)>; -def : Pat<(brcond (i32 (setle RC:$lhs, RC:$rhs)), bb:$dst), - (BEQ (SLTOp RC:$rhs, RC:$lhs), ZERO, bb:$dst)>; -def : Pat<(brcond (i32 (setule RC:$lhs, RC:$rhs)), bb:$dst), - (BEQ (SLTuOp RC:$rhs, RC:$lhs), ZERO, bb:$dst)>; +def : MipsPat<(brcond (i32 (setle RC:$lhs, RC:$rhs)), bb:$dst), + (BEQ (SLTOp RC:$rhs, RC:$lhs), ZERO, bb:$dst)>; +def : MipsPat<(brcond (i32 (setule RC:$lhs, RC:$rhs)), bb:$dst), + (BEQ (SLTuOp RC:$rhs, RC:$lhs), ZERO, bb:$dst)>; -def : Pat<(brcond RC:$cond, bb:$dst), - (BNEOp RC:$cond, ZEROReg, bb:$dst)>; +def : MipsPat<(brcond RC:$cond, bb:$dst), + (BNEOp RC:$cond, ZEROReg, bb:$dst)>; } defm : BrcondPats<CPURegs, BEQ, BNE, SLT, SLTu, SLTi, SLTiu, ZERO>; @@ -1140,39 +1208,39 @@ defm : BrcondPats<CPURegs, BEQ, BNE, SLT, SLTu, SLTi, SLTiu, ZERO>; // setcc patterns multiclass SeteqPats<RegisterClass RC, Instruction SLTiuOp, Instruction XOROp, Instruction SLTuOp, Register ZEROReg> { - def : Pat<(seteq RC:$lhs, RC:$rhs), - (SLTiuOp (XOROp RC:$lhs, RC:$rhs), 1)>; - def : Pat<(setne RC:$lhs, RC:$rhs), - (SLTuOp ZEROReg, (XOROp RC:$lhs, RC:$rhs))>; + def : MipsPat<(seteq RC:$lhs, RC:$rhs), + (SLTiuOp (XOROp RC:$lhs, RC:$rhs), 1)>; + def : MipsPat<(setne RC:$lhs, RC:$rhs), + (SLTuOp ZEROReg, (XOROp RC:$lhs, RC:$rhs))>; } multiclass SetlePats<RegisterClass RC, Instruction SLTOp, Instruction SLTuOp> { - def : Pat<(setle RC:$lhs, RC:$rhs), - (XORi (SLTOp RC:$rhs, RC:$lhs), 1)>; - def : Pat<(setule RC:$lhs, RC:$rhs), - (XORi (SLTuOp RC:$rhs, RC:$lhs), 1)>; + def : MipsPat<(setle RC:$lhs, RC:$rhs), + (XORi (SLTOp RC:$rhs, RC:$lhs), 1)>; + def : MipsPat<(setule RC:$lhs, RC:$rhs), + (XORi (SLTuOp RC:$rhs, RC:$lhs), 1)>; } multiclass SetgtPats<RegisterClass RC, Instruction SLTOp, Instruction SLTuOp> { - def : Pat<(setgt RC:$lhs, RC:$rhs), - (SLTOp RC:$rhs, RC:$lhs)>; - def : Pat<(setugt RC:$lhs, RC:$rhs), - (SLTuOp RC:$rhs, RC:$lhs)>; + def : MipsPat<(setgt RC:$lhs, RC:$rhs), + (SLTOp RC:$rhs, RC:$lhs)>; + def : MipsPat<(setugt RC:$lhs, RC:$rhs), + (SLTuOp RC:$rhs, RC:$lhs)>; } multiclass SetgePats<RegisterClass RC, Instruction SLTOp, Instruction SLTuOp> { - def : Pat<(setge RC:$lhs, RC:$rhs), - (XORi (SLTOp RC:$lhs, RC:$rhs), 1)>; - def : Pat<(setuge RC:$lhs, RC:$rhs), - (XORi (SLTuOp RC:$lhs, RC:$rhs), 1)>; + def : MipsPat<(setge RC:$lhs, RC:$rhs), + (XORi (SLTOp RC:$lhs, RC:$rhs), 1)>; + def : MipsPat<(setuge RC:$lhs, RC:$rhs), + (XORi (SLTuOp RC:$lhs, RC:$rhs), 1)>; } multiclass SetgeImmPats<RegisterClass RC, Instruction SLTiOp, Instruction SLTiuOp> { - def : Pat<(setge RC:$lhs, immSExt16:$rhs), - (XORi (SLTiOp RC:$lhs, immSExt16:$rhs), 1)>; - def : Pat<(setuge RC:$lhs, immSExt16:$rhs), - (XORi (SLTiuOp RC:$lhs, immSExt16:$rhs), 1)>; + def : MipsPat<(setge RC:$lhs, immSExt16:$rhs), + (XORi (SLTiOp RC:$lhs, immSExt16:$rhs), 1)>; + def : MipsPat<(setuge RC:$lhs, immSExt16:$rhs), + (XORi (SLTiuOp RC:$lhs, immSExt16:$rhs), 1)>; } defm : SeteqPats<CPURegs, SLTiu, XOR, SLTu, ZERO>; @@ -1182,10 +1250,10 @@ defm : SetgePats<CPURegs, SLT, SLTu>; defm : SetgeImmPats<CPURegs, SLTi, SLTiu>; // select MipsDynAlloc -def : Pat<(MipsDynAlloc addr:$f), (DynAlloc addr:$f)>; +def : MipsPat<(MipsDynAlloc addr:$f), (DynAlloc addr:$f)>; // bswap pattern -def : Pat<(bswap CPURegs:$rt), (ROTR (WSBH CPURegs:$rt), 16)>; +def : MipsPat<(bswap CPURegs:$rt), (ROTR (WSBH CPURegs:$rt), 16)>; //===----------------------------------------------------------------------===// // Floating Point Support @@ -1195,3 +1263,8 @@ include "MipsInstrFPU.td" include "Mips64InstrInfo.td" include "MipsCondMov.td" +// +// Mips16 + +include "Mips16InstrFormats.td" +include "Mips16InstrInfo.td" diff --git a/lib/Target/Mips/MipsJITInfo.cpp b/lib/Target/Mips/MipsJITInfo.cpp index 76ca3e1..150bdbb 100644 --- a/lib/Target/Mips/MipsJITInfo.cpp +++ b/lib/Target/Mips/MipsJITInfo.cpp @@ -154,8 +154,8 @@ TargetJITInfo::StubLayout MipsJITInfo::getStubLayout() { return Result; } -void *MipsJITInfo::emitFunctionStub(const Function* F, void *Fn, - JITCodeEmitter &JCE) { +void *MipsJITInfo::emitFunctionStub(const Function *F, void *Fn, + JITCodeEmitter &JCE) { JCE.emitAlignment(4); void *Addr = (void*) (JCE.getCurrentPCValue()); if (!sys::Memory::setRangeWritable(Addr, 16)) @@ -193,7 +193,7 @@ void *MipsJITInfo::emitFunctionStub(const Function* F, void *Fn, /// it must rewrite the code to contain the actual addresses of any /// referenced global symbols. void MipsJITInfo::relocate(void *Function, MachineRelocation *MR, - unsigned NumRelocs, unsigned char* GOTBase) { + unsigned NumRelocs, unsigned char *GOTBase) { for (unsigned i = 0; i != NumRelocs; ++i, ++MR) { void *RelocPos = (char*) Function + MR->getMachineCodeOffset(); diff --git a/lib/Target/Mips/MipsJITInfo.h b/lib/Target/Mips/MipsJITInfo.h index f4c4ae8..637a318 100644 --- a/lib/Target/Mips/MipsJITInfo.h +++ b/lib/Target/Mips/MipsJITInfo.h @@ -45,8 +45,8 @@ class MipsJITInfo : public TargetJITInfo { /// emitFunctionStub - Use the specified JITCodeEmitter object to emit a /// small native function that simply calls the function at the specified /// address. - virtual void *emitFunctionStub(const Function* F, void *Fn, - JITCodeEmitter &JCE); + virtual void *emitFunctionStub(const Function *F, void *Fn, + JITCodeEmitter &JCE); /// getLazyResolverFunction - Expose the lazy resolver to the JIT. virtual LazyResolverFn getLazyResolverFunction(JITCompilerFn); @@ -55,7 +55,7 @@ class MipsJITInfo : public TargetJITInfo { /// it must rewrite the code to contain the actual addresses of any /// referenced global symbols. virtual void relocate(void *Function, MachineRelocation *MR, - unsigned NumRelocs, unsigned char* GOTBase); + unsigned NumRelocs, unsigned char *GOTBase); /// Initialize - Initialize internal stage for the function being JITted. void Initialize(const MachineFunction &MF, bool isPIC) { diff --git a/lib/Target/Mips/MipsLongBranch.cpp b/lib/Target/Mips/MipsLongBranch.cpp new file mode 100644 index 0000000..70ecbc1 --- /dev/null +++ b/lib/Target/Mips/MipsLongBranch.cpp @@ -0,0 +1,419 @@ +//===-- MipsLongBranch.cpp - Emit long branches ---------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass expands a branch or jump instruction into a long branch if its +// offset is too large to fit into its immediate field. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "mips-long-branch" + +#include "Mips.h" +#include "MipsTargetMachine.h" +#include "MCTargetDesc/MipsBaseInfo.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/Function.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegisterInfo.h" + +using namespace llvm; + +STATISTIC(LongBranches, "Number of long branches."); + +static cl::opt<bool> SkipLongBranch( + "skip-mips-long-branch", + cl::init(false), + cl::desc("MIPS: Skip long branch pass."), + cl::Hidden); + +static cl::opt<bool> ForceLongBranch( + "force-mips-long-branch", + cl::init(false), + cl::desc("MIPS: Expand all branches to long format."), + cl::Hidden); + +namespace { + typedef MachineBasicBlock::iterator Iter; + typedef MachineBasicBlock::reverse_iterator ReverseIter; + + struct MBBInfo { + uint64_t Size; + bool HasLongBranch; + MachineInstr *Br; + + MBBInfo() : Size(0), HasLongBranch(false), Br(0) {} + }; + + class MipsLongBranch : public MachineFunctionPass { + + public: + static char ID; + MipsLongBranch(TargetMachine &tm) + : MachineFunctionPass(ID), TM(tm), + TII(static_cast<const MipsInstrInfo*>(tm.getInstrInfo())) {} + + virtual const char *getPassName() const { + return "Mips Long Branch"; + } + + bool runOnMachineFunction(MachineFunction &F); + + private: + void splitMBB(MachineBasicBlock *MBB); + void initMBBInfo(); + int64_t computeOffset(const MachineInstr *Br); + void replaceBranch(MachineBasicBlock &MBB, Iter Br, DebugLoc DL, + MachineBasicBlock *MBBOpnd); + void expandToLongBranch(MBBInfo &Info); + + const TargetMachine &TM; + const MipsInstrInfo *TII; + MachineFunction *MF; + SmallVector<MBBInfo, 16> MBBInfos; + }; + + char MipsLongBranch::ID = 0; +} // end of anonymous namespace + +/// createMipsLongBranchPass - Returns a pass that converts branches to long +/// branches. +FunctionPass *llvm::createMipsLongBranchPass(MipsTargetMachine &tm) { + return new MipsLongBranch(tm); +} + +/// Iterate over list of Br's operands and search for a MachineBasicBlock +/// operand. +static MachineBasicBlock *getTargetMBB(const MachineInstr &Br) { + for (unsigned I = 0, E = Br.getDesc().getNumOperands(); I < E; ++I) { + const MachineOperand &MO = Br.getOperand(I); + + if (MO.isMBB()) + return MO.getMBB(); + } + + assert(false && "This instruction does not have an MBB operand."); + return 0; +} + +// Traverse the list of instructions backwards until a non-debug instruction is +// found or it reaches E. +static ReverseIter getNonDebugInstr(ReverseIter B, ReverseIter E) { + for (; B != E; ++B) + if (!B->isDebugValue()) + return B; + + return E; +} + +// Split MBB if it has two direct jumps/branches. +void MipsLongBranch::splitMBB(MachineBasicBlock *MBB) { + ReverseIter End = MBB->rend(); + ReverseIter LastBr = getNonDebugInstr(MBB->rbegin(), End); + + // Return if MBB has no branch instructions. + if ((LastBr == End) || + (!LastBr->isConditionalBranch() && !LastBr->isUnconditionalBranch())) + return; + + ReverseIter FirstBr = getNonDebugInstr(llvm::next(LastBr), End); + + // MBB has only one branch instruction if FirstBr is not a branch + // instruction. + if ((FirstBr == End) || + (!FirstBr->isConditionalBranch() && !FirstBr->isUnconditionalBranch())) + return; + + assert(!FirstBr->isIndirectBranch() && "Unexpected indirect branch found."); + + // Create a new MBB. Move instructions in MBB to the newly created MBB. + MachineBasicBlock *NewMBB = + MF->CreateMachineBasicBlock(MBB->getBasicBlock()); + + // Insert NewMBB and fix control flow. + MachineBasicBlock *Tgt = getTargetMBB(*FirstBr); + NewMBB->transferSuccessors(MBB); + NewMBB->removeSuccessor(Tgt); + MBB->addSuccessor(NewMBB); + MBB->addSuccessor(Tgt); + MF->insert(llvm::next(MachineFunction::iterator(MBB)), NewMBB); + + NewMBB->splice(NewMBB->end(), MBB, (++LastBr).base(), MBB->end()); +} + +// Fill MBBInfos. +void MipsLongBranch::initMBBInfo() { + // Split the MBBs if they have two branches. Each basic block should have at + // most one branch after this loop is executed. + for (MachineFunction::iterator I = MF->begin(), E = MF->end(); I != E;) + splitMBB(I++); + + MF->RenumberBlocks(); + MBBInfos.clear(); + MBBInfos.resize(MF->size()); + + for (unsigned I = 0, E = MBBInfos.size(); I < E; ++I) { + MachineBasicBlock *MBB = MF->getBlockNumbered(I); + + // Compute size of MBB. + for (MachineBasicBlock::instr_iterator MI = MBB->instr_begin(); + MI != MBB->instr_end(); ++MI) + MBBInfos[I].Size += TII->GetInstSizeInBytes(&*MI); + + // Search for MBB's branch instruction. + ReverseIter End = MBB->rend(); + ReverseIter Br = getNonDebugInstr(MBB->rbegin(), End); + + if ((Br != End) && !Br->isIndirectBranch() && + (Br->isConditionalBranch() || + (Br->isUnconditionalBranch() && + TM.getRelocationModel() == Reloc::PIC_))) + MBBInfos[I].Br = (++Br).base(); + } +} + +// Compute offset of branch in number of bytes. +int64_t MipsLongBranch::computeOffset(const MachineInstr *Br) { + int64_t Offset = 0; + int ThisMBB = Br->getParent()->getNumber(); + int TargetMBB = getTargetMBB(*Br)->getNumber(); + + // Compute offset of a forward branch. + if (ThisMBB < TargetMBB) { + for (int N = ThisMBB + 1; N < TargetMBB; ++N) + Offset += MBBInfos[N].Size; + + return Offset + 4; + } + + // Compute offset of a backward branch. + for (int N = ThisMBB; N >= TargetMBB; --N) + Offset += MBBInfos[N].Size; + + return -Offset + 4; +} + +// Replace Br with a branch which has the opposite condition code and a +// MachineBasicBlock operand MBBOpnd. +void MipsLongBranch::replaceBranch(MachineBasicBlock &MBB, Iter Br, + DebugLoc DL, MachineBasicBlock *MBBOpnd) { + unsigned NewOpc = Mips::GetOppositeBranchOpc(Br->getOpcode()); + const MCInstrDesc &NewDesc = TII->get(NewOpc); + + MachineInstrBuilder MIB = BuildMI(MBB, Br, DL, NewDesc); + + for (unsigned I = 0, E = Br->getDesc().getNumOperands(); I < E; ++I) { + MachineOperand &MO = Br->getOperand(I); + + if (!MO.isReg()) { + assert(MO.isMBB() && "MBB operand expected."); + break; + } + + MIB.addReg(MO.getReg()); + } + + MIB.addMBB(MBBOpnd); + + Br->eraseFromParent(); +} + +// Expand branch instructions to long branches. +void MipsLongBranch::expandToLongBranch(MBBInfo &I) { + I.HasLongBranch = true; + + bool IsPIC = TM.getRelocationModel() == Reloc::PIC_; + unsigned ABI = TM.getSubtarget<MipsSubtarget>().getTargetABI(); + bool N64 = ABI == MipsSubtarget::N64; + + MachineBasicBlock::iterator Pos; + MachineBasicBlock *MBB = I.Br->getParent(), *TgtMBB = getTargetMBB(*I.Br); + DebugLoc DL = I.Br->getDebugLoc(); + const BasicBlock *BB = MBB->getBasicBlock(); + MachineFunction::iterator FallThroughMBB = ++MachineFunction::iterator(MBB); + MachineBasicBlock *LongBrMBB = MF->CreateMachineBasicBlock(BB); + + MF->insert(FallThroughMBB, LongBrMBB); + MBB->removeSuccessor(TgtMBB); + MBB->addSuccessor(LongBrMBB); + + if (IsPIC) { + // $longbr: + // addiu $sp, $sp, -regsize * 2 + // sw $ra, 0($sp) + // bal $baltgt + // sw $a3, regsize($sp) + // $baltgt: + // lui $a3, %hi($baltgt) + // lui $at, %hi($tgt) + // addiu $a3, $a3, %lo($baltgt) + // addiu $at, $at, %lo($tgt) + // subu $at, $at, $a3 + // addu $at, $ra, $at + // + // if n64: + // lui $a3, %highest($baltgt) + // lui $ra, %highest($tgt) + // addiu $a3, $a3, %higher($baltgt) + // addiu $ra, $ra, %higher($tgt) + // dsll $a3, $a3, 32 + // dsll $ra, $ra, 32 + // subu $at, $at, $a3 + // addu $at, $at, $ra + // + // lw $ra, 0($sp) + // lw $a3, regsize($sp) + // jr $at + // addiu $sp, $sp, regsize * 2 + // $fallthrough: + // + MF->getInfo<MipsFunctionInfo>()->setEmitNOAT(); + MachineBasicBlock *BalTgtMBB = MF->CreateMachineBasicBlock(BB); + MF->insert(FallThroughMBB, BalTgtMBB); + LongBrMBB->addSuccessor(BalTgtMBB); + BalTgtMBB->addSuccessor(TgtMBB); + + int RegSize = N64 ? 8 : 4; + unsigned AT = N64 ? Mips::AT_64 : Mips::AT; + unsigned A3 = N64 ? Mips::A3_64 : Mips::A3; + unsigned SP = N64 ? Mips::SP_64 : Mips::SP; + unsigned RA = N64 ? Mips::RA_64 : Mips::RA; + unsigned Load = N64 ? Mips::LD_P8 : Mips::LW; + unsigned Store = N64 ? Mips::SD_P8 : Mips::SW; + unsigned LUi = N64 ? Mips::LUi64 : Mips::LUi; + unsigned ADDiu = N64 ? Mips::DADDiu : Mips::ADDiu; + unsigned ADDu = N64 ? Mips::DADDu : Mips::ADDu; + unsigned SUBu = N64 ? Mips::SUBu : Mips::SUBu; + unsigned JR = N64 ? Mips::JR64 : Mips::JR; + + Pos = LongBrMBB->begin(); + + BuildMI(*LongBrMBB, Pos, DL, TII->get(ADDiu), SP).addReg(SP) + .addImm(-RegSize * 2); + BuildMI(*LongBrMBB, Pos, DL, TII->get(Store)).addReg(RA).addReg(SP) + .addImm(0); + BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::BAL_BR)).addMBB(BalTgtMBB); + BuildMI(*LongBrMBB, Pos, DL, TII->get(Store)).addReg(A3).addReg(SP) + .addImm(RegSize)->setIsInsideBundle(); + + Pos = BalTgtMBB->begin(); + + BuildMI(*BalTgtMBB, Pos, DL, TII->get(LUi), A3) + .addMBB(BalTgtMBB, MipsII::MO_ABS_HI); + BuildMI(*BalTgtMBB, Pos, DL, TII->get(LUi), AT) + .addMBB(TgtMBB, MipsII::MO_ABS_HI); + BuildMI(*BalTgtMBB, Pos, DL, TII->get(ADDiu), A3).addReg(A3) + .addMBB(BalTgtMBB, MipsII::MO_ABS_LO); + BuildMI(*BalTgtMBB, Pos, DL, TII->get(ADDiu), AT).addReg(AT) + .addMBB(TgtMBB, MipsII::MO_ABS_LO); + BuildMI(*BalTgtMBB, Pos, DL, TII->get(SUBu), AT).addReg(AT).addReg(A3); + BuildMI(*BalTgtMBB, Pos, DL, TII->get(ADDu), AT).addReg(RA).addReg(AT); + + if (N64) { + BuildMI(*BalTgtMBB, Pos, DL, TII->get(LUi), A3) + .addMBB(BalTgtMBB, MipsII::MO_HIGHEST); + BuildMI(*BalTgtMBB, Pos, DL, TII->get(LUi), RA) + .addMBB(TgtMBB, MipsII::MO_HIGHEST); + BuildMI(*BalTgtMBB, Pos, DL, TII->get(ADDiu), A3).addReg(A3) + .addMBB(BalTgtMBB, MipsII::MO_HIGHER); + BuildMI(*BalTgtMBB, Pos, DL, TII->get(ADDiu), RA).addReg(RA) + .addMBB(TgtMBB, MipsII::MO_HIGHER); + BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::DSLL), A3).addReg(A3) + .addImm(32); + BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::DSLL), RA).addReg(RA) + .addImm(32); + BuildMI(*BalTgtMBB, Pos, DL, TII->get(SUBu), AT).addReg(AT).addReg(A3); + BuildMI(*BalTgtMBB, Pos, DL, TII->get(ADDu), AT).addReg(AT).addReg(RA); + I.Size += 4 * 8; + } + + BuildMI(*BalTgtMBB, Pos, DL, TII->get(Load), RA).addReg(SP).addImm(0); + BuildMI(*BalTgtMBB, Pos, DL, TII->get(Load), A3).addReg(SP).addImm(RegSize); + BuildMI(*BalTgtMBB, Pos, DL, TII->get(JR)).addReg(AT); + BuildMI(*BalTgtMBB, Pos, DL, TII->get(ADDiu), SP).addReg(SP) + .addImm(RegSize * 2)->setIsInsideBundle(); + I.Size += 4 * 14; + } else { + // $longbr: + // j $tgt + // nop + // $fallthrough: + // + Pos = LongBrMBB->begin(); + LongBrMBB->addSuccessor(TgtMBB); + BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::J)).addMBB(TgtMBB); + BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::NOP))->setIsInsideBundle(); + I.Size += 4 * 2; + } + + if (I.Br->isUnconditionalBranch()) { + // Change branch destination. + assert(I.Br->getDesc().getNumOperands() == 1); + I.Br->RemoveOperand(0); + I.Br->addOperand(MachineOperand::CreateMBB(LongBrMBB)); + } else + // Change branch destination and reverse condition. + replaceBranch(*MBB, I.Br, DL, FallThroughMBB); +} + +static void emitGPDisp(MachineFunction &F, const MipsInstrInfo *TII) { + MachineBasicBlock &MBB = F.front(); + MachineBasicBlock::iterator I = MBB.begin(); + DebugLoc DL = MBB.findDebugLoc(MBB.begin()); + BuildMI(MBB, I, DL, TII->get(Mips::LUi), Mips::V0) + .addExternalSymbol("_gp_disp", MipsII::MO_ABS_HI); + BuildMI(MBB, I, DL, TII->get(Mips::ADDiu), Mips::V0) + .addReg(Mips::V0).addExternalSymbol("_gp_disp", MipsII::MO_ABS_LO); + MBB.removeLiveIn(Mips::V0); +} + +bool MipsLongBranch::runOnMachineFunction(MachineFunction &F) { + if ((TM.getRelocationModel() == Reloc::PIC_) && + TM.getSubtarget<MipsSubtarget>().isABI_O32() && + F.getInfo<MipsFunctionInfo>()->globalBaseRegSet()) + emitGPDisp(F, TII); + + if (SkipLongBranch) + return true; + + MF = &F; + initMBBInfo(); + + SmallVector<MBBInfo, 16>::iterator I, E = MBBInfos.end(); + bool EverMadeChange = false, MadeChange = true; + + while (MadeChange) { + MadeChange = false; + + for (I = MBBInfos.begin(); I != E; ++I) { + // Skip if this MBB doesn't have a branch or the branch has already been + // converted to a long branch. + if (!I->Br || I->HasLongBranch) + continue; + + if (!ForceLongBranch) + // Check if offset fits into 16-bit immediate field of branches. + if (isInt<16>(computeOffset(I->Br) / 4)) + continue; + + expandToLongBranch(*I); + ++LongBranches; + EverMadeChange = MadeChange = true; + } + } + + if (EverMadeChange) + MF->RenumberBlocks(); + + return true; +} diff --git a/lib/Target/Mips/MipsMCInstLower.cpp b/lib/Target/Mips/MipsMCInstLower.cpp index 1597b93..d4c5e6d 100644 --- a/lib/Target/Mips/MipsMCInstLower.cpp +++ b/lib/Target/Mips/MipsMCInstLower.cpp @@ -29,7 +29,7 @@ using namespace llvm; MipsMCInstLower::MipsMCInstLower(MipsAsmPrinter &asmprinter) : AsmPrinter(asmprinter) {} -void MipsMCInstLower::Initialize(Mangler *M, MCContext* C) { +void MipsMCInstLower::Initialize(Mangler *M, MCContext *C) { Mang = M; Ctx = C; } @@ -61,6 +61,8 @@ MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO, case MipsII::MO_GOT_DISP: Kind = MCSymbolRefExpr::VK_Mips_GOT_DISP; break; case MipsII::MO_GOT_PAGE: Kind = MCSymbolRefExpr::VK_Mips_GOT_PAGE; break; case MipsII::MO_GOT_OFST: Kind = MCSymbolRefExpr::VK_Mips_GOT_OFST; break; + case MipsII::MO_HIGHER: Kind = MCSymbolRefExpr::VK_Mips_HIGHER; break; + case MipsII::MO_HIGHEST: Kind = MCSymbolRefExpr::VK_Mips_HIGHEST; break; } switch (MOTy) { @@ -70,14 +72,17 @@ MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO, case MachineOperand::MO_GlobalAddress: Symbol = Mang->getSymbol(MO.getGlobal()); + Offset += MO.getOffset(); break; case MachineOperand::MO_BlockAddress: Symbol = AsmPrinter.GetBlockAddressSymbol(MO.getBlockAddress()); + Offset += MO.getOffset(); break; case MachineOperand::MO_ExternalSymbol: Symbol = AsmPrinter.GetExternalSymbolSymbol(MO.getSymbolName()); + Offset += MO.getOffset(); break; case MachineOperand::MO_JumpTableIndex: @@ -86,8 +91,7 @@ MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO, case MachineOperand::MO_ConstantPoolIndex: Symbol = AsmPrinter.GetCPISymbol(MO.getIndex()); - if (MO.getOffset()) - Offset += MO.getOffset(); + Offset += MO.getOffset(); break; default: @@ -103,71 +107,23 @@ MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO, assert(Offset > 0); const MCConstantExpr *OffsetExpr = MCConstantExpr::Create(Offset, *Ctx); - const MCBinaryExpr *AddExpr = MCBinaryExpr::CreateAdd(MCSym, OffsetExpr, *Ctx); - return MCOperand::CreateExpr(AddExpr); + const MCBinaryExpr *Add = MCBinaryExpr::CreateAdd(MCSym, OffsetExpr, *Ctx); + return MCOperand::CreateExpr(Add); } -static void CreateMCInst(MCInst& Inst, unsigned Opc, const MCOperand& Opnd0, - const MCOperand& Opnd1, - const MCOperand& Opnd2 = MCOperand()) { +/* +static void CreateMCInst(MCInst& Inst, unsigned Opc, const MCOperand &Opnd0, + const MCOperand &Opnd1, + const MCOperand &Opnd2 = MCOperand()) { Inst.setOpcode(Opc); Inst.addOperand(Opnd0); Inst.addOperand(Opnd1); if (Opnd2.isValid()) Inst.addOperand(Opnd2); } +*/ -// Lower ".cpload $reg" to -// "lui $gp, %hi(_gp_disp)" -// "addiu $gp, $gp, %lo(_gp_disp)" -// "addu $gp, $gp, $t9" -void MipsMCInstLower::LowerCPLOAD(SmallVector<MCInst, 4>& MCInsts) { - MCOperand GPReg = MCOperand::CreateReg(Mips::GP); - MCOperand T9Reg = MCOperand::CreateReg(Mips::T9); - StringRef SymName("_gp_disp"); - const MCSymbol *Sym = Ctx->GetOrCreateSymbol(SymName); - const MCSymbolRefExpr *MCSym; - - MCSym = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_Mips_ABS_HI, *Ctx); - MCOperand SymHi = MCOperand::CreateExpr(MCSym); - MCSym = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_Mips_ABS_LO, *Ctx); - MCOperand SymLo = MCOperand::CreateExpr(MCSym); - - MCInsts.resize(3); - - CreateMCInst(MCInsts[0], Mips::LUi, GPReg, SymHi); - CreateMCInst(MCInsts[1], Mips::ADDiu, GPReg, GPReg, SymLo); - CreateMCInst(MCInsts[2], Mips::ADDu, GPReg, GPReg, T9Reg); -} - -// Lower ".cprestore offset" to "sw $gp, offset($sp)". -void MipsMCInstLower::LowerCPRESTORE(int64_t Offset, - SmallVector<MCInst, 4>& MCInsts) { - assert(isInt<32>(Offset) && (Offset >= 0) && - "Imm operand of .cprestore must be a non-negative 32-bit value."); - - MCOperand SPReg = MCOperand::CreateReg(Mips::SP), BaseReg = SPReg; - MCOperand GPReg = MCOperand::CreateReg(Mips::GP); - - if (!isInt<16>(Offset)) { - unsigned Hi = ((Offset + 0x8000) >> 16) & 0xffff; - Offset &= 0xffff; - MCOperand ATReg = MCOperand::CreateReg(Mips::AT); - BaseReg = ATReg; - - // lui at,hi - // addu at,at,sp - MCInsts.resize(2); - CreateMCInst(MCInsts[0], Mips::LUi, ATReg, MCOperand::CreateImm(Hi)); - CreateMCInst(MCInsts[1], Mips::ADDu, ATReg, ATReg, SPReg); - } - - MCInst Sw; - CreateMCInst(Sw, Mips::SW, GPReg, BaseReg, MCOperand::CreateImm(Offset)); - MCInsts.push_back(Sw); -} - -MCOperand MipsMCInstLower::LowerOperand(const MachineOperand& MO, +MCOperand MipsMCInstLower::LowerOperand(const MachineOperand &MO, unsigned offset) const { MachineOperandType MOTy = MO.getType(); @@ -205,139 +161,31 @@ void MipsMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { } } -void MipsMCInstLower::LowerUnalignedLoadStore(const MachineInstr *MI, - SmallVector<MCInst, - 4>& MCInsts) { - unsigned Opc = MI->getOpcode(); - MCInst Instr1, Instr2, Instr3, Move; - - bool TwoInstructions = false; - - assert(MI->getNumOperands() == 3); - assert(MI->getOperand(0).isReg()); - assert(MI->getOperand(1).isReg()); - - MCOperand Target = LowerOperand(MI->getOperand(0)); - MCOperand Base = LowerOperand(MI->getOperand(1)); - MCOperand ATReg = MCOperand::CreateReg(Mips::AT); - MCOperand ZeroReg = MCOperand::CreateReg(Mips::ZERO); - - MachineOperand UnLoweredName = MI->getOperand(2); - MCOperand Name = LowerOperand(UnLoweredName); - - Move.setOpcode(Mips::ADDu); - Move.addOperand(Target); - Move.addOperand(ATReg); - Move.addOperand(ZeroReg); - - switch (Opc) { - case Mips::ULW: { - // FIXME: only works for little endian right now - MCOperand AdjName = LowerOperand(UnLoweredName, 3); - if (Base.getReg() == (Target.getReg())) { - Instr1.setOpcode(Mips::LWL); - Instr1.addOperand(ATReg); - Instr1.addOperand(Base); - Instr1.addOperand(AdjName); - Instr2.setOpcode(Mips::LWR); - Instr2.addOperand(ATReg); - Instr2.addOperand(Base); - Instr2.addOperand(Name); - Instr3 = Move; - } else { - TwoInstructions = true; - Instr1.setOpcode(Mips::LWL); - Instr1.addOperand(Target); - Instr1.addOperand(Base); - Instr1.addOperand(AdjName); - Instr2.setOpcode(Mips::LWR); - Instr2.addOperand(Target); - Instr2.addOperand(Base); - Instr2.addOperand(Name); - } +// If the D<shift> instruction has a shift amount that is greater +// than 31 (checked in calling routine), lower it to a D<shift>32 instruction +void MipsMCInstLower::LowerLargeShift(const MachineInstr *MI, + MCInst& Inst, + int64_t Shift) { + // rt + Inst.addOperand(LowerOperand(MI->getOperand(0))); + // rd + Inst.addOperand(LowerOperand(MI->getOperand(1))); + // saminus32 + Inst.addOperand(MCOperand::CreateImm(Shift)); + + switch (MI->getOpcode()) { + default: + // Calling function is not synchronized + llvm_unreachable("Unexpected shift instruction"); break; - } - case Mips::ULHu: { - // FIXME: only works for little endian right now - MCOperand AdjName = LowerOperand(UnLoweredName, 1); - Instr1.setOpcode(Mips::LBu); - Instr1.addOperand(ATReg); - Instr1.addOperand(Base); - Instr1.addOperand(AdjName); - Instr2.setOpcode(Mips::LBu); - Instr2.addOperand(Target); - Instr2.addOperand(Base); - Instr2.addOperand(Name); - Instr3.setOpcode(Mips::INS); - Instr3.addOperand(Target); - Instr3.addOperand(ATReg); - Instr3.addOperand(MCOperand::CreateImm(0x8)); - Instr3.addOperand(MCOperand::CreateImm(0x18)); + case Mips::DSLL: + Inst.setOpcode(Mips::DSLL32); break; - } - - case Mips::USW: { - // FIXME: only works for little endian right now - assert (Base.getReg() != Target.getReg()); - TwoInstructions = true; - MCOperand AdjName = LowerOperand(UnLoweredName, 3); - Instr1.setOpcode(Mips::SWL); - Instr1.addOperand(Target); - Instr1.addOperand(Base); - Instr1.addOperand(AdjName); - Instr2.setOpcode(Mips::SWR); - Instr2.addOperand(Target); - Instr2.addOperand(Base); - Instr2.addOperand(Name); + case Mips::DSRL: + Inst.setOpcode(Mips::DSRL32); break; - } - case Mips::USH: { - MCOperand AdjName = LowerOperand(UnLoweredName, 1); - Instr1.setOpcode(Mips::SB); - Instr1.addOperand(Target); - Instr1.addOperand(Base); - Instr1.addOperand(Name); - Instr2.setOpcode(Mips::SRL); - Instr2.addOperand(ATReg); - Instr2.addOperand(Target); - Instr2.addOperand(MCOperand::CreateImm(8)); - Instr3.setOpcode(Mips::SB); - Instr3.addOperand(ATReg); - Instr3.addOperand(Base); - Instr3.addOperand(AdjName); + case Mips::DSRA: + Inst.setOpcode(Mips::DSRA32); break; } - default: - // FIXME: need to add others - llvm_unreachable("unaligned instruction not processed"); - } - - MCInsts.push_back(Instr1); - MCInsts.push_back(Instr2); - if (!TwoInstructions) MCInsts.push_back(Instr3); -} - -// Convert -// "setgp01 $reg" -// to -// "lui $reg, %hi(_gp_disp)" -// "addiu $reg, $reg, %lo(_gp_disp)" -void MipsMCInstLower::LowerSETGP01(const MachineInstr *MI, - SmallVector<MCInst, 4>& MCInsts) { - const MachineOperand &MO = MI->getOperand(0); - assert(MO.isReg()); - MCOperand RegOpnd = MCOperand::CreateReg(MO.getReg()); - StringRef SymName("_gp_disp"); - const MCSymbol *Sym = Ctx->GetOrCreateSymbol(SymName); - const MCSymbolRefExpr *MCSym; - - MCSym = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_Mips_ABS_HI, *Ctx); - MCOperand SymHi = MCOperand::CreateExpr(MCSym); - MCSym = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_Mips_ABS_LO, *Ctx); - MCOperand SymLo = MCOperand::CreateExpr(MCSym); - - MCInsts.resize(2); - - CreateMCInst(MCInsts[0], Mips::LUi, RegOpnd, SymHi); - CreateMCInst(MCInsts[1], Mips::ADDiu, RegOpnd, RegOpnd, SymLo); } diff --git a/lib/Target/Mips/MipsMCInstLower.h b/lib/Target/Mips/MipsMCInstLower.h index c1d007d..0abb996 100644 --- a/lib/Target/Mips/MipsMCInstLower.h +++ b/lib/Target/Mips/MipsMCInstLower.h @@ -31,13 +31,10 @@ class LLVM_LIBRARY_VISIBILITY MipsMCInstLower { MipsAsmPrinter &AsmPrinter; public: MipsMCInstLower(MipsAsmPrinter &asmprinter); - void Initialize(Mangler *mang, MCContext* C); + void Initialize(Mangler *mang, MCContext *C); void Lower(const MachineInstr *MI, MCInst &OutMI) const; - void LowerCPLOAD(SmallVector<MCInst, 4>& MCInsts); - void LowerCPRESTORE(int64_t Offset, SmallVector<MCInst, 4>& MCInsts); - void LowerUnalignedLoadStore(const MachineInstr *MI, - SmallVector<MCInst, 4>& MCInsts); - void LowerSETGP01(const MachineInstr *MI, SmallVector<MCInst, 4>& MCInsts); + void LowerLargeShift(const MachineInstr *MI, MCInst &Inst, int64_t Shift); + private: MCOperand LowerSymbolOperand(const MachineOperand &MO, MachineOperandType MOTy, unsigned Offset) const; diff --git a/lib/Target/Mips/MipsMachineFunction.cpp b/lib/Target/Mips/MipsMachineFunction.cpp index b00c62b..362173e 100644 --- a/lib/Target/Mips/MipsMachineFunction.cpp +++ b/lib/Target/Mips/MipsMachineFunction.cpp @@ -22,10 +22,6 @@ static cl::opt<bool> FixGlobalBaseReg("mips-fix-global-base-reg", cl::Hidden, cl::init(true), cl::desc("Always use $gp as the global base register.")); -bool MipsFunctionInfo::globalBaseRegFixed() const { - return FixGlobalBaseReg; -} - bool MipsFunctionInfo::globalBaseRegSet() const { return GlobalBaseReg; } @@ -37,13 +33,13 @@ unsigned MipsFunctionInfo::getGlobalBaseReg() { const MipsSubtarget &ST = MF.getTarget().getSubtarget<MipsSubtarget>(); - if (FixGlobalBaseReg) // $gp is the global base register. - return GlobalBaseReg = ST.isABI_N64() ? Mips::GP_64 : Mips::GP; - const TargetRegisterClass *RC; - RC = ST.isABI_N64() ? - Mips::CPU64RegsRegisterClass : Mips::CPURegsRegisterClass; - + if (ST.inMips16Mode()) + RC=(const TargetRegisterClass*)&Mips::CPU16RegsRegClass; + else + RC = ST.isABI_N64() ? + (const TargetRegisterClass*)&Mips::CPU64RegsRegClass : + (const TargetRegisterClass*)&Mips::CPURegsRegClass; return GlobalBaseReg = MF.getRegInfo().createVirtualRegister(RC); } diff --git a/lib/Target/Mips/MipsMachineFunction.h b/lib/Target/Mips/MipsMachineFunction.h index 0fde55c..b2232c6 100644 --- a/lib/Target/Mips/MipsMachineFunction.h +++ b/lib/Target/Mips/MipsMachineFunction.h @@ -14,8 +14,11 @@ #ifndef MIPS_MACHINE_FUNCTION_INFO_H #define MIPS_MACHINE_FUNCTION_INFO_H +#include "MipsSubtarget.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/Target/TargetFrameLowering.h" +#include "llvm/Target/TargetMachine.h" #include <utility> namespace llvm { @@ -45,7 +48,7 @@ class MipsFunctionInfo : public MachineFunctionInfo { // OutArgFIRange: Range of indices of all frame objects created during call to // LowerCall except for the frame object for restoring $gp. std::pair<int, int> InArgFIRange, OutArgFIRange; - int GPFI; // Index of the frame object for restoring $gp + int GlobalRegFI; mutable int DynAllocFI; // Frame index of dynamically allocated stack area. unsigned MaxCallFrameSize; @@ -55,7 +58,7 @@ public: MipsFunctionInfo(MachineFunction& MF) : MF(MF), SRetReturnReg(0), GlobalBaseReg(0), VarArgsFrameIndex(0), InArgFIRange(std::make_pair(-1, 0)), - OutArgFIRange(std::make_pair(-1, 0)), GPFI(0), DynAllocFI(0), + OutArgFIRange(std::make_pair(-1, 0)), GlobalRegFI(0), DynAllocFI(0), MaxCallFrameSize(0), EmitNOAT(false) {} @@ -74,10 +77,23 @@ public: OutArgFIRange.second = LastFI; } - int getGPFI() const { return GPFI; } - void setGPFI(int FI) { GPFI = FI; } - bool needGPSaveRestore() const { return getGPFI(); } - bool isGPFI(int FI) const { return GPFI && GPFI == FI; } + bool isGlobalRegFI(int FI) const { + return GlobalRegFI && (FI == GlobalRegFI); + } + + int getGlobalRegFI() const { + return GlobalRegFI; + } + + int initGlobalRegFI() { + const TargetMachine &TM = MF.getTarget(); + unsigned RegSize = TM.getSubtarget<MipsSubtarget>().isABI_N64() ? 8 : 4; + int64_t StackAlignment = TM.getFrameLowering()->getStackAlignment(); + uint64_t Offset = RoundUpToAlignment(MaxCallFrameSize, StackAlignment); + + GlobalRegFI = MF.getFrameInfo()->CreateFixedObject(RegSize, Offset, true); + return GlobalRegFI; + } // The first call to this function creates a frame object for dynamically // allocated stack area. @@ -92,7 +108,6 @@ public: unsigned getSRetReturnReg() const { return SRetReturnReg; } void setSRetReturnReg(unsigned Reg) { SRetReturnReg = Reg; } - bool globalBaseRegFixed() const; bool globalBaseRegSet() const; unsigned getGlobalBaseReg(); diff --git a/lib/Target/Mips/MipsRegisterInfo.cpp b/lib/Target/Mips/MipsRegisterInfo.cpp index f30de44..a3ce236 100644 --- a/lib/Target/Mips/MipsRegisterInfo.cpp +++ b/lib/Target/Mips/MipsRegisterInfo.cpp @@ -16,9 +16,11 @@ #include "MipsRegisterInfo.h" #include "Mips.h" #include "MipsAnalyzeImmediate.h" +#include "MipsInstrInfo.h" #include "MipsSubtarget.h" #include "MipsMachineFunction.h" #include "llvm/Constants.h" +#include "llvm/DebugInfo.h" #include "llvm/Type.h" #include "llvm/Function.h" #include "llvm/CodeGen/ValueTypes.h" @@ -35,7 +37,6 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/Analysis/DebugInfo.h" #define GET_REGINFO_TARGET_DESC #include "MipsGenRegisterInfo.inc" @@ -54,8 +55,7 @@ unsigned MipsRegisterInfo::getPICCallReg() { return Mips::T9; } /// Mips Callee Saved Registers const uint16_t* MipsRegisterInfo:: -getCalleeSavedRegs(const MachineFunction *MF) const -{ +getCalleeSavedRegs(const MachineFunction *MF) const { if (Subtarget.isSingleFloat()) return CSR_SingleFloatOnly_SaveList; else if (!Subtarget.hasMips64()) @@ -64,12 +64,11 @@ getCalleeSavedRegs(const MachineFunction *MF) const return CSR_N32_SaveList; assert(Subtarget.isABI_N64()); - return CSR_N64_SaveList; + return CSR_N64_SaveList; } const uint32_t* -MipsRegisterInfo::getCallPreservedMask(CallingConv::ID) const -{ +MipsRegisterInfo::getCallPreservedMask(CallingConv::ID) const { if (Subtarget.isSingleFloat()) return CSR_SingleFloatOnly_RegMask; else if (!Subtarget.hasMips64()) @@ -78,23 +77,21 @@ MipsRegisterInfo::getCallPreservedMask(CallingConv::ID) const return CSR_N32_RegMask; assert(Subtarget.isABI_N64()); - return CSR_N64_RegMask; + return CSR_N64_RegMask; } BitVector MipsRegisterInfo:: getReservedRegs(const MachineFunction &MF) const { static const uint16_t ReservedCPURegs[] = { - Mips::ZERO, Mips::AT, Mips::K0, Mips::K1, - Mips::SP, Mips::FP, Mips::RA + Mips::ZERO, Mips::AT, Mips::K0, Mips::K1, Mips::SP }; static const uint16_t ReservedCPU64Regs[] = { - Mips::ZERO_64, Mips::AT_64, Mips::K0_64, Mips::K1_64, - Mips::SP_64, Mips::FP_64, Mips::RA_64 + Mips::ZERO_64, Mips::AT_64, Mips::K0_64, Mips::K1_64, Mips::SP_64 }; BitVector Reserved(getNumRegs()); - typedef TargetRegisterClass::iterator RegIter; + typedef TargetRegisterClass::const_iterator RegIter; for (unsigned I = 0; I < array_lengthof(ReservedCPURegs); ++I) Reserved.set(ReservedCPURegs[I]); @@ -104,31 +101,36 @@ getReservedRegs(const MachineFunction &MF) const { Reserved.set(ReservedCPU64Regs[I]); // Reserve all registers in AFGR64. - for (RegIter Reg = Mips::AFGR64RegisterClass->begin(); - Reg != Mips::AFGR64RegisterClass->end(); ++Reg) + for (RegIter Reg = Mips::AFGR64RegClass.begin(), + EReg = Mips::AFGR64RegClass.end(); Reg != EReg; ++Reg) Reserved.set(*Reg); - } - else { + } else { // Reserve all registers in CPU64Regs & FGR64. - for (RegIter Reg = Mips::CPU64RegsRegisterClass->begin(); - Reg != Mips::CPU64RegsRegisterClass->end(); ++Reg) + for (RegIter Reg = Mips::CPU64RegsRegClass.begin(), + EReg = Mips::CPU64RegsRegClass.end(); Reg != EReg; ++Reg) Reserved.set(*Reg); - for (RegIter Reg = Mips::FGR64RegisterClass->begin(); - Reg != Mips::FGR64RegisterClass->end(); ++Reg) + for (RegIter Reg = Mips::FGR64RegClass.begin(), + EReg = Mips::FGR64RegClass.end(); Reg != EReg; ++Reg) Reserved.set(*Reg); } - // If GP is dedicated as a global base register, reserve it. - if (MF.getInfo<MipsFunctionInfo>()->globalBaseRegFixed()) { - Reserved.set(Mips::GP); - Reserved.set(Mips::GP_64); + // Reserve FP if this function should have a dedicated frame pointer register. + if (MF.getTarget().getFrameLowering()->hasFP(MF)) { + Reserved.set(Mips::FP); + Reserved.set(Mips::FP_64); } // Reserve hardware registers. Reserved.set(Mips::HWR29); Reserved.set(Mips::HWR29_64); + // Reserve RA if in mips16 mode. + if (Subtarget.inMips16Mode()) { + Reserved.set(Mips::RA); + Reserved.set(Mips::RA_64); + } + return Reserved; } @@ -137,6 +139,11 @@ MipsRegisterInfo::requiresRegisterScavenging(const MachineFunction &MF) const { return true; } +bool +MipsRegisterInfo::trackLivenessAfterRegAlloc(const MachineFunction &MF) const { + return true; +} + // This function eliminate ADJCALLSTACKDOWN, // ADJCALLSTACKUP pseudo instructions void MipsRegisterInfo:: @@ -207,8 +214,8 @@ eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, // incoming argument, callee-saved register location or local variable. int64_t Offset; - if (MipsFI->isOutArgFI(FrameIndex) || MipsFI->isGPFI(FrameIndex) || - MipsFI->isDynAllocFI(FrameIndex)) + if (MipsFI->isOutArgFI(FrameIndex) || MipsFI->isDynAllocFI(FrameIndex) || + MipsFI->isGlobalRegFI(FrameIndex)) Offset = spOffset; else Offset = spOffset + (int64_t)stackSize; @@ -222,37 +229,17 @@ eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, if (!MI.isDebugValue() && !isInt<16>(Offset)) { MachineBasicBlock &MBB = *MI.getParent(); DebugLoc DL = II->getDebugLoc(); - MipsAnalyzeImmediate AnalyzeImm; - unsigned Size = Subtarget.isABI_N64() ? 64 : 32; - unsigned LUi = Subtarget.isABI_N64() ? Mips::LUi64 : Mips::LUi; unsigned ADDu = Subtarget.isABI_N64() ? Mips::DADDu : Mips::ADDu; - unsigned ZEROReg = Subtarget.isABI_N64() ? Mips::ZERO_64 : Mips::ZERO; unsigned ATReg = Subtarget.isABI_N64() ? Mips::AT_64 : Mips::AT; - const MipsAnalyzeImmediate::InstSeq &Seq = - AnalyzeImm.Analyze(Offset, Size, true /* LastInstrIsADDiu */); - MipsAnalyzeImmediate::InstSeq::const_iterator Inst = Seq.begin(); + MipsAnalyzeImmediate::Inst LastInst(0, 0); MipsFI->setEmitNOAT(); - - // The first instruction can be a LUi, which is different from other - // instructions (ADDiu, ORI and SLL) in that it does not have a register - // operand. - if (Inst->Opc == LUi) - BuildMI(MBB, II, DL, TII.get(LUi), ATReg) - .addImm(SignExtend64<16>(Inst->ImmOpnd)); - else - BuildMI(MBB, II, DL, TII.get(Inst->Opc), ATReg).addReg(ZEROReg) - .addImm(SignExtend64<16>(Inst->ImmOpnd)); - - // Build the remaining instructions in Seq except for the last one. - for (++Inst; Inst != Seq.end() - 1; ++Inst) - BuildMI(MBB, II, DL, TII.get(Inst->Opc), ATReg).addReg(ATReg) - .addImm(SignExtend64<16>(Inst->ImmOpnd)); - + Mips::loadImmediate(Offset, Subtarget.isABI_N64(), TII, MBB, II, DL, true, + &LastInst); BuildMI(MBB, II, DL, TII.get(ADDu), ATReg).addReg(FrameReg).addReg(ATReg); FrameReg = ATReg; - Offset = SignExtend64<16>(Inst->ImmOpnd); + Offset = SignExtend64<16>(LastInst.ImmOpnd); } MI.getOperand(i).ChangeToRegister(FrameReg, false); diff --git a/lib/Target/Mips/MipsRegisterInfo.h b/lib/Target/Mips/MipsRegisterInfo.h index 0716d29..f320bae 100644 --- a/lib/Target/Mips/MipsRegisterInfo.h +++ b/lib/Target/Mips/MipsRegisterInfo.h @@ -42,13 +42,15 @@ struct MipsRegisterInfo : public MipsGenRegisterInfo { void adjustMipsStackFrame(MachineFunction &MF) const; /// Code Generation virtual methods... - const uint16_t *getCalleeSavedRegs(const MachineFunction* MF = 0) const; + const uint16_t *getCalleeSavedRegs(const MachineFunction *MF = 0) const; const uint32_t *getCallPreservedMask(CallingConv::ID) const; BitVector getReservedRegs(const MachineFunction &MF) const; virtual bool requiresRegisterScavenging(const MachineFunction &MF) const; + virtual bool trackLivenessAfterRegAlloc(const MachineFunction &MF) const; + void eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const; diff --git a/lib/Target/Mips/MipsRegisterInfo.td b/lib/Target/Mips/MipsRegisterInfo.td index ce399a0..b255e42 100644 --- a/lib/Target/Mips/MipsRegisterInfo.td +++ b/lib/Target/Mips/MipsRegisterInfo.td @@ -70,8 +70,8 @@ class HWR<bits<5> num, string n> : MipsReg<n> { let Namespace = "Mips" in { // General Purpose Registers - def ZERO : MipsGPRReg< 0, "ZERO">, DwarfRegNum<[0]>; - def AT : MipsGPRReg< 1, "AT">, DwarfRegNum<[1]>; + def ZERO : MipsGPRReg< 0, "zero">, DwarfRegNum<[0]>; + def AT : MipsGPRReg< 1, "at">, DwarfRegNum<[1]>; def V0 : MipsGPRReg< 2, "2">, DwarfRegNum<[2]>; def V1 : MipsGPRReg< 3, "3">, DwarfRegNum<[3]>; def A0 : MipsGPRReg< 4, "4">, DwarfRegNum<[4]>; @@ -98,14 +98,14 @@ let Namespace = "Mips" in { def T9 : MipsGPRReg< 25, "25">, DwarfRegNum<[25]>; def K0 : MipsGPRReg< 26, "26">, DwarfRegNum<[26]>; def K1 : MipsGPRReg< 27, "27">, DwarfRegNum<[27]>; - def GP : MipsGPRReg< 28, "GP">, DwarfRegNum<[28]>; - def SP : MipsGPRReg< 29, "SP">, DwarfRegNum<[29]>; - def FP : MipsGPRReg< 30, "FP">, DwarfRegNum<[30]>; - def RA : MipsGPRReg< 31, "RA">, DwarfRegNum<[31]>; + def GP : MipsGPRReg< 28, "gp">, DwarfRegNum<[28]>; + def SP : MipsGPRReg< 29, "sp">, DwarfRegNum<[29]>; + def FP : MipsGPRReg< 30, "fp">, DwarfRegNum<[30]>; + def RA : MipsGPRReg< 31, "ra">, DwarfRegNum<[31]>; // General Purpose 64-bit Registers - def ZERO_64 : Mips64GPRReg< 0, "ZERO", [ZERO]>, DwarfRegNum<[0]>; - def AT_64 : Mips64GPRReg< 1, "AT", [AT]>, DwarfRegNum<[1]>; + def ZERO_64 : Mips64GPRReg< 0, "zero", [ZERO]>, DwarfRegNum<[0]>; + def AT_64 : Mips64GPRReg< 1, "at", [AT]>, DwarfRegNum<[1]>; def V0_64 : Mips64GPRReg< 2, "2", [V0]>, DwarfRegNum<[2]>; def V1_64 : Mips64GPRReg< 3, "3", [V1]>, DwarfRegNum<[3]>; def A0_64 : Mips64GPRReg< 4, "4", [A0]>, DwarfRegNum<[4]>; @@ -132,97 +132,97 @@ let Namespace = "Mips" in { def T9_64 : Mips64GPRReg< 25, "25", [T9]>, DwarfRegNum<[25]>; def K0_64 : Mips64GPRReg< 26, "26", [K0]>, DwarfRegNum<[26]>; def K1_64 : Mips64GPRReg< 27, "27", [K1]>, DwarfRegNum<[27]>; - def GP_64 : Mips64GPRReg< 28, "GP", [GP]>, DwarfRegNum<[28]>; - def SP_64 : Mips64GPRReg< 29, "SP", [SP]>, DwarfRegNum<[29]>; - def FP_64 : Mips64GPRReg< 30, "FP", [FP]>, DwarfRegNum<[30]>; - def RA_64 : Mips64GPRReg< 31, "RA", [RA]>, DwarfRegNum<[31]>; + def GP_64 : Mips64GPRReg< 28, "gp", [GP]>, DwarfRegNum<[28]>; + def SP_64 : Mips64GPRReg< 29, "sp", [SP]>, DwarfRegNum<[29]>; + def FP_64 : Mips64GPRReg< 30, "fp", [FP]>, DwarfRegNum<[30]>; + def RA_64 : Mips64GPRReg< 31, "ra", [RA]>, DwarfRegNum<[31]>; /// Mips Single point precision FPU Registers - def F0 : FPR< 0, "F0">, DwarfRegNum<[32]>; - def F1 : FPR< 1, "F1">, DwarfRegNum<[33]>; - def F2 : FPR< 2, "F2">, DwarfRegNum<[34]>; - def F3 : FPR< 3, "F3">, DwarfRegNum<[35]>; - def F4 : FPR< 4, "F4">, DwarfRegNum<[36]>; - def F5 : FPR< 5, "F5">, DwarfRegNum<[37]>; - def F6 : FPR< 6, "F6">, DwarfRegNum<[38]>; - def F7 : FPR< 7, "F7">, DwarfRegNum<[39]>; - def F8 : FPR< 8, "F8">, DwarfRegNum<[40]>; - def F9 : FPR< 9, "F9">, DwarfRegNum<[41]>; - def F10 : FPR<10, "F10">, DwarfRegNum<[42]>; - def F11 : FPR<11, "F11">, DwarfRegNum<[43]>; - def F12 : FPR<12, "F12">, DwarfRegNum<[44]>; - def F13 : FPR<13, "F13">, DwarfRegNum<[45]>; - def F14 : FPR<14, "F14">, DwarfRegNum<[46]>; - def F15 : FPR<15, "F15">, DwarfRegNum<[47]>; - def F16 : FPR<16, "F16">, DwarfRegNum<[48]>; - def F17 : FPR<17, "F17">, DwarfRegNum<[49]>; - def F18 : FPR<18, "F18">, DwarfRegNum<[50]>; - def F19 : FPR<19, "F19">, DwarfRegNum<[51]>; - def F20 : FPR<20, "F20">, DwarfRegNum<[52]>; - def F21 : FPR<21, "F21">, DwarfRegNum<[53]>; - def F22 : FPR<22, "F22">, DwarfRegNum<[54]>; - def F23 : FPR<23, "F23">, DwarfRegNum<[55]>; - def F24 : FPR<24, "F24">, DwarfRegNum<[56]>; - def F25 : FPR<25, "F25">, DwarfRegNum<[57]>; - def F26 : FPR<26, "F26">, DwarfRegNum<[58]>; - def F27 : FPR<27, "F27">, DwarfRegNum<[59]>; - def F28 : FPR<28, "F28">, DwarfRegNum<[60]>; - def F29 : FPR<29, "F29">, DwarfRegNum<[61]>; - def F30 : FPR<30, "F30">, DwarfRegNum<[62]>; - def F31 : FPR<31, "F31">, DwarfRegNum<[63]>; + def F0 : FPR< 0, "f0">, DwarfRegNum<[32]>; + def F1 : FPR< 1, "f1">, DwarfRegNum<[33]>; + def F2 : FPR< 2, "f2">, DwarfRegNum<[34]>; + def F3 : FPR< 3, "f3">, DwarfRegNum<[35]>; + def F4 : FPR< 4, "f4">, DwarfRegNum<[36]>; + def F5 : FPR< 5, "f5">, DwarfRegNum<[37]>; + def F6 : FPR< 6, "f6">, DwarfRegNum<[38]>; + def F7 : FPR< 7, "f7">, DwarfRegNum<[39]>; + def F8 : FPR< 8, "f8">, DwarfRegNum<[40]>; + def F9 : FPR< 9, "f9">, DwarfRegNum<[41]>; + def F10 : FPR<10, "f10">, DwarfRegNum<[42]>; + def F11 : FPR<11, "f11">, DwarfRegNum<[43]>; + def F12 : FPR<12, "f12">, DwarfRegNum<[44]>; + def F13 : FPR<13, "f13">, DwarfRegNum<[45]>; + def F14 : FPR<14, "f14">, DwarfRegNum<[46]>; + def F15 : FPR<15, "f15">, DwarfRegNum<[47]>; + def F16 : FPR<16, "f16">, DwarfRegNum<[48]>; + def F17 : FPR<17, "f17">, DwarfRegNum<[49]>; + def F18 : FPR<18, "f18">, DwarfRegNum<[50]>; + def F19 : FPR<19, "f19">, DwarfRegNum<[51]>; + def F20 : FPR<20, "f20">, DwarfRegNum<[52]>; + def F21 : FPR<21, "f21">, DwarfRegNum<[53]>; + def F22 : FPR<22, "f22">, DwarfRegNum<[54]>; + def F23 : FPR<23, "f23">, DwarfRegNum<[55]>; + def F24 : FPR<24, "f24">, DwarfRegNum<[56]>; + def F25 : FPR<25, "f25">, DwarfRegNum<[57]>; + def F26 : FPR<26, "f26">, DwarfRegNum<[58]>; + def F27 : FPR<27, "f27">, DwarfRegNum<[59]>; + def F28 : FPR<28, "f28">, DwarfRegNum<[60]>; + def F29 : FPR<29, "f29">, DwarfRegNum<[61]>; + def F30 : FPR<30, "f30">, DwarfRegNum<[62]>; + def F31 : FPR<31, "f31">, DwarfRegNum<[63]>; /// Mips Double point precision FPU Registers (aliased /// with the single precision to hold 64 bit values) - def D0 : AFPR< 0, "F0", [F0, F1]>; - def D1 : AFPR< 2, "F2", [F2, F3]>; - def D2 : AFPR< 4, "F4", [F4, F5]>; - def D3 : AFPR< 6, "F6", [F6, F7]>; - def D4 : AFPR< 8, "F8", [F8, F9]>; - def D5 : AFPR<10, "F10", [F10, F11]>; - def D6 : AFPR<12, "F12", [F12, F13]>; - def D7 : AFPR<14, "F14", [F14, F15]>; - def D8 : AFPR<16, "F16", [F16, F17]>; - def D9 : AFPR<18, "F18", [F18, F19]>; - def D10 : AFPR<20, "F20", [F20, F21]>; - def D11 : AFPR<22, "F22", [F22, F23]>; - def D12 : AFPR<24, "F24", [F24, F25]>; - def D13 : AFPR<26, "F26", [F26, F27]>; - def D14 : AFPR<28, "F28", [F28, F29]>; - def D15 : AFPR<30, "F30", [F30, F31]>; + def D0 : AFPR< 0, "f0", [F0, F1]>; + def D1 : AFPR< 2, "f2", [F2, F3]>; + def D2 : AFPR< 4, "f4", [F4, F5]>; + def D3 : AFPR< 6, "f6", [F6, F7]>; + def D4 : AFPR< 8, "f8", [F8, F9]>; + def D5 : AFPR<10, "f10", [F10, F11]>; + def D6 : AFPR<12, "f12", [F12, F13]>; + def D7 : AFPR<14, "f14", [F14, F15]>; + def D8 : AFPR<16, "f16", [F16, F17]>; + def D9 : AFPR<18, "f18", [F18, F19]>; + def D10 : AFPR<20, "f20", [F20, F21]>; + def D11 : AFPR<22, "f22", [F22, F23]>; + def D12 : AFPR<24, "f24", [F24, F25]>; + def D13 : AFPR<26, "f26", [F26, F27]>; + def D14 : AFPR<28, "f28", [F28, F29]>; + def D15 : AFPR<30, "f30", [F30, F31]>; /// Mips Double point precision FPU Registers in MFP64 mode. - def D0_64 : AFPR64<0, "F0", [F0]>, DwarfRegNum<[32]>; - def D1_64 : AFPR64<1, "F1", [F1]>, DwarfRegNum<[33]>; - def D2_64 : AFPR64<2, "F2", [F2]>, DwarfRegNum<[34]>; - def D3_64 : AFPR64<3, "F3", [F3]>, DwarfRegNum<[35]>; - def D4_64 : AFPR64<4, "F4", [F4]>, DwarfRegNum<[36]>; - def D5_64 : AFPR64<5, "F5", [F5]>, DwarfRegNum<[37]>; - def D6_64 : AFPR64<6, "F6", [F6]>, DwarfRegNum<[38]>; - def D7_64 : AFPR64<7, "F7", [F7]>, DwarfRegNum<[39]>; - def D8_64 : AFPR64<8, "F8", [F8]>, DwarfRegNum<[40]>; - def D9_64 : AFPR64<9, "F9", [F9]>, DwarfRegNum<[41]>; - def D10_64 : AFPR64<10, "F10", [F10]>, DwarfRegNum<[42]>; - def D11_64 : AFPR64<11, "F11", [F11]>, DwarfRegNum<[43]>; - def D12_64 : AFPR64<12, "F12", [F12]>, DwarfRegNum<[44]>; - def D13_64 : AFPR64<13, "F13", [F13]>, DwarfRegNum<[45]>; - def D14_64 : AFPR64<14, "F14", [F14]>, DwarfRegNum<[46]>; - def D15_64 : AFPR64<15, "F15", [F15]>, DwarfRegNum<[47]>; - def D16_64 : AFPR64<16, "F16", [F16]>, DwarfRegNum<[48]>; - def D17_64 : AFPR64<17, "F17", [F17]>, DwarfRegNum<[49]>; - def D18_64 : AFPR64<18, "F18", [F18]>, DwarfRegNum<[50]>; - def D19_64 : AFPR64<19, "F19", [F19]>, DwarfRegNum<[51]>; - def D20_64 : AFPR64<20, "F20", [F20]>, DwarfRegNum<[52]>; - def D21_64 : AFPR64<21, "F21", [F21]>, DwarfRegNum<[53]>; - def D22_64 : AFPR64<22, "F22", [F22]>, DwarfRegNum<[54]>; - def D23_64 : AFPR64<23, "F23", [F23]>, DwarfRegNum<[55]>; - def D24_64 : AFPR64<24, "F24", [F24]>, DwarfRegNum<[56]>; - def D25_64 : AFPR64<25, "F25", [F25]>, DwarfRegNum<[57]>; - def D26_64 : AFPR64<26, "F26", [F26]>, DwarfRegNum<[58]>; - def D27_64 : AFPR64<27, "F27", [F27]>, DwarfRegNum<[59]>; - def D28_64 : AFPR64<28, "F28", [F28]>, DwarfRegNum<[60]>; - def D29_64 : AFPR64<29, "F29", [F29]>, DwarfRegNum<[61]>; - def D30_64 : AFPR64<30, "F30", [F30]>, DwarfRegNum<[62]>; - def D31_64 : AFPR64<31, "F31", [F31]>, DwarfRegNum<[63]>; + def D0_64 : AFPR64<0, "f0", [F0]>, DwarfRegNum<[32]>; + def D1_64 : AFPR64<1, "f1", [F1]>, DwarfRegNum<[33]>; + def D2_64 : AFPR64<2, "f2", [F2]>, DwarfRegNum<[34]>; + def D3_64 : AFPR64<3, "f3", [F3]>, DwarfRegNum<[35]>; + def D4_64 : AFPR64<4, "f4", [F4]>, DwarfRegNum<[36]>; + def D5_64 : AFPR64<5, "f5", [F5]>, DwarfRegNum<[37]>; + def D6_64 : AFPR64<6, "f6", [F6]>, DwarfRegNum<[38]>; + def D7_64 : AFPR64<7, "f7", [F7]>, DwarfRegNum<[39]>; + def D8_64 : AFPR64<8, "f8", [F8]>, DwarfRegNum<[40]>; + def D9_64 : AFPR64<9, "f9", [F9]>, DwarfRegNum<[41]>; + def D10_64 : AFPR64<10, "f10", [F10]>, DwarfRegNum<[42]>; + def D11_64 : AFPR64<11, "f11", [F11]>, DwarfRegNum<[43]>; + def D12_64 : AFPR64<12, "f12", [F12]>, DwarfRegNum<[44]>; + def D13_64 : AFPR64<13, "f13", [F13]>, DwarfRegNum<[45]>; + def D14_64 : AFPR64<14, "f14", [F14]>, DwarfRegNum<[46]>; + def D15_64 : AFPR64<15, "f15", [F15]>, DwarfRegNum<[47]>; + def D16_64 : AFPR64<16, "f16", [F16]>, DwarfRegNum<[48]>; + def D17_64 : AFPR64<17, "f17", [F17]>, DwarfRegNum<[49]>; + def D18_64 : AFPR64<18, "f18", [F18]>, DwarfRegNum<[50]>; + def D19_64 : AFPR64<19, "f19", [F19]>, DwarfRegNum<[51]>; + def D20_64 : AFPR64<20, "f20", [F20]>, DwarfRegNum<[52]>; + def D21_64 : AFPR64<21, "f21", [F21]>, DwarfRegNum<[53]>; + def D22_64 : AFPR64<22, "f22", [F22]>, DwarfRegNum<[54]>; + def D23_64 : AFPR64<23, "f23", [F23]>, DwarfRegNum<[55]>; + def D24_64 : AFPR64<24, "f24", [F24]>, DwarfRegNum<[56]>; + def D25_64 : AFPR64<25, "f25", [F25]>, DwarfRegNum<[57]>; + def D26_64 : AFPR64<26, "f26", [F26]>, DwarfRegNum<[58]>; + def D27_64 : AFPR64<27, "f27", [F27]>, DwarfRegNum<[59]>; + def D28_64 : AFPR64<28, "f28", [F28]>, DwarfRegNum<[60]>; + def D29_64 : AFPR64<29, "f29", [F29]>, DwarfRegNum<[61]>; + def D30_64 : AFPR64<30, "f30", [F30]>, DwarfRegNum<[62]>; + def D31_64 : AFPR64<31, "f31", [F31]>, DwarfRegNum<[63]>; // Hi/Lo registers def HI : Register<"hi">, DwarfRegNum<[64]>; @@ -236,6 +236,9 @@ let Namespace = "Mips" in { // Status flags register def FCR31 : Register<"31">; + // fcc0 register + def FCC0 : Register<"fcc0">; + // Hardware register $29 def HWR29 : Register<"29">; def HWR29_64 : Register<"29">; @@ -246,26 +249,41 @@ let Namespace = "Mips" in { //===----------------------------------------------------------------------===// def CPURegs : RegisterClass<"Mips", [i32], 32, (add + // Reserved + ZERO, AT, // Return Values and Arguments V0, V1, A0, A1, A2, A3, // Not preserved across procedure calls - T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, + T0, T1, T2, T3, T4, T5, T6, T7, // Callee save S0, S1, S2, S3, S4, S5, S6, S7, + // Not preserved across procedure calls + T8, T9, // Reserved - ZERO, AT, K0, K1, GP, SP, FP, RA)>; + K0, K1, GP, SP, FP, RA)>; def CPU64Regs : RegisterClass<"Mips", [i64], 64, (add +// Reserved + ZERO_64, AT_64, // Return Values and Arguments V0_64, V1_64, A0_64, A1_64, A2_64, A3_64, // Not preserved across procedure calls - T0_64, T1_64, T2_64, T3_64, T4_64, T5_64, T6_64, T7_64, T8_64, T9_64, + T0_64, T1_64, T2_64, T3_64, T4_64, T5_64, T6_64, T7_64, // Callee save S0_64, S1_64, S2_64, S3_64, S4_64, S5_64, S6_64, S7_64, + // Not preserved across procedure calls + T8_64, T9_64, // Reserved - ZERO_64, AT_64, K0_64, K1_64, GP_64, SP_64, FP_64, RA_64)> { - let SubRegClasses = [(CPURegs sub_32)]; -} + K0_64, K1_64, GP_64, SP_64, FP_64, RA_64)>; + +def CPU16Regs : RegisterClass<"Mips", [i32], 32, (add + // Return Values and Arguments + V0, V1, A0, A1, A2, A3, + // Callee save + S0, S1)>; + +def CPURAReg : RegisterClass<"Mips", [i32], 32, (add RA)>; + // 64bit fp: // * FGR64 - 32 64-bit registers @@ -278,26 +296,24 @@ def FGR32 : RegisterClass<"Mips", [f32], 32, (sequence "F%u", 0, 31)>; def AFGR64 : RegisterClass<"Mips", [f64], 64, (add // Return Values and Arguments - D0, D1, D6, D7, + D0, D1, + // Not preserved across procedure calls + D2, D3, D4, D5, + // Return Values and Arguments + D6, D7, // Not preserved across procedure calls - D2, D3, D4, D5, D8, D9, + D8, D9, // Callee save - D10, D11, D12, D13, D14, D15)> { - let SubRegClasses = [(FGR32 sub_fpeven, sub_fpodd)]; -} + D10, D11, D12, D13, D14, D15)>; -def FGR64 : RegisterClass<"Mips", [f64], 64, (sequence "D%u_64", 0, 31)> { - let SubRegClasses = [(FGR32 sub_32)]; -} +def FGR64 : RegisterClass<"Mips", [f64], 64, (sequence "D%u_64", 0, 31)>; // Condition Register for floating point operations -def CCR : RegisterClass<"Mips", [i32], 32, (add FCR31)>; +def CCR : RegisterClass<"Mips", [i32], 32, (add FCR31,FCC0)>; // Hi/Lo Registers def HILO : RegisterClass<"Mips", [i32], 32, (add HI, LO)>; -def HILO64 : RegisterClass<"Mips", [i64], 64, (add HI64, LO64)> { - let SubRegClasses = [(HILO sub_32)]; -} +def HILO64 : RegisterClass<"Mips", [i64], 64, (add HI64, LO64)>; // Hardware registers def HWRegs : RegisterClass<"Mips", [i32], 32, (add HWR29)>; diff --git a/lib/Target/Mips/MipsSubtarget.cpp b/lib/Target/Mips/MipsSubtarget.cpp index 00347df..11ff809 100644 --- a/lib/Target/Mips/MipsSubtarget.cpp +++ b/lib/Target/Mips/MipsSubtarget.cpp @@ -30,7 +30,7 @@ MipsSubtarget::MipsSubtarget(const std::string &TT, const std::string &CPU, MipsArchVersion(Mips32), MipsABI(UnknownABI), IsLittle(little), IsSingleFloat(false), IsFP64bit(false), IsGP64bit(false), HasVFPU(false), IsLinux(true), HasSEInReg(false), HasCondMov(false), HasMulDivAdd(false), - HasMinMax(false), HasSwap(false), HasBitCount(false) + HasMinMax(false), HasSwap(false), HasBitCount(false), InMips16Mode(false) { std::string CPUName = CPU; if (CPUName.empty()) @@ -58,9 +58,9 @@ MipsSubtarget::MipsSubtarget(const std::string &TT, const std::string &CPU, bool MipsSubtarget::enablePostRAScheduler(CodeGenOpt::Level OptLevel, - TargetSubtargetInfo::AntiDepBreakMode& Mode, - RegClassVector& CriticalPathRCs) const { - Mode = TargetSubtargetInfo::ANTIDEP_CRITICAL; + TargetSubtargetInfo::AntiDepBreakMode &Mode, + RegClassVector &CriticalPathRCs) const { + Mode = TargetSubtargetInfo::ANTIDEP_NONE; CriticalPathRCs.clear(); CriticalPathRCs.push_back(hasMips64() ? &Mips::CPU64RegsRegClass : &Mips::CPURegsRegClass); diff --git a/lib/Target/Mips/MipsSubtarget.h b/lib/Target/Mips/MipsSubtarget.h index 7faf77b..3215c44 100644 --- a/lib/Target/Mips/MipsSubtarget.h +++ b/lib/Target/Mips/MipsSubtarget.h @@ -86,6 +86,9 @@ protected: // HasBitCount - Count leading '1' and '0' bits. bool HasBitCount; + // InMips16 -- can process Mips16 instructions + bool InMips16Mode; + InstrItineraryData InstrItins; public: @@ -124,8 +127,11 @@ public: bool isSingleFloat() const { return IsSingleFloat; } bool isNotSingleFloat() const { return !IsSingleFloat; } bool hasVFPU() const { return HasVFPU; } + bool inMips16Mode() const { return InMips16Mode; } bool isLinux() const { return IsLinux; } + bool hasStandardEncoding() const { return !inMips16Mode(); } + /// Features related to the presence of specific instructions. bool hasSEInReg() const { return HasSEInReg; } bool hasCondMov() const { return HasCondMov; } diff --git a/lib/Target/Mips/MipsTargetMachine.cpp b/lib/Target/Mips/MipsTargetMachine.cpp index ad02231..dd5d35f 100644 --- a/lib/Target/Mips/MipsTargetMachine.cpp +++ b/lib/Target/Mips/MipsTargetMachine.cpp @@ -105,8 +105,6 @@ public: } virtual bool addInstSelector(); - virtual bool addPreRegAlloc(); - virtual bool addPreSched2(); virtual bool addPreEmitPass(); }; } // namespace @@ -117,31 +115,22 @@ TargetPassConfig *MipsTargetMachine::createPassConfig(PassManagerBase &PM) { // Install an instruction selector pass using // the ISelDag to gen Mips code. -bool MipsPassConfig::addInstSelector() -{ - PM.add(createMipsISelDag(getMipsTargetMachine())); +bool MipsPassConfig::addInstSelector() { + addPass(createMipsISelDag(getMipsTargetMachine())); return false; } // Implemented by targets that want to run passes immediately before // machine code is emitted. return true if -print-machineinstrs should // print out the code after the passes. -bool MipsPassConfig::addPreEmitPass() -{ - PM.add(createMipsDelaySlotFillerPass(getMipsTargetMachine())); - return true; -} +bool MipsPassConfig::addPreEmitPass() { + MipsTargetMachine &TM = getMipsTargetMachine(); + addPass(createMipsDelaySlotFillerPass(TM)); -bool MipsPassConfig::addPreRegAlloc() { - // Do not restore $gp if target is Mips64. - // In N32/64, $gp is a callee-saved register. - if (!getMipsSubtarget().hasMips64()) - PM.add(createMipsEmitGPRestorePass(getMipsTargetMachine())); - return true; -} + // NOTE: long branch has not been implemented for mips16. + if (TM.getSubtarget<MipsSubtarget>().hasStandardEncoding()) + addPass(createMipsLongBranchPass(TM)); -bool MipsPassConfig::addPreSched2() { - PM.add(createMipsExpandPseudoPass(getMipsTargetMachine())); return true; } diff --git a/lib/Target/Mips/MipsTargetMachine.h b/lib/Target/Mips/MipsTargetMachine.h index 80c00e8..5cbf057 100644 --- a/lib/Target/Mips/MipsTargetMachine.h +++ b/lib/Target/Mips/MipsTargetMachine.h @@ -69,9 +69,7 @@ namespace llvm { // Pass Pipeline Configuration virtual TargetPassConfig *createPassConfig(PassManagerBase &PM); - virtual bool addCodeEmitter(PassManagerBase &PM, - JITCodeEmitter &JCE); - + virtual bool addCodeEmitter(PassManagerBase &PM, JITCodeEmitter &JCE); }; /// MipsebTargetMachine - Mips32 big endian target machine. |