diff options
Diffstat (limited to 'contrib/llvm/lib/Target/Mips')
47 files changed, 3395 insertions, 1357 deletions
diff --git a/contrib/llvm/lib/Target/Mips/InstPrinter/CMakeLists.txt b/contrib/llvm/lib/Target/Mips/InstPrinter/CMakeLists.txt deleted file mode 100644 index 8852fd4..0000000 --- a/contrib/llvm/lib/Target/Mips/InstPrinter/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. ) - -add_llvm_library(LLVMMipsAsmPrinter - MipsInstPrinter.cpp - ) -add_dependencies(LLVMMipsAsmPrinter MipsCodeGenTable_gen) diff --git a/contrib/llvm/lib/Target/Mips/InstPrinter/Makefile b/contrib/llvm/lib/Target/Mips/InstPrinter/Makefile deleted file mode 100644 index 63e38ef..0000000 --- a/contrib/llvm/lib/Target/Mips/InstPrinter/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===- lib/Target/Mips/AsmPrinter/Makefile --------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../../.. -LIBRARYNAME = LLVMMipsAsmPrinter - -# Hack: we need to include 'main' arm target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/contrib/llvm/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp b/contrib/llvm/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp index 41c1dd3..3dafc61 100644 --- a/contrib/llvm/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp +++ b/contrib/llvm/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp @@ -1,4 +1,4 @@ -//===-- MipsInstPrinter.cpp - Convert Mips MCInst to assembly syntax --------===// +//===-- MipsInstPrinter.cpp - Convert Mips MCInst to assembly syntax ------===// // // The LLVM Compiler Infrastructure // @@ -69,8 +69,10 @@ void MipsInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const { OS << '$' << LowercaseString(getRegisterName(RegNo)); } -void MipsInstPrinter::printInst(const MCInst *MI, raw_ostream &O) { +void MipsInstPrinter::printInst(const MCInst *MI, raw_ostream &O, + StringRef Annot) { printInstruction(MI, O); + printAnnotation(O, Annot); } void MipsInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, diff --git a/contrib/llvm/lib/Target/Mips/InstPrinter/MipsInstPrinter.h b/contrib/llvm/lib/Target/Mips/InstPrinter/MipsInstPrinter.h index 680208e..5c11165 100644 --- a/contrib/llvm/lib/Target/Mips/InstPrinter/MipsInstPrinter.h +++ b/contrib/llvm/lib/Target/Mips/InstPrinter/MipsInstPrinter.h @@ -1,4 +1,4 @@ -//===-- MipsInstPrinter.h - Convert Mips MCInst to assembly syntax ----------===// +//===-- MipsInstPrinter.h - Convert Mips MCInst to assembly syntax --------===// // // The LLVM Compiler Infrastructure // @@ -86,7 +86,7 @@ public: virtual StringRef getOpcodeName(unsigned Opcode) const; virtual void printRegName(raw_ostream &OS, unsigned RegNo) const; - virtual void printInst(const MCInst *MI, raw_ostream &O); + virtual void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot); private: void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O); diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/CMakeLists.txt b/contrib/llvm/lib/Target/Mips/MCTargetDesc/CMakeLists.txt deleted file mode 100644 index 97de75d..0000000 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -add_llvm_library(LLVMMipsDesc - MipsMCTargetDesc.cpp - MipsMCAsmInfo.cpp - ) diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/Makefile b/contrib/llvm/lib/Target/Mips/MCTargetDesc/Makefile deleted file mode 100644 index 7fe2086..0000000 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===- lib/Target/Mips/TargetDesc/Makefile -----------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../../.. -LIBRARYNAME = LLVMMipsDesc - -# Hack: we need to include 'main' target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp new file mode 100644 index 0000000..f190ec4 --- /dev/null +++ b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp @@ -0,0 +1,117 @@ +#include "MCTargetDesc/MipsMCTargetDesc.h" +#include "llvm/ADT/Twine.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCDirectives.h" +#include "llvm/MC/MCELFObjectWriter.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCMachObjectWriter.h" +#include "llvm/MC/MCObjectWriter.h" +#include "llvm/MC/MCSectionELF.h" +#include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MCAsmBackend.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Object/MachOFormat.h" +#include "llvm/Support/ELF.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +namespace { +class MipsELFObjectWriter : public MCELFObjectTargetWriter { +public: + MipsELFObjectWriter(bool is64Bit, Triple::OSType OSType, uint16_t EMachine, + bool HasRelocationAddend) + : MCELFObjectTargetWriter(is64Bit, OSType, EMachine, + HasRelocationAddend) {} +}; + +class MipsAsmBackend : public MCAsmBackend { +public: + MipsAsmBackend(const Target &T) + : MCAsmBackend() {} + + unsigned getNumFixupKinds() const { + return 1; //tbd + } + + /// ApplyFixup - Apply the \arg Value for given \arg Fixup into the provided + /// data fragment, at the offset specified by the fixup and following the + /// fixup kind as appropriate. + void ApplyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, + uint64_t Value) const { + } + + /// @name Target Relaxation Interfaces + /// @{ + + /// MayNeedRelaxation - Check whether the given instruction may need + /// relaxation. + /// + /// \param Inst - The instruction to test. + bool MayNeedRelaxation(const MCInst &Inst) const { + return false; + } + + /// RelaxInstruction - Relax the instruction in the given fragment to the next + /// wider instruction. + /// + /// \param Inst - The instruction to relax, which may be the same as the + /// output. + /// \parm Res [output] - On return, the relaxed instruction. + void RelaxInstruction(const MCInst &Inst, MCInst &Res) const { + } + + /// @} + + /// WriteNopData - Write an (optimal) nop sequence of Count bytes to the given + /// output. If the target cannot generate such a sequence, it should return an + /// error. + /// + /// \return - True on success. + bool WriteNopData(uint64_t Count, MCObjectWriter *OW) const { + return false; + } +}; + +class MipsEB_AsmBackend : public MipsAsmBackend { +public: + Triple::OSType OSType; + + MipsEB_AsmBackend(const Target &T, Triple::OSType _OSType) + : MipsAsmBackend(T), OSType(_OSType) {} + + MCObjectWriter *createObjectWriter(raw_ostream &OS) const { + return createELFObjectWriter(createELFObjectTargetWriter(), + OS, /*IsLittleEndian*/ false); + } + + MCELFObjectTargetWriter *createELFObjectTargetWriter() const { + return new MipsELFObjectWriter(false, OSType, ELF::EM_MIPS, false); + } +}; + +class MipsEL_AsmBackend : public MipsAsmBackend { +public: + Triple::OSType OSType; + + MipsEL_AsmBackend(const Target &T, Triple::OSType _OSType) + : MipsAsmBackend(T), OSType(_OSType) {} + + MCObjectWriter *createObjectWriter(raw_ostream &OS) const { + return createELFObjectWriter(createELFObjectTargetWriter(), + OS, /*IsLittleEndian*/ true); + } + + MCELFObjectTargetWriter *createELFObjectTargetWriter() const { + return new MipsELFObjectWriter(false, OSType, ELF::EM_MIPS, false); + } +}; +} + +MCAsmBackend *llvm::createMipsAsmBackend(const Target &T, StringRef TT) { + Triple TheTriple(TT); + + // just return little endian for now + // + return new MipsEL_AsmBackend(T, Triple(TT).getOS()); +} diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h new file mode 100644 index 0000000..f7a6fa9 --- /dev/null +++ b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h @@ -0,0 +1,113 @@ +//===-- MipsBaseInfo.h - Top level definitions for ARM ------- --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains small standalone helper functions and enum definitions for +// the Mips target useful for the compiler back-end and the MC libraries. +// +//===----------------------------------------------------------------------===// +#ifndef MIPSBASEINFO_H +#define MIPSBASEINFO_H + +#include "MipsMCTargetDesc.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/ErrorHandling.h" + +namespace llvm { +/// getMipsRegisterNumbering - Given the enum value for some register, +/// return the number that it corresponds to. +inline static unsigned getMipsRegisterNumbering(unsigned RegEnum) +{ + switch (RegEnum) { + case Mips::ZERO: case Mips::ZERO_64: case Mips::F0: case Mips::D0_64: + case Mips::D0: + return 0; + case Mips::AT: case Mips::AT_64: case Mips::F1: case Mips::D1_64: + return 1; + case Mips::V0: case Mips::V0_64: case Mips::F2: case Mips::D2_64: + case Mips::D1: + return 2; + case Mips::V1: case Mips::V1_64: case Mips::F3: case Mips::D3_64: + return 3; + case Mips::A0: case Mips::A0_64: case Mips::F4: case Mips::D4_64: + case Mips::D2: + return 4; + case Mips::A1: case Mips::A1_64: case Mips::F5: case Mips::D5_64: + return 5; + case Mips::A2: case Mips::A2_64: case Mips::F6: case Mips::D6_64: + case Mips::D3: + return 6; + case Mips::A3: case Mips::A3_64: case Mips::F7: case Mips::D7_64: + return 7; + case Mips::T0: case Mips::T0_64: case Mips::F8: case Mips::D8_64: + case Mips::D4: + return 8; + case Mips::T1: case Mips::T1_64: case Mips::F9: case Mips::D9_64: + return 9; + case Mips::T2: case Mips::T2_64: case Mips::F10: case Mips::D10_64: + case Mips::D5: + return 10; + case Mips::T3: case Mips::T3_64: case Mips::F11: case Mips::D11_64: + return 11; + case Mips::T4: case Mips::T4_64: case Mips::F12: case Mips::D12_64: + case Mips::D6: + return 12; + case Mips::T5: case Mips::T5_64: case Mips::F13: case Mips::D13_64: + return 13; + case Mips::T6: case Mips::T6_64: case Mips::F14: case Mips::D14_64: + case Mips::D7: + return 14; + case Mips::T7: case Mips::T7_64: case Mips::F15: case Mips::D15_64: + return 15; + case Mips::S0: case Mips::S0_64: case Mips::F16: case Mips::D16_64: + case Mips::D8: + return 16; + case Mips::S1: case Mips::S1_64: case Mips::F17: case Mips::D17_64: + return 17; + case Mips::S2: case Mips::S2_64: case Mips::F18: case Mips::D18_64: + case Mips::D9: + return 18; + case Mips::S3: case Mips::S3_64: case Mips::F19: case Mips::D19_64: + return 19; + case Mips::S4: case Mips::S4_64: case Mips::F20: case Mips::D20_64: + case Mips::D10: + return 20; + case Mips::S5: case Mips::S5_64: case Mips::F21: case Mips::D21_64: + return 21; + case Mips::S6: case Mips::S6_64: case Mips::F22: case Mips::D22_64: + case Mips::D11: + return 22; + case Mips::S7: case Mips::S7_64: case Mips::F23: case Mips::D23_64: + return 23; + case Mips::T8: case Mips::T8_64: case Mips::F24: case Mips::D24_64: + case Mips::D12: + return 24; + case Mips::T9: case Mips::T9_64: case Mips::F25: case Mips::D25_64: + return 25; + case Mips::K0: case Mips::K0_64: case Mips::F26: case Mips::D26_64: + case Mips::D13: + return 26; + case Mips::K1: case Mips::K1_64: case Mips::F27: case Mips::D27_64: + return 27; + case Mips::GP: case Mips::GP_64: case Mips::F28: case Mips::D28_64: + case Mips::D14: + return 28; + case Mips::SP: case Mips::SP_64: case Mips::F29: case Mips::D29_64: + return 29; + case Mips::FP: case Mips::FP_64: case Mips::F30: case Mips::D30_64: + case Mips::D15: + return 30; + case Mips::RA: case Mips::RA_64: case Mips::F31: case Mips::D31_64: + return 31; + default: llvm_unreachable("Unknown register number!"); + } + return 0; // Not reached +} +} + +#endif diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h new file mode 100644 index 0000000..8b099ea --- /dev/null +++ b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h @@ -0,0 +1,90 @@ +#ifndef LLVM_Mips_MipsFIXUPKINDS_H +#define LLVM_Mips_MipsFIXUPKINDS_H + +//===-- Mips/MipsFixupKinds.h - Mips Specific Fixup Entries --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + + +#include "llvm/MC/MCFixup.h" + +namespace llvm { +namespace Mips { + enum Fixups { + // fixup_Mips_xxx - R_MIPS_NONE + fixup_Mips_NONE = FirstTargetFixupKind, + + // fixup_Mips_xxx - R_MIPS_16. + fixup_Mips_16, + + // fixup_Mips_xxx - R_MIPS_32. + fixup_Mips_32, + + // fixup_Mips_xxx - R_MIPS_REL32. + fixup_Mips_REL32, + + // fixup_Mips_xxx - R_MIPS_26. + fixup_Mips_26, + + // fixup_Mips_xxx - R_MIPS_HI16. + fixup_Mips_HI16, + + // fixup_Mips_xxx - R_MIPS_LO16. + fixup_Mips_LO16, + + // fixup_Mips_xxx - R_MIPS_GPREL16. + fixup_Mips_GPREL16, + + // fixup_Mips_xxx - R_MIPS_LITERAL. + fixup_Mips_LITERAL, + + // fixup_Mips_xxx - R_MIPS_GOT16. + fixup_Mips_GOT16, + + // fixup_Mips_xxx - R_MIPS_PC16. + fixup_Mips_PC16, + + // fixup_Mips_xxx - R_MIPS_CALL16. + fixup_Mips_CALL16, + + // fixup_Mips_xxx - R_MIPS_GPREL32. + fixup_Mips_GPREL32, + + // fixup_Mips_xxx - R_MIPS_SHIFT5. + fixup_Mips_SHIFT5, + + // fixup_Mips_xxx - R_MIPS_SHIFT6. + fixup_Mips_SHIFT6, + + // fixup_Mips_xxx - R_MIPS_64. + fixup_Mips_64, + + // fixup_Mips_xxx - R_MIPS_TLS_GD. + fixup_Mips_TLSGD, + + // fixup_Mips_xxx - R_MIPS_TLS_GOTTPREL. + fixup_Mips_GOTTPREL, + + // fixup_Mips_xxx - R_MIPS_TLS_TPREL_HI16. + fixup_Mips_TPREL_HI, + + // fixup_Mips_xxx - R_MIPS_TLS_TPREL_LO16. + fixup_Mips_TPREL_LO, + + // fixup_Mips_xxx - yyy. // This should become R_MIPS_PC16 + fixup_Mips_Branch_PCRel, + + // Marker + LastTargetFixupKind, + NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind + }; +} // namespace llvm +} // namespace Mips + + +#endif /* LLVM_Mips_MipsFIXUPKINDS_H */ diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp index 5d92425..71ae804 100644 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp +++ b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp @@ -18,7 +18,8 @@ using namespace llvm; MipsMCAsmInfo::MipsMCAsmInfo(const Target &T, StringRef TT) { Triple TheTriple(TT); - if (TheTriple.getArch() == Triple::mips) + if ((TheTriple.getArch() == Triple::mips) || + (TheTriple.getArch() == Triple::mips64)) IsLittleEndian = false; AlignmentIsInBytes = false; diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp new file mode 100644 index 0000000..d66de23 --- /dev/null +++ b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp @@ -0,0 +1,52 @@ +//===-- MipsMCCodeEmitter.cpp - Convert Mips code to machine code ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the MipsMCCodeEmitter class. +// +//===----------------------------------------------------------------------===// +// +#define DEBUG_TYPE "mccodeemitter" +#include "llvm/MC/MCCodeEmitter.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/raw_ostream.h" +#include "MCTargetDesc/MipsMCTargetDesc.h" + +using namespace llvm; + +namespace { +class MipsMCCodeEmitter : public MCCodeEmitter { + MipsMCCodeEmitter(const MipsMCCodeEmitter &); // DO NOT IMPLEMENT + void operator=(const MipsMCCodeEmitter &); // DO NOT IMPLEMENT + const MCInstrInfo &MCII; + const MCSubtargetInfo &STI; + +public: + MipsMCCodeEmitter(const MCInstrInfo &mcii, const MCSubtargetInfo &sti, + MCContext &ctx) + : MCII(mcii), STI(sti) {} + + ~MipsMCCodeEmitter() {} + + void EncodeInstruction(const MCInst &MI, raw_ostream &OS, + SmallVectorImpl<MCFixup> &Fixups) const { + } +}; // class MipsMCCodeEmitter +} // namespace + +MCCodeEmitter *llvm::createMipsMCCodeEmitter(const MCInstrInfo &MCII, + const MCSubtargetInfo &STI, + MCContext &Ctx) { + return new MipsMCCodeEmitter(MCII, STI, Ctx); +} diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp index 06f0d0b..1f9e3dd 100644 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp +++ b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp @@ -13,10 +13,14 @@ #include "MipsMCTargetDesc.h" #include "MipsMCAsmInfo.h" +#include "InstPrinter/MipsInstPrinter.h" +#include "llvm/MC/MachineLocation.h" +#include "llvm/MC/MCCodeGenInfo.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSubtargetInfo.h" -#include "llvm/Target/TargetRegistry.h" +#include "llvm/Support/TargetRegistry.h" #define GET_INSTRINFO_MC_DESC #include "MipsGenInstrInfo.inc" @@ -35,11 +39,12 @@ static MCInstrInfo *createMipsMCInstrInfo() { return X; } -extern "C" void LLVMInitializeMipsMCInstrInfo() { - TargetRegistry::RegisterMCInstrInfo(TheMipsTarget, createMipsMCInstrInfo); +static MCRegisterInfo *createMipsMCRegisterInfo(StringRef TT) { + MCRegisterInfo *X = new MCRegisterInfo(); + InitMipsMCRegisterInfo(X, Mips::RA); + return X; } - static MCSubtargetInfo *createMipsMCSubtargetInfo(StringRef TT, StringRef CPU, StringRef FS) { MCSubtargetInfo *X = new MCSubtargetInfo(); @@ -47,12 +52,111 @@ static MCSubtargetInfo *createMipsMCSubtargetInfo(StringRef TT, StringRef CPU, return X; } -extern "C" void LLVMInitializeMipsMCSubtargetInfo() { +static MCAsmInfo *createMipsMCAsmInfo(const Target &T, StringRef TT) { + MCAsmInfo *MAI = new MipsMCAsmInfo(T, TT); + + MachineLocation Dst(MachineLocation::VirtualFP); + MachineLocation Src(Mips::SP, 0); + MAI->addInitialFrameState(0, Dst, Src); + + return MAI; +} + +static MCCodeGenInfo *createMipsMCCodeGenInfo(StringRef TT, Reloc::Model RM, + CodeModel::Model CM) { + MCCodeGenInfo *X = new MCCodeGenInfo(); + if (RM == Reloc::Default) + RM = Reloc::PIC_; + X->InitMCCodeGenInfo(RM, CM); + return X; +} + +static MCInstPrinter *createMipsMCInstPrinter(const Target &T, + unsigned SyntaxVariant, + const MCAsmInfo &MAI, + const MCSubtargetInfo &STI) { + return new MipsInstPrinter(MAI); +} + +static MCStreamer *createMCStreamer(const Target &T, StringRef TT, + MCContext &Ctx, MCAsmBackend &MAB, + raw_ostream &_OS, + MCCodeEmitter *_Emitter, + bool RelaxAll, + bool NoExecStack) { + Triple TheTriple(TT); + + return createELFStreamer(Ctx, MAB, _OS, _Emitter, RelaxAll, NoExecStack); +} + +extern "C" void LLVMInitializeMipsTargetMC() { + // Register the MC asm info. + RegisterMCAsmInfoFn X(TheMipsTarget, createMipsMCAsmInfo); + RegisterMCAsmInfoFn Y(TheMipselTarget, createMipsMCAsmInfo); + RegisterMCAsmInfoFn A(TheMips64Target, createMipsMCAsmInfo); + RegisterMCAsmInfoFn B(TheMips64elTarget, createMipsMCAsmInfo); + + // Register the MC codegen info. + TargetRegistry::RegisterMCCodeGenInfo(TheMipsTarget, + createMipsMCCodeGenInfo); + TargetRegistry::RegisterMCCodeGenInfo(TheMipselTarget, + createMipsMCCodeGenInfo); + TargetRegistry::RegisterMCCodeGenInfo(TheMips64Target, + createMipsMCCodeGenInfo); + TargetRegistry::RegisterMCCodeGenInfo(TheMips64elTarget, + createMipsMCCodeGenInfo); + + // Register the MC instruction info. + TargetRegistry::RegisterMCInstrInfo(TheMipsTarget, createMipsMCInstrInfo); + TargetRegistry::RegisterMCInstrInfo(TheMipselTarget, createMipsMCInstrInfo); + TargetRegistry::RegisterMCInstrInfo(TheMips64Target, createMipsMCInstrInfo); + TargetRegistry::RegisterMCInstrInfo(TheMips64elTarget, createMipsMCInstrInfo); + + // Register the MC register info. + TargetRegistry::RegisterMCRegInfo(TheMipsTarget, createMipsMCRegisterInfo); + TargetRegistry::RegisterMCRegInfo(TheMipselTarget, createMipsMCRegisterInfo); + TargetRegistry::RegisterMCRegInfo(TheMips64Target, createMipsMCRegisterInfo); + TargetRegistry::RegisterMCRegInfo(TheMips64elTarget, + createMipsMCRegisterInfo); + + // Register the MC Code Emitter + TargetRegistry::RegisterMCCodeEmitter(TheMipsTarget, createMipsMCCodeEmitter); + TargetRegistry::RegisterMCCodeEmitter(TheMipselTarget, + createMipsMCCodeEmitter); + TargetRegistry::RegisterMCCodeEmitter(TheMips64Target, + createMipsMCCodeEmitter); + TargetRegistry::RegisterMCCodeEmitter(TheMips64elTarget, + createMipsMCCodeEmitter); + + // Register the object streamer. + TargetRegistry::RegisterMCObjectStreamer(TheMipsTarget, createMCStreamer); + TargetRegistry::RegisterMCObjectStreamer(TheMipselTarget, createMCStreamer); + TargetRegistry::RegisterMCObjectStreamer(TheMips64Target, createMCStreamer); + TargetRegistry::RegisterMCObjectStreamer(TheMips64elTarget, createMCStreamer); + + // Register the asm backend. + TargetRegistry::RegisterMCAsmBackend(TheMipsTarget, createMipsAsmBackend); + TargetRegistry::RegisterMCAsmBackend(TheMipselTarget, createMipsAsmBackend); + TargetRegistry::RegisterMCAsmBackend(TheMips64Target, createMipsAsmBackend); + TargetRegistry::RegisterMCAsmBackend(TheMips64elTarget, createMipsAsmBackend); + + // Register the MC subtarget info. TargetRegistry::RegisterMCSubtargetInfo(TheMipsTarget, createMipsMCSubtargetInfo); -} + TargetRegistry::RegisterMCSubtargetInfo(TheMipselTarget, + createMipsMCSubtargetInfo); + TargetRegistry::RegisterMCSubtargetInfo(TheMips64Target, + createMipsMCSubtargetInfo); + TargetRegistry::RegisterMCSubtargetInfo(TheMips64elTarget, + createMipsMCSubtargetInfo); -extern "C" void LLVMInitializeMipsMCAsmInfo() { - RegisterMCAsmInfo<MipsMCAsmInfo> X(TheMipsTarget); - RegisterMCAsmInfo<MipsMCAsmInfo> Y(TheMipselTarget); + // Register the MCInstPrinter. + TargetRegistry::RegisterMCInstPrinter(TheMipsTarget, + createMipsMCInstPrinter); + TargetRegistry::RegisterMCInstPrinter(TheMipselTarget, + createMipsMCInstPrinter); + TargetRegistry::RegisterMCInstPrinter(TheMips64Target, + createMipsMCInstPrinter); + TargetRegistry::RegisterMCInstPrinter(TheMips64elTarget, + createMipsMCInstPrinter); } diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h index 3d18f11..7a0042a 100644 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h +++ b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h @@ -1,4 +1,4 @@ -//===-- AlphaMCTargetDesc.h - Alpha Target Descriptions ---------*- C++ -*-===// +//===-- MipsMCTargetDesc.h - Mips Target Descriptions -----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,21 +7,32 @@ // //===----------------------------------------------------------------------===// // -// This file provides Alpha specific target descriptions. +// This file provides Mips specific target descriptions. // //===----------------------------------------------------------------------===// -#ifndef ALPHAMCTARGETDESC_H -#define ALPHAMCTARGETDESC_H +#ifndef MIPSMCTARGETDESC_H +#define MIPSMCTARGETDESC_H namespace llvm { +class MCAsmBackend; +class MCInstrInfo; +class MCCodeEmitter; +class MCContext; class MCSubtargetInfo; -class Target; class StringRef; +class Target; extern Target TheMipsTarget; extern Target TheMipselTarget; +extern Target TheMips64Target; +extern Target TheMips64elTarget; + +MCCodeEmitter *createMipsMCCodeEmitter(const MCInstrInfo &MCII, + const MCSubtargetInfo &STI, + MCContext &Ctx); +MCAsmBackend *createMipsAsmBackend(const Target &T, StringRef TT); } // End llvm namespace // Defines symbolic names for Mips registers. This defines a mapping from diff --git a/contrib/llvm/lib/Target/Mips/Mips.h b/contrib/llvm/lib/Target/Mips/Mips.h index 984b5ad..bacecf2 100644 --- a/contrib/llvm/lib/Target/Mips/Mips.h +++ b/contrib/llvm/lib/Target/Mips/Mips.h @@ -29,6 +29,9 @@ namespace llvm { FunctionPass *createMipsExpandPseudoPass(MipsTargetMachine &TM); FunctionPass *createMipsEmitGPRestorePass(MipsTargetMachine &TM); + FunctionPass *createMipsJITCodeEmitterPass(MipsTargetMachine &TM, + JITCodeEmitter &JCE); + } // end namespace llvm; #endif diff --git a/contrib/llvm/lib/Target/Mips/Mips.td b/contrib/llvm/lib/Target/Mips/Mips.td index 433cd57..39c2c16 100644 --- a/contrib/llvm/lib/Target/Mips/Mips.td +++ b/contrib/llvm/lib/Target/Mips/Mips.td @@ -38,6 +38,10 @@ def FeatureSingleFloat : SubtargetFeature<"single-float", "IsSingleFloat", "true", "Only supports single precision float">; def FeatureO32 : SubtargetFeature<"o32", "MipsABI", "O32", "Enable o32 ABI">; +def FeatureN32 : SubtargetFeature<"n32", "MipsABI", "N32", + "Enable n32 ABI">; +def FeatureN64 : SubtargetFeature<"n64", "MipsABI", "N64", + "Enable n64 ABI">; def FeatureEABI : SubtargetFeature<"eabi", "MipsABI", "EABI", "Enable eabi ABI">; def FeatureVFPU : SubtargetFeature<"vfpu", "HasVFPU", @@ -54,16 +58,19 @@ def FeatureSwap : SubtargetFeature<"swap", "HasSwap", "true", "Enable 'byte/half swap' instructions.">; def FeatureBitCount : SubtargetFeature<"bitcount", "HasBitCount", "true", "Enable 'count leading bits' instructions.">; -def FeatureMips1 : SubtargetFeature<"mips1", "MipsArchVersion", "Mips1", - "Mips1 ISA Support">; -def FeatureMips2 : SubtargetFeature<"mips2", "MipsArchVersion", "Mips2", - "Mips2 ISA Support">; def FeatureMips32 : SubtargetFeature<"mips32", "MipsArchVersion", "Mips32", "Mips32 ISA Support", [FeatureCondMov, FeatureBitCount]>; def FeatureMips32r2 : SubtargetFeature<"mips32r2", "MipsArchVersion", "Mips32r2", "Mips32r2 ISA Support", [FeatureMips32, FeatureSEInReg]>; +def FeatureMips64 : SubtargetFeature<"mips64", "MipsArchVersion", + "Mips64", "Mips64 ISA Support", + [FeatureGP64Bit, FeatureFP64Bit, + FeatureMips32]>; +def FeatureMips64r2 : SubtargetFeature<"mips64r2", "MipsArchVersion", + "Mips64r2", "Mips64r2 ISA Support", + [FeatureMips64, FeatureMips32r2]>; //===----------------------------------------------------------------------===// // Mips processors supported. @@ -72,21 +79,10 @@ def FeatureMips32r2 : SubtargetFeature<"mips32r2", "MipsArchVersion", class Proc<string Name, list<SubtargetFeature> Features> : Processor<Name, MipsGenericItineraries, Features>; -def : Proc<"mips1", [FeatureMips1]>; -def : Proc<"r2000", [FeatureMips1]>; -def : Proc<"r3000", [FeatureMips1]>; - -def : Proc<"mips2", [FeatureMips2]>; -def : Proc<"r6000", [FeatureMips2]>; - +def : Proc<"mips32r1", [FeatureMips32]>; def : Proc<"4ke", [FeatureMips32r2]>; - -// Allegrex is a 32bit subset of r4000, both for integer and fp registers, -// but much more similar to Mips2 than Mips3. It also contains some of -// Mips32/Mips32r2 instructions and a custom vector fpu processor. -def : Proc<"allegrex", [FeatureMips2, FeatureSingleFloat, FeatureEABI, - FeatureVFPU, FeatureSEInReg, FeatureCondMov, FeatureMulDivAdd, - FeatureMinMax, FeatureSwap, FeatureBitCount]>; +def : Proc<"mips64r1", [FeatureMips64]>; +def : Proc<"mips64r2", [FeatureMips64r2]>; def MipsAsmWriter : AsmWriter { string AsmWriterClassName = "InstPrinter"; diff --git a/contrib/llvm/lib/Target/Mips/Mips64InstrInfo.td b/contrib/llvm/lib/Target/Mips/Mips64InstrInfo.td new file mode 100644 index 0000000..49b0223 --- /dev/null +++ b/contrib/llvm/lib/Target/Mips/Mips64InstrInfo.td @@ -0,0 +1,214 @@ +//===- Mips64InstrInfo.td - Mips64 Instruction Information -*- 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 Mips64 instructions. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Mips Operand, Complex Patterns and Transformations Definitions. +//===----------------------------------------------------------------------===// + +// Instruction operand types +def shamt_64 : Operand<i64>; + +// Unsigned Operand +def uimm16_64 : Operand<i64> { + let PrintMethod = "printUnsignedImm"; +} + +// Transformation Function - get Imm - 32. +def Subtract32 : SDNodeXForm<imm, [{ + return getI32Imm((unsigned)N->getZExtValue() - 32); +}]>; + +// imm32_63 predicate - True if imm is in range [32, 63]. +def imm32_63 : ImmLeaf<i64, + [{return (int32_t)Imm >= 32 && (int32_t)Imm < 64;}], + Subtract32>; + +//===----------------------------------------------------------------------===// +// Instructions specific format +//===----------------------------------------------------------------------===// +// Shifts +class LogicR_shift_rotate_imm64<bits<6> func, bits<5> _rs, string instr_asm, + SDNode OpNode, PatFrag PF>: + FR<0x00, func, (outs CPU64Regs:$dst), (ins CPU64Regs:$b, shamt_64:$c), + !strconcat(instr_asm, "\t$dst, $b, $c"), + [(set CPU64Regs:$dst, (OpNode CPU64Regs:$b, (i64 PF:$c)))], + IIAlu> { + let rs = _rs; +} + +class LogicR_shift_rotate_reg64<bits<6> func, bits<5> _shamt, string instr_asm, + SDNode OpNode>: + FR<0x00, func, (outs CPU64Regs:$dst), (ins CPU64Regs:$c, CPU64Regs:$b), + !strconcat(instr_asm, "\t$dst, $b, $c"), + [(set CPU64Regs:$dst, (OpNode CPU64Regs:$b, CPU64Regs:$c))], IIAlu> { + let shamt = _shamt; +} + +// Mul, Div +let Defs = [HI64, LO64] in { + let isCommutable = 1 in + class Mul64<bits<6> func, string instr_asm, InstrItinClass itin>: + FR<0x00, func, (outs), (ins CPU64Regs:$a, CPU64Regs:$b), + !strconcat(instr_asm, "\t$a, $b"), [], itin>; + + class Div64<SDNode op, bits<6> func, string instr_asm, InstrItinClass itin>: + FR<0x00, func, (outs), (ins CPU64Regs:$a, CPU64Regs:$b), + !strconcat(instr_asm, "\t$$zero, $a, $b"), + [(op CPU64Regs:$a, CPU64Regs:$b)], itin>; +} + +// Move from Hi/Lo +let shamt = 0 in { +let rs = 0, rt = 0 in +class MoveFromLOHI64<bits<6> func, string instr_asm>: + FR<0x00, func, (outs CPU64Regs:$dst), (ins), + !strconcat(instr_asm, "\t$dst"), [], IIHiLo>; + +let rt = 0, rd = 0 in +class MoveToLOHI64<bits<6> func, string instr_asm>: + FR<0x00, func, (outs), (ins CPU64Regs:$src), + !strconcat(instr_asm, "\t$src"), [], IIHiLo>; +} + +// Count Leading Ones/Zeros in Word +class CountLeading64<bits<6> func, string instr_asm, list<dag> pattern>: + FR<0x1c, func, (outs CPU64Regs:$dst), (ins CPU64Regs:$src), + !strconcat(instr_asm, "\t$dst, $src"), pattern, IIAlu>, + Requires<[HasBitCount]> { + let shamt = 0; + let rt = rd; +} + +//===----------------------------------------------------------------------===// +// Instruction definition +//===----------------------------------------------------------------------===// + +/// Arithmetic Instructions (ALU Immediate) +def DADDiu : ArithLogicI<0x19, "daddiu", add, simm16_64, immSExt16, + CPU64Regs>; +def DANDi : ArithLogicI<0x0c, "andi", and, uimm16_64, immZExt16, CPU64Regs>; +def SLTi64 : SetCC_I<0x0a, "slti", setlt, simm16_64, immSExt16, CPU64Regs>; +def SLTiu64 : SetCC_I<0x0b, "sltiu", setult, simm16_64, immSExt16, CPU64Regs>; +def ORi64 : ArithLogicI<0x0d, "ori", or, uimm16_64, immZExt16, CPU64Regs>; +def XORi64 : ArithLogicI<0x0e, "xori", xor, uimm16_64, immZExt16, CPU64Regs>; + +/// Arithmetic Instructions (3-Operand, R-Type) +def DADDu : ArithLogicR<0x00, 0x2d, "daddu", add, IIAlu, CPU64Regs, 1>; +def DSUBu : ArithLogicR<0x00, 0x2f, "dsubu", sub, IIAlu, CPU64Regs>; +def SLT64 : SetCC_R<0x00, 0x2a, "slt", setlt, CPU64Regs>; +def SLTu64 : SetCC_R<0x00, 0x2b, "sltu", setult, CPU64Regs>; +def AND64 : ArithLogicR<0x00, 0x24, "and", and, IIAlu, CPU64Regs, 1>; +def OR64 : ArithLogicR<0x00, 0x25, "or", or, IIAlu, CPU64Regs, 1>; +def XOR64 : ArithLogicR<0x00, 0x26, "xor", xor, IIAlu, CPU64Regs, 1>; +def NOR64 : LogicNOR<0x00, 0x27, "nor", CPU64Regs>; + +/// Shift Instructions +def DSLL : LogicR_shift_rotate_imm64<0x38, 0x00, "dsll", shl, immZExt5>; +def DSRL : LogicR_shift_rotate_imm64<0x3a, 0x00, "dsrl", srl, immZExt5>; +def DSRA : LogicR_shift_rotate_imm64<0x3b, 0x00, "dsra", sra, immZExt5>; +def DSLL32 : LogicR_shift_rotate_imm64<0x3c, 0x00, "dsll32", shl, imm32_63>; +def DSRL32 : LogicR_shift_rotate_imm64<0x3e, 0x00, "dsrl32", srl, imm32_63>; +def DSRA32 : LogicR_shift_rotate_imm64<0x3f, 0x00, "dsra32", sra, imm32_63>; +def DSLLV : LogicR_shift_rotate_reg64<0x24, 0x00, "dsllv", shl>; +def DSRLV : LogicR_shift_rotate_reg64<0x26, 0x00, "dsrlv", srl>; +def DSRAV : LogicR_shift_rotate_reg64<0x27, 0x00, "dsrav", sra>; + +// Rotate Instructions +let Predicates = [HasMips64r2] in { + def DROTR : LogicR_shift_rotate_imm64<0x3a, 0x01, "drotr", rotr, immZExt5>; + def DROTR32 : LogicR_shift_rotate_imm64<0x3e, 0x01, "drotr32", rotr, + imm32_63>; + def DROTRV : LogicR_shift_rotate_reg64<0x16, 0x01, "drotrv", rotr>; +} + +/// Load and Store Instructions +/// aligned +defm LB64 : LoadM64<0x20, "lb", sextloadi8>; +defm LBu64 : LoadM64<0x24, "lbu", zextloadi8>; +defm LH64 : LoadM64<0x21, "lh", sextloadi16_a>; +defm LHu64 : LoadM64<0x25, "lhu", zextloadi16_a>; +defm LW64 : LoadM64<0x23, "lw", sextloadi32_a>; +defm LWu64 : LoadM64<0x27, "lwu", zextloadi32_a>; +defm SB64 : StoreM64<0x28, "sb", truncstorei8>; +defm SH64 : StoreM64<0x29, "sh", truncstorei16_a>; +defm SW64 : StoreM64<0x2b, "sw", truncstorei32_a>; +defm LD : LoadM64<0x37, "ld", load_a>; +defm SD : StoreM64<0x3f, "sd", store_a>; + +/// unaligned +defm ULH64 : LoadM64<0x21, "ulh", sextloadi16_u, 1>; +defm ULHu64 : LoadM64<0x25, "ulhu", zextloadi16_u, 1>; +defm ULW64 : LoadM64<0x23, "ulw", sextloadi32_u, 1>; +defm USH64 : StoreM64<0x29, "ush", truncstorei16_u, 1>; +defm USW64 : StoreM64<0x2b, "usw", truncstorei32_u, 1>; +defm ULD : LoadM64<0x37, "uld", load_u, 1>; +defm USD : StoreM64<0x3f, "usd", store_u, 1>; + +/// Jump and Branch Instructions +def BEQ64 : CBranch<0x04, "beq", seteq, CPU64Regs>; +def BNE64 : CBranch<0x05, "bne", setne, CPU64Regs>; +def BGEZ64 : CBranchZero<0x01, 1, "bgez", setge, CPU64Regs>; +def BGTZ64 : CBranchZero<0x07, 0, "bgtz", setgt, CPU64Regs>; +def BLEZ64 : CBranchZero<0x07, 0, "blez", setle, CPU64Regs>; +def BLTZ64 : CBranchZero<0x01, 0, "bltz", setlt, CPU64Regs>; + +/// Multiply and Divide Instructions. +def DMULT : Mul64<0x1c, "dmult", IIImul>; +def DMULTu : Mul64<0x1d, "dmultu", IIImul>; +def DSDIV : Div64<MipsDivRem, 0x1e, "ddiv", IIIdiv>; +def DUDIV : Div64<MipsDivRemU, 0x1f, "ddivu", IIIdiv>; + +let Defs = [HI64] in + def MTHI64 : MoveToLOHI64<0x11, "mthi">; +let Defs = [LO64] in + def MTLO64 : MoveToLOHI64<0x13, "mtlo">; + +let Uses = [HI64] in + def MFHI64 : MoveFromLOHI64<0x10, "mfhi">; +let Uses = [LO64] in + def MFLO64 : MoveFromLOHI64<0x12, "mflo">; + +/// Count Leading +def DCLZ : CountLeading64<0x24, "dclz", + [(set CPU64Regs:$dst, (ctlz CPU64Regs:$src))]>; +def DCLO : CountLeading64<0x25, "dclo", + [(set CPU64Regs:$dst, (ctlz (not CPU64Regs:$src)))]>; + +//===----------------------------------------------------------------------===// +// Arbitrary patterns that map to one or more instructions +//===----------------------------------------------------------------------===// + +// Small immediates +def : Pat<(i64 immSExt16:$in), + (DADDiu ZERO_64, imm:$in)>; +def : Pat<(i64 immZExt16:$in), + (ORi64 ZERO_64, imm:$in)>; + +// zextloadi32_u +def : Pat<(zextloadi32_u addr:$a), (DSRL (DSLL (ULW64_P8 addr:$a), 32), 32)>, + Requires<[IsN64]>; +def : Pat<(zextloadi32_u addr:$a), (DSRL (DSLL (ULW64 addr:$a), 32), 32)>, + Requires<[NotN64]>; + +// hi/lo relocs +def : Pat<(i64 (MipsLo tglobaladdr:$in)), (DADDiu ZERO_64, tglobaladdr:$in)>; + +defm : BrcondPats<CPU64Regs, BEQ64, BNE64, SLT64, SLTu64, SLTi64, SLTiu64, + ZERO_64>; + +// setcc patterns +defm : SeteqPats<CPU64Regs, SLTiu64, XOR64, SLTu64, ZERO_64>; +defm : SetlePats<CPU64Regs, SLT64, SLTu64>; +defm : SetgtPats<CPU64Regs, SLT64, SLTu64>; +defm : SetgePats<CPU64Regs, SLT64, SLTu64>; +defm : SetgeImmPats<CPU64Regs, SLTi64, SLTiu64>; diff --git a/contrib/llvm/lib/Target/Mips/MipsAsmPrinter.cpp b/contrib/llvm/lib/Target/Mips/MipsAsmPrinter.cpp index 69e03bd..0e82681 100644 --- a/contrib/llvm/lib/Target/Mips/MipsAsmPrinter.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsAsmPrinter.cpp @@ -18,6 +18,7 @@ #include "MipsInstrInfo.h" #include "MipsMachineFunction.h" #include "MipsMCInstLower.h" +#include "MipsMCSymbolRefExpr.h" #include "InstPrinter/MipsInstPrinter.h" #include "llvm/BasicBlock.h" #include "llvm/Instructions.h" @@ -25,6 +26,7 @@ #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCInst.h" @@ -33,15 +35,22 @@ #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetOptions.h" -#include "llvm/Target/TargetRegistry.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Twine.h" +#include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Analysis/DebugInfo.h" using namespace llvm; +static bool isUnalignedLoadStore(unsigned Opc) { + return Opc == Mips::ULW || Opc == Mips::ULH || Opc == Mips::ULHu || + Opc == Mips::USW || Opc == Mips::USH || + Opc == Mips::ULW_P8 || Opc == Mips::ULH_P8 || Opc == Mips::ULHu_P8 || + Opc == Mips::USW_P8 || Opc == Mips::USH_P8; +} + void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) { SmallString<128> Str; raw_svector_ostream OS(Str); @@ -52,8 +61,21 @@ void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) { } MipsMCInstLower MCInstLowering(Mang, *MF, *this); + unsigned Opc = MI->getOpcode(); MCInst TmpInst0; MCInstLowering.Lower(MI, TmpInst0); + + // Enclose unaligned load or store with .macro & .nomacro directives. + if (isUnalignedLoadStore(Opc)) { + MCInst Directive; + Directive.setOpcode(Mips::MACRO); + OutStreamer.EmitInstruction(Directive); + OutStreamer.EmitInstruction(TmpInst0); + Directive.setOpcode(Mips::NOMACRO); + OutStreamer.EmitInstruction(Directive); + return; + } + OutStreamer.EmitInstruction(TmpInst0); } @@ -180,7 +202,6 @@ void MipsAsmPrinter::emitFrameDirective() { const char *MipsAsmPrinter::getCurrentABIString() const { switch (Subtarget->getTargetABI()) { case MipsSubtarget::O32: return "abi32"; - case MipsSubtarget::O64: return "abiO64"; case MipsSubtarget::N32: return "abiN32"; case MipsSubtarget::N64: return "abi64"; case MipsSubtarget::EABI: return "eabi32"; // TODO: handle eabi64 @@ -304,6 +325,11 @@ void MipsAsmPrinter::printOperand(const MachineInstr *MI, int opNum, case MipsII::MO_GOTTPREL: O << "%gottprel("; break; case MipsII::MO_TPREL_HI: O << "%tprel_hi("; break; case MipsII::MO_TPREL_LO: O << "%tprel_lo("; break; + case MipsII::MO_GPOFF_HI: O << "%hi(%neg(%gp_rel("; break; + case MipsII::MO_GPOFF_LO: O << "%lo(%neg(%gp_rel("; break; + case MipsII::MO_GOT_DISP: O << "%got_disp("; break; + case MipsII::MO_GOT_PAGE: O << "%got_page("; break; + case MipsII::MO_GOT_OFST: O << "%got_ofst("; break; } switch (MO.getType()) { @@ -424,17 +450,9 @@ void MipsAsmPrinter::PrintDebugValueComment(const MachineInstr *MI, } // Force static initialization. -static MCInstPrinter *createMipsMCInstPrinter(const Target &T, - unsigned SyntaxVariant, - const MCAsmInfo &MAI) { - return new MipsInstPrinter(MAI); -} - extern "C" void LLVMInitializeMipsAsmPrinter() { RegisterAsmPrinter<MipsAsmPrinter> X(TheMipsTarget); RegisterAsmPrinter<MipsAsmPrinter> Y(TheMipselTarget); - - TargetRegistry::RegisterMCInstPrinter(TheMipsTarget, createMipsMCInstPrinter); - TargetRegistry::RegisterMCInstPrinter(TheMipselTarget, - createMipsMCInstPrinter); + RegisterAsmPrinter<MipsAsmPrinter> A(TheMips64Target); + RegisterAsmPrinter<MipsAsmPrinter> B(TheMips64elTarget); } diff --git a/contrib/llvm/lib/Target/Mips/MipsCallingConv.td b/contrib/llvm/lib/Target/Mips/MipsCallingConv.td index 876f0fc..0ae4ef6 100644 --- a/contrib/llvm/lib/Target/Mips/MipsCallingConv.td +++ b/contrib/llvm/lib/Target/Mips/MipsCallingConv.td @@ -31,6 +31,55 @@ def RetCC_MipsO32 : CallingConv<[ ]>; //===----------------------------------------------------------------------===// +// Mips N32/64 Calling Convention +//===----------------------------------------------------------------------===// + +def CC_MipsN : CallingConv<[ + // FIXME: Handle byval, complex and float double parameters. + + // Promote i8/i16/i32 arguments to i64. + CCIfType<[i8, i16, i32], CCPromoteToType<i64>>, + + // Integer arguments are passed in integer registers. + CCIfType<[i64], CCAssignToRegWithShadow<[A0_64, A1_64, A2_64, A3_64, + T0_64, T1_64, T2_64, T3_64], + [D12_64, D13_64, D14_64, D15_64, + D16_64, D17_64, D18_64, D19_64]>>, + + // f32 arguments are passed in single precision FP registers. + CCIfType<[f32], CCAssignToRegWithShadow<[F12, F13, F14, F15, + F16, F17, F18, F19], + [A0_64, A1_64, A2_64, A3_64, + T0_64, T1_64, T2_64, T3_64]>>, + + // f64 arguments are passed in double precision FP registers. + CCIfType<[f64], CCAssignToRegWithShadow<[D12_64, D13_64, D14_64, D15_64, + D16_64, D17_64, D18_64, D19_64], + [A0_64, A1_64, A2_64, A3_64, + T0_64, T1_64, T2_64, T3_64]>>, + + // All stack parameter slots become 64-bit doublewords and are 8-byte aligned. + CCIfType<[i64, f64], CCAssignToStack<8, 8>>, + CCIfType<[f32], CCAssignToStack<4, 8>> +]>; + +def RetCC_MipsN : CallingConv<[ + // FIXME: Handle complex and float double return values. + + // i32 are returned in registers V0, V1 + CCIfType<[i32], CCAssignToReg<[V0, V1]>>, + + // i64 are returned in registers V0_64, V1_64 + CCIfType<[i64], CCAssignToReg<[V0_64, V1_64]>>, + + // f32 are returned in registers F0, F2 + CCIfType<[f32], CCAssignToReg<[F0, F2]>>, + + // f64 are returned in registers D0, D2 + CCIfType<[f64], CCAssignToReg<[D0_64, D2_64]>> +]>; + +//===----------------------------------------------------------------------===// // Mips EABI Calling Convention //===----------------------------------------------------------------------===// @@ -77,10 +126,14 @@ def RetCC_MipsEABI : CallingConv<[ //===----------------------------------------------------------------------===// def CC_Mips : CallingConv<[ - CCIfSubtarget<"isABI_EABI()", CCDelegateTo<CC_MipsEABI>> + CCIfSubtarget<"isABI_EABI()", CCDelegateTo<CC_MipsEABI>>, + CCIfSubtarget<"isABI_N32()", CCDelegateTo<CC_MipsN>>, + CCIfSubtarget<"isABI_N64()", CCDelegateTo<CC_MipsN>> ]>; def RetCC_Mips : CallingConv<[ CCIfSubtarget<"isABI_EABI()", CCDelegateTo<RetCC_MipsEABI>>, + CCIfSubtarget<"isABI_N32()", CCDelegateTo<RetCC_MipsN>>, + CCIfSubtarget<"isABI_N64()", CCDelegateTo<RetCC_MipsN>>, CCDelegateTo<RetCC_MipsO32> ]>; diff --git a/contrib/llvm/lib/Target/Mips/MipsCodeEmitter.cpp b/contrib/llvm/lib/Target/Mips/MipsCodeEmitter.cpp new file mode 100644 index 0000000..9220d9c --- /dev/null +++ b/contrib/llvm/lib/Target/Mips/MipsCodeEmitter.cpp @@ -0,0 +1,245 @@ +//===-- Mips/MipsCodeEmitter.cpp - Convert Mips code to machine code -----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// +// +// This file contains the pass that transforms the Mips machine instructions +// into relocatable machine code. +// +//===---------------------------------------------------------------------===// + +#define DEBUG_TYPE "jit" +#include "Mips.h" +#include "MipsInstrInfo.h" +#include "MipsRelocations.h" +#include "MipsSubtarget.h" +#include "MipsTargetMachine.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/PassManager.h" +#include "llvm/CodeGen/JITCodeEmitter.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#ifndef NDEBUG +#include <iomanip> +#endif + +#include "llvm/CodeGen/MachineOperand.h" + +using namespace llvm; + +STATISTIC(NumEmitted, "Number of machine instructions emitted"); + +namespace { + +class MipsCodeEmitter : public MachineFunctionPass { + MipsJITInfo *JTI; + const MipsInstrInfo *II; + const TargetData *TD; + const MipsSubtarget *Subtarget; + TargetMachine &TM; + JITCodeEmitter &MCE; + const std::vector<MachineConstantPoolEntry> *MCPEs; + const std::vector<MachineJumpTableEntry> *MJTEs; + bool IsPIC; + + void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired<MachineModuleInfo> (); + MachineFunctionPass::getAnalysisUsage(AU); + } + + static char ID; + + public: + MipsCodeEmitter(TargetMachine &tm, JITCodeEmitter &mce) : + MachineFunctionPass(ID), JTI(0), + II((const MipsInstrInfo *) tm.getInstrInfo()), + TD(tm.getTargetData()), TM(tm), MCE(mce), MCPEs(0), MJTEs(0), + IsPIC(TM.getRelocationModel() == Reloc::PIC_) { + } + + bool runOnMachineFunction(MachineFunction &MF); + + virtual const char *getPassName() const { + return "Mips Machine Code Emitter"; + } + + /// getBinaryCodeForInstr - This function, generated by the + /// CodeEmitterGenerator using TableGen, produces the binary encoding for + /// machine instructions. + unsigned getBinaryCodeForInstr(const MachineInstr &MI) const; + + void emitInstruction(const MachineInstr &MI); + + private: + + void emitWordLE(unsigned Word); + + /// Routines that handle operands which add machine relocations which are + /// fixed up by the relocation stage. + void emitGlobalAddress(const GlobalValue *GV, unsigned Reloc, + bool MayNeedFarStub) const; + void emitExternalSymbolAddress(const char *ES, unsigned Reloc) const; + void emitConstPoolAddress(unsigned CPI, unsigned Reloc) const; + void emitJumpTableAddress(unsigned JTIndex, unsigned Reloc) const; + void emitMachineBasicBlock(MachineBasicBlock *BB, unsigned Reloc) const; + + /// getMachineOpValue - Return binary encoding of operand. If the machine + /// operand requires relocation, record the relocation and return zero. + unsigned getMachineOpValue(const MachineInstr &MI, + const MachineOperand &MO) const; + + unsigned getRelocation(const MachineInstr &MI, + const MachineOperand &MO) const; + + }; +} + +char MipsCodeEmitter::ID = 0; + +bool MipsCodeEmitter::runOnMachineFunction(MachineFunction &MF) { + JTI = ((MipsTargetMachine&) MF.getTarget()).getJITInfo(); + II = ((const MipsTargetMachine&) MF.getTarget()).getInstrInfo(); + TD = ((const MipsTargetMachine&) MF.getTarget()).getTargetData(); + Subtarget = &TM.getSubtarget<MipsSubtarget> (); + MCPEs = &MF.getConstantPool()->getConstants(); + MJTEs = 0; + if (MF.getJumpTableInfo()) MJTEs = &MF.getJumpTableInfo()->getJumpTables(); + JTI->Initialize(MF, IsPIC); + MCE.setModuleInfo(&getAnalysis<MachineModuleInfo> ()); + + do { + DEBUG(errs() << "JITTing function '" + << MF.getFunction()->getName() << "'\n"); + MCE.startFunction(MF); + + for (MachineFunction::iterator MBB = MF.begin(), E = MF.end(); + MBB != E; ++MBB){ + MCE.StartMachineBasicBlock(MBB); + for (MachineBasicBlock::const_iterator I = MBB->begin(), E = MBB->end(); + I != E; ++I) + emitInstruction(*I); + } + } while (MCE.finishFunction(MF)); + + return false; +} + +unsigned MipsCodeEmitter::getRelocation(const MachineInstr &MI, + const MachineOperand &MO) const { + // NOTE: This relocations are for static. + uint64_t TSFlags = MI.getDesc().TSFlags; + uint64_t Form = TSFlags & MipsII::FormMask; + if (Form == MipsII::FrmJ) + return Mips::reloc_mips_26; + if ((Form == MipsII::FrmI || Form == MipsII::FrmFI) + && MI.getDesc().isBranch()) + return Mips::reloc_mips_branch; + if (Form == MipsII::FrmI && MI.getOpcode() == Mips::LUi) + return Mips::reloc_mips_hi; + return Mips::reloc_mips_lo; +} + +/// getMachineOpValue - Return binary encoding of operand. If the machine +/// operand requires relocation, record the relocation and return zero. +unsigned MipsCodeEmitter::getMachineOpValue(const MachineInstr &MI, + const MachineOperand &MO) const { + if (MO.isReg()) + return MipsRegisterInfo::getRegisterNumbering(MO.getReg()); + else if (MO.isImm()) + return static_cast<unsigned>(MO.getImm()); + else if (MO.isGlobal()) + emitGlobalAddress(MO.getGlobal(), getRelocation(MI, MO), true); + else if (MO.isSymbol()) + emitExternalSymbolAddress(MO.getSymbolName(), getRelocation(MI, MO)); + else if (MO.isCPI()) + emitConstPoolAddress(MO.getIndex(), getRelocation(MI, MO)); + else if (MO.isJTI()) + emitJumpTableAddress(MO.getIndex(), getRelocation(MI, MO)); + else if (MO.isMBB()) + emitMachineBasicBlock(MO.getMBB(), getRelocation(MI, MO)); + else + llvm_unreachable("Unable to encode MachineOperand!"); + return 0; +} + +void MipsCodeEmitter::emitGlobalAddress(const GlobalValue *GV, unsigned Reloc, + bool MayNeedFarStub) const { + MCE.addRelocation(MachineRelocation::getGV(MCE.getCurrentPCOffset(), Reloc, + const_cast<GlobalValue *>(GV), 0, MayNeedFarStub)); +} + +void MipsCodeEmitter:: +emitExternalSymbolAddress(const char *ES, unsigned Reloc) const { + MCE.addRelocation(MachineRelocation::getExtSym(MCE.getCurrentPCOffset(), + Reloc, ES, 0, 0, false)); +} + +void MipsCodeEmitter::emitConstPoolAddress(unsigned CPI, unsigned Reloc) const { + MCE.addRelocation(MachineRelocation::getConstPool(MCE.getCurrentPCOffset(), + Reloc, CPI, 0, false)); +} + +void MipsCodeEmitter:: +emitJumpTableAddress(unsigned JTIndex, unsigned Reloc) const { + MCE.addRelocation(MachineRelocation::getJumpTable(MCE.getCurrentPCOffset(), + Reloc, JTIndex, 0, false)); +} + +void MipsCodeEmitter::emitMachineBasicBlock(MachineBasicBlock *BB, + unsigned Reloc) const { + MCE.addRelocation(MachineRelocation::getBB(MCE.getCurrentPCOffset(), + Reloc, BB)); +} + +void MipsCodeEmitter::emitInstruction(const MachineInstr &MI) { + DEBUG(errs() << "JIT: " << (void*)MCE.getCurrentPCValue() << ":\t" << MI); + + MCE.processDebugLoc(MI.getDebugLoc(), true); + + // Skip pseudo instructions. + if ((MI.getDesc().TSFlags & MipsII::FormMask) == MipsII::Pseudo) + return; + + ++NumEmitted; // Keep track of the # of mi's emitted + + switch (MI.getOpcode()) { + default: + emitWordLE(getBinaryCodeForInstr(MI)); + break; + } + + MCE.processDebugLoc(MI.getDebugLoc(), false); +} + +void MipsCodeEmitter::emitWordLE(unsigned Word) { + DEBUG(errs() << " 0x"; + errs().write_hex(Word) << "\n"); + MCE.emitWordLE(Word); +} + +/// createMipsJITCodeEmitterPass - Return a pass that emits the collected Mips +/// code to the specified MCE object. +FunctionPass *llvm::createMipsJITCodeEmitterPass(MipsTargetMachine &TM, + JITCodeEmitter &JCE) { + return new MipsCodeEmitter(TM, JCE); +} + +unsigned MipsCodeEmitter::getBinaryCodeForInstr(const MachineInstr &MI) const { + // this function will be automatically generated by the CodeEmitterGenerator + // using TableGen + return 0; +} diff --git a/contrib/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp b/contrib/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp index c3a6211..be3b7a0 100644 --- a/contrib/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// Simple pass to fills delay slots with NOPs. +// Simple pass to fills delay slots with useful instructions. // //===----------------------------------------------------------------------===// @@ -17,18 +17,31 @@ #include "MipsTargetMachine.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/Statistic.h" using namespace llvm; STATISTIC(FilledSlots, "Number of delay slots filled"); +STATISTIC(UsefulSlots, "Number of delay slots filled with instructions that" + " are not NOP."); + +static cl::opt<bool> EnableDelaySlotFiller( + "enable-mips-delay-filler", + cl::init(false), + cl::desc("Fill the Mips delay slots useful instructions."), + cl::Hidden); namespace { struct Filler : public MachineFunctionPass { TargetMachine &TM; const TargetInstrInfo *TII; + MachineBasicBlock::iterator LastFiller; static char ID; Filler(TargetMachine &tm) @@ -47,31 +60,61 @@ namespace { return Changed; } + bool isDelayFiller(MachineBasicBlock &MBB, + MachineBasicBlock::iterator candidate); + + void insertCallUses(MachineBasicBlock::iterator MI, + SmallSet<unsigned, 32>& RegDefs, + SmallSet<unsigned, 32>& RegUses); + + void insertDefsUses(MachineBasicBlock::iterator MI, + SmallSet<unsigned, 32>& RegDefs, + SmallSet<unsigned, 32>& RegUses); + + bool IsRegInSet(SmallSet<unsigned, 32>& RegSet, + unsigned Reg); + + bool delayHasHazard(MachineBasicBlock::iterator candidate, + bool &sawLoad, bool &sawStore, + SmallSet<unsigned, 32> &RegDefs, + SmallSet<unsigned, 32> &RegUses); + + bool + findDelayInstr(MachineBasicBlock &MBB, MachineBasicBlock::iterator slot, + MachineBasicBlock::iterator &Filler); + + }; char Filler::ID = 0; } // end of anonymous namespace /// runOnMachineBasicBlock - Fill in delay slots for the given basic block. -/// Currently, we fill delay slots with NOPs. We assume there is only one -/// delay slot per delayed instruction. +/// We assume there is only one delay slot per delayed instruction. bool Filler:: -runOnMachineBasicBlock(MachineBasicBlock &MBB) -{ +runOnMachineBasicBlock(MachineBasicBlock &MBB) { bool Changed = false; - for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I) { - const MCInstrDesc& MCid = I->getDesc(); - if (MCid.hasDelaySlot() && - (TM.getSubtarget<MipsSubtarget>().isMips1() || - MCid.isCall() || MCid.isBranch() || MCid.isReturn())) { - MachineBasicBlock::iterator J = I; - ++J; - BuildMI(MBB, J, I->getDebugLoc(), TII->get(Mips::NOP)); + LastFiller = MBB.end(); + + for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I) + if (I->getDesc().hasDelaySlot()) { ++FilledSlots; Changed = true; - } - } + MachineBasicBlock::iterator D; + + if (EnableDelaySlotFiller && findDelayInstr(MBB, I, D)) { + MBB.splice(llvm::next(I), &MBB, D); + ++UsefulSlots; + } + else + BuildMI(MBB, llvm::next(I), I->getDebugLoc(), TII->get(Mips::NOP)); + + // Record the filler instruction that filled the delay slot. + // The instruction after it will be visited in the next iteration. + LastFiller = ++I; + } return Changed; + } /// createMipsDelaySlotFillerPass - Returns a pass that fills in delay @@ -80,3 +123,134 @@ FunctionPass *llvm::createMipsDelaySlotFillerPass(MipsTargetMachine &tm) { return new Filler(tm); } +bool Filler::findDelayInstr(MachineBasicBlock &MBB, + MachineBasicBlock::iterator slot, + MachineBasicBlock::iterator &Filler) { + SmallSet<unsigned, 32> RegDefs; + SmallSet<unsigned, 32> RegUses; + + insertDefsUses(slot, RegDefs, RegUses); + + bool sawLoad = false; + bool sawStore = false; + + for (MachineBasicBlock::reverse_iterator I(slot); I != MBB.rend(); ++I) { + // skip debug value + if (I->isDebugValue()) + continue; + + // Convert to forward iterator. + MachineBasicBlock::iterator FI(llvm::next(I).base()); + + if (I->hasUnmodeledSideEffects() + || I->isInlineAsm() + || I->isLabel() + || FI == LastFiller + || I->getDesc().isPseudo() + // + // Should not allow: + // ERET, DERET or WAIT, PAUSE. Need to add these to instruction + // list. TBD. + ) + break; + + if (delayHasHazard(FI, sawLoad, sawStore, RegDefs, RegUses)) { + insertDefsUses(FI, RegDefs, RegUses); + continue; + } + + Filler = FI; + return true; + } + + return false; +} + +bool Filler::delayHasHazard(MachineBasicBlock::iterator candidate, + bool &sawLoad, + bool &sawStore, + SmallSet<unsigned, 32> &RegDefs, + SmallSet<unsigned, 32> &RegUses) { + if (candidate->isImplicitDef() || candidate->isKill()) + return true; + + MCInstrDesc MCID = candidate->getDesc(); + // Loads or stores cannot be moved past a store to the delay slot + // and stores cannot be moved past a load. + if (MCID.mayLoad()) { + if (sawStore) + return true; + sawLoad = true; + } + + if (MCID.mayStore()) { + if (sawStore) + return true; + sawStore = true; + if (sawLoad) + return true; + } + + assert((!MCID.isCall() && !MCID.isReturn()) && + "Cannot put calls or returns in delay slot."); + + for (unsigned i = 0, e = candidate->getNumOperands(); i!= e; ++i) { + const MachineOperand &MO = candidate->getOperand(i); + unsigned Reg; + + if (!MO.isReg() || !(Reg = MO.getReg())) + continue; // skip + + if (MO.isDef()) { + // check whether Reg is defined or used before delay slot. + if (IsRegInSet(RegDefs, Reg) || IsRegInSet(RegUses, Reg)) + return true; + } + if (MO.isUse()) { + // check whether Reg is defined before delay slot. + if (IsRegInSet(RegDefs, Reg)) + return true; + } + } + return false; +} + +// 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) { + // If MI is a call or return, just examine the explicit non-variadic operands. + MCInstrDesc MCID = MI->getDesc(); + unsigned e = MCID.isCall() || MCID.isReturn() ? MCID.getNumOperands() : + MI->getNumOperands(); + + // Add RA to RegDefs to prevent users of RA from going into delay slot. + if (MCID.isCall()) + RegDefs.insert(Mips::RA); + + for (unsigned i = 0; i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + unsigned Reg; + + if (!MO.isReg() || !(Reg = MO.getReg())) + continue; + + if (MO.isDef()) + RegDefs.insert(Reg); + else if (MO.isUse()) + RegUses.insert(Reg); + } +} + +//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 unsigned *Alias = TM.getRegisterInfo()->getAliasSet(Reg); + *Alias; ++Alias) + if (RegSet.count(*Alias)) + return true; + + return false; +} diff --git a/contrib/llvm/lib/Target/Mips/MipsFrameLowering.cpp b/contrib/llvm/lib/Target/Mips/MipsFrameLowering.cpp index a0f90a0..22d1e47 100644 --- a/contrib/llvm/lib/Target/Mips/MipsFrameLowering.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsFrameLowering.cpp @@ -254,9 +254,15 @@ void MipsFrameLowering::emitPrologue(MachineFunction &MF) const { } // Restore GP from the saved stack location - if (MipsFI->needGPSaveRestore()) - BuildMI(MBB, MBBI, dl, TII.get(Mips::CPRESTORE)) - .addImm(MFI->getObjectOffset(MipsFI->getGPFI())); + if (MipsFI->needGPSaveRestore()) { + unsigned Offset = MFI->getObjectOffset(MipsFI->getGPFI()); + BuildMI(MBB, MBBI, dl, TII.get(Mips::CPRESTORE)).addImm(Offset); + + if (Offset >= 0x8000) { + BuildMI(MBB, llvm::prior(MBBI), dl, TII.get(Mips::MACRO)); + BuildMI(MBB, MBBI, dl, TII.get(Mips::NOMACRO)); + } + } } void MipsFrameLowering::emitEpilogue(MachineFunction &MF, @@ -300,13 +306,6 @@ void MipsFrameLowering::emitEpilogue(MachineFunction &MF, } } -void -MipsFrameLowering::getInitialFrameState(std::vector<MachineMove> &Moves) const { - MachineLocation Dst(MachineLocation::VirtualFP); - MachineLocation Src(Mips::SP, 0); - Moves.push_back(MachineMove(0, Dst, Src)); -} - void MipsFrameLowering:: processFunctionBeforeCalleeSavedScan(MachineFunction &MF, RegScavenger *RS) const { diff --git a/contrib/llvm/lib/Target/Mips/MipsFrameLowering.h b/contrib/llvm/lib/Target/Mips/MipsFrameLowering.h index 78c78ee..c249756 100644 --- a/contrib/llvm/lib/Target/Mips/MipsFrameLowering.h +++ b/contrib/llvm/lib/Target/Mips/MipsFrameLowering.h @@ -27,7 +27,8 @@ protected: public: explicit MipsFrameLowering(const MipsSubtarget &sti) - : TargetFrameLowering(StackGrowsDown, 8, 0), STI(sti) { + : TargetFrameLowering(StackGrowsDown, sti.hasMips64() ? 16 : 8, 0), + STI(sti) { } bool targetHandlesStackFrameRounding() const; @@ -39,8 +40,6 @@ public: bool hasFP(const MachineFunction &MF) const; - void getInitialFrameState(std::vector<MachineMove> &Moves) const; - void processFunctionBeforeCalleeSavedScan(MachineFunction &MF, RegScavenger *RS) const; }; diff --git a/contrib/llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp b/contrib/llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp index 90aaeb6..9c831ed 100644 --- a/contrib/llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp @@ -86,9 +86,6 @@ private: // Complex Pattern. bool SelectAddr(SDValue N, SDValue &Base, SDValue &Offset); - SDNode *SelectLoadFp64(SDNode *N); - SDNode *SelectStoreFp64(SDNode *N); - // getI32Imm - Return a target constant with the specified // value, of type i32. inline SDValue getI32Imm(unsigned Imm) { @@ -114,17 +111,20 @@ SDNode *MipsDAGToDAGISel::getGlobalBaseReg() { /// Used on Mips Load/Store instructions bool MipsDAGToDAGISel:: SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset) { + EVT ValTy = Addr.getValueType(); + unsigned GPReg = ValTy == MVT::i32 ? Mips::GP : Mips::GP_64; + // if Address is FI, get the TargetFrameIndex. if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { - Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); - Offset = CurDAG->getTargetConstant(0, MVT::i32); + Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy); + Offset = CurDAG->getTargetConstant(0, ValTy); return true; } // on PIC code Load GA if (TM.getRelocationModel() == Reloc::PIC_) { if (Addr.getOpcode() == MipsISD::WrapperPIC) { - Base = CurDAG->getRegister(Mips::GP, MVT::i32); + Base = CurDAG->getRegister(GPReg, ValTy); Offset = Addr.getOperand(0); return true; } @@ -133,7 +133,7 @@ SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset) { Addr.getOpcode() == ISD::TargetGlobalAddress)) return false; else if (Addr.getOpcode() == ISD::TargetGlobalTLSAddress) { - Base = CurDAG->getRegister(Mips::GP, MVT::i32); + Base = CurDAG->getRegister(GPReg, ValTy); Offset = Addr; return true; } @@ -147,11 +147,11 @@ SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset) { // If the first operand is a FI, get the TargetFI Node if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode> (Addr.getOperand(0))) - Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); + Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy); else Base = Addr.getOperand(0); - Offset = CurDAG->getTargetConstant(CN->getZExtValue(), MVT::i32); + Offset = CurDAG->getTargetConstant(CN->getZExtValue(), ValTy); return true; } } @@ -180,134 +180,10 @@ SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset) { } Base = Addr; - Offset = CurDAG->getTargetConstant(0, MVT::i32); + Offset = CurDAG->getTargetConstant(0, ValTy); return true; } -SDNode *MipsDAGToDAGISel::SelectLoadFp64(SDNode *N) { - MVT::SimpleValueType NVT = - N->getValueType(0).getSimpleVT().SimpleTy; - - if (!Subtarget.isMips1() || NVT != MVT::f64) - return NULL; - - LoadSDNode *LN = cast<LoadSDNode>(N); - if (LN->getExtensionType() != ISD::NON_EXTLOAD || - LN->getAddressingMode() != ISD::UNINDEXED) - return NULL; - - SDValue Chain = N->getOperand(0); - SDValue N1 = N->getOperand(1); - SDValue Offset0, Offset1, Base; - - if (!SelectAddr(N1, Base, Offset0) || - N1.getValueType() != MVT::i32) - return NULL; - - MachineSDNode::mmo_iterator MemRefs0 = MF->allocateMemRefsArray(1); - MemRefs0[0] = cast<MemSDNode>(N)->getMemOperand(); - DebugLoc dl = N->getDebugLoc(); - - // The second load should start after for 4 bytes. - if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Offset0)) - Offset1 = CurDAG->getTargetConstant(C->getSExtValue()+4, MVT::i32); - else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Offset0)) - Offset1 = CurDAG->getTargetConstantPool(CP->getConstVal(), - MVT::i32, - CP->getAlignment(), - CP->getOffset()+4, - CP->getTargetFlags()); - else - return NULL; - - // Choose the offsets depending on the endianess - if (TM.getTargetData()->isBigEndian()) - std::swap(Offset0, Offset1); - - // Instead of: - // ldc $f0, X($3) - // Generate: - // lwc $f0, X($3) - // lwc $f1, X+4($3) - SDNode *LD0 = CurDAG->getMachineNode(Mips::LWC1, dl, MVT::f32, - MVT::Other, Base, Offset0, Chain); - SDValue Undef = SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, - dl, NVT), 0); - SDValue I0 = CurDAG->getTargetInsertSubreg(Mips::sub_fpeven, dl, - MVT::f64, Undef, SDValue(LD0, 0)); - - SDNode *LD1 = CurDAG->getMachineNode(Mips::LWC1, dl, MVT::f32, - MVT::Other, Base, Offset1, SDValue(LD0, 1)); - SDValue I1 = CurDAG->getTargetInsertSubreg(Mips::sub_fpodd, dl, - MVT::f64, I0, SDValue(LD1, 0)); - - ReplaceUses(SDValue(N, 0), I1); - ReplaceUses(SDValue(N, 1), Chain); - cast<MachineSDNode>(LD0)->setMemRefs(MemRefs0, MemRefs0 + 1); - cast<MachineSDNode>(LD1)->setMemRefs(MemRefs0, MemRefs0 + 1); - return I1.getNode(); -} - -SDNode *MipsDAGToDAGISel::SelectStoreFp64(SDNode *N) { - - if (!Subtarget.isMips1() || - N->getOperand(1).getValueType() != MVT::f64) - return NULL; - - SDValue Chain = N->getOperand(0); - - StoreSDNode *SN = cast<StoreSDNode>(N); - if (SN->isTruncatingStore() || SN->getAddressingMode() != ISD::UNINDEXED) - return NULL; - - SDValue N1 = N->getOperand(1); - SDValue N2 = N->getOperand(2); - SDValue Offset0, Offset1, Base; - - if (!SelectAddr(N2, Base, Offset0) || - N1.getValueType() != MVT::f64 || - N2.getValueType() != MVT::i32) - return NULL; - - MachineSDNode::mmo_iterator MemRefs0 = MF->allocateMemRefsArray(1); - MemRefs0[0] = cast<MemSDNode>(N)->getMemOperand(); - DebugLoc dl = N->getDebugLoc(); - - // Get the even and odd part from the f64 register - SDValue FPOdd = CurDAG->getTargetExtractSubreg(Mips::sub_fpodd, - dl, MVT::f32, N1); - SDValue FPEven = CurDAG->getTargetExtractSubreg(Mips::sub_fpeven, - dl, MVT::f32, N1); - - // The second store should start after for 4 bytes. - if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Offset0)) - Offset1 = CurDAG->getTargetConstant(C->getSExtValue()+4, MVT::i32); - else - return NULL; - - // Choose the offsets depending on the endianess - if (TM.getTargetData()->isBigEndian()) - std::swap(Offset0, Offset1); - - // Instead of: - // sdc $f0, X($3) - // Generate: - // swc $f0, X($3) - // swc $f1, X+4($3) - SDValue Ops0[] = { FPEven, Base, Offset0, Chain }; - Chain = SDValue(CurDAG->getMachineNode(Mips::SWC1, dl, - MVT::Other, Ops0, 4), 0); - cast<MachineSDNode>(Chain.getNode())->setMemRefs(MemRefs0, MemRefs0 + 1); - - SDValue Ops1[] = { FPOdd, Base, Offset1, Chain }; - Chain = SDValue(CurDAG->getMachineNode(Mips::SWC1, dl, - MVT::Other, Ops1, 4), 0); - cast<MachineSDNode>(Chain.getNode())->setMemRefs(MemRefs0, MemRefs0 + 1); - - ReplaceUses(SDValue(N, 0), Chain); - return Chain.getNode(); -} - /// Select instructions not customized! Used for /// expanded, promoted and normal instructions SDNode* MipsDAGToDAGISel::Select(SDNode *Node) { @@ -364,6 +240,8 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) { /// Mul with two results case ISD::SMUL_LOHI: case ISD::UMUL_LOHI: { + assert(Node->getValueType(0) != MVT::i64 && + "64-bit multiplication with two results not handled."); SDValue Op1 = Node->getOperand(0); SDValue Op2 = Node->getOperand(1); @@ -389,21 +267,29 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) { /// Special Muls case ISD::MUL: - if (Subtarget.isMips32()) + // Mips32 has a 32-bit three operand mul instruction. + if (Subtarget.hasMips32() && Node->getValueType(0) == MVT::i32) break; case ISD::MULHS: case ISD::MULHU: { + assert((Opcode == ISD::MUL || Node->getValueType(0) != MVT::i64) && + "64-bit MULH* not handled."); + EVT Ty = Node->getValueType(0); SDValue MulOp1 = Node->getOperand(0); SDValue MulOp2 = Node->getOperand(1); - unsigned MulOp = (Opcode == ISD::MULHU ? Mips::MULTu : Mips::MULT); + unsigned MulOp = (Opcode == ISD::MULHU ? + Mips::MULTu : + (Ty == MVT::i32 ? Mips::MULT : Mips::DMULT)); SDNode *MulNode = CurDAG->getMachineNode(MulOp, dl, MVT::Glue, MulOp1, MulOp2); SDValue InFlag = SDValue(MulNode, 0); - if (Opcode == ISD::MUL) - return CurDAG->getMachineNode(Mips::MFLO, dl, MVT::i32, InFlag); + if (Opcode == ISD::MUL) { + unsigned Opc = (Ty == MVT::i32 ? Mips::MFLO : Mips::MFLO64); + return CurDAG->getMachineNode(Opc, dl, Ty, InFlag); + } else return CurDAG->getMachineNode(Mips::MFHI, dl, MVT::i32, InFlag); } @@ -417,31 +303,12 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) { if (Node->getValueType(0) == MVT::f64 && CN->isExactlyValue(+0.0)) { SDValue Zero = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl, Mips::ZERO, MVT::i32); - SDValue Undef = SDValue( - CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, MVT::f64), 0); - SDNode *MTC = CurDAG->getMachineNode(Mips::MTC1, dl, MVT::f32, Zero); - SDValue I0 = CurDAG->getTargetInsertSubreg(Mips::sub_fpeven, dl, - MVT::f64, Undef, SDValue(MTC, 0)); - SDValue I1 = CurDAG->getTargetInsertSubreg(Mips::sub_fpodd, dl, - MVT::f64, I0, SDValue(MTC, 0)); - ReplaceUses(SDValue(Node, 0), I1); - return I1.getNode(); + return CurDAG->getMachineNode(Mips::BuildPairF64, dl, MVT::f64, Zero, + Zero); } break; } - case ISD::LOAD: - if (SDNode *ResNode = SelectLoadFp64(Node)) - return ResNode; - // Other cases are autogenerated. - break; - - case ISD::STORE: - if (SDNode *ResNode = SelectStoreFp64(Node)) - return ResNode; - // Other cases are autogenerated. - break; - case MipsISD::ThreadPointer: { unsigned SrcReg = Mips::HWR29; unsigned DestReg = Mips::V1; diff --git a/contrib/llvm/lib/Target/Mips/MipsISelLowering.cpp b/contrib/llvm/lib/Target/Mips/MipsISelLowering.cpp index b4f4b1b..1932e74 100644 --- a/contrib/llvm/lib/Target/Mips/MipsISelLowering.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsISelLowering.cpp @@ -35,6 +35,18 @@ #include "llvm/Support/ErrorHandling.h" using namespace llvm; +// If I is a shifted mask, set the size (Size) and the first bit of the +// mask (Pos), and return true. +// For example, if I is 0x003ff800, (Pos, Size) = (11, 11). +static bool IsShiftedMask(uint64_t I, uint64_t &Pos, uint64_t &Size) { + if (!isUInt<32>(I) || !isShiftedMask_32(I)) + return false; + + Size = CountPopulation_32(I); + Pos = CountTrailingZeros_32(I); + return true; +} + const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const { switch (Opcode) { case MipsISD::JmpLink: return "MipsISD::JmpLink"; @@ -61,27 +73,38 @@ const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const { case MipsISD::ExtractElementF64: return "MipsISD::ExtractElementF64"; case MipsISD::WrapperPIC: return "MipsISD::WrapperPIC"; case MipsISD::DynAlloc: return "MipsISD::DynAlloc"; + case MipsISD::Sync: return "MipsISD::Sync"; + case MipsISD::Ext: return "MipsISD::Ext"; + case MipsISD::Ins: return "MipsISD::Ins"; default: return NULL; } } MipsTargetLowering:: MipsTargetLowering(MipsTargetMachine &TM) - : TargetLowering(TM, new MipsTargetObjectFile()) { - Subtarget = &TM.getSubtarget<MipsSubtarget>(); + : TargetLowering(TM, new MipsTargetObjectFile()), + Subtarget(&TM.getSubtarget<MipsSubtarget>()), + HasMips64(Subtarget->hasMips64()), IsN64(Subtarget->isABI_N64()) { // Mips does not have i1 type, so use i32 for // setcc operations results (slt, sgt, ...). setBooleanContents(ZeroOrOneBooleanContent); + setBooleanVectorContents(ZeroOrOneBooleanContent); // FIXME: Is this correct? // Set up the register classes addRegisterClass(MVT::i32, Mips::CPURegsRegisterClass); addRegisterClass(MVT::f32, Mips::FGR32RegisterClass); + if (HasMips64) + addRegisterClass(MVT::i64, Mips::CPU64RegsRegisterClass); + // When dealing with single precision only, use libcalls - if (!Subtarget->isSingleFloat()) - if (!Subtarget->isFP64bit()) + if (!Subtarget->isSingleFloat()) { + if (HasMips64) + addRegisterClass(MVT::f64, Mips::FGR64RegisterClass); + else addRegisterClass(MVT::f64, Mips::AFGR64RegisterClass); + } // Load extented operations for i1 types must be promoted setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote); @@ -100,6 +123,7 @@ MipsTargetLowering(MipsTargetMachine &TM) // Mips Custom Operations setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); + setOperationAction(ISD::GlobalAddress, MVT::i64, Custom); setOperationAction(ISD::BlockAddress, MVT::i32, Custom); setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom); setOperationAction(ISD::JumpTable, MVT::i32, Custom); @@ -115,6 +139,10 @@ MipsTargetLowering(MipsTargetMachine &TM) setOperationAction(ISD::SREM, MVT::i32, Expand); setOperationAction(ISD::UDIV, MVT::i32, Expand); setOperationAction(ISD::UREM, MVT::i32, Expand); + setOperationAction(ISD::SDIV, MVT::i64, Expand); + setOperationAction(ISD::SREM, MVT::i64, Expand); + setOperationAction(ISD::UDIV, MVT::i64, Expand); + setOperationAction(ISD::UREM, MVT::i64, Expand); // Operations not directly supported by Mips. setOperationAction(ISD::BR_JT, MVT::Other, Expand); @@ -126,10 +154,14 @@ MipsTargetLowering(MipsTargetMachine &TM) setOperationAction(ISD::CTPOP, MVT::i32, Expand); setOperationAction(ISD::CTTZ, MVT::i32, Expand); setOperationAction(ISD::ROTL, MVT::i32, Expand); + setOperationAction(ISD::ROTL, MVT::i64, Expand); - if (!Subtarget->isMips32r2()) + if (!Subtarget->hasMips32r2()) setOperationAction(ISD::ROTR, MVT::i32, Expand); + 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); @@ -159,7 +191,14 @@ MipsTargetLowering(MipsTargetMachine &TM) // Use the default for now setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand); - setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand); + + setOperationAction(ISD::MEMBARRIER, MVT::Other, Custom); + setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom); + + setOperationAction(ISD::ATOMIC_LOAD, MVT::i32, Expand); + setOperationAction(ISD::ATOMIC_STORE, MVT::i32, Expand); + + setInsertFencesForAtomic(true); if (Subtarget->isSingleFloat()) setOperationAction(ISD::SELECT_CC, MVT::f64, Expand); @@ -180,6 +219,8 @@ MipsTargetLowering(MipsTargetMachine &TM) setTargetDAGCombine(ISD::SDIVREM); setTargetDAGCombine(ISD::UDIVREM); setTargetDAGCombine(ISD::SETCC); + setTargetDAGCombine(ISD::AND); + setTargetDAGCombine(ISD::OR); setMinFunctionAlignment(2); @@ -190,7 +231,12 @@ MipsTargetLowering(MipsTargetMachine &TM) setExceptionSelectorRegister(Mips::A1); } -MVT::SimpleValueType MipsTargetLowering::getSetCCResultType(EVT VT) const { +bool MipsTargetLowering::allowsUnalignedMemoryAccesses(EVT VT) const { + MVT::SimpleValueType SVT = VT.getSimpleVT().SimpleTy; + return SVT == MVT::i64 || SVT == MVT::i32 || SVT == MVT::i16; +} + +EVT MipsTargetLowering::getSetCCResultType(EVT VT) const { return MVT::i32; } @@ -348,7 +394,7 @@ static SDValue PerformADDECombine(SDNode *N, SelectionDAG& DAG, if (DCI.isBeforeLegalize()) return SDValue(); - if (Subtarget->isMips32() && SelectMadd(N, &DAG)) + if (Subtarget->hasMips32() && SelectMadd(N, &DAG)) return SDValue(N, 0); return SDValue(); @@ -360,7 +406,7 @@ static SDValue PerformSUBECombine(SDNode *N, SelectionDAG& DAG, if (DCI.isBeforeLegalize()) return SDValue(); - if (Subtarget->isMips32() && SelectMsub(N, &DAG)) + if (Subtarget->hasMips32() && SelectMsub(N, &DAG)) return SDValue(N, 0); return SDValue(); @@ -372,6 +418,9 @@ static SDValue PerformDivRemCombine(SDNode *N, SelectionDAG& DAG, if (DCI.isBeforeLegalizeOps()) return SDValue(); + EVT Ty = N->getValueType(0); + unsigned LO = (Ty == MVT::i32) ? Mips::LO : Mips::LO64; + unsigned HI = (Ty == MVT::i32) ? Mips::HI : Mips::HI64; unsigned opc = N->getOpcode() == ISD::SDIVREM ? MipsISD::DivRem : MipsISD::DivRemU; DebugLoc dl = N->getDebugLoc(); @@ -383,7 +432,7 @@ static SDValue PerformDivRemCombine(SDNode *N, SelectionDAG& DAG, // insert MFLO if (N->hasAnyUseOfValue(0)) { - SDValue CopyFromLo = DAG.getCopyFromReg(InChain, dl, Mips::LO, MVT::i32, + SDValue CopyFromLo = DAG.getCopyFromReg(InChain, dl, LO, Ty, InGlue); DAG.ReplaceAllUsesOfValueWith(SDValue(N, 0), CopyFromLo); InChain = CopyFromLo.getValue(1); @@ -393,7 +442,7 @@ static SDValue PerformDivRemCombine(SDNode *N, SelectionDAG& DAG, // insert MFHI if (N->hasAnyUseOfValue(1)) { SDValue CopyFromHi = DAG.getCopyFromReg(InChain, dl, - Mips::HI, MVT::i32, InGlue); + HI, Ty, InGlue); DAG.ReplaceAllUsesOfValueWith(SDValue(N, 1), CopyFromHi); } @@ -490,6 +539,101 @@ static SDValue PerformSETCCCombine(SDNode *N, SelectionDAG& DAG, return CreateCMovFP(DAG, Cond, True, False, N->getDebugLoc()); } +static SDValue PerformANDCombine(SDNode *N, SelectionDAG& DAG, + TargetLowering::DAGCombinerInfo &DCI, + const MipsSubtarget* Subtarget) { + // Pattern match EXT. + // $dst = and ((sra or srl) $src , pos), (2**size - 1) + // => ext $dst, $src, size, pos + if (DCI.isBeforeLegalizeOps() || !Subtarget->hasMips32r2()) + return SDValue(); + + SDValue ShiftRight = N->getOperand(0), Mask = N->getOperand(1); + + // Op's first operand must be a shift right. + if (ShiftRight.getOpcode() != ISD::SRA && ShiftRight.getOpcode() != ISD::SRL) + return SDValue(); + + // The second operand of the shift must be an immediate. + uint64_t Pos; + ConstantSDNode *CN; + if (!(CN = dyn_cast<ConstantSDNode>(ShiftRight.getOperand(1)))) + return SDValue(); + + Pos = CN->getZExtValue(); + + uint64_t SMPos, SMSize; + // Op's second operand must be a shifted mask. + if (!(CN = dyn_cast<ConstantSDNode>(Mask)) || + !IsShiftedMask(CN->getZExtValue(), SMPos, SMSize)) + return SDValue(); + + // Return if the shifted mask does not start at bit 0 or the sum of its size + // and Pos exceeds the word's size. + if (SMPos != 0 || Pos + SMSize > 32) + return SDValue(); + + return DAG.getNode(MipsISD::Ext, N->getDebugLoc(), MVT::i32, + ShiftRight.getOperand(0), + DAG.getConstant(Pos, MVT::i32), + DAG.getConstant(SMSize, MVT::i32)); +} + +static SDValue PerformORCombine(SDNode *N, SelectionDAG& DAG, + TargetLowering::DAGCombinerInfo &DCI, + const MipsSubtarget* Subtarget) { + // Pattern match INS. + // $dst = or (and $src1 , mask0), (and (shl $src, pos), mask1), + // where mask1 = (2**size - 1) << pos, mask0 = ~mask1 + // => ins $dst, $src, size, pos, $src1 + if (DCI.isBeforeLegalizeOps() || !Subtarget->hasMips32r2()) + return SDValue(); + + SDValue And0 = N->getOperand(0), And1 = N->getOperand(1); + uint64_t SMPos0, SMSize0, SMPos1, SMSize1; + ConstantSDNode *CN; + + // See if Op's first operand matches (and $src1 , mask0). + if (And0.getOpcode() != ISD::AND) + return SDValue(); + + if (!(CN = dyn_cast<ConstantSDNode>(And0.getOperand(1))) || + !IsShiftedMask(~CN->getSExtValue(), SMPos0, SMSize0)) + return SDValue(); + + // See if Op's second operand matches (and (shl $src, pos), mask1). + if (And1.getOpcode() != ISD::AND) + return SDValue(); + + if (!(CN = dyn_cast<ConstantSDNode>(And1.getOperand(1))) || + !IsShiftedMask(CN->getZExtValue(), SMPos1, SMSize1)) + return SDValue(); + + // The shift masks must have the same position and size. + if (SMPos0 != SMPos1 || SMSize0 != SMSize1) + return SDValue(); + + SDValue Shl = And1.getOperand(0); + if (Shl.getOpcode() != ISD::SHL) + return SDValue(); + + if (!(CN = dyn_cast<ConstantSDNode>(Shl.getOperand(1)))) + return SDValue(); + + unsigned Shamt = CN->getZExtValue(); + + // Return if the shift amount and the first bit position of mask are not the + // same. + if (Shamt != SMPos0) + return SDValue(); + + return DAG.getNode(MipsISD::Ins, N->getDebugLoc(), MVT::i32, + Shl.getOperand(0), + DAG.getConstant(SMPos0, MVT::i32), + DAG.getConstant(SMSize0, MVT::i32), + And0.getOperand(0)); +} + SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const { SelectionDAG &DAG = DCI.DAG; @@ -506,6 +650,10 @@ SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) return PerformDivRemCombine(N, DAG, DCI, Subtarget); case ISD::SETCC: return PerformSETCCCombine(N, DAG, DCI, Subtarget); + case ISD::AND: + return PerformANDCombine(N, DAG, DCI, Subtarget); + case ISD::OR: + return PerformORCombine(N, DAG, DCI, Subtarget); } return SDValue(); @@ -527,6 +675,8 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const case ISD::VASTART: return LowerVASTART(Op, DAG); case ISD::FCOPYSIGN: return LowerFCOPYSIGN(Op, DAG); case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG); + case ISD::MEMBARRIER: return LowerMEMBARRIER(Op, DAG); + case ISD::ATOMIC_FENCE: return LowerATOMIC_FENCE(Op, DAG); } return SDValue(); } @@ -733,13 +883,13 @@ MipsTargetLowering::EmitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB, const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); DebugLoc dl = MI->getDebugLoc(); - unsigned Dest = MI->getOperand(0).getReg(); + unsigned OldVal = MI->getOperand(0).getReg(); unsigned Ptr = MI->getOperand(1).getReg(); unsigned Incr = MI->getOperand(2).getReg(); - unsigned Oldval = RegInfo.createVirtualRegister(RC); - unsigned Tmp1 = RegInfo.createVirtualRegister(RC); - unsigned Tmp2 = RegInfo.createVirtualRegister(RC); + unsigned StoreVal = RegInfo.createVirtualRegister(RC); + unsigned AndRes = RegInfo.createVirtualRegister(RC); + unsigned Success = RegInfo.createVirtualRegister(RC); // insert new blocks after the current block const BasicBlock *LLVM_BB = BB->getBasicBlock(); @@ -758,61 +908,38 @@ MipsTargetLowering::EmitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB, // thisMBB: // ... - // sw incr, fi(sp) // store incr to stack (when BinOpcode == 0) // fallthrough --> loopMBB - - // Note: for atomic.swap (when BinOpcode == 0), storing incr to stack before - // the loop and then loading it from stack in block loopMBB is necessary to - // prevent MachineLICM pass to hoist "or" instruction out of the block - // loopMBB. - - int fi = 0; - if (BinOpcode == 0 && !Nand) { - // Get or create a temporary stack location. - MipsFunctionInfo *MipsFI = MF->getInfo<MipsFunctionInfo>(); - fi = MipsFI->getAtomicFrameIndex(); - if (fi == -1) { - fi = MF->getFrameInfo()->CreateStackObject(Size, Size, false); - MipsFI->setAtomicFrameIndex(fi); - } - - BuildMI(BB, dl, TII->get(Mips::SW)) - .addReg(Incr).addFrameIndex(fi).addImm(0); - } BB->addSuccessor(loopMBB); + loopMBB->addSuccessor(loopMBB); + loopMBB->addSuccessor(exitMBB); // loopMBB: // ll oldval, 0(ptr) - // or dest, $0, oldval - // <binop> tmp1, oldval, incr - // sc tmp1, 0(ptr) - // beq tmp1, $0, loopMBB + // <binop> storeval, oldval, incr + // sc success, storeval, 0(ptr) + // beq success, $0, loopMBB BB = loopMBB; - BuildMI(BB, dl, TII->get(Mips::LL), Oldval).addReg(Ptr).addImm(0); - BuildMI(BB, dl, TII->get(Mips::OR), Dest).addReg(Mips::ZERO).addReg(Oldval); + BuildMI(BB, dl, TII->get(Mips::LL), OldVal).addReg(Ptr).addImm(0); if (Nand) { - // and tmp2, oldval, incr - // nor tmp1, $0, tmp2 - BuildMI(BB, dl, TII->get(Mips::AND), Tmp2).addReg(Oldval).addReg(Incr); - BuildMI(BB, dl, TII->get(Mips::NOR), Tmp1).addReg(Mips::ZERO).addReg(Tmp2); + // and andres, oldval, incr + // nor storeval, $0, andres + BuildMI(BB, dl, TII->get(Mips::AND), AndRes).addReg(OldVal).addReg(Incr); + BuildMI(BB, dl, TII->get(Mips::NOR), StoreVal) + .addReg(Mips::ZERO).addReg(AndRes); } else if (BinOpcode) { - // <binop> tmp1, oldval, incr - BuildMI(BB, dl, TII->get(BinOpcode), Tmp1).addReg(Oldval).addReg(Incr); + // <binop> storeval, oldval, incr + BuildMI(BB, dl, TII->get(BinOpcode), StoreVal).addReg(OldVal).addReg(Incr); } else { - // lw tmp2, fi(sp) // load incr from stack - // or tmp1, $zero, tmp2 - BuildMI(BB, dl, TII->get(Mips::LW), Tmp2).addFrameIndex(fi).addImm(0); - BuildMI(BB, dl, TII->get(Mips::OR), Tmp1).addReg(Mips::ZERO).addReg(Tmp2); + StoreVal = Incr; } - BuildMI(BB, dl, TII->get(Mips::SC), Tmp1).addReg(Tmp1).addReg(Ptr).addImm(0); + BuildMI(BB, dl, TII->get(Mips::SC), Success) + .addReg(StoreVal).addReg(Ptr).addImm(0); BuildMI(BB, dl, TII->get(Mips::BEQ)) - .addReg(Tmp1).addReg(Mips::ZERO).addMBB(loopMBB); - BB->addSuccessor(loopMBB); - BB->addSuccessor(exitMBB); + .addReg(Success).addReg(Mips::ZERO).addMBB(loopMBB); MI->eraseFromParent(); // The instruction is gone now. - return BB; + return exitMBB; } MachineBasicBlock * @@ -833,33 +960,34 @@ MipsTargetLowering::EmitAtomicBinaryPartword(MachineInstr *MI, unsigned Ptr = MI->getOperand(1).getReg(); unsigned Incr = MI->getOperand(2).getReg(); - unsigned Addr = RegInfo.createVirtualRegister(RC); - unsigned Shift = RegInfo.createVirtualRegister(RC); + unsigned AlignedAddr = RegInfo.createVirtualRegister(RC); + unsigned ShiftAmt = RegInfo.createVirtualRegister(RC); unsigned Mask = RegInfo.createVirtualRegister(RC); unsigned Mask2 = RegInfo.createVirtualRegister(RC); - unsigned Newval = RegInfo.createVirtualRegister(RC); - unsigned Oldval = RegInfo.createVirtualRegister(RC); + unsigned NewVal = RegInfo.createVirtualRegister(RC); + unsigned OldVal = RegInfo.createVirtualRegister(RC); unsigned Incr2 = RegInfo.createVirtualRegister(RC); - unsigned Tmp1 = RegInfo.createVirtualRegister(RC); - unsigned Tmp2 = RegInfo.createVirtualRegister(RC); - unsigned Tmp3 = RegInfo.createVirtualRegister(RC); - unsigned Tmp4 = RegInfo.createVirtualRegister(RC); - unsigned Tmp5 = RegInfo.createVirtualRegister(RC); - unsigned Tmp6 = RegInfo.createVirtualRegister(RC); - unsigned Tmp7 = RegInfo.createVirtualRegister(RC); - unsigned Tmp8 = RegInfo.createVirtualRegister(RC); - unsigned Tmp9 = RegInfo.createVirtualRegister(RC); - unsigned Tmp10 = RegInfo.createVirtualRegister(RC); - unsigned Tmp11 = RegInfo.createVirtualRegister(RC); - unsigned Tmp12 = RegInfo.createVirtualRegister(RC); + unsigned MaskLSB2 = RegInfo.createVirtualRegister(RC); + unsigned PtrLSB2 = RegInfo.createVirtualRegister(RC); + unsigned MaskUpper = RegInfo.createVirtualRegister(RC); + unsigned AndRes = RegInfo.createVirtualRegister(RC); + unsigned BinOpRes = RegInfo.createVirtualRegister(RC); + unsigned MaskedOldVal0 = RegInfo.createVirtualRegister(RC); + unsigned StoreVal = RegInfo.createVirtualRegister(RC); + unsigned MaskedOldVal1 = RegInfo.createVirtualRegister(RC); + unsigned SrlRes = RegInfo.createVirtualRegister(RC); + unsigned SllRes = RegInfo.createVirtualRegister(RC); + unsigned Success = RegInfo.createVirtualRegister(RC); // insert new blocks after the current block const BasicBlock *LLVM_BB = BB->getBasicBlock(); MachineBasicBlock *loopMBB = MF->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *sinkMBB = MF->CreateMachineBasicBlock(LLVM_BB); MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB); MachineFunction::iterator It = BB; ++It; MF->insert(It, loopMBB); + MF->insert(It, sinkMBB); MF->insert(It, exitMBB); // Transfer the remainder of BB and its successor edges to exitMBB. @@ -868,111 +996,104 @@ MipsTargetLowering::EmitAtomicBinaryPartword(MachineInstr *MI, BB->end()); exitMBB->transferSuccessorsAndUpdatePHIs(BB); + BB->addSuccessor(loopMBB); + loopMBB->addSuccessor(loopMBB); + loopMBB->addSuccessor(sinkMBB); + sinkMBB->addSuccessor(exitMBB); + // thisMBB: - // addiu tmp1,$0,-4 # 0xfffffffc - // and addr,ptr,tmp1 - // andi tmp2,ptr,3 - // sll shift,tmp2,3 - // ori tmp3,$0,255 # 0xff - // sll mask,tmp3,shift + // addiu masklsb2,$0,-4 # 0xfffffffc + // and alignedaddr,ptr,masklsb2 + // andi ptrlsb2,ptr,3 + // sll shiftamt,ptrlsb2,3 + // ori maskupper,$0,255 # 0xff + // sll mask,maskupper,shiftamt // nor mask2,$0,mask - // andi tmp4,incr,255 - // sll incr2,tmp4,shift - // sw incr2, fi(sp) // store incr2 to stack (when BinOpcode == 0) - - // Note: for atomic.swap (when BinOpcode == 0), storing incr2 to stack before - // the loop and then loading it from stack in block loopMBB is necessary to - // prevent MachineLICM pass to hoist "or" instruction out of the block - // loopMBB. + // sll incr2,incr,shiftamt int64_t MaskImm = (Size == 1) ? 255 : 65535; - BuildMI(BB, dl, TII->get(Mips::ADDiu), Tmp1).addReg(Mips::ZERO).addImm(-4); - BuildMI(BB, dl, TII->get(Mips::AND), Addr).addReg(Ptr).addReg(Tmp1); - BuildMI(BB, dl, TII->get(Mips::ANDi), Tmp2).addReg(Ptr).addImm(3); - BuildMI(BB, dl, TII->get(Mips::SLL), Shift).addReg(Tmp2).addImm(3); - BuildMI(BB, dl, TII->get(Mips::ORi), Tmp3).addReg(Mips::ZERO).addImm(MaskImm); - BuildMI(BB, dl, TII->get(Mips::SLL), Mask).addReg(Tmp3).addReg(Shift); + BuildMI(BB, dl, TII->get(Mips::ADDiu), MaskLSB2) + .addReg(Mips::ZERO).addImm(-4); + BuildMI(BB, dl, TII->get(Mips::AND), AlignedAddr) + .addReg(Ptr).addReg(MaskLSB2); + BuildMI(BB, dl, TII->get(Mips::ANDi), PtrLSB2).addReg(Ptr).addImm(3); + BuildMI(BB, dl, TII->get(Mips::SLL), ShiftAmt).addReg(PtrLSB2).addImm(3); + BuildMI(BB, dl, TII->get(Mips::ORi), MaskUpper) + .addReg(Mips::ZERO).addImm(MaskImm); + BuildMI(BB, dl, TII->get(Mips::SLLV), Mask) + .addReg(ShiftAmt).addReg(MaskUpper); BuildMI(BB, dl, TII->get(Mips::NOR), Mask2).addReg(Mips::ZERO).addReg(Mask); - if (BinOpcode != Mips::SUBu) { - BuildMI(BB, dl, TII->get(Mips::ANDi), Tmp4).addReg(Incr).addImm(MaskImm); - BuildMI(BB, dl, TII->get(Mips::SLL), Incr2).addReg(Tmp4).addReg(Shift); - } else { - BuildMI(BB, dl, TII->get(Mips::SUBu), Tmp4).addReg(Mips::ZERO).addReg(Incr); - BuildMI(BB, dl, TII->get(Mips::ANDi), Tmp5).addReg(Tmp4).addImm(MaskImm); - BuildMI(BB, dl, TII->get(Mips::SLL), Incr2).addReg(Tmp5).addReg(Shift); - } + BuildMI(BB, dl, TII->get(Mips::SLLV), Incr2).addReg(ShiftAmt).addReg(Incr); - int fi = 0; - if (BinOpcode == 0 && !Nand) { - // Get or create a temporary stack location. - MipsFunctionInfo *MipsFI = MF->getInfo<MipsFunctionInfo>(); - fi = MipsFI->getAtomicFrameIndex(); - if (fi == -1) { - fi = MF->getFrameInfo()->CreateStackObject(Size, Size, false); - MipsFI->setAtomicFrameIndex(fi); - } - - BuildMI(BB, dl, TII->get(Mips::SW)) - .addReg(Incr2).addFrameIndex(fi).addImm(0); - } - BB->addSuccessor(loopMBB); + // atomic.load.binop + // loopMBB: + // ll oldval,0(alignedaddr) + // binop binopres,oldval,incr2 + // and newval,binopres,mask + // and maskedoldval0,oldval,mask2 + // or storeval,maskedoldval0,newval + // sc success,storeval,0(alignedaddr) + // beq success,$0,loopMBB + + // atomic.swap // loopMBB: - // ll oldval,0(addr) - // binop tmp7,oldval,incr2 - // and newval,tmp7,mask - // and tmp8,oldval,mask2 - // or tmp9,tmp8,newval - // sc tmp9,0(addr) - // beq tmp9,$0,loopMBB + // ll oldval,0(alignedaddr) + // and newval,incr2,mask + // and maskedoldval0,oldval,mask2 + // or storeval,maskedoldval0,newval + // sc success,storeval,0(alignedaddr) + // beq success,$0,loopMBB + BB = loopMBB; - BuildMI(BB, dl, TII->get(Mips::LL), Oldval).addReg(Addr).addImm(0); + BuildMI(BB, dl, TII->get(Mips::LL), OldVal).addReg(AlignedAddr).addImm(0); if (Nand) { - // and tmp6, oldval, incr2 - // nor tmp7, $0, tmp6 - BuildMI(BB, dl, TII->get(Mips::AND), Tmp6).addReg(Oldval).addReg(Incr2); - BuildMI(BB, dl, TII->get(Mips::NOR), Tmp7).addReg(Mips::ZERO).addReg(Tmp6); - } else if (BinOpcode == Mips::SUBu) { - // addu tmp7, oldval, incr2 - BuildMI(BB, dl, TII->get(Mips::ADDu), Tmp7).addReg(Oldval).addReg(Incr2); + // and andres, oldval, incr2 + // nor binopres, $0, andres + // and newval, binopres, mask + BuildMI(BB, dl, TII->get(Mips::AND), AndRes).addReg(OldVal).addReg(Incr2); + BuildMI(BB, dl, TII->get(Mips::NOR), BinOpRes) + .addReg(Mips::ZERO).addReg(AndRes); + BuildMI(BB, dl, TII->get(Mips::AND), NewVal).addReg(BinOpRes).addReg(Mask); } else if (BinOpcode) { - // <binop> tmp7, oldval, incr2 - BuildMI(BB, dl, TII->get(BinOpcode), Tmp7).addReg(Oldval).addReg(Incr2); - } else { - // lw tmp6, fi(sp) // load incr2 from stack - // or tmp7, $zero, tmp6 - BuildMI(BB, dl, TII->get(Mips::LW), Tmp6).addFrameIndex(fi).addImm(0); - BuildMI(BB, dl, TII->get(Mips::OR), Tmp7).addReg(Mips::ZERO).addReg(Tmp6); + // <binop> binopres, oldval, incr2 + // and newval, binopres, mask + BuildMI(BB, dl, TII->get(BinOpcode), BinOpRes).addReg(OldVal).addReg(Incr2); + BuildMI(BB, dl, TII->get(Mips::AND), NewVal).addReg(BinOpRes).addReg(Mask); + } else {// atomic.swap + // and newval, incr2, mask + BuildMI(BB, dl, TII->get(Mips::AND), NewVal).addReg(Incr2).addReg(Mask); } - BuildMI(BB, dl, TII->get(Mips::AND), Newval).addReg(Tmp7).addReg(Mask); - BuildMI(BB, dl, TII->get(Mips::AND), Tmp8).addReg(Oldval).addReg(Mask2); - BuildMI(BB, dl, TII->get(Mips::OR), Tmp9).addReg(Tmp8).addReg(Newval); - BuildMI(BB, dl, TII->get(Mips::SC), Tmp9).addReg(Tmp9).addReg(Addr).addImm(0); + + BuildMI(BB, dl, TII->get(Mips::AND), MaskedOldVal0) + .addReg(OldVal).addReg(Mask2); + BuildMI(BB, dl, TII->get(Mips::OR), StoreVal) + .addReg(MaskedOldVal0).addReg(NewVal); + BuildMI(BB, dl, TII->get(Mips::SC), Success) + .addReg(StoreVal).addReg(AlignedAddr).addImm(0); BuildMI(BB, dl, TII->get(Mips::BEQ)) - .addReg(Tmp9).addReg(Mips::ZERO).addMBB(loopMBB); - BB->addSuccessor(loopMBB); - BB->addSuccessor(exitMBB); - - // exitMBB: - // and tmp10,oldval,mask - // srl tmp11,tmp10,shift - // sll tmp12,tmp11,24 - // sra dest,tmp12,24 - BB = exitMBB; + .addReg(Success).addReg(Mips::ZERO).addMBB(loopMBB); + + // sinkMBB: + // and maskedoldval1,oldval,mask + // srl srlres,maskedoldval1,shiftamt + // sll sllres,srlres,24 + // sra dest,sllres,24 + BB = sinkMBB; int64_t ShiftImm = (Size == 1) ? 24 : 16; - // reverse order - BuildMI(*BB, BB->begin(), dl, TII->get(Mips::SRA), Dest) - .addReg(Tmp12).addImm(ShiftImm); - BuildMI(*BB, BB->begin(), dl, TII->get(Mips::SLL), Tmp12) - .addReg(Tmp11).addImm(ShiftImm); - BuildMI(*BB, BB->begin(), dl, TII->get(Mips::SRL), Tmp11) - .addReg(Tmp10).addReg(Shift); - BuildMI(*BB, BB->begin(), dl, TII->get(Mips::AND), Tmp10) - .addReg(Oldval).addReg(Mask); + + BuildMI(BB, dl, TII->get(Mips::AND), MaskedOldVal1) + .addReg(OldVal).addReg(Mask); + BuildMI(BB, dl, TII->get(Mips::SRLV), SrlRes) + .addReg(ShiftAmt).addReg(MaskedOldVal1); + BuildMI(BB, dl, TII->get(Mips::SLL), SllRes) + .addReg(SrlRes).addImm(ShiftImm); + BuildMI(BB, dl, TII->get(Mips::SRA), Dest) + .addReg(SllRes).addImm(ShiftImm); MI->eraseFromParent(); // The instruction is gone now. - return BB; + return exitMBB; } MachineBasicBlock * @@ -989,11 +1110,10 @@ MipsTargetLowering::EmitAtomicCmpSwap(MachineInstr *MI, unsigned Dest = MI->getOperand(0).getReg(); unsigned Ptr = MI->getOperand(1).getReg(); - unsigned Oldval = MI->getOperand(2).getReg(); - unsigned Newval = MI->getOperand(3).getReg(); + unsigned OldVal = MI->getOperand(2).getReg(); + unsigned NewVal = MI->getOperand(3).getReg(); - unsigned Tmp1 = RegInfo.createVirtualRegister(RC); - unsigned Tmp2 = RegInfo.createVirtualRegister(RC); + unsigned Success = RegInfo.createVirtualRegister(RC); // insert new blocks after the current block const BasicBlock *LLVM_BB = BB->getBasicBlock(); @@ -1012,26 +1132,14 @@ MipsTargetLowering::EmitAtomicCmpSwap(MachineInstr *MI, BB->end()); exitMBB->transferSuccessorsAndUpdatePHIs(BB); - // Get or create a temporary stack location. - MipsFunctionInfo *MipsFI = MF->getInfo<MipsFunctionInfo>(); - int fi = MipsFI->getAtomicFrameIndex(); - if (fi == -1) { - fi = MF->getFrameInfo()->CreateStackObject(Size, Size, false); - MipsFI->setAtomicFrameIndex(fi); - } - // thisMBB: // ... - // sw newval, fi(sp) // store newval to stack // fallthrough --> loop1MBB - - // Note: storing newval to stack before the loop and then loading it from - // stack in block loop2MBB is necessary to prevent MachineLICM pass to - // hoist "or" instruction out of the block loop2MBB. - - BuildMI(BB, dl, TII->get(Mips::SW)) - .addReg(Newval).addFrameIndex(fi).addImm(0); BB->addSuccessor(loop1MBB); + loop1MBB->addSuccessor(exitMBB); + loop1MBB->addSuccessor(loop2MBB); + loop2MBB->addSuccessor(loop1MBB); + loop2MBB->addSuccessor(exitMBB); // loop1MBB: // ll dest, 0(ptr) @@ -1039,27 +1147,20 @@ MipsTargetLowering::EmitAtomicCmpSwap(MachineInstr *MI, BB = loop1MBB; BuildMI(BB, dl, TII->get(Mips::LL), Dest).addReg(Ptr).addImm(0); BuildMI(BB, dl, TII->get(Mips::BNE)) - .addReg(Dest).addReg(Oldval).addMBB(exitMBB); - BB->addSuccessor(exitMBB); - BB->addSuccessor(loop2MBB); + .addReg(Dest).addReg(OldVal).addMBB(exitMBB); // loop2MBB: - // lw tmp2, fi(sp) // load newval from stack - // or tmp1, $0, tmp2 - // sc tmp1, 0(ptr) - // beq tmp1, $0, loop1MBB + // sc success, newval, 0(ptr) + // beq success, $0, loop1MBB BB = loop2MBB; - BuildMI(BB, dl, TII->get(Mips::LW), Tmp2).addFrameIndex(fi).addImm(0); - BuildMI(BB, dl, TII->get(Mips::OR), Tmp1).addReg(Mips::ZERO).addReg(Tmp2); - BuildMI(BB, dl, TII->get(Mips::SC), Tmp1).addReg(Tmp1).addReg(Ptr).addImm(0); + BuildMI(BB, dl, TII->get(Mips::SC), Success) + .addReg(NewVal).addReg(Ptr).addImm(0); BuildMI(BB, dl, TII->get(Mips::BEQ)) - .addReg(Tmp1).addReg(Mips::ZERO).addMBB(loop1MBB); - BB->addSuccessor(loop1MBB); - BB->addSuccessor(exitMBB); + .addReg(Success).addReg(Mips::ZERO).addMBB(loop1MBB); MI->eraseFromParent(); // The instruction is gone now. - return BB; + return exitMBB; } MachineBasicBlock * @@ -1077,36 +1178,39 @@ MipsTargetLowering::EmitAtomicCmpSwapPartword(MachineInstr *MI, unsigned Dest = MI->getOperand(0).getReg(); unsigned Ptr = MI->getOperand(1).getReg(); - unsigned Oldval = MI->getOperand(2).getReg(); - unsigned Newval = MI->getOperand(3).getReg(); + unsigned CmpVal = MI->getOperand(2).getReg(); + unsigned NewVal = MI->getOperand(3).getReg(); - unsigned Addr = RegInfo.createVirtualRegister(RC); - unsigned Shift = RegInfo.createVirtualRegister(RC); + unsigned AlignedAddr = RegInfo.createVirtualRegister(RC); + unsigned ShiftAmt = RegInfo.createVirtualRegister(RC); unsigned Mask = RegInfo.createVirtualRegister(RC); unsigned Mask2 = RegInfo.createVirtualRegister(RC); - unsigned Oldval2 = RegInfo.createVirtualRegister(RC); - unsigned Oldval3 = RegInfo.createVirtualRegister(RC); - unsigned Oldval4 = RegInfo.createVirtualRegister(RC); - unsigned Newval2 = RegInfo.createVirtualRegister(RC); - unsigned Tmp1 = RegInfo.createVirtualRegister(RC); - unsigned Tmp2 = RegInfo.createVirtualRegister(RC); - unsigned Tmp3 = RegInfo.createVirtualRegister(RC); - unsigned Tmp4 = RegInfo.createVirtualRegister(RC); - unsigned Tmp5 = RegInfo.createVirtualRegister(RC); - unsigned Tmp6 = RegInfo.createVirtualRegister(RC); - unsigned Tmp7 = RegInfo.createVirtualRegister(RC); - unsigned Tmp8 = RegInfo.createVirtualRegister(RC); - unsigned Tmp9 = RegInfo.createVirtualRegister(RC); + unsigned ShiftedCmpVal = RegInfo.createVirtualRegister(RC); + unsigned OldVal = RegInfo.createVirtualRegister(RC); + unsigned MaskedOldVal0 = RegInfo.createVirtualRegister(RC); + unsigned ShiftedNewVal = RegInfo.createVirtualRegister(RC); + unsigned MaskLSB2 = RegInfo.createVirtualRegister(RC); + unsigned PtrLSB2 = RegInfo.createVirtualRegister(RC); + unsigned MaskUpper = RegInfo.createVirtualRegister(RC); + unsigned MaskedCmpVal = RegInfo.createVirtualRegister(RC); + unsigned MaskedNewVal = RegInfo.createVirtualRegister(RC); + unsigned MaskedOldVal1 = RegInfo.createVirtualRegister(RC); + unsigned StoreVal = RegInfo.createVirtualRegister(RC); + unsigned SrlRes = RegInfo.createVirtualRegister(RC); + unsigned SllRes = RegInfo.createVirtualRegister(RC); + unsigned Success = RegInfo.createVirtualRegister(RC); // insert new blocks after the current block const BasicBlock *LLVM_BB = BB->getBasicBlock(); MachineBasicBlock *loop1MBB = MF->CreateMachineBasicBlock(LLVM_BB); MachineBasicBlock *loop2MBB = MF->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *sinkMBB = MF->CreateMachineBasicBlock(LLVM_BB); MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB); MachineFunction::iterator It = BB; ++It; MF->insert(It, loop1MBB); MF->insert(It, loop2MBB); + MF->insert(It, sinkMBB); MF->insert(It, exitMBB); // Transfer the remainder of BB and its successor edges to exitMBB. @@ -1115,76 +1219,90 @@ MipsTargetLowering::EmitAtomicCmpSwapPartword(MachineInstr *MI, BB->end()); exitMBB->transferSuccessorsAndUpdatePHIs(BB); + BB->addSuccessor(loop1MBB); + loop1MBB->addSuccessor(sinkMBB); + loop1MBB->addSuccessor(loop2MBB); + loop2MBB->addSuccessor(loop1MBB); + loop2MBB->addSuccessor(sinkMBB); + sinkMBB->addSuccessor(exitMBB); + + // FIXME: computation of newval2 can be moved to loop2MBB. // thisMBB: - // addiu tmp1,$0,-4 # 0xfffffffc - // and addr,ptr,tmp1 - // andi tmp2,ptr,3 - // sll shift,tmp2,3 - // ori tmp3,$0,255 # 0xff - // sll mask,tmp3,shift + // addiu masklsb2,$0,-4 # 0xfffffffc + // and alignedaddr,ptr,masklsb2 + // andi ptrlsb2,ptr,3 + // sll shiftamt,ptrlsb2,3 + // ori maskupper,$0,255 # 0xff + // sll mask,maskupper,shiftamt // nor mask2,$0,mask - // andi tmp4,oldval,255 - // sll oldval2,tmp4,shift - // andi tmp5,newval,255 - // sll newval2,tmp5,shift + // andi maskedcmpval,cmpval,255 + // sll shiftedcmpval,maskedcmpval,shiftamt + // andi maskednewval,newval,255 + // sll shiftednewval,maskednewval,shiftamt int64_t MaskImm = (Size == 1) ? 255 : 65535; - BuildMI(BB, dl, TII->get(Mips::ADDiu), Tmp1).addReg(Mips::ZERO).addImm(-4); - BuildMI(BB, dl, TII->get(Mips::AND), Addr).addReg(Ptr).addReg(Tmp1); - BuildMI(BB, dl, TII->get(Mips::ANDi), Tmp2).addReg(Ptr).addImm(3); - BuildMI(BB, dl, TII->get(Mips::SLL), Shift).addReg(Tmp2).addImm(3); - BuildMI(BB, dl, TII->get(Mips::ORi), Tmp3).addReg(Mips::ZERO).addImm(MaskImm); - BuildMI(BB, dl, TII->get(Mips::SLL), Mask).addReg(Tmp3).addReg(Shift); + BuildMI(BB, dl, TII->get(Mips::ADDiu), MaskLSB2) + .addReg(Mips::ZERO).addImm(-4); + BuildMI(BB, dl, TII->get(Mips::AND), AlignedAddr) + .addReg(Ptr).addReg(MaskLSB2); + BuildMI(BB, dl, TII->get(Mips::ANDi), PtrLSB2).addReg(Ptr).addImm(3); + BuildMI(BB, dl, TII->get(Mips::SLL), ShiftAmt).addReg(PtrLSB2).addImm(3); + BuildMI(BB, dl, TII->get(Mips::ORi), MaskUpper) + .addReg(Mips::ZERO).addImm(MaskImm); + BuildMI(BB, dl, TII->get(Mips::SLLV), Mask) + .addReg(ShiftAmt).addReg(MaskUpper); BuildMI(BB, dl, TII->get(Mips::NOR), Mask2).addReg(Mips::ZERO).addReg(Mask); - BuildMI(BB, dl, TII->get(Mips::ANDi), Tmp4).addReg(Oldval).addImm(MaskImm); - BuildMI(BB, dl, TII->get(Mips::SLL), Oldval2).addReg(Tmp4).addReg(Shift); - BuildMI(BB, dl, TII->get(Mips::ANDi), Tmp5).addReg(Newval).addImm(MaskImm); - BuildMI(BB, dl, TII->get(Mips::SLL), Newval2).addReg(Tmp5).addReg(Shift); - BB->addSuccessor(loop1MBB); + BuildMI(BB, dl, TII->get(Mips::ANDi), MaskedCmpVal) + .addReg(CmpVal).addImm(MaskImm); + BuildMI(BB, dl, TII->get(Mips::SLLV), ShiftedCmpVal) + .addReg(ShiftAmt).addReg(MaskedCmpVal); + BuildMI(BB, dl, TII->get(Mips::ANDi), MaskedNewVal) + .addReg(NewVal).addImm(MaskImm); + BuildMI(BB, dl, TII->get(Mips::SLLV), ShiftedNewVal) + .addReg(ShiftAmt).addReg(MaskedNewVal); // loop1MBB: - // ll oldval3,0(addr) - // and oldval4,oldval3,mask - // bne oldval4,oldval2,exitMBB + // ll oldval,0(alginedaddr) + // and maskedoldval0,oldval,mask + // bne maskedoldval0,shiftedcmpval,sinkMBB BB = loop1MBB; - BuildMI(BB, dl, TII->get(Mips::LL), Oldval3).addReg(Addr).addImm(0); - BuildMI(BB, dl, TII->get(Mips::AND), Oldval4).addReg(Oldval3).addReg(Mask); + BuildMI(BB, dl, TII->get(Mips::LL), OldVal).addReg(AlignedAddr).addImm(0); + BuildMI(BB, dl, TII->get(Mips::AND), MaskedOldVal0) + .addReg(OldVal).addReg(Mask); BuildMI(BB, dl, TII->get(Mips::BNE)) - .addReg(Oldval4).addReg(Oldval2).addMBB(exitMBB); - BB->addSuccessor(exitMBB); - BB->addSuccessor(loop2MBB); + .addReg(MaskedOldVal0).addReg(ShiftedCmpVal).addMBB(sinkMBB); // loop2MBB: - // and tmp6,oldval3,mask2 - // or tmp7,tmp6,newval2 - // sc tmp7,0(addr) - // beq tmp7,$0,loop1MBB + // and maskedoldval1,oldval,mask2 + // or storeval,maskedoldval1,shiftednewval + // sc success,storeval,0(alignedaddr) + // beq success,$0,loop1MBB BB = loop2MBB; - BuildMI(BB, dl, TII->get(Mips::AND), Tmp6).addReg(Oldval3).addReg(Mask2); - BuildMI(BB, dl, TII->get(Mips::OR), Tmp7).addReg(Tmp6).addReg(Newval2); - BuildMI(BB, dl, TII->get(Mips::SC), Tmp7) - .addReg(Tmp7).addReg(Addr).addImm(0); + BuildMI(BB, dl, TII->get(Mips::AND), MaskedOldVal1) + .addReg(OldVal).addReg(Mask2); + BuildMI(BB, dl, TII->get(Mips::OR), StoreVal) + .addReg(MaskedOldVal1).addReg(ShiftedNewVal); + BuildMI(BB, dl, TII->get(Mips::SC), Success) + .addReg(StoreVal).addReg(AlignedAddr).addImm(0); BuildMI(BB, dl, TII->get(Mips::BEQ)) - .addReg(Tmp7).addReg(Mips::ZERO).addMBB(loop1MBB); - BB->addSuccessor(loop1MBB); - BB->addSuccessor(exitMBB); + .addReg(Success).addReg(Mips::ZERO).addMBB(loop1MBB); - // exitMBB: - // srl tmp8,oldval4,shift - // sll tmp9,tmp8,24 - // sra dest,tmp9,24 - BB = exitMBB; + // sinkMBB: + // srl srlres,maskedoldval0,shiftamt + // sll sllres,srlres,24 + // sra dest,sllres,24 + BB = sinkMBB; int64_t ShiftImm = (Size == 1) ? 24 : 16; - // reverse order - BuildMI(*BB, BB->begin(), dl, TII->get(Mips::SRA), Dest) - .addReg(Tmp9).addImm(ShiftImm); - BuildMI(*BB, BB->begin(), dl, TII->get(Mips::SLL), Tmp9) - .addReg(Tmp8).addImm(ShiftImm); - BuildMI(*BB, BB->begin(), dl, TII->get(Mips::SRL), Tmp8) - .addReg(Oldval4).addReg(Shift); + + BuildMI(BB, dl, TII->get(Mips::SRLV), SrlRes) + .addReg(ShiftAmt).addReg(MaskedOldVal0); + BuildMI(BB, dl, TII->get(Mips::SLL), SllRes) + .addReg(SrlRes).addImm(ShiftImm); + BuildMI(BB, dl, TII->get(Mips::SRA), Dest) + .addReg(SllRes).addImm(ShiftImm); MI->eraseFromParent(); // The instruction is gone now. - return BB; + return exitMBB; } //===----------------------------------------------------------------------===// @@ -1267,9 +1385,9 @@ SDValue MipsTargetLowering::LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const { // FIXME there isn't actually debug info here DebugLoc dl = Op.getDebugLoc(); - const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal(); + const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal(); - if (getTargetMachine().getRelocationModel() != Reloc::PIC_) { + if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && !IsN64) { SDVTList VTs = DAG.getVTList(MVT::i32); MipsTargetObjectFile &TLOF = (MipsTargetObjectFile&)getObjFileLowering(); @@ -1292,21 +1410,26 @@ SDValue MipsTargetLowering::LowerGlobalAddress(SDValue Op, return DAG.getNode(ISD::ADD, dl, MVT::i32, HiPart, Lo); } - SDValue GA = DAG.getTargetGlobalAddress(GV, dl, MVT::i32, 0, - MipsII::MO_GOT); - GA = DAG.getNode(MipsISD::WrapperPIC, dl, MVT::i32, GA); - SDValue ResNode = DAG.getLoad(MVT::i32, dl, + EVT ValTy = Op.getValueType(); + bool HasGotOfst = (GV->hasInternalLinkage() || + (GV->hasLocalLinkage() && !isa<Function>(GV))); + unsigned GotFlag = IsN64 ? + (HasGotOfst ? MipsII::MO_GOT_PAGE : MipsII::MO_GOT_DISP) : + MipsII::MO_GOT; + SDValue GA = DAG.getTargetGlobalAddress(GV, dl, ValTy, 0, GotFlag); + GA = DAG.getNode(MipsISD::WrapperPIC, dl, ValTy, GA); + SDValue ResNode = DAG.getLoad(ValTy, dl, DAG.getEntryNode(), GA, MachinePointerInfo(), false, false, 0); // On functions and global targets not internal linked only // a load from got/GP is necessary for PIC to work. - if (!GV->hasInternalLinkage() && - (!GV->hasLocalLinkage() || isa<Function>(GV))) + if (!HasGotOfst) return ResNode; - SDValue GALo = DAG.getTargetGlobalAddress(GV, dl, MVT::i32, 0, - MipsII::MO_ABS_LO); - SDValue Lo = DAG.getNode(MipsISD::Lo, dl, MVT::i32, GALo); - return DAG.getNode(ISD::ADD, dl, MVT::i32, ResNode, Lo); + SDValue GALo = DAG.getTargetGlobalAddress(GV, dl, ValTy, 0, + IsN64 ? MipsII::MO_GOT_OFST : + MipsII::MO_ABS_LO); + SDValue Lo = DAG.getNode(MipsISD::Lo, dl, ValTy, GALo); + return DAG.getNode(ISD::ADD, dl, ValTy, ResNode, Lo); } SDValue MipsTargetLowering::LowerBlockAddress(SDValue Op, @@ -1361,11 +1484,11 @@ LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const ArgListTy Args; ArgListEntry Entry; Entry.Node = Argument; - Entry.Ty = (const Type *) Type::getInt32Ty(*DAG.getContext()); + Entry.Ty = (Type *) Type::getInt32Ty(*DAG.getContext()); Args.push_back(Entry); std::pair<SDValue, SDValue> CallResult = LowerCallTo(DAG.getEntryNode(), - (const Type *) Type::getInt32Ty(*DAG.getContext()), + (Type *) Type::getInt32Ty(*DAG.getContext()), false, false, false, false, 0, CallingConv::C, false, true, DAG.getExternalSymbol("__tls_get_addr", PtrVT), Args, DAG, dl); @@ -1557,6 +1680,25 @@ LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const { return FrameAddr; } +// TODO: set SType according to the desired memory barrier behavior. +SDValue 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), + DAG.getConstant(SType, MVT::i32)); +} + +SDValue MipsTargetLowering::LowerATOMIC_FENCE(SDValue Op, + SelectionDAG& DAG) const { + // FIXME: Need pseudo-fence for 'singlethread' fences + // FIXME: Set SType for weaker fences where supported/appropriate. + unsigned SType = 0; + DebugLoc dl = Op.getDebugLoc(); + return DAG.getNode(MipsISD::Sync, dl, MVT::Other, Op.getOperand(0), + DAG.getConstant(SType, MVT::i32)); +} + //===----------------------------------------------------------------------===// // Calling Convention Implementation //===----------------------------------------------------------------------===// @@ -1679,55 +1821,109 @@ static const unsigned O32IntRegs[] = { Mips::A0, Mips::A1, Mips::A2, Mips::A3 }; +// Return next O32 integer argument register. +static unsigned getNextIntArgReg(unsigned Reg) { + assert((Reg == Mips::A0) || (Reg == Mips::A2)); + return (Reg == Mips::A0) ? Mips::A1 : Mips::A3; +} + // Write ByVal Arg to arg registers and stack. static void -WriteByValArg(SDValue& Chain, DebugLoc dl, +WriteByValArg(SDValue& ByValChain, SDValue Chain, DebugLoc dl, 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, - MVT PtrType) { - unsigned FirstWord = VA.getLocMemOffset() / 4; - unsigned NumWords = (Flags.getByValSize() + 3) / 4; - unsigned LastWord = FirstWord + NumWords; - unsigned CurWord; - - // copy the first 4 words of byval arg to registers A0 - A3 - for (CurWord = FirstWord; CurWord < std::min(LastWord, O32IntRegsSize); - ++CurWord) { + MVT PtrType, bool isLittle) { + unsigned LocMemOffset = VA.getLocMemOffset(); + unsigned Offset = 0; + uint32_t RemainingSize = Flags.getByValSize(); + unsigned ByValAlign = Flags.getByValAlign(); + + // Copy the first 4 words of byval arg to registers A0 - A3. + // FIXME: Use a stricter alignment if it enables better optimization in passes + // run later. + for (; RemainingSize >= 4 && LocMemOffset < 4 * 4; + Offset += 4, RemainingSize -= 4, LocMemOffset += 4) { SDValue LoadPtr = DAG.getNode(ISD::ADD, dl, MVT::i32, Arg, - DAG.getConstant((CurWord - FirstWord) * 4, - MVT::i32)); + DAG.getConstant(Offset, MVT::i32)); SDValue LoadVal = DAG.getLoad(MVT::i32, dl, Chain, LoadPtr, MachinePointerInfo(), - false, false, 0); + false, false, std::min(ByValAlign, + (unsigned )4)); MemOpChains.push_back(LoadVal.getValue(1)); - unsigned DstReg = O32IntRegs[CurWord]; + unsigned DstReg = O32IntRegs[LocMemOffset / 4]; RegsToPass.push_back(std::make_pair(DstReg, LoadVal)); } - // copy remaining part of byval arg to stack. - if (CurWord < LastWord) { - unsigned SizeInBytes = (LastWord - CurWord) * 4; - SDValue Src = DAG.getNode(ISD::ADD, dl, MVT::i32, Arg, - DAG.getConstant((CurWord - FirstWord) * 4, - MVT::i32)); - LastFI = MFI->CreateFixedObject(SizeInBytes, CurWord * 4, true); - SDValue Dst = DAG.getFrameIndex(LastFI, PtrType); - Chain = DAG.getMemcpy(Chain, dl, Dst, Src, - DAG.getConstant(SizeInBytes, MVT::i32), - /*Align*/4, - /*isVolatile=*/false, /*AlwaysInline=*/false, - MachinePointerInfo(0), MachinePointerInfo(0)); - MemOpChains.push_back(Chain); + if (RemainingSize == 0) + return; + + // If there still is a register available for argument passing, write the + // remaining part of the structure to it using subword loads and shifts. + if (LocMemOffset < 4 * 4) { + assert(RemainingSize <= 3 && RemainingSize >= 1 && + "There must be one to three bytes remaining."); + unsigned LoadSize = (RemainingSize == 3 ? 2 : RemainingSize); + SDValue LoadPtr = DAG.getNode(ISD::ADD, dl, MVT::i32, Arg, + DAG.getConstant(Offset, MVT::i32)); + unsigned Alignment = std::min(ByValAlign, (unsigned )4); + SDValue LoadVal = DAG.getExtLoad(ISD::ZEXTLOAD, dl, MVT::i32, Chain, + LoadPtr, MachinePointerInfo(), + MVT::getIntegerVT(LoadSize * 8), false, + false, Alignment); + MemOpChains.push_back(LoadVal.getValue(1)); + + // If target is big endian, shift it to the most significant half-word or + // byte. + if (!isLittle) + LoadVal = DAG.getNode(ISD::SHL, dl, MVT::i32, LoadVal, + DAG.getConstant(32 - LoadSize * 8, MVT::i32)); + + Offset += LoadSize; + RemainingSize -= LoadSize; + + // Read second subword if necessary. + if (RemainingSize != 0) { + assert(RemainingSize == 1 && "There must be one byte remaining."); + LoadPtr = DAG.getNode(ISD::ADD, dl, MVT::i32, Arg, + DAG.getConstant(Offset, MVT::i32)); + unsigned Alignment = std::min(ByValAlign, (unsigned )2); + SDValue Subword = DAG.getExtLoad(ISD::ZEXTLOAD, dl, MVT::i32, Chain, + LoadPtr, MachinePointerInfo(), + MVT::i8, false, false, Alignment); + MemOpChains.push_back(Subword.getValue(1)); + // Insert the loaded byte to LoadVal. + // FIXME: Use INS if supported by target. + unsigned ShiftAmt = isLittle ? 16 : 8; + SDValue Shift = DAG.getNode(ISD::SHL, dl, MVT::i32, Subword, + DAG.getConstant(ShiftAmt, MVT::i32)); + LoadVal = DAG.getNode(ISD::OR, dl, MVT::i32, LoadVal, Shift); + } + + unsigned DstReg = O32IntRegs[LocMemOffset / 4]; + RegsToPass.push_back(std::make_pair(DstReg, LoadVal)); + return; } + + // Create a fixed object on stack at offset LocMemOffset and copy + // remaining part of byval arg to it using memcpy. + SDValue Src = DAG.getNode(ISD::ADD, dl, MVT::i32, Arg, + DAG.getConstant(Offset, MVT::i32)); + LastFI = MFI->CreateFixedObject(RemainingSize, LocMemOffset, true); + SDValue Dst = DAG.getFrameIndex(LastFI, PtrType); + ByValChain = DAG.getMemcpy(ByValChain, dl, Dst, Src, + DAG.getConstant(RemainingSize, MVT::i32), + std::min(ByValAlign, (unsigned)4), + /*isVolatile=*/false, /*AlwaysInline=*/false, + MachinePointerInfo(0), MachinePointerInfo(0)); } /// LowerCall - functions arguments are copied from virtual regs to /// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted. /// TODO: isTailCall. SDValue -MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee, +MipsTargetLowering::LowerCall(SDValue InChain, SDValue Callee, CallingConv::ID CallConv, bool isVarArg, bool &isTailCall, const SmallVectorImpl<ISD::OutputArg> &Outs, @@ -1757,8 +1953,13 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee, // Get a count of how many bytes are to be pushed on the stack. unsigned NextStackOffset = CCInfo.getNextStackOffset(); - Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NextStackOffset, - true)); + // Chain is the output chain of the last Load/Store or CopyToReg node. + // ByValChain is the output chain of the last Memcpy node created for copying + // byval arguments to the stack. + SDValue Chain, CallSeqStart, ByValChain; + SDValue NextStackOffsetVal = DAG.getIntPtrConstant(NextStackOffset, true); + 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. @@ -1818,8 +2019,10 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee, Arg, DAG.getConstant(1, MVT::i32)); if (!Subtarget->isLittle()) std::swap(Lo, Hi); - RegsToPass.push_back(std::make_pair(VA.getLocReg(), Lo)); - RegsToPass.push_back(std::make_pair(VA.getLocReg()+1, Hi)); + unsigned LocRegLo = VA.getLocReg(); + unsigned LocRegHigh = getNextIntArgReg(LocRegLo); + RegsToPass.push_back(std::make_pair(LocRegLo, Lo)); + RegsToPass.push_back(std::make_pair(LocRegHigh, Hi)); continue; } } @@ -1852,8 +2055,8 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee, "No support for ByVal args by ABIs other than O32 yet."); assert(Flags.getByValSize() && "ByVal args of size 0 should have been ignored by front-end."); - WriteByValArg(Chain, dl, RegsToPass, MemOpChains, LastFI, MFI, DAG, Arg, - VA, Flags, getPointerTy()); + WriteByValArg(ByValChain, Chain, dl, RegsToPass, MemOpChains, LastFI, MFI, + DAG, Arg, VA, Flags, getPointerTy(), Subtarget->isLittle()); continue; } @@ -1875,6 +2078,12 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee, if (LastFI) MipsFI->extendOutArgFIRange(FirstFI, LastFI); + // If a memcpy has been created to copy a byval arg to a stack, replace the + // chain input of CallSeqStart with ByValChain. + if (InChain != ByValChain) + DAG.UpdateNodeOperands(CallSeqStart.getNode(), ByValChain, + NextStackOffsetVal); + // Transform all store nodes into one single node because all store // nodes are independent of each other. if (!MemOpChains.empty()) @@ -2071,12 +2280,13 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, if (RegVT == MVT::i32) RC = Mips::CPURegsRegisterClass; + else if (RegVT == MVT::i64) + RC = Mips::CPU64RegsRegisterClass; else if (RegVT == MVT::f32) RC = Mips::FGR32RegisterClass; - else if (RegVT == MVT::f64) { - if (!Subtarget->isSingleFloat()) - RC = Mips::AFGR64RegisterClass; - } else + else if (RegVT == MVT::f64) + RC = HasMips64 ? Mips::FGR64RegisterClass : Mips::AFGR64RegisterClass; + else llvm_unreachable("RegVT not supported by FormalArguments Lowering"); // Transform the arguments stored on @@ -2105,7 +2315,7 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, ArgValue = DAG.getNode(ISD::BITCAST, dl, MVT::f32, ArgValue); if (RegVT == MVT::i32 && VA.getValVT() == MVT::f64) { unsigned Reg2 = AddLiveIn(DAG.getMachineFunction(), - VA.getLocReg()+1, RC); + getNextIntArgReg(ArgReg), RC); SDValue ArgValue2 = DAG.getCopyFromReg(Chain, dl, Reg2, RegVT); if (!Subtarget->isLittle()) std::swap(ArgValue, ArgValue2); @@ -2313,7 +2523,7 @@ MipsTargetLowering::getSingleConstraintMatchWeight( // but allow it at the lowest weight. if (CallOperandVal == NULL) return CW_Default; - const Type *type = CallOperandVal->getType(); + Type *type = CallOperandVal->getType(); // Look at the constraint type. switch (*constraint) { default: diff --git a/contrib/llvm/lib/Target/Mips/MipsISelLowering.h b/contrib/llvm/lib/Target/Mips/MipsISelLowering.h index bda26a2..4be3fed5 100644 --- a/contrib/llvm/lib/Target/Mips/MipsISelLowering.h +++ b/contrib/llvm/lib/Target/Mips/MipsISelLowering.h @@ -81,7 +81,12 @@ namespace llvm { WrapperPIC, - DynAlloc + DynAlloc, + + Sync, + + Ext, + Ins }; } @@ -93,6 +98,8 @@ namespace llvm { public: explicit MipsTargetLowering(MipsTargetMachine &TM); + virtual bool allowsUnalignedMemoryAccesses (EVT VT) const; + /// LowerOperation - Provide custom lowering hooks for some operations. virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const; @@ -101,13 +108,14 @@ namespace llvm { virtual const char *getTargetNodeName(unsigned Opcode) const; /// getSetCCResultType - get the ISD::SETCC result ValueType - MVT::SimpleValueType getSetCCResultType(EVT VT) const; + EVT getSetCCResultType(EVT VT) const; virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const; private: // Subtarget Info const MipsSubtarget *Subtarget; - + + bool HasMips64, IsN64; // Lower Operand helpers SDValue LowerCallResult(SDValue Chain, SDValue InFlag, @@ -128,6 +136,8 @@ namespace llvm { SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const; SDValue LowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const; SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerMEMBARRIER(SDValue Op, SelectionDAG& DAG) const; + SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG& DAG) const; virtual SDValue LowerFormalArguments(SDValue Chain, diff --git a/contrib/llvm/lib/Target/Mips/MipsInstrFPU.td b/contrib/llvm/lib/Target/Mips/MipsInstrFPU.td index 021c167..2fb9d18 100644 --- a/contrib/llvm/lib/Target/Mips/MipsInstrFPU.td +++ b/contrib/llvm/lib/Target/Mips/MipsInstrFPU.td @@ -27,7 +27,7 @@ def SDT_MipsFPBrcond : SDTypeProfile<0, 2, [SDTCisInt<0>, SDTCisVT<1, OtherVT>]>; def SDT_MipsFPCmp : SDTypeProfile<0, 3, [SDTCisSameAs<0, 1>, SDTCisFP<1>, - SDTCisInt<2>]>; + SDTCisVT<2, i32>]>; def SDT_MipsCMovFP : SDTypeProfile<1, 2, [SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>]>; def SDT_MipsBuildPairF64 : SDTypeProfile<1, 2, [SDTCisVT<0, f64>, @@ -35,12 +35,11 @@ def SDT_MipsBuildPairF64 : SDTypeProfile<1, 2, [SDTCisVT<0, f64>, SDTCisSameAs<1, 2>]>; def SDT_MipsExtractElementF64 : SDTypeProfile<1, 2, [SDTCisVT<0, i32>, SDTCisVT<1, f64>, - SDTCisVT<0, i32>]>; + SDTCisVT<2, i32>]>; def MipsFPCmp : SDNode<"MipsISD::FPCmp", SDT_MipsFPCmp, [SDNPOutGlue]>; def MipsCMovFP_T : SDNode<"MipsISD::CMovFP_T", SDT_MipsCMovFP, [SDNPInGlue]>; def MipsCMovFP_F : SDNode<"MipsISD::CMovFP_F", SDT_MipsCMovFP, [SDNPInGlue]>; -def MipsFPRound : SDNode<"MipsISD::FPRound", SDTFPRoundOp, [SDNPOptInGlue]>; def MipsFPBrcond : SDNode<"MipsISD::FPBrcond", SDT_MipsFPBrcond, [SDNPHasChain, SDNPOptInGlue]>; def MipsBuildPairF64 : SDNode<"MipsISD::BuildPairF64", SDT_MipsBuildPairF64>; @@ -55,10 +54,10 @@ let PrintMethod = "printFCCOperand" in // Feature predicates. //===----------------------------------------------------------------------===// -def In32BitMode : Predicate<"!Subtarget.isFP64bit()">; +def IsFP64bit : Predicate<"Subtarget.isFP64bit()">; +def NotFP64bit : Predicate<"!Subtarget.isFP64bit()">; def IsSingleFloat : Predicate<"Subtarget.isSingleFloat()">; def IsNotSingleFloat : Predicate<"!Subtarget.isSingleFloat()">; -def IsNotMipsI : Predicate<"!Subtarget.isMips1()">; //===----------------------------------------------------------------------===// // Instruction Class Templates @@ -74,97 +73,87 @@ def IsNotMipsI : Predicate<"!Subtarget.isMips1()">; // Only S32 and D32 are supported right now. //===----------------------------------------------------------------------===// -multiclass FFR1_1<bits<6> funct, string asmstr> -{ - def _S32 : FFR<0x11, funct, 0x0, (outs FGR32:$fd), (ins FGR32:$fs), - !strconcat(asmstr, ".s\t$fd, $fs"), []>; - - def _D32 : FFR<0x11, funct, 0x1, (outs FGR32:$fd), (ins AFGR64:$fs), - !strconcat(asmstr, ".d\t$fd, $fs"), []>, Requires<[In32BitMode]>; +// FP load. +class FPLoad<bits<6> op, string opstr, PatFrag FOp, RegisterClass RC, + Operand MemOpnd>: + FFI<op, (outs RC:$ft), (ins MemOpnd:$base), + !strconcat(opstr, "\t$ft, $base"), [(set RC:$ft, (FOp addr:$base))]>; + +// FP store. +class FPStore<bits<6> op, string opstr, PatFrag FOp, RegisterClass RC, + Operand MemOpnd>: + FFI<op, (outs), (ins RC:$ft, MemOpnd:$base), + !strconcat(opstr, "\t$ft, $base"), [(store RC:$ft, addr:$base)]>; + +// Instructions that convert an FP value to 32-bit fixed point. +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]>; + def _D64 : FFR1<funct, 17, opstr, "w.d", FGR32, FGR64>, + Requires<[IsFP64bit]>; } -multiclass FFR1_2<bits<6> funct, string asmstr, SDNode FOp> -{ - def _S32 : FFR<0x11, funct, 0x0, (outs FGR32:$fd), (ins FGR32:$fs), - !strconcat(asmstr, ".s\t$fd, $fs"), - [(set FGR32:$fd, (FOp FGR32:$fs))]>; - - def _D32 : FFR<0x11, funct, 0x1, (outs AFGR64:$fd), (ins AFGR64:$fs), - !strconcat(asmstr, ".d\t$fd, $fs"), - [(set AFGR64:$fd, (FOp AFGR64:$fs))]>, Requires<[In32BitMode]>; +// Instructions that convert an FP value to 64-bit fixed point. +let Predicates = [IsFP64bit] 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>; } -class FFR1_3<bits<6> funct, bits<5> fmt, RegisterClass RcSrc, - RegisterClass RcDst, string asmstr>: - FFR<0x11, funct, fmt, (outs RcSrc:$fd), (ins RcDst:$fs), - !strconcat(asmstr, "\t$fd, $fs"), []>; - +// FP-to-FP conversion instructions. +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]>; + def _D64 : FFR1P<funct, 17, opstr, "d", FGR64, FGR64, OpNode>, + Requires<[IsFP64bit]>; +} -multiclass FFR1_4<bits<6> funct, string asmstr, SDNode FOp, bit isComm = 0> { +multiclass FFR2P_M<bits<6> funct, string opstr, SDNode OpNode, bit isComm = 0> { let isCommutable = isComm in { - def _S32 : FFR<0x11, funct, 0x0, (outs FGR32:$fd), - (ins FGR32:$fs, FGR32:$ft), - !strconcat(asmstr, ".s\t$fd, $fs, $ft"), - [(set FGR32:$fd, (FOp FGR32:$fs, FGR32:$ft))]>; - - def _D32 : FFR<0x11, funct, 0x1, (outs AFGR64:$fd), - (ins AFGR64:$fs, AFGR64:$ft), - !strconcat(asmstr, ".d\t$fd, $fs, $ft"), - [(set AFGR64:$fd, (FOp AFGR64:$fs, AFGR64:$ft))]>, - Requires<[In32BitMode]>; + def _S : FFR2P<funct, 16, opstr, "s", FGR32, OpNode>; + def _D32 : FFR2P<funct, 17, opstr, "d", AFGR64, OpNode>, + Requires<[NotFP64bit]>; + def _D64 : FFR2P<funct, 17, opstr, "d", FGR64, OpNode>, + Requires<[IsFP64bit]>; } } //===----------------------------------------------------------------------===// // Floating Point Instructions //===----------------------------------------------------------------------===// +defm ROUND_W : FFR1_W_M<0xc, "round">; +defm ROUND_L : FFR1_L_M<0x8, "round">; +defm TRUNC_W : FFR1_W_M<0xd, "trunc">; +defm TRUNC_L : FFR1_L_M<0x9, "trunc">; +defm CEIL_W : FFR1_W_M<0xe, "ceil">; +defm CEIL_L : FFR1_L_M<0xa, "ceil">; +defm FLOOR_W : FFR1_W_M<0xf, "floor">; +defm FLOOR_L : FFR1_L_M<0xb, "floor">; +defm CVT_W : FFR1_W_M<0x24, "cvt">; +defm CVT_L : FFR1_L_M<0x25, "cvt">; + +def CVT_S_W : FFR1<0x20, 20, "cvt", "s.w", FGR32, FGR32>; + +let Predicates = [NotFP64bit] 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 ft = 0 in { - defm FLOOR_W : FFR1_1<0b001111, "floor.w">; - defm CEIL_W : FFR1_1<0b001110, "ceil.w">; - defm ROUND_W : FFR1_1<0b001100, "round.w">; - defm TRUNC_W : FFR1_1<0b001101, "trunc.w">; - defm CVTW : FFR1_1<0b100100, "cvt.w">; - - defm FABS : FFR1_2<0b000101, "abs", fabs>; - defm FNEG : FFR1_2<0b000111, "neg", fneg>; - defm FSQRT : FFR1_2<0b000100, "sqrt", fsqrt>; - - /// Convert to Single Precison - def CVTS_W32 : FFR1_3<0b100000, 0x2, FGR32, FGR32, "cvt.s.w">; - - let Predicates = [IsNotSingleFloat] in { - /// Ceil to long signed integer - def CEIL_LS : FFR1_3<0b001010, 0x0, FGR32, FGR32, "ceil.l">; - def CEIL_LD : FFR1_3<0b001010, 0x1, AFGR64, AFGR64, "ceil.l">; - - /// Round to long signed integer - def ROUND_LS : FFR1_3<0b001000, 0x0, FGR32, FGR32, "round.l">; - def ROUND_LD : FFR1_3<0b001000, 0x1, AFGR64, AFGR64, "round.l">; - - /// Floor to long signed integer - def FLOOR_LS : FFR1_3<0b001011, 0x0, FGR32, FGR32, "floor.l">; - def FLOOR_LD : FFR1_3<0b001011, 0x1, AFGR64, AFGR64, "floor.l">; - - /// Trunc to long signed integer - def TRUNC_LS : FFR1_3<0b001001, 0x0, FGR32, FGR32, "trunc.l">; - def TRUNC_LD : FFR1_3<0b001001, 0x1, AFGR64, AFGR64, "trunc.l">; - - /// Convert to long signed integer - def CVTL_S : FFR1_3<0b100101, 0x0, FGR32, FGR32, "cvt.l">; - def CVTL_D : FFR1_3<0b100101, 0x1, AFGR64, AFGR64, "cvt.l">; - - /// Convert to Double Precison - def CVTD_S32 : FFR1_3<0b100001, 0x0, AFGR64, FGR32, "cvt.d.s">; - def CVTD_W32 : FFR1_3<0b100001, 0x2, AFGR64, FGR32, "cvt.d.w">; - def CVTD_L32 : FFR1_3<0b100001, 0x3, AFGR64, AFGR64, "cvt.d.l">; - - /// Convert to Single Precison - def CVTS_D32 : FFR1_3<0b100000, 0x1, FGR32, AFGR64, "cvt.s.d">; - def CVTS_L32 : FFR1_3<0b100000, 0x3, FGR32, AFGR64, "cvt.s.l">; - } +let Predicates = [IsFP64bit] 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>; + def CVT_D64_S : FFR1<0x21, 16, "cvt", "d.s", FGR64, FGR32>; + def CVT_D64_L : FFR1<0x21, 21, "cvt", "d.l", FGR64, FGR64>; } +defm FABS : FFR1P_M<0x5, "abs", fabs>; +defm FNEG : FFR1P_M<0x7, "neg", fneg>; +defm FSQRT : FFR1P_M<0x4, "sqrt", fsqrt>; + // The odd-numbered registers are only referenced when doing loads, // stores, and moves between floating-point and integer registers. // When defining instructions, we reference all 32-bit registers, @@ -178,37 +167,46 @@ let fd = 0 in { "ctc1\t$fs, $rt", []>; def MFC1 : FFR<0x11, 0x00, 0x00, (outs CPURegs:$rt), (ins FGR32:$fs), - "mfc1\t$rt, $fs", []>; + "mfc1\t$rt, $fs", + [(set CPURegs:$rt, (bitconvert FGR32:$fs))]>; def MTC1 : FFR<0x11, 0x00, 0x04, (outs FGR32:$fs), (ins CPURegs:$rt), - "mtc1\t$rt, $fs", []>; + "mtc1\t$rt, $fs", + [(set FGR32:$fs, (bitconvert CPURegs:$rt))]>; } -def FMOV_S32 : FFR<0x11, 0b000110, 0x0, (outs FGR32:$fd), (ins FGR32:$fs), - "mov.s\t$fd, $fs", []>; -def FMOV_D32 : FFR<0x11, 0b000110, 0x1, (outs AFGR64:$fd), (ins AFGR64:$fs), - "mov.d\t$fd, $fs", []>; +def FMOV_S : FFR1<0x6, 16, "mov", "s", FGR32, FGR32>; +def FMOV_D32 : FFR1<0x6, 17, "mov", "d", AFGR64, AFGR64>, + Requires<[NotFP64bit]>; +def FMOV_D64 : FFR1<0x6, 17, "mov", "d", FGR64, FGR64>, + Requires<[IsFP64bit]>; /// Floating Point Memory Instructions -let Predicates = [IsNotSingleFloat, IsNotMipsI] in { - def LDC1 : FFI<0b110101, (outs AFGR64:$ft), (ins mem:$addr), - "ldc1\t$ft, $addr", [(set AFGR64:$ft, (load addr:$addr))]>; - - def SDC1 : FFI<0b111101, (outs), (ins AFGR64:$ft, mem:$addr), - "sdc1\t$ft, $addr", [(store AFGR64:$ft, addr:$addr)]>; +let Predicates = [IsN64] in { + def LWC1_P8 : FPLoad<0x31, "lwc1", load, FGR32, mem64>; + def SWC1_P8 : FPStore<0x39, "swc1", store, FGR32, mem64>; + def LDC164_P8 : FPLoad<0x35, "ldc1", load, FGR64, mem64>; + def SDC164_P8 : FPStore<0x3d, "sdc1", store, FGR64, mem64>; } -// LWC1 and SWC1 can always be emitted with odd registers. -def LWC1 : FFI<0b110001, (outs FGR32:$ft), (ins mem:$addr), "lwc1\t$ft, $addr", - [(set FGR32:$ft, (load addr:$addr))]>; -def SWC1 : FFI<0b111001, (outs), (ins FGR32:$ft, mem:$addr), - "swc1\t$ft, $addr", [(store FGR32:$ft, addr:$addr)]>; +let Predicates = [NotN64] in { + def LWC1 : FPLoad<0x31, "lwc1", load, FGR32, mem>; + def SWC1 : FPStore<0x39, "swc1", store, FGR32, mem>; + let Predicates = [HasMips64] in { + def LDC164 : FPLoad<0x35, "ldc1", load, FGR64, mem>; + def SDC164 : FPStore<0x3d, "sdc1", store, FGR64, mem>; + } + let Predicates = [NotMips64] in { + def LDC1 : FPLoad<0x35, "ldc1", load, AFGR64, mem>; + def SDC1 : FPStore<0x3d, "sdc1", store, AFGR64, mem>; + } +} /// Floating-point Aritmetic -defm FADD : FFR1_4<0x10, "add", fadd, 1>; -defm FDIV : FFR1_4<0x03, "div", fdiv>; -defm FMUL : FFR1_4<0x02, "mul", fmul, 1>; -defm FSUB : FFR1_4<0x01, "sub", fsub>; +defm FADD : FFR2P_M<0x10, "add", fadd, 1>; +defm FDIV : FFR2P_M<0x03, "div", fdiv>; +defm FMUL : FFR2P_M<0x02, "mul", fmul, 1>; +defm FSUB : FFR2P_M<0x01, "sub", fsub>; //===----------------------------------------------------------------------===// // Floating Point Branch Codes @@ -217,8 +215,6 @@ defm FSUB : FFR1_4<0x01, "sub", fsub>; // They must be kept in synch. def MIPS_BRANCH_F : PatLeaf<(i32 0)>; def MIPS_BRANCH_T : PatLeaf<(i32 1)>; -def MIPS_BRANCH_FL : PatLeaf<(i32 2)>; -def MIPS_BRANCH_TL : PatLeaf<(i32 3)>; /// Floating Point Branch of False/True (Likely) let isBranch=1, isTerminator=1, hasDelaySlot=1, base=0x8, Uses=[FCR31] in @@ -228,8 +224,6 @@ let isBranch=1, isTerminator=1, hasDelaySlot=1, base=0x8, Uses=[FCR31] in def BC1F : FBRANCH<MIPS_BRANCH_F, "bc1f">; def BC1T : FBRANCH<MIPS_BRANCH_T, "bc1t">; -def BC1FL : FBRANCH<MIPS_BRANCH_FL, "bc1fl">; -def BC1TL : FBRANCH<MIPS_BRANCH_TL, "bc1tl">; //===----------------------------------------------------------------------===// // Floating Point Flag Conditions @@ -254,7 +248,7 @@ def MIPS_FCOND_LE : PatLeaf<(i32 14)>; def MIPS_FCOND_NGT : PatLeaf<(i32 15)>; /// Floating Point Compare -let hasDelaySlot = 1, Defs=[FCR31] in { +let Defs=[FCR31] in { def FCMP_S32 : FCC<0x0, (outs), (ins FGR32:$fs, FGR32:$ft, condcode:$cc), "c.$cc.s\t$fs, $ft", [(MipsFPCmp FGR32:$fs, FGR32:$ft, imm:$cc)]>; @@ -262,7 +256,7 @@ let hasDelaySlot = 1, Defs=[FCR31] in { def FCMP_D32 : FCC<0x1, (outs), (ins AFGR64:$fs, AFGR64:$ft, condcode:$cc), "c.$cc.d\t$fs, $ft", [(MipsFPCmp AFGR64:$fs, AFGR64:$ft, imm:$cc)]>, - Requires<[In32BitMode]>; + Requires<[NotFP64bit]>; } @@ -280,7 +274,7 @@ class CondMovIntFP<RegisterClass RC, bits<5> fmt, bits<6> func, def MOVZ_S : CondMovIntFP<FGR32, 16, 18, "movz.s">; def MOVN_S : CondMovIntFP<FGR32, 16, 19, "movn.s">; -let Predicates = [In32BitMode] in { +let Predicates = [NotFP64bit] in { def MOVZ_D : CondMovIntFP<AFGR64, 17, 18, "movz.d">; def MOVN_D : CondMovIntFP<AFGR64, 17, 19, "movn.d">; } @@ -288,7 +282,7 @@ let Predicates = [In32BitMode] in { defm : MovzPats<FGR32, MOVZ_S>; defm : MovnPats<FGR32, MOVN_S>; -let Predicates = [In32BitMode] in { +let Predicates = [NotFP64bit] in { defm : MovzPats<AFGR64, MOVZ_D>; defm : MovnPats<AFGR64, MOVN_D>; } @@ -313,7 +307,7 @@ def MOVF : CondMovFPInt<MipsCMovFP_F, 0, "movf">; def MOVT_S : CondMovFPFP<FGR32, MipsCMovFP_T, 16, 1, "movt.s">; def MOVF_S : CondMovFPFP<FGR32, MipsCMovFP_F, 16, 0, "movf.s">; -let Predicates = [In32BitMode] in { +let Predicates = [NotFP64bit] in { def MOVT_D : CondMovFPFP<AFGR64, MipsCMovFP_T, 17, 1, "movt.d">; def MOVF_D : CondMovFPFP<AFGR64, MipsCMovFP_F, 17, 0, "movf.d">; } @@ -353,22 +347,16 @@ def fpimm0neg : PatLeaf<(fpimm), [{ }]>; def : Pat<(f32 fpimm0), (MTC1 ZERO)>; -def : Pat<(f32 fpimm0neg), (FNEG_S32 (MTC1 ZERO))>; +def : Pat<(f32 fpimm0neg), (FNEG_S (MTC1 ZERO))>; -def : Pat<(f32 (sint_to_fp CPURegs:$src)), (CVTS_W32 (MTC1 CPURegs:$src))>; -def : Pat<(f64 (sint_to_fp CPURegs:$src)), (CVTD_W32 (MTC1 CPURegs:$src))>; +def : Pat<(f32 (sint_to_fp CPURegs:$src)), (CVT_S_W (MTC1 CPURegs:$src))>; +def : Pat<(f64 (sint_to_fp CPURegs:$src)), (CVT_D32_W (MTC1 CPURegs:$src))>; -def : Pat<(i32 (fp_to_sint FGR32:$src)), (MFC1 (TRUNC_W_S32 FGR32:$src))>; +def : Pat<(i32 (fp_to_sint FGR32:$src)), (MFC1 (TRUNC_W_S FGR32:$src))>; def : Pat<(i32 (fp_to_sint AFGR64:$src)), (MFC1 (TRUNC_W_D32 AFGR64:$src))>; -def : Pat<(i32 (bitconvert FGR32:$src)), (MFC1 FGR32:$src)>; -def : Pat<(f32 (bitconvert CPURegs:$src)), (MTC1 CPURegs:$src)>; - -let Predicates = [In32BitMode] in { - def : Pat<(f32 (fround AFGR64:$src)), (CVTS_D32 AFGR64:$src)>; - def : Pat<(f64 (fextend FGR32:$src)), (CVTD_S32 FGR32:$src)>; +let Predicates = [NotFP64bit] in { + def : Pat<(f32 (fround AFGR64:$src)), (CVT_S_D32 AFGR64:$src)>; + def : Pat<(f64 (fextend FGR32:$src)), (CVT_D32_S FGR32:$src)>; } -// MipsFPRound is only emitted for MipsI targets. -def : Pat<(f32 (MipsFPRound AFGR64:$src)), (CVTW_D32 AFGR64:$src)>; - diff --git a/contrib/llvm/lib/Target/Mips/MipsInstrFormats.td b/contrib/llvm/lib/Target/Mips/MipsInstrFormats.td index 9f55fb3..d246a26 100644 --- a/contrib/llvm/lib/Target/Mips/MipsInstrFormats.td +++ b/contrib/llvm/lib/Target/Mips/MipsInstrFormats.td @@ -44,7 +44,9 @@ class MipsInst<dag outs, dag ins, string asmstr, list<dag> pattern, // Mips Pseudo Instructions Format class MipsPseudo<dag outs, dag ins, string asmstr, list<dag> pattern>: - MipsInst<outs, ins, asmstr, pattern, IIPseudo>; + MipsInst<outs, ins, asmstr, pattern, IIPseudo> { + let isPseudo = 1; +} //===----------------------------------------------------------------------===// // Format R instruction class in Mips : <|opcode|rs|rt|rd|shamt|funct|> @@ -88,6 +90,21 @@ class FI<bits<6> op, dag outs, dag ins, string asmstr, list<dag> pattern, let Inst{15-0} = imm16; } +class CBranchBase<bits<6> op, dag outs, dag ins, string asmstr, + list<dag> pattern, InstrItinClass itin>: + MipsInst<outs, ins, asmstr, pattern, itin> +{ + bits<5> rs; + bits<5> rt; + bits<16> imm16; + + let opcode = op; + + let Inst{25-21} = rs; + let Inst{20-16} = rt; + let Inst{15-0} = imm16; +} + //===----------------------------------------------------------------------===// // Format J instruction class in Mips : <|opcode|address|> //===----------------------------------------------------------------------===// @@ -224,4 +241,27 @@ class FFCMOV<bits<5> _fmt, bits<1> _tf, dag outs, dag ins, string asmstr, let Inst{15-11} = fs; let Inst{10-6} = fd; let Inst{5-0} = 17; -}
\ No newline at end of file +} + +// FP unary instructions without patterns. +class FFR1<bits<6> funct, bits<5> fmt, string opstr, string fmtstr, + RegisterClass DstRC, RegisterClass SrcRC> : + FFR<0x11, funct, fmt, (outs DstRC:$fd), (ins SrcRC:$fs), + !strconcat(opstr, ".", fmtstr, "\t$fd, $fs"), []> { + let ft = 0; +} + +// FP unary instructions with patterns. +class FFR1P<bits<6> funct, bits<5> fmt, string opstr, string fmtstr, + RegisterClass DstRC, RegisterClass SrcRC, SDNode OpNode> : + FFR<0x11, funct, fmt, (outs DstRC:$fd), (ins SrcRC:$fs), + !strconcat(opstr, ".", fmtstr, "\t$fd, $fs"), + [(set DstRC:$fd, (OpNode SrcRC:$fs))]> { + let ft = 0; +} + +class FFR2P<bits<6> funct, bits<5> fmt, string opstr, + string fmtstr, RegisterClass RC, SDNode OpNode> : + FFR<0x11, funct, fmt, (outs RC:$fd), (ins RC:$fs, RC:$ft), + !strconcat(opstr, ".", fmtstr, "\t$fd, $fs, $ft"), + [(set RC:$fd, (OpNode RC:$fs, RC:$ft))]>; diff --git a/contrib/llvm/lib/Target/Mips/MipsInstrInfo.cpp b/contrib/llvm/lib/Target/Mips/MipsInstrInfo.cpp index 0a7a7f2..559943a 100644 --- a/contrib/llvm/lib/Target/Mips/MipsInstrInfo.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsInstrInfo.cpp @@ -17,8 +17,8 @@ #include "InstPrinter/MipsInstPrinter.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/Target/TargetRegistry.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/TargetRegistry.h" #include "llvm/ADT/STLExtras.h" #define GET_INSTRINFO_CTOR @@ -28,7 +28,8 @@ using namespace llvm; MipsInstrInfo::MipsInstrInfo(MipsTargetMachine &tm) : MipsGenInstrInfo(Mips::ADJCALLSTACKDOWN, Mips::ADJCALLSTACKUP), - TM(tm), RI(*TM.getSubtargetImpl(), *this) {} + TM(tm), IsN64(TM.getSubtarget<MipsSubtarget>().isABI_N64()), + RI(*TM.getSubtargetImpl(), *this) {} const MipsRegisterInfo &MipsInstrInfo::getRegisterInfo() const { @@ -47,8 +48,12 @@ static bool isZeroImm(const MachineOperand &op) { unsigned MipsInstrInfo:: isLoadFromStackSlot(const MachineInstr *MI, int &FrameIndex) const { - if ((MI->getOpcode() == Mips::LW) || (MI->getOpcode() == Mips::LWC1) || - (MI->getOpcode() == Mips::LDC1)) { + unsigned Opc = MI->getOpcode(); + + if ((Opc == Mips::LW) || (Opc == Mips::LW_P8) || (Opc == Mips::LD) || + (Opc == Mips::LD_P8) || (Opc == Mips::LWC1) || (Opc == Mips::LWC1_P8) || + (Opc == Mips::LDC1) || (Opc == Mips::LDC164) || + (Opc == Mips::LDC164_P8)) { if ((MI->getOperand(1).isFI()) && // is a stack slot (MI->getOperand(2).isImm()) && // the imm is zero (isZeroImm(MI->getOperand(2)))) { @@ -68,8 +73,12 @@ isLoadFromStackSlot(const MachineInstr *MI, int &FrameIndex) const unsigned MipsInstrInfo:: isStoreToStackSlot(const MachineInstr *MI, int &FrameIndex) const { - if ((MI->getOpcode() == Mips::SW) || (MI->getOpcode() == Mips::SWC1) || - (MI->getOpcode() == Mips::SDC1)) { + unsigned Opc = MI->getOpcode(); + + if ((Opc == Mips::SW) || (Opc == Mips::SW_P8) || (Opc == Mips::SD) || + (Opc == Mips::SD_P8) || (Opc == Mips::SWC1) || (Opc == Mips::SWC1_P8) || + (Opc == Mips::SDC1) || (Opc == Mips::SDC164) || + (Opc == Mips::SDC164_P8)) { if ((MI->getOperand(1).isFI()) && // is a stack slot (MI->getOperand(2).isImm()) && // the imm is zero (isZeroImm(MI->getOperand(2)))) { @@ -94,70 +103,63 @@ copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, DebugLoc DL, unsigned DestReg, unsigned SrcReg, bool KillSrc) const { - bool DestCPU = Mips::CPURegsRegClass.contains(DestReg); - bool SrcCPU = Mips::CPURegsRegClass.contains(SrcReg); - - // CPU-CPU is the most common. - if (DestCPU && SrcCPU) { - BuildMI(MBB, I, DL, get(Mips::ADDu), DestReg).addReg(Mips::ZERO) - .addReg(SrcReg, getKillRegState(KillSrc)); - return; - } + unsigned Opc = 0, ZeroReg = 0; - // Copy to CPU from other registers. - if (DestCPU) { - if (Mips::CCRRegClass.contains(SrcReg)) - BuildMI(MBB, I, DL, get(Mips::CFC1), DestReg) - .addReg(SrcReg, getKillRegState(KillSrc)); + if (Mips::CPURegsRegClass.contains(DestReg)) { // Copy to CPU Reg. + if (Mips::CPURegsRegClass.contains(SrcReg)) + Opc = Mips::ADDu, ZeroReg = Mips::ZERO; + else if (Mips::CCRRegClass.contains(SrcReg)) + Opc = Mips::CFC1; else if (Mips::FGR32RegClass.contains(SrcReg)) - BuildMI(MBB, I, DL, get(Mips::MFC1), DestReg) - .addReg(SrcReg, getKillRegState(KillSrc)); + Opc = Mips::MFC1; else if (SrcReg == Mips::HI) - BuildMI(MBB, I, DL, get(Mips::MFHI), DestReg); + Opc = Mips::MFHI, SrcReg = 0; else if (SrcReg == Mips::LO) - BuildMI(MBB, I, DL, get(Mips::MFLO), DestReg); - else - llvm_unreachable("Copy to CPU from invalid register"); - return; + Opc = Mips::MFLO, SrcReg = 0; } - - // Copy to other registers from CPU. - if (SrcCPU) { + else if (Mips::CPURegsRegClass.contains(SrcReg)) { // Copy from CPU Reg. if (Mips::CCRRegClass.contains(DestReg)) - BuildMI(MBB, I, DL, get(Mips::CTC1), DestReg) - .addReg(SrcReg, getKillRegState(KillSrc)); + Opc = Mips::CTC1; else if (Mips::FGR32RegClass.contains(DestReg)) - BuildMI(MBB, I, DL, get(Mips::MTC1), DestReg) - .addReg(SrcReg, getKillRegState(KillSrc)); + Opc = Mips::MTC1; else if (DestReg == Mips::HI) - BuildMI(MBB, I, DL, get(Mips::MTHI)) - .addReg(SrcReg, getKillRegState(KillSrc)); + Opc = Mips::MTHI, DestReg = 0; else if (DestReg == Mips::LO) - BuildMI(MBB, I, DL, get(Mips::MTLO)) - .addReg(SrcReg, getKillRegState(KillSrc)); - else - llvm_unreachable("Copy from CPU to invalid register"); - return; + Opc = Mips::MTLO, DestReg = 0; } - - if (Mips::FGR32RegClass.contains(DestReg, SrcReg)) { - BuildMI(MBB, I, DL, get(Mips::FMOV_S32), DestReg) - .addReg(SrcReg, getKillRegState(KillSrc)); - return; + else if (Mips::FGR32RegClass.contains(DestReg, SrcReg)) + Opc = Mips::FMOV_S; + else if (Mips::AFGR64RegClass.contains(DestReg, SrcReg)) + Opc = Mips::FMOV_D32; + else if (Mips::CCRRegClass.contains(DestReg, SrcReg)) + Opc = Mips::MOVCCRToCCR; + else if (Mips::CPU64RegsRegClass.contains(DestReg)) { // Copy to CPU64 Reg. + if (Mips::CPU64RegsRegClass.contains(SrcReg)) + Opc = Mips::DADDu, ZeroReg = Mips::ZERO_64; + else if (SrcReg == Mips::HI64) + Opc = Mips::MFHI64, SrcReg = 0; + else if (SrcReg == Mips::LO64) + Opc = Mips::MFLO64, SrcReg = 0; } - - if (Mips::AFGR64RegClass.contains(DestReg, SrcReg)) { - BuildMI(MBB, I, DL, get(Mips::FMOV_D32), DestReg) - .addReg(SrcReg, getKillRegState(KillSrc)); - return; + else if (Mips::CPU64RegsRegClass.contains(SrcReg)) { // Copy from CPU64 Reg. + if (DestReg == Mips::HI64) + Opc = Mips::MTHI64, DestReg = 0; + else if (DestReg == Mips::LO64) + Opc = Mips::MTLO64, DestReg = 0; } - if (Mips::CCRRegClass.contains(DestReg, SrcReg)) { - BuildMI(MBB, I, DL, get(Mips::MOVCCRToCCR), DestReg) - .addReg(SrcReg, getKillRegState(KillSrc)); - return; - } - llvm_unreachable("Cannot copy registers"); + assert(Opc && "Cannot copy registers"); + + MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(Opc)); + + if (DestReg) + MIB.addReg(DestReg, RegState::Define); + + if (ZeroReg) + MIB.addReg(ZeroReg); + + if (SrcReg) + MIB.addReg(SrcReg, getKillRegState(KillSrc)); } void MipsInstrInfo:: @@ -167,31 +169,22 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const TargetRegisterInfo *TRI) const { DebugLoc DL; if (I != MBB.end()) DL = I->getDebugLoc(); + unsigned Opc = 0; if (RC == Mips::CPURegsRegisterClass) - BuildMI(MBB, I, DL, get(Mips::SW)).addReg(SrcReg, getKillRegState(isKill)) - .addFrameIndex(FI).addImm(0); + Opc = IsN64 ? Mips::SW_P8 : Mips::SW; + else if (RC == Mips::CPU64RegsRegisterClass) + Opc = IsN64 ? Mips::SD_P8 : Mips::SD; else if (RC == Mips::FGR32RegisterClass) - BuildMI(MBB, I, DL, get(Mips::SWC1)).addReg(SrcReg, getKillRegState(isKill)) - .addFrameIndex(FI).addImm(0); - else if (RC == Mips::AFGR64RegisterClass) { - if (!TM.getSubtarget<MipsSubtarget>().isMips1()) { - BuildMI(MBB, I, DL, get(Mips::SDC1)) - .addReg(SrcReg, getKillRegState(isKill)) - .addFrameIndex(FI).addImm(0); - } else { - const TargetRegisterInfo *TRI = - MBB.getParent()->getTarget().getRegisterInfo(); - const unsigned *SubSet = TRI->getSubRegisters(SrcReg); - BuildMI(MBB, I, DL, get(Mips::SWC1)) - .addReg(SubSet[0], getKillRegState(isKill)) - .addFrameIndex(FI).addImm(0); - BuildMI(MBB, I, DL, get(Mips::SWC1)) - .addReg(SubSet[1], getKillRegState(isKill)) - .addFrameIndex(FI).addImm(4); - } - } else - llvm_unreachable("Register class not handled!"); + Opc = IsN64 ? Mips::SWC1_P8 : Mips::SWC1; + else if (RC == Mips::AFGR64RegisterClass) + Opc = Mips::SDC1; + else if (RC == Mips::FGR64RegisterClass) + Opc = IsN64 ? Mips::SDC164_P8 : Mips::SDC164; + + assert(Opc && "Register class not handled!"); + BuildMI(MBB, I, DL, get(Opc)).addReg(SrcReg, getKillRegState(isKill)) + .addFrameIndex(FI).addImm(0); } void MipsInstrInfo:: @@ -202,25 +195,21 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, { DebugLoc DL; if (I != MBB.end()) DL = I->getDebugLoc(); + unsigned Opc = 0; if (RC == Mips::CPURegsRegisterClass) - BuildMI(MBB, I, DL, get(Mips::LW), DestReg).addFrameIndex(FI).addImm(0); + Opc = IsN64 ? Mips::LW_P8 : Mips::LW; + else if (RC == Mips::CPU64RegsRegisterClass) + Opc = IsN64 ? Mips::LD_P8 : Mips::LD; else if (RC == Mips::FGR32RegisterClass) - BuildMI(MBB, I, DL, get(Mips::LWC1), DestReg).addFrameIndex(FI).addImm(0); - else if (RC == Mips::AFGR64RegisterClass) { - if (!TM.getSubtarget<MipsSubtarget>().isMips1()) { - BuildMI(MBB, I, DL, get(Mips::LDC1), DestReg).addFrameIndex(FI).addImm(0); - } else { - const TargetRegisterInfo *TRI = - MBB.getParent()->getTarget().getRegisterInfo(); - const unsigned *SubSet = TRI->getSubRegisters(DestReg); - BuildMI(MBB, I, DL, get(Mips::LWC1), SubSet[0]) - .addFrameIndex(FI).addImm(0); - BuildMI(MBB, I, DL, get(Mips::LWC1), SubSet[1]) - .addFrameIndex(FI).addImm(4); - } - } else - llvm_unreachable("Register class not handled!"); + Opc = IsN64 ? Mips::LWC1_P8 : Mips::LWC1; + else if (RC == Mips::AFGR64RegisterClass) + Opc = Mips::LDC1; + else if (RC == Mips::FGR64RegisterClass) + Opc = IsN64 ? Mips::LDC164_P8 : Mips::LDC164; + + assert(Opc && "Register class not handled!"); + BuildMI(MBB, I, DL, get(Opc), DestReg).addFrameIndex(FI).addImm(0); } MachineInstr* @@ -237,9 +226,12 @@ MipsInstrInfo::emitFrameIndexDebugValue(MachineFunction &MF, int FrameIx, //===----------------------------------------------------------------------===// static unsigned GetAnalyzableBrOpc(unsigned Opc) { - return (Opc == Mips::BEQ || Opc == Mips::BNE || Opc == Mips::BGTZ || - Opc == Mips::BGEZ || Opc == Mips::BLTZ || Opc == Mips::BLEZ || - Opc == Mips::BC1T || Opc == Mips::BC1F || Opc == Mips::J) ? Opc : 0; + return (Opc == Mips::BEQ || Opc == Mips::BNE || Opc == Mips::BGTZ || + Opc == Mips::BGEZ || Opc == Mips::BLTZ || Opc == Mips::BLEZ || + Opc == Mips::BEQ64 || Opc == Mips::BNE64 || Opc == Mips::BGTZ64 || + Opc == Mips::BGEZ64 || Opc == Mips::BLTZ64 || Opc == Mips::BLEZ64 || + Opc == Mips::BC1T || Opc == Mips::BC1F || Opc == Mips::J) ? + Opc : 0; } /// GetOppositeBranchOpc - Return the inverse of the specified @@ -248,14 +240,20 @@ unsigned Mips::GetOppositeBranchOpc(unsigned Opc) { switch (Opc) { default: llvm_unreachable("Illegal opcode!"); - case Mips::BEQ : return Mips::BNE; - case Mips::BNE : return Mips::BEQ; - case Mips::BGTZ : return Mips::BLEZ; - case Mips::BGEZ : return Mips::BLTZ; - case Mips::BLTZ : return Mips::BGEZ; - case Mips::BLEZ : return Mips::BGTZ; - case Mips::BC1T : return Mips::BC1F; - case Mips::BC1F : return Mips::BC1T; + case Mips::BEQ : return Mips::BNE; + case Mips::BNE : return Mips::BEQ; + case Mips::BGTZ : return Mips::BLEZ; + case Mips::BGEZ : return Mips::BLTZ; + case Mips::BLTZ : return Mips::BGEZ; + case Mips::BLEZ : return Mips::BGTZ; + case Mips::BEQ64 : return Mips::BNE64; + case Mips::BNE64 : return Mips::BEQ64; + case Mips::BGTZ64 : return Mips::BLEZ64; + case Mips::BGEZ64 : return Mips::BLTZ64; + case Mips::BLTZ64 : return Mips::BGEZ64; + case Mips::BLEZ64 : return Mips::BGTZ64; + case Mips::BC1T : return Mips::BC1F; + case Mips::BC1F : return Mips::BC1T; } } diff --git a/contrib/llvm/lib/Target/Mips/MipsInstrInfo.h b/contrib/llvm/lib/Target/Mips/MipsInstrInfo.h index 4421c48..271d248 100644 --- a/contrib/llvm/lib/Target/Mips/MipsInstrInfo.h +++ b/contrib/llvm/lib/Target/Mips/MipsInstrInfo.h @@ -72,12 +72,47 @@ namespace MipsII { /// MO_TPREL_HI/LO - Represents the hi and low part of the offset from // the thread pointer (Local Exec TLS). MO_TPREL_HI, - MO_TPREL_LO + MO_TPREL_LO, + + // N32/64 Flags. + MO_GPOFF_HI, + MO_GPOFF_LO, + MO_GOT_DISP, + MO_GOT_PAGE, + MO_GOT_OFST + }; + + enum { + //===------------------------------------------------------------------===// + // Instruction encodings. These are the standard/most common forms for + // Mips instructions. + // + + // Pseudo - This represents an instruction that is a pseudo instruction + // or one that has not been implemented yet. It is illegal to code generate + // it, but tolerated for intermediate implementation stages. + Pseudo = 0, + + /// FrmR - This form is for instructions of the format R. + FrmR = 1, + /// FrmI - This form is for instructions of the format I. + FrmI = 2, + /// FrmJ - This form is for instructions of the format J. + FrmJ = 3, + /// FrmFR - This form is for instructions of the format FR. + FrmFR = 4, + /// FrmFI - This form is for instructions of the format FI. + FrmFI = 5, + /// FrmOther - This form is for instructions that have no specific format. + FrmOther = 6, + + FormMask = 15 }; } class MipsInstrInfo : public MipsGenInstrInfo { MipsTargetMachine &TM; + bool IsN64; const MipsRegisterInfo RI; public: explicit MipsInstrInfo(MipsTargetMachine &TM); diff --git a/contrib/llvm/lib/Target/Mips/MipsInstrInfo.td b/contrib/llvm/lib/Target/Mips/MipsInstrInfo.td index d1a0587..06b7de7 100644 --- a/contrib/llvm/lib/Target/Mips/MipsInstrInfo.td +++ b/contrib/llvm/lib/Target/Mips/MipsInstrInfo.td @@ -34,13 +34,20 @@ def SDT_MipsMAddMSub : SDTypeProfile<0, 4, SDTCisSameAs<1, 2>, SDTCisSameAs<2, 3>]>; def SDT_MipsDivRem : SDTypeProfile<0, 2, - [SDTCisVT<0, i32>, + [SDTCisInt<0>, SDTCisSameAs<0, 1>]>; def SDT_MipsThreadPointer : SDTypeProfile<1, 0, [SDTCisPtrTy<0>]>; def SDT_MipsDynAlloc : SDTypeProfile<1, 1, [SDTCisVT<0, i32>, SDTCisVT<1, iPTR>]>; +def SDT_Sync : SDTypeProfile<0, 1, [SDTCisVT<0, i32>]>; + +def SDT_Ext : SDTypeProfile<1, 3, [SDTCisInt<0>, SDTCisSameAs<0, 1>, + SDTCisVT<2, i32>, SDTCisSameAs<2, 3>]>; +def SDT_Ins : SDTypeProfile<1, 4, [SDTCisInt<0>, SDTCisSameAs<0, 1>, + SDTCisVT<2, i32>, SDTCisSameAs<2, 3>, + SDTCisSameAs<0, 4>]>; // Call def MipsJmpLink : SDNode<"MipsISD::JmpLink",SDT_MipsJmpLink, @@ -106,6 +113,11 @@ def MipsWrapperPIC : SDNode<"MipsISD::WrapperPIC", SDTIntUnaryOp>; def MipsDynAlloc : SDNode<"MipsISD::DynAlloc", SDT_MipsDynAlloc, [SDNPHasChain, SDNPInGlue]>; +def MipsSync : SDNode<"MipsISD::Sync", SDT_Sync, [SDNPHasChain]>; + +def MipsExt : SDNode<"MipsISD::Ext", SDT_Ext>; +def MipsIns : SDNode<"MipsISD::Ins", SDT_Ins>; + //===----------------------------------------------------------------------===// // Mips Instruction Predicate Definitions. //===----------------------------------------------------------------------===// @@ -113,8 +125,13 @@ def HasSEInReg : Predicate<"Subtarget.hasSEInReg()">; def HasBitCount : Predicate<"Subtarget.hasBitCount()">; def HasSwap : Predicate<"Subtarget.hasSwap()">; def HasCondMov : Predicate<"Subtarget.hasCondMov()">; -def IsMips32 : Predicate<"Subtarget.isMips32()">; -def IsMips32r2 : Predicate<"Subtarget.isMips32r2()">; +def HasMips32 : Predicate<"Subtarget.hasMips32()">; +def HasMips32r2 : Predicate<"Subtarget.hasMips32r2()">; +def HasMips64 : Predicate<"Subtarget.hasMips64()">; +def NotMips64 : Predicate<"!Subtarget.hasMips64()">; +def HasMips64r2 : Predicate<"Subtarget.hasMips64r2()">; +def IsN64 : Predicate<"Subtarget.isABI_N64()">; +def NotN64 : Predicate<"!Subtarget.isABI_N64()">; //===----------------------------------------------------------------------===// // Mips Operand, Complex Patterns and Transformations Definitions. @@ -124,6 +141,7 @@ def IsMips32r2 : Predicate<"Subtarget.isMips32r2()">; def brtarget : Operand<OtherVT>; def calltarget : Operand<i32>; def simm16 : Operand<i32>; +def simm16_64 : Operand<i64>; def shamt : Operand<i32>; // Unsigned Operand @@ -137,6 +155,11 @@ def mem : Operand<i32> { let MIOperandInfo = (ops CPURegs, simm16); } +def mem64 : Operand<i64> { + let PrintMethod = "printMemOperand"; + let MIOperandInfo = (ops CPU64Regs, simm16_64); +} + def mem_ea : Operand<i32> { let PrintMethod = "printMemOperandEA"; let MIOperandInfo = (ops CPURegs, simm16); @@ -177,36 +200,85 @@ def immZExt5 : PatLeaf<(imm), [{ def addr : ComplexPattern<iPTR, 2, "SelectAddr", [frameindex], []>; //===----------------------------------------------------------------------===// +// Pattern fragment for load/store +//===----------------------------------------------------------------------===// +class UnalignedLoad<PatFrag Node> : PatFrag<(ops node:$ptr), (Node node:$ptr), [{ + LoadSDNode *LD = cast<LoadSDNode>(N); + return LD->getMemoryVT().getSizeInBits()/8 > LD->getAlignment(); +}]>; + +class AlignedLoad<PatFrag Node> : PatFrag<(ops node:$ptr), (Node node:$ptr), [{ + LoadSDNode *LD = cast<LoadSDNode>(N); + return LD->getMemoryVT().getSizeInBits()/8 <= LD->getAlignment(); +}]>; + +class UnalignedStore<PatFrag Node> : PatFrag<(ops node:$val, node:$ptr), + (Node node:$val, node:$ptr), [{ + StoreSDNode *SD = cast<StoreSDNode>(N); + return SD->getMemoryVT().getSizeInBits()/8 > SD->getAlignment(); +}]>; + +class AlignedStore<PatFrag Node> : PatFrag<(ops node:$val, node:$ptr), + (Node node:$val, node:$ptr), [{ + StoreSDNode *SD = cast<StoreSDNode>(N); + return SD->getMemoryVT().getSizeInBits()/8 <= SD->getAlignment(); +}]>; + +// Load/Store PatFrags. +def sextloadi16_a : AlignedLoad<sextloadi16>; +def zextloadi16_a : AlignedLoad<zextloadi16>; +def extloadi16_a : AlignedLoad<extloadi16>; +def load_a : AlignedLoad<load>; +def sextloadi32_a : AlignedLoad<sextloadi32>; +def zextloadi32_a : AlignedLoad<zextloadi32>; +def extloadi32_a : AlignedLoad<extloadi32>; +def truncstorei16_a : AlignedStore<truncstorei16>; +def store_a : AlignedStore<store>; +def truncstorei32_a : AlignedStore<truncstorei32>; +def sextloadi16_u : UnalignedLoad<sextloadi16>; +def zextloadi16_u : UnalignedLoad<zextloadi16>; +def extloadi16_u : UnalignedLoad<extloadi16>; +def load_u : UnalignedLoad<load>; +def sextloadi32_u : UnalignedLoad<sextloadi32>; +def zextloadi32_u : UnalignedLoad<zextloadi32>; +def extloadi32_u : UnalignedLoad<extloadi32>; +def truncstorei16_u : UnalignedStore<truncstorei16>; +def store_u : UnalignedStore<store>; +def truncstorei32_u : UnalignedStore<truncstorei32>; + +//===----------------------------------------------------------------------===// // Instructions specific format //===----------------------------------------------------------------------===// -// Arithmetic 3 register operands -class ArithR<bits<6> op, bits<6> func, string instr_asm, SDNode OpNode, - InstrItinClass itin, bit isComm = 0>: - FR<op, func, (outs CPURegs:$dst), (ins CPURegs:$b, CPURegs:$c), - !strconcat(instr_asm, "\t$dst, $b, $c"), - [(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))], itin> { +// Arithmetic and logical instructions with 3 register operands. +class ArithLogicR<bits<6> op, bits<6> func, string instr_asm, SDNode OpNode, + InstrItinClass itin, RegisterClass RC, bit isComm = 0>: + FR<op, func, (outs RC:$rd), (ins RC:$rs, RC:$rt), + !strconcat(instr_asm, "\t$rd, $rs, $rt"), + [(set RC:$rd, (OpNode RC:$rs, RC:$rt))], itin> { + let shamt = 0; let isCommutable = isComm; } class ArithOverflowR<bits<6> op, bits<6> func, string instr_asm, - bit isComm = 0>: - FR<op, func, (outs CPURegs:$dst), (ins CPURegs:$b, CPURegs:$c), - !strconcat(instr_asm, "\t$dst, $b, $c"), [], IIAlu> { + InstrItinClass itin, RegisterClass RC, bit isComm = 0>: + FR<op, func, (outs RC:$rd), (ins RC:$rs, RC:$rt), + !strconcat(instr_asm, "\t$rd, $rs, $rt"), [], itin> { + let shamt = 0; let isCommutable = isComm; } -// Arithmetic 2 register operands -class ArithI<bits<6> op, string instr_asm, SDNode OpNode, - Operand Od, PatLeaf imm_type> : - FI<op, (outs CPURegs:$dst), (ins CPURegs:$b, Od:$c), - !strconcat(instr_asm, "\t$dst, $b, $c"), - [(set CPURegs:$dst, (OpNode CPURegs:$b, imm_type:$c))], IIAlu>; +// Arithmetic and logical instructions with 2 register operands. +class ArithLogicI<bits<6> op, string instr_asm, SDNode OpNode, + Operand Od, PatLeaf imm_type, RegisterClass RC> : + FI<op, (outs RC:$rt), (ins RC:$rs, Od:$i), + !strconcat(instr_asm, "\t$rt, $rs, $i"), + [(set RC:$rt, (OpNode RC:$rs, imm_type:$i))], IIAlu>; class ArithOverflowI<bits<6> op, string instr_asm, SDNode OpNode, - Operand Od, PatLeaf imm_type> : - FI<op, (outs CPURegs:$dst), (ins CPURegs:$b, Od:$c), - !strconcat(instr_asm, "\t$dst, $b, $c"), [], IIAlu>; + Operand Od, PatLeaf imm_type, RegisterClass RC> : + FI<op, (outs RC:$rt), (ins RC:$rs, Od:$i), + !strconcat(instr_asm, "\t$rt, $rs, $i"), [], IIAlu>; // Arithmetic Multiply ADD/SUB let rd = 0, shamt = 0, Defs = [HI, LO], Uses = [HI, LO] in @@ -214,92 +286,134 @@ class MArithR<bits<6> func, string instr_asm, SDNode op, bit isComm = 0> : FR<0x1c, func, (outs), (ins CPURegs:$rs, CPURegs:$rt), !strconcat(instr_asm, "\t$rs, $rt"), [(op CPURegs:$rs, CPURegs:$rt, LO, HI)], IIImul> { + let rd = 0; + let shamt = 0; let isCommutable = isComm; } // Logical -let isCommutable = 1 in -class LogicR<bits<6> func, string instr_asm, SDNode OpNode>: - FR<0x00, func, (outs CPURegs:$dst), (ins CPURegs:$b, CPURegs:$c), - !strconcat(instr_asm, "\t$dst, $b, $c"), - [(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))], IIAlu>; - -class LogicI<bits<6> op, string instr_asm, SDNode OpNode>: - FI<op, (outs CPURegs:$dst), (ins CPURegs:$b, uimm16:$c), - !strconcat(instr_asm, "\t$dst, $b, $c"), - [(set CPURegs:$dst, (OpNode CPURegs:$b, immZExt16:$c))], IIAlu>; - -let isCommutable = 1 in -class LogicNOR<bits<6> op, bits<6> func, string instr_asm>: - FR<op, func, (outs CPURegs:$dst), (ins CPURegs:$b, CPURegs:$c), - !strconcat(instr_asm, "\t$dst, $b, $c"), - [(set CPURegs:$dst, (not (or CPURegs:$b, CPURegs:$c)))], IIAlu>; +class LogicNOR<bits<6> op, bits<6> func, string instr_asm, RegisterClass RC>: + FR<op, func, (outs RC:$rd), (ins RC:$rs, RC:$rt), + !strconcat(instr_asm, "\t$rd, $rs, $rt"), + [(set RC:$rd, (not (or RC:$rs, RC:$rt)))], IIAlu> { + let shamt = 0; + let isCommutable = 1; +} // Shifts class LogicR_shift_rotate_imm<bits<6> func, bits<5> _rs, string instr_asm, SDNode OpNode>: - FR<0x00, func, (outs CPURegs:$dst), (ins CPURegs:$b, shamt:$c), - !strconcat(instr_asm, "\t$dst, $b, $c"), - [(set CPURegs:$dst, (OpNode CPURegs:$b, immZExt5:$c))], IIAlu> { + FR<0x00, func, (outs CPURegs:$rd), (ins CPURegs:$rt, shamt:$shamt), + !strconcat(instr_asm, "\t$rd, $rt, $shamt"), + [(set CPURegs:$rd, (OpNode CPURegs:$rt, (i32 immZExt5:$shamt)))], IIAlu> { let rs = _rs; } -class LogicR_shift_rotate_reg<bits<6> func, bits<5> _shamt, string instr_asm, +class LogicR_shift_rotate_reg<bits<6> func, bits<5> isRotate, string instr_asm, SDNode OpNode>: - FR<0x00, func, (outs CPURegs:$dst), (ins CPURegs:$c, CPURegs:$b), - !strconcat(instr_asm, "\t$dst, $b, $c"), - [(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))], IIAlu> { - let shamt = _shamt; + FR<0x00, func, (outs CPURegs:$rd), (ins CPURegs:$rs, CPURegs:$rt), + !strconcat(instr_asm, "\t$rd, $rt, $rs"), + [(set CPURegs:$rd, (OpNode CPURegs:$rt, CPURegs:$rs))], IIAlu> { + let shamt = isRotate; } // Load Upper Imediate class LoadUpper<bits<6> op, string instr_asm>: - FI< op, - (outs CPURegs:$dst), - (ins uimm16:$imm), - !strconcat(instr_asm, "\t$dst, $imm"), - [], IIAlu>; + FI<op, (outs CPURegs:$rt), (ins uimm16:$imm), + !strconcat(instr_asm, "\t$rt, $imm"), [], IIAlu> { + let rs = 0; +} // Memory Load/Store -let canFoldAsLoad = 1, hasDelaySlot = 1 in -class LoadM<bits<6> op, string instr_asm, PatFrag OpNode>: - FI<op, (outs CPURegs:$dst), (ins mem:$addr), - !strconcat(instr_asm, "\t$dst, $addr"), - [(set CPURegs:$dst, (OpNode addr:$addr))], IILoad>; +let canFoldAsLoad = 1 in +class LoadM<bits<6> op, string instr_asm, PatFrag OpNode, RegisterClass RC, + Operand MemOpnd, bit Pseudo>: + FI<op, (outs RC:$rt), (ins MemOpnd:$addr), + !strconcat(instr_asm, "\t$rt, $addr"), + [(set RC:$rt, (OpNode addr:$addr))], IILoad> { + let isPseudo = Pseudo; +} -class StoreM<bits<6> op, string instr_asm, PatFrag OpNode>: - FI<op, (outs), (ins CPURegs:$dst, mem:$addr), - !strconcat(instr_asm, "\t$dst, $addr"), - [(OpNode CPURegs:$dst, addr:$addr)], IIStore>; +class StoreM<bits<6> op, string instr_asm, PatFrag OpNode, RegisterClass RC, + Operand MemOpnd, bit Pseudo>: + FI<op, (outs), (ins RC:$rt, MemOpnd:$addr), + !strconcat(instr_asm, "\t$rt, $addr"), + [(OpNode RC:$rt, addr:$addr)], IIStore> { + let isPseudo = Pseudo; +} + +// 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]>; + def _P8 : LoadM<op, instr_asm, OpNode, CPURegs, mem64, Pseudo>, + Requires<[IsN64]>; +} + +// 64-bit load. +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]>; + def _P8 : LoadM<op, instr_asm, OpNode, CPU64Regs, mem64, Pseudo>, + Requires<[IsN64]>; +} + +// 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]>; + def _P8 : StoreM<op, instr_asm, OpNode, CPURegs, mem64, Pseudo>, + Requires<[IsN64]>; +} + +// 64-bit store. +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]>; + def _P8 : StoreM<op, instr_asm, OpNode, CPU64Regs, mem64, Pseudo>, + Requires<[IsN64]>; +} // Conditional Branch -let isBranch = 1, isTerminator=1, hasDelaySlot = 1 in { -class CBranch<bits<6> op, string instr_asm, PatFrag cond_op>: - FI<op, (outs), (ins CPURegs:$a, CPURegs:$b, brtarget:$offset), - !strconcat(instr_asm, "\t$a, $b, $offset"), - [(brcond (cond_op CPURegs:$a, CPURegs:$b), bb:$offset)], - IIBranch>; +class CBranch<bits<6> op, string instr_asm, PatFrag cond_op, RegisterClass RC>: + CBranchBase<op, (outs), (ins RC:$rs, RC:$rt, brtarget:$offset), + !strconcat(instr_asm, "\t$rs, $rt, $offset"), + [(brcond (i32 (cond_op RC:$rs, RC:$rt)), bb:$offset)], IIBranch> { + let isBranch = 1; + let isTerminator = 1; + let hasDelaySlot = 1; +} -class CBranchZero<bits<6> op, string instr_asm, PatFrag cond_op>: - FI<op, (outs), (ins CPURegs:$src, brtarget:$offset), - !strconcat(instr_asm, "\t$src, $offset"), - [(brcond (cond_op CPURegs:$src, 0), bb:$offset)], - IIBranch>; +class CBranchZero<bits<6> op, bits<5> _rt, string instr_asm, PatFrag cond_op, + RegisterClass RC>: + CBranchBase<op, (outs), (ins RC:$rs, brtarget:$offset), + !strconcat(instr_asm, "\t$rs, $offset"), + [(brcond (i32 (cond_op RC:$rs, 0)), bb:$offset)], IIBranch> { + let rt = _rt; + let isBranch = 1; + let isTerminator = 1; + let hasDelaySlot = 1; } // SetCC -class SetCC_R<bits<6> op, bits<6> func, string instr_asm, - PatFrag cond_op>: - FR<op, func, (outs CPURegs:$dst), (ins CPURegs:$b, CPURegs:$c), - !strconcat(instr_asm, "\t$dst, $b, $c"), - [(set CPURegs:$dst, (cond_op CPURegs:$b, CPURegs:$c))], - IIAlu>; +class SetCC_R<bits<6> op, bits<6> func, string instr_asm, PatFrag cond_op, + RegisterClass RC>: + FR<op, func, (outs CPURegs:$rd), (ins RC:$rs, RC:$rt), + !strconcat(instr_asm, "\t$rd, $rs, $rt"), + [(set CPURegs:$rd, (cond_op RC:$rs, RC:$rt))], + IIAlu> { + let shamt = 0; +} -class SetCC_I<bits<6> op, string instr_asm, PatFrag cond_op, - Operand Od, PatLeaf imm_type>: - FI<op, (outs CPURegs:$dst), (ins CPURegs:$b, Od:$c), - !strconcat(instr_asm, "\t$dst, $b, $c"), - [(set CPURegs:$dst, (cond_op CPURegs:$b, imm_type:$c))], +class SetCC_I<bits<6> op, string instr_asm, PatFrag cond_op, Operand Od, + PatLeaf imm_type, RegisterClass RC>: + FI<op, (outs CPURegs:$rd), (ins RC:$rs, Od:$i), + !strconcat(instr_asm, "\t$rd, $rs, $i"), + [(set CPURegs:$rd, (cond_op RC:$rs, imm_type:$i))], IIAlu>; // Unconditional branch @@ -310,8 +424,12 @@ class JumpFJ<bits<6> op, string instr_asm>: let isBranch=1, isTerminator=1, isBarrier=1, rd=0, hasDelaySlot = 1 in class JumpFR<bits<6> op, bits<6> func, string instr_asm>: - FR<op, func, (outs), (ins CPURegs:$target), - !strconcat(instr_asm, "\t$target"), [(brind CPURegs:$target)], IIBranch>; + FR<op, func, (outs), (ins CPURegs:$rs), + !strconcat(instr_asm, "\t$rs"), [(brind CPURegs:$rs)], IIBranch> { + let rt = 0; + let rd = 0; + let shamt = 0; +} // Jump and Link (Call) let isCall=1, hasDelaySlot=1, @@ -323,76 +441,124 @@ let isCall=1, hasDelaySlot=1, !strconcat(instr_asm, "\t$target"), [(MipsJmpLink imm:$target)], IIBranch>; - let rd=31 in class JumpLinkReg<bits<6> op, bits<6> func, string instr_asm>: FR<op, func, (outs), (ins CPURegs:$rs, variable_ops), - !strconcat(instr_asm, "\t$rs"), [(MipsJmpLink CPURegs:$rs)], IIBranch>; + !strconcat(instr_asm, "\t$rs"), [(MipsJmpLink CPURegs:$rs)], IIBranch> { + let rt = 0; + let rd = 31; + let shamt = 0; + } class BranchLink<string instr_asm>: FI<0x1, (outs), (ins CPURegs:$rs, brtarget:$target, variable_ops), - !strconcat(instr_asm, "\t$rs, $target"), [], IIBranch>; + !strconcat(instr_asm, "\t$rs, $target"), [], IIBranch> { + let rt = 0; + } } // Mul, Div -let Defs = [HI, LO] in { - let isCommutable = 1 in - class Mul<bits<6> func, string instr_asm, InstrItinClass itin>: - FR<0x00, func, (outs), (ins CPURegs:$a, CPURegs:$b), - !strconcat(instr_asm, "\t$a, $b"), [], itin>; +class Mul<bits<6> func, string instr_asm, InstrItinClass itin>: + FR<0x00, func, (outs), (ins CPURegs:$rs, CPURegs:$rt), + !strconcat(instr_asm, "\t$rs, $rt"), [], itin> { + let rd = 0; + let shamt = 0; + let isCommutable = 1; + let Defs = [HI, LO]; +} - class Div<SDNode op, bits<6> func, string instr_asm, InstrItinClass itin>: - FR<0x00, func, (outs), (ins CPURegs:$a, CPURegs:$b), - !strconcat(instr_asm, "\t$$zero, $a, $b"), - [(op CPURegs:$a, CPURegs:$b)], itin>; +class Div<SDNode op, bits<6> func, string instr_asm, InstrItinClass itin>: + FR<0x00, func, (outs), (ins CPURegs:$rs, CPURegs:$rt), + !strconcat(instr_asm, "\t$$zero, $rs, $rt"), + [(op CPURegs:$rs, CPURegs:$rt)], itin> { + let rd = 0; + let shamt = 0; + let Defs = [HI, LO]; } // Move from Hi/Lo class MoveFromLOHI<bits<6> func, string instr_asm>: - FR<0x00, func, (outs CPURegs:$dst), (ins), - !strconcat(instr_asm, "\t$dst"), [], IIHiLo>; + FR<0x00, func, (outs CPURegs:$rd), (ins), + !strconcat(instr_asm, "\t$rd"), [], IIHiLo> { + let rs = 0; + let rt = 0; + let shamt = 0; +} class MoveToLOHI<bits<6> func, string instr_asm>: - FR<0x00, func, (outs), (ins CPURegs:$src), - !strconcat(instr_asm, "\t$src"), [], IIHiLo>; + FR<0x00, func, (outs), (ins CPURegs:$rs), + !strconcat(instr_asm, "\t$rs"), [], IIHiLo> { + let rt = 0; + let rd = 0; + let shamt = 0; +} class EffectiveAddress<string instr_asm> : - FI<0x09, (outs CPURegs:$dst), (ins mem_ea:$addr), - instr_asm, [(set CPURegs:$dst, addr:$addr)], IIAlu>; + FI<0x09, (outs CPURegs:$rt), (ins mem_ea:$addr), + instr_asm, [(set CPURegs:$rt, addr:$addr)], IIAlu>; // Count Leading Ones/Zeros in Word class CountLeading<bits<6> func, string instr_asm, list<dag> pattern>: - FR<0x1c, func, (outs CPURegs:$dst), (ins CPURegs:$src), - !strconcat(instr_asm, "\t$dst, $src"), pattern, IIAlu>, + FR<0x1c, func, (outs CPURegs:$rd), (ins CPURegs:$rs), + !strconcat(instr_asm, "\t$rd, $rs"), pattern, IIAlu>, Requires<[HasBitCount]> { let shamt = 0; let rt = rd; } // Sign Extend in Register. -class SignExtInReg<bits<6> func, string instr_asm, ValueType vt>: - FR<0x3f, func, (outs CPURegs:$dst), (ins CPURegs:$src), - !strconcat(instr_asm, "\t$dst, $src"), - [(set CPURegs:$dst, (sext_inreg CPURegs:$src, vt))], NoItinerary>; +class SignExtInReg<bits<5> sa, string instr_asm, ValueType vt>: + FR<0x3f, 0x20, (outs CPURegs:$rd), (ins CPURegs:$rt), + !strconcat(instr_asm, "\t$rd, $rt"), + [(set CPURegs:$rd, (sext_inreg CPURegs:$rt, vt))], NoItinerary> { + let rs = 0; + let shamt = sa; + let Predicates = [HasSEInReg]; +} // Byte Swap -class ByteSwap<bits<6> func, string instr_asm>: - FR<0x1f, func, (outs CPURegs:$dst), (ins CPURegs:$src), - !strconcat(instr_asm, "\t$dst, $src"), - [(set CPURegs:$dst, (bswap CPURegs:$src))], NoItinerary>; - -// Conditional Move -class CondMov<bits<6> func, string instr_asm, PatLeaf MovCode>: - FR<0x00, func, (outs CPURegs:$dst), (ins CPURegs:$F, CPURegs:$T, - CPURegs:$cond), !strconcat(instr_asm, "\t$dst, $T, $cond"), - [], NoItinerary>; +class ByteSwap<bits<6> func, bits<5> sa, string instr_asm>: + FR<0x1f, func, (outs CPURegs:$rd), (ins CPURegs:$rt), + !strconcat(instr_asm, "\t$rd, $rt"), + [(set CPURegs:$rd, (bswap CPURegs:$rt))], NoItinerary> { + let rs = 0; + let shamt = sa; + let Predicates = [HasSwap]; +} // Read Hardware -class ReadHardware: FR<0x1f, 0x3b, (outs CPURegs:$dst), (ins HWRegs:$src), - "rdhwr\t$dst, $src", [], IIAlu> { +class ReadHardware: FR<0x1f, 0x3b, (outs CPURegs:$rt), (ins HWRegs:$rd), + "rdhwr\t$rt, $rd", [], IIAlu> { let rs = 0; let shamt = 0; } +// Ext and Ins +class ExtIns<bits<6> _funct, string instr_asm, dag outs, dag ins, + list<dag> pattern, InstrItinClass itin>: + FR<0x1f, _funct, outs, ins, !strconcat(instr_asm, " $rt, $rs, $pos, $sz"), + pattern, itin>, Requires<[HasMips32r2]> { + bits<5> pos; + bits<5> sz; + let rd = sz; + let shamt = pos; +} + +// Atomic instructions with 2 source operands (ATOMIC_SWAP & ATOMIC_LOAD_*). +class Atomic2Ops<PatFrag Op, string Opstr> : + MipsPseudo<(outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr), + !strconcat("atomic_", Opstr, "\t$dst, $ptr, $incr"), + [(set CPURegs:$dst, + (Op CPURegs:$ptr, CPURegs:$incr))]>; + +// Atomic Compare & Swap. +class AtomicCmpSwap<PatFrag Op, string Width> : + MipsPseudo<(outs CPURegs:$dst), + (ins CPURegs:$ptr, CPURegs:$cmp, CPURegs:$swap), + !strconcat("atomic_cmp_swap_", Width, + "\t$dst, $ptr, $cmp, $swap"), + [(set CPURegs:$dst, + (Op CPURegs:$ptr, CPURegs:$cmp, CPURegs:$swap))]>; + //===----------------------------------------------------------------------===// // Pseudo instructions //===----------------------------------------------------------------------===// @@ -427,112 +593,32 @@ def CPLOAD : MipsPseudo<(outs), (ins CPURegs:$picreg), ".cpload\t$picreg", []>; def CPRESTORE : MipsPseudo<(outs), (ins i32imm:$loc), ".cprestore\t$loc", []>; let usesCustomInserter = 1 in { - def ATOMIC_LOAD_ADD_I8 : MipsPseudo< - (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr), - "atomic_load_add_8\t$dst, $ptr, $incr", - [(set CPURegs:$dst, (atomic_load_add_8 CPURegs:$ptr, CPURegs:$incr))]>; - def ATOMIC_LOAD_ADD_I16 : MipsPseudo< - (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr), - "atomic_load_add_16\t$dst, $ptr, $incr", - [(set CPURegs:$dst, (atomic_load_add_16 CPURegs:$ptr, CPURegs:$incr))]>; - def ATOMIC_LOAD_ADD_I32 : MipsPseudo< - (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr), - "atomic_load_add_32\t$dst, $ptr, $incr", - [(set CPURegs:$dst, (atomic_load_add_32 CPURegs:$ptr, CPURegs:$incr))]>; - - def ATOMIC_LOAD_SUB_I8 : MipsPseudo< - (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr), - "atomic_load_sub_8\t$dst, $ptr, $incr", - [(set CPURegs:$dst, (atomic_load_sub_8 CPURegs:$ptr, CPURegs:$incr))]>; - def ATOMIC_LOAD_SUB_I16 : MipsPseudo< - (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr), - "atomic_load_sub_16\t$dst, $ptr, $incr", - [(set CPURegs:$dst, (atomic_load_sub_16 CPURegs:$ptr, CPURegs:$incr))]>; - def ATOMIC_LOAD_SUB_I32 : MipsPseudo< - (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr), - "atomic_load_sub_32\t$dst, $ptr, $incr", - [(set CPURegs:$dst, (atomic_load_sub_32 CPURegs:$ptr, CPURegs:$incr))]>; - - def ATOMIC_LOAD_AND_I8 : MipsPseudo< - (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr), - "atomic_load_and_8\t$dst, $ptr, $incr", - [(set CPURegs:$dst, (atomic_load_and_8 CPURegs:$ptr, CPURegs:$incr))]>; - def ATOMIC_LOAD_AND_I16 : MipsPseudo< - (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr), - "atomic_load_and_16\t$dst, $ptr, $incr", - [(set CPURegs:$dst, (atomic_load_and_16 CPURegs:$ptr, CPURegs:$incr))]>; - def ATOMIC_LOAD_AND_I32 : MipsPseudo< - (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr), - "atomic_load_and_32\t$dst, $ptr, $incr", - [(set CPURegs:$dst, (atomic_load_and_32 CPURegs:$ptr, CPURegs:$incr))]>; - - def ATOMIC_LOAD_OR_I8 : MipsPseudo< - (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr), - "atomic_load_or_8\t$dst, $ptr, $incr", - [(set CPURegs:$dst, (atomic_load_or_8 CPURegs:$ptr, CPURegs:$incr))]>; - def ATOMIC_LOAD_OR_I16 : MipsPseudo< - (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr), - "atomic_load_or_16\t$dst, $ptr, $incr", - [(set CPURegs:$dst, (atomic_load_or_16 CPURegs:$ptr, CPURegs:$incr))]>; - def ATOMIC_LOAD_OR_I32 : MipsPseudo< - (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr), - "atomic_load_or_32\t$dst, $ptr, $incr", - [(set CPURegs:$dst, (atomic_load_or_32 CPURegs:$ptr, CPURegs:$incr))]>; - - def ATOMIC_LOAD_XOR_I8 : MipsPseudo< - (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr), - "atomic_load_xor_8\t$dst, $ptr, $incr", - [(set CPURegs:$dst, (atomic_load_xor_8 CPURegs:$ptr, CPURegs:$incr))]>; - def ATOMIC_LOAD_XOR_I16 : MipsPseudo< - (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr), - "atomic_load_xor_16\t$dst, $ptr, $incr", - [(set CPURegs:$dst, (atomic_load_xor_16 CPURegs:$ptr, CPURegs:$incr))]>; - def ATOMIC_LOAD_XOR_I32 : MipsPseudo< - (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr), - "atomic_load_xor_32\t$dst, $ptr, $incr", - [(set CPURegs:$dst, (atomic_load_xor_32 CPURegs:$ptr, CPURegs:$incr))]>; - - def ATOMIC_LOAD_NAND_I8 : MipsPseudo< - (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr), - "atomic_load_nand_8\t$dst, $ptr, $incr", - [(set CPURegs:$dst, (atomic_load_nand_8 CPURegs:$ptr, CPURegs:$incr))]>; - def ATOMIC_LOAD_NAND_I16 : MipsPseudo< - (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr), - "atomic_load_nand_16\t$dst, $ptr, $incr", - [(set CPURegs:$dst, (atomic_load_nand_16 CPURegs:$ptr, CPURegs:$incr))]>; - def ATOMIC_LOAD_NAND_I32 : MipsPseudo< - (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr), - "atomic_load_nand_32\t$dst, $ptr, $incr", - [(set CPURegs:$dst, (atomic_load_nand_32 CPURegs:$ptr, CPURegs:$incr))]>; - - def ATOMIC_SWAP_I8 : MipsPseudo< - (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$val), - "atomic_swap_8\t$dst, $ptr, $val", - [(set CPURegs:$dst, (atomic_swap_8 CPURegs:$ptr, CPURegs:$val))]>; - def ATOMIC_SWAP_I16 : MipsPseudo< - (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$val), - "atomic_swap_16\t$dst, $ptr, $val", - [(set CPURegs:$dst, (atomic_swap_16 CPURegs:$ptr, CPURegs:$val))]>; - def ATOMIC_SWAP_I32 : MipsPseudo< - (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$val), - "atomic_swap_32\t$dst, $ptr, $val", - [(set CPURegs:$dst, (atomic_swap_32 CPURegs:$ptr, CPURegs:$val))]>; - - def ATOMIC_CMP_SWAP_I8 : MipsPseudo< - (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$oldval, CPURegs:$newval), - "atomic_cmp_swap_8\t$dst, $ptr, $oldval, $newval", - [(set CPURegs:$dst, - (atomic_cmp_swap_8 CPURegs:$ptr, CPURegs:$oldval, CPURegs:$newval))]>; - def ATOMIC_CMP_SWAP_I16 : MipsPseudo< - (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$oldval, CPURegs:$newval), - "atomic_cmp_swap_16\t$dst, $ptr, $oldval, $newval", - [(set CPURegs:$dst, - (atomic_cmp_swap_16 CPURegs:$ptr, CPURegs:$oldval, CPURegs:$newval))]>; - def ATOMIC_CMP_SWAP_I32 : MipsPseudo< - (outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$oldval, CPURegs:$newval), - "atomic_cmp_swap_32\t$dst, $ptr, $oldval, $newval", - [(set CPURegs:$dst, - (atomic_cmp_swap_32 CPURegs:$ptr, CPURegs:$oldval, CPURegs:$newval))]>; + def ATOMIC_LOAD_ADD_I8 : Atomic2Ops<atomic_load_add_8, "load_add_8">; + def ATOMIC_LOAD_ADD_I16 : Atomic2Ops<atomic_load_add_16, "load_add_16">; + def ATOMIC_LOAD_ADD_I32 : Atomic2Ops<atomic_load_add_32, "load_add_32">; + def ATOMIC_LOAD_SUB_I8 : Atomic2Ops<atomic_load_sub_8, "load_sub_8">; + def ATOMIC_LOAD_SUB_I16 : Atomic2Ops<atomic_load_sub_16, "load_sub_16">; + def ATOMIC_LOAD_SUB_I32 : Atomic2Ops<atomic_load_sub_32, "load_sub_32">; + def ATOMIC_LOAD_AND_I8 : Atomic2Ops<atomic_load_and_8, "load_and_8">; + def ATOMIC_LOAD_AND_I16 : Atomic2Ops<atomic_load_and_16, "load_and_16">; + def ATOMIC_LOAD_AND_I32 : Atomic2Ops<atomic_load_and_32, "load_and_32">; + def ATOMIC_LOAD_OR_I8 : Atomic2Ops<atomic_load_or_8, "load_or_8">; + def ATOMIC_LOAD_OR_I16 : Atomic2Ops<atomic_load_or_16, "load_or_16">; + def ATOMIC_LOAD_OR_I32 : Atomic2Ops<atomic_load_or_32, "load_or_32">; + def ATOMIC_LOAD_XOR_I8 : Atomic2Ops<atomic_load_xor_8, "load_xor_8">; + def ATOMIC_LOAD_XOR_I16 : Atomic2Ops<atomic_load_xor_16, "load_xor_16">; + def ATOMIC_LOAD_XOR_I32 : Atomic2Ops<atomic_load_xor_32, "load_xor_32">; + def ATOMIC_LOAD_NAND_I8 : Atomic2Ops<atomic_load_nand_8, "load_nand_8">; + def ATOMIC_LOAD_NAND_I16 : Atomic2Ops<atomic_load_nand_16, "load_nand_16">; + def ATOMIC_LOAD_NAND_I32 : Atomic2Ops<atomic_load_nand_32, "load_nand_32">; + + def ATOMIC_SWAP_I8 : Atomic2Ops<atomic_swap_8, "swap_8">; + def ATOMIC_SWAP_I16 : Atomic2Ops<atomic_swap_16, "swap_16">; + def ATOMIC_SWAP_I32 : Atomic2Ops<atomic_swap_32, "swap_32">; + + def ATOMIC_CMP_SWAP_I8 : AtomicCmpSwap<atomic_cmp_swap_8, "8">; + def ATOMIC_CMP_SWAP_I16 : AtomicCmpSwap<atomic_cmp_swap_16, "16">; + def ATOMIC_CMP_SWAP_I32 : AtomicCmpSwap<atomic_cmp_swap_32, "32">; } //===----------------------------------------------------------------------===// @@ -544,26 +630,26 @@ let usesCustomInserter = 1 in { //===----------------------------------------------------------------------===// /// Arithmetic Instructions (ALU Immediate) -def ADDiu : ArithI<0x09, "addiu", add, simm16, immSExt16>; -def ADDi : ArithOverflowI<0x08, "addi", add, simm16, immSExt16>; -def SLTi : SetCC_I<0x0a, "slti", setlt, simm16, immSExt16>; -def SLTiu : SetCC_I<0x0b, "sltiu", setult, simm16, immSExt16>; -def ANDi : LogicI<0x0c, "andi", and>; -def ORi : LogicI<0x0d, "ori", or>; -def XORi : LogicI<0x0e, "xori", xor>; +def ADDiu : ArithLogicI<0x09, "addiu", add, simm16, immSExt16, CPURegs>; +def ADDi : ArithOverflowI<0x08, "addi", add, simm16, immSExt16, CPURegs>; +def SLTi : SetCC_I<0x0a, "slti", setlt, simm16, immSExt16, CPURegs>; +def SLTiu : SetCC_I<0x0b, "sltiu", setult, simm16, immSExt16, CPURegs>; +def ANDi : ArithLogicI<0x0c, "andi", and, uimm16, immZExt16, CPURegs>; +def ORi : ArithLogicI<0x0d, "ori", or, uimm16, immZExt16, CPURegs>; +def XORi : ArithLogicI<0x0e, "xori", xor, uimm16, immZExt16, CPURegs>; def LUi : LoadUpper<0x0f, "lui">; /// Arithmetic Instructions (3-Operand, R-Type) -def ADDu : ArithR<0x00, 0x21, "addu", add, IIAlu, 1>; -def SUBu : ArithR<0x00, 0x23, "subu", sub, IIAlu>; -def ADD : ArithOverflowR<0x00, 0x20, "add", 1>; -def SUB : ArithOverflowR<0x00, 0x22, "sub">; -def SLT : SetCC_R<0x00, 0x2a, "slt", setlt>; -def SLTu : SetCC_R<0x00, 0x2b, "sltu", setult>; -def AND : LogicR<0x24, "and", and>; -def OR : LogicR<0x25, "or", or>; -def XOR : LogicR<0x26, "xor", xor>; -def NOR : LogicNOR<0x00, 0x27, "nor">; +def ADDu : ArithLogicR<0x00, 0x21, "addu", add, IIAlu, CPURegs, 1>; +def SUBu : ArithLogicR<0x00, 0x23, "subu", sub, IIAlu, CPURegs>; +def ADD : ArithOverflowR<0x00, 0x20, "add", IIAlu, CPURegs, 1>; +def SUB : ArithOverflowR<0x00, 0x22, "sub", IIAlu, CPURegs>; +def SLT : SetCC_R<0x00, 0x2a, "slt", setlt, CPURegs>; +def SLTu : SetCC_R<0x00, 0x2b, "sltu", setult, CPURegs>; +def AND : ArithLogicR<0x00, 0x24, "and", and, IIAlu, CPURegs, 1>; +def OR : ArithLogicR<0x00, 0x25, "or", or, IIAlu, CPURegs, 1>; +def XOR : ArithLogicR<0x00, 0x26, "xor", xor, IIAlu, CPURegs, 1>; +def NOR : LogicNOR<0x00, 0x27, "nor", CPURegs>; /// Shift Instructions def SLL : LogicR_shift_rotate_imm<0x00, 0x00, "sll", shl>; @@ -574,45 +660,58 @@ def SRLV : LogicR_shift_rotate_reg<0x06, 0x00, "srlv", srl>; def SRAV : LogicR_shift_rotate_reg<0x07, 0x00, "srav", sra>; // Rotate Instructions -let Predicates = [IsMips32r2] in { +let Predicates = [HasMips32r2] in { def ROTR : LogicR_shift_rotate_imm<0x02, 0x01, "rotr", rotr>; def ROTRV : LogicR_shift_rotate_reg<0x06, 0x01, "rotrv", rotr>; } /// Load and Store Instructions -def LB : LoadM<0x20, "lb", sextloadi8>; -def LBu : LoadM<0x24, "lbu", zextloadi8>; -def LH : LoadM<0x21, "lh", sextloadi16>; -def LHu : LoadM<0x25, "lhu", zextloadi16>; -def LW : LoadM<0x23, "lw", load>; -def SB : StoreM<0x28, "sb", truncstorei8>; -def SH : StoreM<0x29, "sh", truncstorei16>; -def SW : StoreM<0x2b, "sw", store>; +/// aligned +defm LB : LoadM32<0x20, "lb", sextloadi8>; +defm LBu : LoadM32<0x24, "lbu", zextloadi8>; +defm LH : LoadM32<0x21, "lh", sextloadi16_a>; +defm LHu : LoadM32<0x25, "lhu", zextloadi16_a>; +defm LW : LoadM32<0x23, "lw", load_a>; +defm SB : StoreM32<0x28, "sb", truncstorei8>; +defm SH : StoreM32<0x29, "sh", truncstorei16_a>; +defm SW : StoreM32<0x2b, "sw", store_a>; + +/// unaligned +defm ULH : LoadM32<0x21, "ulh", sextloadi16_u, 1>; +defm ULHu : LoadM32<0x25, "ulhu", zextloadi16_u, 1>; +defm ULW : LoadM32<0x23, "ulw", load_u, 1>; +defm USH : StoreM32<0x29, "ush", truncstorei16_u, 1>; +defm USW : StoreM32<0x2b, "usw", store_u, 1>; + +let hasSideEffects = 1 in +def SYNC : MipsInst<(outs), (ins i32imm:$stype), "sync $stype", + [(MipsSync imm:$stype)], NoItinerary> +{ + let opcode = 0; + let Inst{25-11} = 0; + let Inst{5-0} = 15; +} /// Load-linked, Store-conditional -let hasDelaySlot = 1 in +let mayLoad = 1 in def LL : FI<0x30, (outs CPURegs:$dst), (ins mem:$addr), "ll\t$dst, $addr", [], IILoad>; -let Constraints = "$src = $dst" in +let mayStore = 1, Constraints = "$src = $dst" in def SC : FI<0x38, (outs CPURegs:$dst), (ins CPURegs:$src, mem:$addr), "sc\t$src, $addr", [], IIStore>; /// Jump and Branch Instructions def J : JumpFJ<0x02, "j">; -def JR : JumpFR<0x00, 0x08, "jr">; +let isIndirectBranch = 1 in + def JR : JumpFR<0x00, 0x08, "jr">; def JAL : JumpLink<0x03, "jal">; def JALR : JumpLinkReg<0x00, 0x09, "jalr">; -def BEQ : CBranch<0x04, "beq", seteq>; -def BNE : CBranch<0x05, "bne", setne>; - -let rt=1 in - def BGEZ : CBranchZero<0x01, "bgez", setge>; - -let rt=0 in { - def BGTZ : CBranchZero<0x07, "bgtz", setgt>; - def BLEZ : CBranchZero<0x07, "blez", setle>; - def BLTZ : CBranchZero<0x01, "bltz", setlt>; -} +def BEQ : CBranch<0x04, "beq", seteq, CPURegs>; +def BNE : CBranch<0x05, "bne", setne, CPURegs>; +def BGEZ : CBranchZero<0x01, 1, "bgez", setge, CPURegs>; +def BGTZ : CBranchZero<0x07, 0, "bgtz", setgt, CPURegs>; +def BLEZ : CBranchZero<0x07, 0, "blez", setle, CPURegs>; +def BLTZ : CBranchZero<0x01, 0, "bltz", setlt, CPURegs>; def BGEZAL : BranchLink<"bgezal">; def BLTZAL : BranchLink<"bltzal">; @@ -639,40 +738,31 @@ let Uses = [LO] in def MFLO : MoveFromLOHI<0x12, "mflo">; /// Sign Ext In Register Instructions. -let Predicates = [HasSEInReg] in { - let shamt = 0x10, rs = 0 in - def SEB : SignExtInReg<0x21, "seb", i8>; - - let shamt = 0x18, rs = 0 in - def SEH : SignExtInReg<0x20, "seh", i16>; -} +def SEB : SignExtInReg<0x10, "seb", i8>; +def SEH : SignExtInReg<0x18, "seh", i16>; /// Count Leading -def CLZ : CountLeading<0b100000, "clz", - [(set CPURegs:$dst, (ctlz CPURegs:$src))]>; -def CLO : CountLeading<0b100001, "clo", - [(set CPURegs:$dst, (ctlz (not CPURegs:$src)))]>; +def CLZ : CountLeading<0x20, "clz", + [(set CPURegs:$rd, (ctlz CPURegs:$rs))]>; +def CLO : CountLeading<0x21, "clo", + [(set CPURegs:$rd, (ctlz (not CPURegs:$rs)))]>; /// Byte Swap -let Predicates = [HasSwap] in { - let shamt = 0x3, rs = 0 in - def WSBW : ByteSwap<0x20, "wsbw">; -} - -/// Conditional Move -def MIPS_CMOV_ZERO : PatLeaf<(i32 0)>; -def MIPS_CMOV_NZERO : PatLeaf<(i32 1)>; +def WSBW : ByteSwap<0x20, 0x2, "wsbw">; // Conditional moves: // These instructions are expanded in // MipsISelLowering::EmitInstrWithCustomInserter if target does not have // conditional move instructions. // flag:int, data:int -let usesCustomInserter = 1, shamt = 0, Constraints = "$F = $dst" in - class CondMovIntInt<bits<6> funct, string instr_asm> : - FR<0, funct, (outs CPURegs:$dst), - (ins CPURegs:$T, CPURegs:$cond, CPURegs:$F), - !strconcat(instr_asm, "\t$dst, $T, $cond"), [], NoItinerary>; +class CondMovIntInt<bits<6> funct, string instr_asm> : + FR<0, funct, (outs CPURegs:$rd), + (ins CPURegs:$rs, CPURegs:$rt, CPURegs:$F), + !strconcat(instr_asm, "\t$rd, $rs, $rt"), [], NoItinerary> { + let shamt = 0; + let usesCustomInserter = 1; + let Constraints = "$F = $rd"; +} def MOVZ_I : CondMovIntInt<0x0a, "movz">; def MOVN_I : CondMovIntInt<0x0b, "movn">; @@ -685,13 +775,13 @@ let addr=0 in // instructions. The same not happens for stack address copies, so an // add op with mem ComplexPattern is used and the stack address copy // can be matched. It's similar to Sparc LEA_ADDRi -def LEA_ADDiu : EffectiveAddress<"addiu\t$dst, $addr">; +def LEA_ADDiu : EffectiveAddress<"addiu\t$rt, $addr">; // DynAlloc node points to dynamically allocated stack space. // $sp is added to the list of implicitly used registers to prevent dead code // elimination from removing instructions that modify $sp. let Uses = [SP] in -def DynAlloc : EffectiveAddress<"addiu\t$dst, $addr">; +def DynAlloc : EffectiveAddress<"addiu\t$rt, $addr">; // MADD*/MSUB* def MADD : MArithR<0, "madd", MipsMAdd, 1>; @@ -701,10 +791,25 @@ 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 : ArithR<0x1c, 0x02, "mul", mul, IIImul, 1>, Requires<[IsMips32]>; +def MUL : ArithLogicR<0x1c, 0x02, "mul", mul, IIImul, CPURegs, 1>, + Requires<[HasMips32]>; def RDHWR : ReadHardware; +def EXT : ExtIns<0, "ext", (outs CPURegs:$rt), + (ins CPURegs:$rs, uimm16:$pos, uimm16:$sz), + [(set CPURegs:$rt, + (MipsExt CPURegs:$rs, immZExt5:$pos, immZExt5:$sz))], + NoItinerary>; + +let Constraints = "$src = $rt" in +def INS : ExtIns<4, "ins", (outs CPURegs:$rt), + (ins CPURegs:$rs, uimm16:$pos, uimm16:$sz, CPURegs:$src), + [(set CPURegs:$rt, + (MipsIns CPURegs:$rs, immZExt5:$pos, immZExt5:$sz, + CPURegs:$src))], + NoItinerary>; + //===----------------------------------------------------------------------===// // Arbitrary patterns that map to one or more instructions //===----------------------------------------------------------------------===// @@ -738,16 +843,20 @@ def : Pat<(MipsJmpLink (i32 texternalsym:$dst)), // hi/lo relocs def : Pat<(MipsHi tglobaladdr:$in), (LUi tglobaladdr:$in)>; def : Pat<(MipsHi tblockaddress:$in), (LUi tblockaddress:$in)>; +def : Pat<(MipsLo tglobaladdr:$in), (ADDiu ZERO, tglobaladdr:$in)>; +def : Pat<(MipsLo tblockaddress:$in), (ADDiu ZERO, tblockaddress:$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<(MipsHi tjumptable:$in), (LUi tjumptable:$in)>; +def : Pat<(MipsLo tjumptable:$in), (ADDiu ZERO, tjumptable:$in)>; def : Pat<(add CPURegs:$hi, (MipsLo tjumptable:$lo)), (ADDiu CPURegs:$hi, tjumptable:$lo)>; def : Pat<(MipsHi tconstpool:$in), (LUi tconstpool:$in)>; +def : Pat<(MipsLo tconstpool:$in), (ADDiu ZERO, tconstpool:$in)>; def : Pat<(add CPURegs:$hi, (MipsLo tconstpool:$lo)), (ADDiu CPURegs:$hi, tconstpool:$lo)>; @@ -763,6 +872,7 @@ def : Pat<(add CPURegs:$gp, (MipsTlsGd tglobaltlsaddr:$in)), // tprel hi/lo def : Pat<(MipsTprelHi tglobaltlsaddr:$in), (LUi tglobaltlsaddr:$in)>; +def : Pat<(MipsTprelLo tglobaltlsaddr:$in), (ADDiu ZERO, tglobaltlsaddr:$in)>; def : Pat<(add CPURegs:$hi, (MipsTprelLo tglobaltlsaddr:$lo)), (ADDiu CPURegs:$hi, tglobaltlsaddr:$lo)>; @@ -784,60 +894,67 @@ def : Pat<(not CPURegs:$in), // extended load and stores def : Pat<(extloadi1 addr:$src), (LBu addr:$src)>; def : Pat<(extloadi8 addr:$src), (LBu addr:$src)>; -def : Pat<(extloadi16 addr:$src), (LHu addr:$src)>; +def : Pat<(extloadi16_a addr:$src), (LHu addr:$src)>; +def : Pat<(extloadi16_u addr:$src), (ULHu addr:$src)>; // peepholes def : Pat<(store (i32 0), addr:$dst), (SW ZERO, addr:$dst)>; // brcond patterns -def : Pat<(brcond (setne CPURegs:$lhs, 0), bb:$dst), - (BNE CPURegs:$lhs, ZERO, bb:$dst)>; -def : Pat<(brcond (seteq CPURegs:$lhs, 0), bb:$dst), - (BEQ CPURegs:$lhs, ZERO, bb:$dst)>; - -def : Pat<(brcond (setge CPURegs:$lhs, CPURegs:$rhs), bb:$dst), - (BEQ (SLT CPURegs:$lhs, CPURegs:$rhs), ZERO, bb:$dst)>; -def : Pat<(brcond (setuge CPURegs:$lhs, CPURegs:$rhs), bb:$dst), - (BEQ (SLTu CPURegs:$lhs, CPURegs:$rhs), ZERO, bb:$dst)>; -def : Pat<(brcond (setge CPURegs:$lhs, immSExt16:$rhs), bb:$dst), - (BEQ (SLTi CPURegs:$lhs, immSExt16:$rhs), ZERO, bb:$dst)>; -def : Pat<(brcond (setuge CPURegs:$lhs, immSExt16:$rhs), bb:$dst), - (BEQ (SLTiu CPURegs:$lhs, immSExt16:$rhs), ZERO, bb:$dst)>; - -def : Pat<(brcond (setle CPURegs:$lhs, CPURegs:$rhs), bb:$dst), - (BEQ (SLT CPURegs:$rhs, CPURegs:$lhs), ZERO, bb:$dst)>; -def : Pat<(brcond (setule CPURegs:$lhs, CPURegs:$rhs), bb:$dst), - (BEQ (SLTu CPURegs:$rhs, CPURegs:$lhs), ZERO, bb:$dst)>; - -def : Pat<(brcond CPURegs:$cond, bb:$dst), - (BNE CPURegs:$cond, ZERO, bb:$dst)>; +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 : 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 : 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 : Pat<(brcond RC:$cond, bb:$dst), + (BNEOp RC:$cond, ZEROReg, bb:$dst)>; +} + +defm : BrcondPats<CPURegs, BEQ, BNE, SLT, SLTu, SLTi, SLTiu, ZERO>; // select patterns multiclass MovzPats<RegisterClass RC, Instruction MOVZInst> { - def : Pat<(select (setge CPURegs:$lhs, CPURegs:$rhs), RC:$T, RC:$F), + def : Pat<(select (i32 (setge CPURegs:$lhs, CPURegs:$rhs)), RC:$T, RC:$F), (MOVZInst RC:$T, (SLT CPURegs:$lhs, CPURegs:$rhs), RC:$F)>; - def : Pat<(select (setuge CPURegs:$lhs, CPURegs:$rhs), RC:$T, RC:$F), + def : Pat<(select (i32 (setuge CPURegs:$lhs, CPURegs:$rhs)), RC:$T, RC:$F), (MOVZInst RC:$T, (SLTu CPURegs:$lhs, CPURegs:$rhs), RC:$F)>; - def : Pat<(select (setge CPURegs:$lhs, immSExt16:$rhs), RC:$T, RC:$F), + def : Pat<(select (i32 (setge CPURegs:$lhs, immSExt16:$rhs)), RC:$T, RC:$F), (MOVZInst RC:$T, (SLTi CPURegs:$lhs, immSExt16:$rhs), RC:$F)>; - def : Pat<(select (setuge CPURegs:$lh, immSExt16:$rh), RC:$T, RC:$F), + def : Pat<(select (i32 (setuge CPURegs:$lh, immSExt16:$rh)), RC:$T, RC:$F), (MOVZInst RC:$T, (SLTiu CPURegs:$lh, immSExt16:$rh), RC:$F)>; - def : Pat<(select (setle CPURegs:$lhs, CPURegs:$rhs), RC:$T, RC:$F), + def : Pat<(select (i32 (setle CPURegs:$lhs, CPURegs:$rhs)), RC:$T, RC:$F), (MOVZInst RC:$T, (SLT CPURegs:$rhs, CPURegs:$lhs), RC:$F)>; - def : Pat<(select (setule CPURegs:$lhs, CPURegs:$rhs), RC:$T, RC:$F), + def : Pat<(select (i32 (setule CPURegs:$lhs, CPURegs:$rhs)), RC:$T, RC:$F), (MOVZInst RC:$T, (SLTu CPURegs:$rhs, CPURegs:$lhs), RC:$F)>; - def : Pat<(select (seteq CPURegs:$lhs, CPURegs:$rhs), RC:$T, RC:$F), + def : Pat<(select (i32 (seteq CPURegs:$lhs, CPURegs:$rhs)), RC:$T, RC:$F), (MOVZInst RC:$T, (XOR CPURegs:$lhs, CPURegs:$rhs), RC:$F)>; - def : Pat<(select (seteq CPURegs:$lhs, 0), RC:$T, RC:$F), + def : Pat<(select (i32 (seteq CPURegs:$lhs, 0)), RC:$T, RC:$F), (MOVZInst RC:$T, CPURegs:$lhs, RC:$F)>; } multiclass MovnPats<RegisterClass RC, Instruction MOVNInst> { - def : Pat<(select (setne CPURegs:$lhs, CPURegs:$rhs), RC:$T, RC:$F), + def : Pat<(select (i32 (setne CPURegs:$lhs, CPURegs:$rhs)), RC:$T, RC:$F), (MOVNInst RC:$T, (XOR CPURegs:$lhs, CPURegs:$rhs), RC:$F)>; def : Pat<(select CPURegs:$cond, RC:$T, RC:$F), (MOVNInst RC:$T, CPURegs:$cond, RC:$F)>; - def : Pat<(select (setne CPURegs:$lhs, 0), RC:$T, RC:$F), + def : Pat<(select (i32 (setne CPURegs:$lhs, 0)), RC:$T, RC:$F), (MOVNInst RC:$T, CPURegs:$lhs, RC:$F)>; } @@ -845,30 +962,48 @@ defm : MovzPats<CPURegs, MOVZ_I>; defm : MovnPats<CPURegs, MOVN_I>; // setcc patterns -def : Pat<(seteq CPURegs:$lhs, CPURegs:$rhs), - (SLTu (XOR CPURegs:$lhs, CPURegs:$rhs), 1)>; -def : Pat<(setne CPURegs:$lhs, CPURegs:$rhs), - (SLTu ZERO, (XOR CPURegs:$lhs, CPURegs:$rhs))>; - -def : Pat<(setle CPURegs:$lhs, CPURegs:$rhs), - (XORi (SLT CPURegs:$rhs, CPURegs:$lhs), 1)>; -def : Pat<(setule CPURegs:$lhs, CPURegs:$rhs), - (XORi (SLTu CPURegs:$rhs, CPURegs:$lhs), 1)>; - -def : Pat<(setgt CPURegs:$lhs, CPURegs:$rhs), - (SLT CPURegs:$rhs, CPURegs:$lhs)>; -def : Pat<(setugt CPURegs:$lhs, CPURegs:$rhs), - (SLTu CPURegs:$rhs, CPURegs:$lhs)>; - -def : Pat<(setge CPURegs:$lhs, CPURegs:$rhs), - (XORi (SLT CPURegs:$lhs, CPURegs:$rhs), 1)>; -def : Pat<(setuge CPURegs:$lhs, CPURegs:$rhs), - (XORi (SLTu CPURegs:$lhs, CPURegs:$rhs), 1)>; - -def : Pat<(setge CPURegs:$lhs, immSExt16:$rhs), - (XORi (SLTi CPURegs:$lhs, immSExt16:$rhs), 1)>; -def : Pat<(setuge CPURegs:$lhs, immSExt16:$rhs), - (XORi (SLTiu CPURegs:$lhs, immSExt16:$rhs), 1)>; +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))>; +} + +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)>; +} + +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)>; +} + +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)>; +} + +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)>; +} + +defm : SeteqPats<CPURegs, SLTiu, XOR, SLTu, ZERO>; +defm : SetlePats<CPURegs, SLT, SLTu>; +defm : SetgtPats<CPURegs, SLT, SLTu>; +defm : SetgePats<CPURegs, SLT, SLTu>; +defm : SetgeImmPats<CPURegs, SLTi, SLTiu>; // select MipsDynAlloc def : Pat<(MipsDynAlloc addr:$f), (DynAlloc addr:$f)>; @@ -878,4 +1013,5 @@ def : Pat<(MipsDynAlloc addr:$f), (DynAlloc addr:$f)>; //===----------------------------------------------------------------------===// include "MipsInstrFPU.td" +include "Mips64InstrInfo.td" diff --git a/contrib/llvm/lib/Target/Mips/MipsJITInfo.cpp b/contrib/llvm/lib/Target/Mips/MipsJITInfo.cpp new file mode 100644 index 0000000..28c2b48 --- /dev/null +++ b/contrib/llvm/lib/Target/Mips/MipsJITInfo.cpp @@ -0,0 +1,230 @@ +//===- MipsJITInfo.cpp - Implement the JIT interfaces for the Mips target -===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the JIT interfaces for the Mips target. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "jit" +#include "MipsJITInfo.h" +#include "MipsInstrInfo.h" +#include "MipsRelocations.h" +#include "MipsSubtarget.h" +#include "llvm/Function.h" +#include "llvm/CodeGen/JITCodeEmitter.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Memory.h" +#include <cstdlib> +using namespace llvm; + + +void MipsJITInfo::replaceMachineCodeForFunction(void *Old, void *New) { + report_fatal_error("MipsJITInfo::replaceMachineCodeForFunction"); +} + +/// JITCompilerFunction - This contains the address of the JIT function used to +/// compile a function lazily. +static TargetJITInfo::JITCompilerFn JITCompilerFunction; + +// Get the ASMPREFIX for the current host. This is often '_'. +#ifndef __USER_LABEL_PREFIX__ +#define __USER_LABEL_PREFIX__ +#endif +#define GETASMPREFIX2(X) #X +#define GETASMPREFIX(X) GETASMPREFIX2(X) +#define ASMPREFIX GETASMPREFIX(__USER_LABEL_PREFIX__) + +// CompilationCallback stub - We can't use a C function with inline assembly in +// it, because the prolog/epilog inserted by GCC won't work for us. Instead, +// write our own wrapper, which does things our way, so we have complete control +// over register saving and restoring. This code saves registers, calls +// MipsCompilationCallbackC and restores registers. +extern "C" { +#if defined (__mips__) +void MipsCompilationCallback(); + + asm( + ".text\n" + ".align 2\n" + ".globl " ASMPREFIX "MipsCompilationCallback\n" + ASMPREFIX "MipsCompilationCallback:\n" + ".ent " ASMPREFIX "MipsCompilationCallback\n" + ".frame $29, 32, $31\n" + ".set noreorder\n" + ".cpload $t9\n" + + "addiu $sp, $sp, -60\n" + ".cprestore 16\n" + + // Save argument registers a0, a1, a2, a3, f12, f14 since they may contain + // stuff for the real target function right now. We have to act as if this + // whole compilation callback doesn't exist as far as the caller is + // concerned. We also need to save the ra register since it contains the + // original return address, and t8 register since it contains the address + // of the end of function stub. + "sw $a0, 20($sp)\n" + "sw $a1, 24($sp)\n" + "sw $a2, 28($sp)\n" + "sw $a3, 32($sp)\n" + "sw $ra, 36($sp)\n" + "sw $t8, 40($sp)\n" + "sdc1 $f12, 44($sp)\n" + "sdc1 $f14, 52($sp)\n" + + // t8 points at the end of function stub. Pass the beginning of the stub + // to the MipsCompilationCallbackC. + "addiu $a0, $t8, -16\n" + "jal " ASMPREFIX "MipsCompilationCallbackC\n" + "nop\n" + + // Restore registers. + "lw $a0, 20($sp)\n" + "lw $a1, 24($sp)\n" + "lw $a2, 28($sp)\n" + "lw $a3, 32($sp)\n" + "lw $ra, 36($sp)\n" + "lw $t8, 40($sp)\n" + "ldc1 $f12, 44($sp)\n" + "ldc1 $f14, 52($sp)\n" + "addiu $sp, $sp, 60\n" + + // Jump to the (newly modified) stub to invoke the real function. + "addiu $t8, $t8, -16\n" + "jr $t8\n" + "nop\n" + + ".set reorder\n" + ".end " ASMPREFIX "MipsCompilationCallback\n" + ); +#else // host != Mips + void MipsCompilationCallback() { + llvm_unreachable( + "Cannot call MipsCompilationCallback() on a non-Mips arch!"); + } +#endif +} + +/// MipsCompilationCallbackC - This is the target-specific function invoked +/// by the function stub when we did not know the real target of a call. +/// This function must locate the start of the stub or call site and pass +/// it into the JIT compiler function. +extern "C" void MipsCompilationCallbackC(intptr_t StubAddr) { + // Get the address of the compiled code for this function. + intptr_t NewVal = (intptr_t) JITCompilerFunction((void*) StubAddr); + + // Rewrite the function stub so that we don't end up here every time we + // execute the call. We're replacing the first four instructions of the + // stub with code that jumps to the compiled function: + // lui $t9, %hi(NewVal) + // addiu $t9, $t9, %lo(NewVal) + // jr $t9 + // nop + + int Hi = ((unsigned)NewVal & 0xffff0000) >> 16; + if ((NewVal & 0x8000) != 0) + Hi++; + int Lo = (int)(NewVal & 0xffff); + + *(intptr_t *)(StubAddr) = 0xf << 26 | 25 << 16 | Hi; + *(intptr_t *)(StubAddr + 4) = 9 << 26 | 25 << 21 | 25 << 16 | Lo; + *(intptr_t *)(StubAddr + 8) = 25 << 21 | 8; + *(intptr_t *)(StubAddr + 12) = 0; + + sys::Memory::InvalidateInstructionCache((void*) StubAddr, 16); +} + +TargetJITInfo::LazyResolverFn MipsJITInfo::getLazyResolverFunction( + JITCompilerFn F) { + JITCompilerFunction = F; + return MipsCompilationCallback; +} + +TargetJITInfo::StubLayout MipsJITInfo::getStubLayout() { + // The stub contains 4 4-byte instructions, aligned at 4 bytes. See + // emitFunctionStub for details. + StubLayout Result = { 4*4, 4 }; + return Result; +} + +void *MipsJITInfo::emitFunctionStub(const Function* F, void *Fn, + JITCodeEmitter &JCE) { + JCE.emitAlignment(4); + void *Addr = (void*) (JCE.getCurrentPCValue()); + if (!sys::Memory::setRangeWritable(Addr, 16)) + llvm_unreachable("ERROR: Unable to mark stub writable."); + + intptr_t EmittedAddr; + if (Fn != (void*)(intptr_t)MipsCompilationCallback) + EmittedAddr = (intptr_t)Fn; + else + EmittedAddr = (intptr_t)MipsCompilationCallback; + + + int Hi = ((unsigned)EmittedAddr & 0xffff0000) >> 16; + if ((EmittedAddr & 0x8000) != 0) + Hi++; + int Lo = (int)(EmittedAddr & 0xffff); + + // lui t9, %hi(EmittedAddr) + // addiu t9, t9, %lo(EmittedAddr) + // jalr t8, t9 + // nop + JCE.emitWordLE(0xf << 26 | 25 << 16 | Hi); + JCE.emitWordLE(9 << 26 | 25 << 21 | 25 << 16 | Lo); + JCE.emitWordLE(25 << 21 | 24 << 11 | 9); + JCE.emitWordLE(0); + + sys::Memory::InvalidateInstructionCache(Addr, 16); + if (!sys::Memory::setRangeExecutable(Addr, 16)) + llvm_unreachable("ERROR: Unable to mark stub executable."); + + return Addr; +} + +/// relocate - Before the JIT can run a block of code that has been emitted, +/// 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) { + for (unsigned i = 0; i != NumRelocs; ++i, ++MR) { + + void *RelocPos = (char*) Function + MR->getMachineCodeOffset(); + intptr_t ResultPtr = (intptr_t) MR->getResultPointer(); + + switch ((Mips::RelocationType) MR->getRelocationType()) { + case Mips::reloc_mips_branch: + ResultPtr = (((ResultPtr - (intptr_t) RelocPos) - 4) >> 2) & 0xffff; + *((unsigned*) RelocPos) |= (unsigned) ResultPtr; + break; + + case Mips::reloc_mips_26: + ResultPtr = (ResultPtr & 0x0fffffff) >> 2; + *((unsigned*) RelocPos) |= (unsigned) ResultPtr; + break; + + case Mips::reloc_mips_hi: + ResultPtr = ResultPtr >> 16; + if ((((intptr_t) (MR->getResultPointer()) & 0xffff) >> 15) == 1) { + ResultPtr += 1; + } + *((unsigned*) RelocPos) |= (unsigned) ResultPtr; + break; + + case Mips::reloc_mips_lo: + ResultPtr = ResultPtr & 0xffff; + *((unsigned*) RelocPos) |= (unsigned) ResultPtr; + break; + + default: + llvm_unreachable("ERROR: Unknown Mips relocation."); + } + } +} diff --git a/contrib/llvm/lib/Target/Mips/MipsJITInfo.h b/contrib/llvm/lib/Target/Mips/MipsJITInfo.h new file mode 100644 index 0000000..41f32a3 --- /dev/null +++ b/contrib/llvm/lib/Target/Mips/MipsJITInfo.h @@ -0,0 +1,70 @@ +//===- MipsJITInfo.h - Mips implementation of the JIT interface -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the MipsJITInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef MIPSJITINFO_H +#define MIPSJITINFO_H + +#include "MipsMachineFunction.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/Target/TargetJITInfo.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" + +namespace llvm { +class MipsTargetMachine; + +class MipsJITInfo : public TargetJITInfo { + + bool IsPIC; + + public: + explicit MipsJITInfo() : + IsPIC(false) {} + + /// replaceMachineCodeForFunction - Make it so that calling the function + /// whose machine code is at OLD turns into a call to NEW, perhaps by + /// overwriting OLD with a branch to NEW. This is used for self-modifying + /// code. + /// + virtual void replaceMachineCodeForFunction(void *Old, void *New); + + // getStubLayout - Returns the size and alignment of the largest call stub + // on Mips. + virtual StubLayout getStubLayout(); + + /// 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); + + /// getLazyResolverFunction - Expose the lazy resolver to the JIT. + virtual LazyResolverFn getLazyResolverFunction(JITCompilerFn); + + /// relocate - Before the JIT can run a block of code that has been emitted, + /// 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); + + /// Initialize - Initialize internal stage for the function being JITted. + void Initialize(const MachineFunction &MF, bool isPIC) { + IsPIC = isPIC; + } + +}; +} + +#endif diff --git a/contrib/llvm/lib/Target/Mips/MipsMCInstLower.cpp b/contrib/llvm/lib/Target/Mips/MipsMCInstLower.cpp index f5cc3aa..608a7d2 100644 --- a/contrib/llvm/lib/Target/Mips/MipsMCInstLower.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsMCInstLower.cpp @@ -29,10 +29,10 @@ MipsMCInstLower::MipsMCInstLower(Mangler *mang, const MachineFunction &mf, : Ctx(mf.getContext()), Mang(mang), AsmPrinter(asmprinter) {} MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO, - MachineOperandType MOTy) const { + MachineOperandType MOTy, + unsigned Offset) const { MipsMCSymbolRefExpr::VariantKind Kind; const MCSymbol *Symbol; - int Offset = 0; switch(MO.getTargetFlags()) { default: assert(0 && "Invalid target flag!"); @@ -46,6 +46,11 @@ MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO, case MipsII::MO_GOTTPREL: Kind = MipsMCSymbolRefExpr::VK_Mips_GOTTPREL; break; case MipsII::MO_TPREL_HI: Kind = MipsMCSymbolRefExpr::VK_Mips_TPREL_HI; break; case MipsII::MO_TPREL_LO: Kind = MipsMCSymbolRefExpr::VK_Mips_TPREL_LO; break; + case MipsII::MO_GPOFF_HI: Kind = MipsMCSymbolRefExpr::VK_Mips_GPOFF_HI; break; + case MipsII::MO_GPOFF_LO: Kind = MipsMCSymbolRefExpr::VK_Mips_GPOFF_LO; break; + case MipsII::MO_GOT_DISP: Kind = MipsMCSymbolRefExpr::VK_Mips_GOT_DISP; break; + case MipsII::MO_GOT_PAGE: Kind = MipsMCSymbolRefExpr::VK_Mips_GOT_PAGE; break; + case MipsII::MO_GOT_OFST: Kind = MipsMCSymbolRefExpr::VK_Mips_GOT_OFST; break; } switch (MOTy) { @@ -72,7 +77,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: @@ -83,36 +88,39 @@ MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO, Ctx)); } +MCOperand MipsMCInstLower::LowerOperand(const MachineOperand& MO) const { + MachineOperandType MOTy = MO.getType(); + + switch (MOTy) { + default: + assert(0 && "unknown operand type"); + break; + case MachineOperand::MO_Register: + // Ignore all implicit register operands. + if (MO.isImplicit()) break; + return MCOperand::CreateReg(MO.getReg()); + case MachineOperand::MO_Immediate: + return MCOperand::CreateImm(MO.getImm()); + case MachineOperand::MO_MachineBasicBlock: + case MachineOperand::MO_GlobalAddress: + case MachineOperand::MO_ExternalSymbol: + case MachineOperand::MO_JumpTableIndex: + case MachineOperand::MO_ConstantPoolIndex: + case MachineOperand::MO_BlockAddress: + return LowerSymbolOperand(MO, MOTy, 0); + } + + return MCOperand(); +} + void MipsMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { OutMI.setOpcode(MI->getOpcode()); for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { const MachineOperand &MO = MI->getOperand(i); - MCOperand MCOp; - MachineOperandType MOTy = MO.getType(); + MCOperand MCOp = LowerOperand(MO); - switch (MOTy) { - default: - MI->dump(); - llvm_unreachable("unknown operand type"); - case MachineOperand::MO_Register: - // Ignore all implicit register operands. - if (MO.isImplicit()) continue; - MCOp = MCOperand::CreateReg(MO.getReg()); - break; - case MachineOperand::MO_Immediate: - MCOp = MCOperand::CreateImm(MO.getImm()); - break; - case MachineOperand::MO_MachineBasicBlock: - case MachineOperand::MO_GlobalAddress: - case MachineOperand::MO_ExternalSymbol: - case MachineOperand::MO_JumpTableIndex: - case MachineOperand::MO_ConstantPoolIndex: - case MachineOperand::MO_BlockAddress: - MCOp = LowerSymbolOperand(MO, MOTy); - break; - } - - OutMI.addOperand(MCOp); + if (MCOp.isValid()) + OutMI.addOperand(MCOp); } } diff --git a/contrib/llvm/lib/Target/Mips/MipsMCInstLower.h b/contrib/llvm/lib/Target/Mips/MipsMCInstLower.h index ec5201b..223f23a 100644 --- a/contrib/llvm/lib/Target/Mips/MipsMCInstLower.h +++ b/contrib/llvm/lib/Target/Mips/MipsMCInstLower.h @@ -1,4 +1,4 @@ -//===-- MipsMCInstLower.h - Lower MachineInstr to MCInst -------------------===// +//===-- MipsMCInstLower.h - Lower MachineInstr to MCInst -------------------==// // // The LLVM Compiler Infrastructure // @@ -36,7 +36,8 @@ public: void Lower(const MachineInstr *MI, MCInst &OutMI) const; private: MCOperand LowerSymbolOperand(const MachineOperand &MO, - MachineOperandType MOTy) const; + MachineOperandType MOTy, unsigned Offset) const; + MCOperand LowerOperand(const MachineOperand& MO) const; }; } diff --git a/contrib/llvm/lib/Target/Mips/MipsMCSymbolRefExpr.cpp b/contrib/llvm/lib/Target/Mips/MipsMCSymbolRefExpr.cpp index 9a2bdae..a0a242c 100644 --- a/contrib/llvm/lib/Target/Mips/MipsMCSymbolRefExpr.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsMCSymbolRefExpr.cpp @@ -33,6 +33,11 @@ void MipsMCSymbolRefExpr::PrintImpl(raw_ostream &OS) const { case VK_Mips_GOTTPREL: OS << "%gottprel("; break; case VK_Mips_TPREL_HI: OS << "%tprel_hi("; break; case VK_Mips_TPREL_LO: OS << "%tprel_lo("; break; + case VK_Mips_GPOFF_HI: OS << "%hi(%neg(%gp_rel("; break; + case VK_Mips_GPOFF_LO: OS << "%lo(%neg(%gp_rel("; break; + case VK_Mips_GOT_DISP: OS << "%got_disp("; break; + case VK_Mips_GOT_PAGE: OS << "%got_page("; break; + case VK_Mips_GOT_OFST: OS << "%got_ofst("; break; } OS << *Symbol; @@ -43,7 +48,9 @@ void MipsMCSymbolRefExpr::PrintImpl(raw_ostream &OS) const { OS << Offset; } - if (Kind != VK_Mips_None) + if (Kind == VK_Mips_GPOFF_HI || Kind == VK_Mips_GPOFF_LO) + OS << ")))"; + else if (Kind != VK_Mips_None) OS << ')'; } diff --git a/contrib/llvm/lib/Target/Mips/MipsMCSymbolRefExpr.h b/contrib/llvm/lib/Target/Mips/MipsMCSymbolRefExpr.h index 3e69596..55e85a7 100644 --- a/contrib/llvm/lib/Target/Mips/MipsMCSymbolRefExpr.h +++ b/contrib/llvm/lib/Target/Mips/MipsMCSymbolRefExpr.h @@ -25,7 +25,12 @@ public: VK_Mips_TLSGD, VK_Mips_GOTTPREL, VK_Mips_TPREL_HI, - VK_Mips_TPREL_LO + VK_Mips_TPREL_LO, + VK_Mips_GPOFF_HI, + VK_Mips_GPOFF_LO, + VK_Mips_GOT_DISP, + VK_Mips_GOT_PAGE, + VK_Mips_GOT_OFST }; private: diff --git a/contrib/llvm/lib/Target/Mips/MipsMachineFunction.h b/contrib/llvm/lib/Target/Mips/MipsMachineFunction.h index dbb7a67..bc30b6b 100644 --- a/contrib/llvm/lib/Target/Mips/MipsMachineFunction.h +++ b/contrib/llvm/lib/Target/Mips/MipsMachineFunction.h @@ -51,16 +51,12 @@ private: mutable int DynAllocFI; // Frame index of dynamically allocated stack area. unsigned MaxCallFrameSize; - /// AtomicFrameIndex - To implement atomic.swap and atomic.cmp.swap - /// intrinsics, it is necessary to use a temporary stack location. - /// This field holds the frame index of this location. - int AtomicFrameIndex; 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), - MaxCallFrameSize(0), AtomicFrameIndex(-1) + MaxCallFrameSize(0) {} bool isInArgFI(int FI) const { @@ -104,9 +100,6 @@ public: unsigned getMaxCallFrameSize() const { return MaxCallFrameSize; } void setMaxCallFrameSize(unsigned S) { MaxCallFrameSize = S; } - - int getAtomicFrameIndex() const { return AtomicFrameIndex; } - void setAtomicFrameIndex(int Index) { AtomicFrameIndex = Index; } }; } // end of namespace llvm diff --git a/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.cpp b/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.cpp index 24390da..f8c0fda 100644 --- a/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.cpp @@ -24,7 +24,6 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/CodeGen/MachineLocation.h" #include "llvm/Target/TargetFrameLowering.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" @@ -44,7 +43,7 @@ using namespace llvm; MipsRegisterInfo::MipsRegisterInfo(const MipsSubtarget &ST, const TargetInstrInfo &tii) - : MipsGenRegisterInfo(), Subtarget(ST), TII(tii) {} + : MipsGenRegisterInfo(Mips::RA), Subtarget(ST), TII(tii) {} /// getRegisterNumbering - Given the enum value for some register, e.g. /// Mips::RA, return the number that it corresponds to (e.g. 31). @@ -52,39 +51,87 @@ unsigned MipsRegisterInfo:: getRegisterNumbering(unsigned RegEnum) { switch (RegEnum) { - case Mips::ZERO : case Mips::F0 : case Mips::D0 : return 0; - case Mips::AT : case Mips::F1 : return 1; - case Mips::V0 : case Mips::F2 : case Mips::D1 : return 2; - case Mips::V1 : case Mips::F3 : return 3; - case Mips::A0 : case Mips::F4 : case Mips::D2 : return 4; - case Mips::A1 : case Mips::F5 : return 5; - case Mips::A2 : case Mips::F6 : case Mips::D3 : return 6; - case Mips::A3 : case Mips::F7 : return 7; - case Mips::T0 : case Mips::F8 : case Mips::D4 : return 8; - case Mips::T1 : case Mips::F9 : return 9; - case Mips::T2 : case Mips::F10: case Mips::D5: return 10; - case Mips::T3 : case Mips::F11: return 11; - case Mips::T4 : case Mips::F12: case Mips::D6: return 12; - case Mips::T5 : case Mips::F13: return 13; - case Mips::T6 : case Mips::F14: case Mips::D7: return 14; - case Mips::T7 : case Mips::F15: return 15; - case Mips::S0 : case Mips::F16: case Mips::D8: return 16; - case Mips::S1 : case Mips::F17: return 17; - case Mips::S2 : case Mips::F18: case Mips::D9: return 18; - case Mips::S3 : case Mips::F19: return 19; - case Mips::S4 : case Mips::F20: case Mips::D10: return 20; - case Mips::S5 : case Mips::F21: return 21; - case Mips::S6 : case Mips::F22: case Mips::D11: return 22; - case Mips::S7 : case Mips::F23: return 23; - case Mips::T8 : case Mips::F24: case Mips::D12: return 24; - case Mips::T9 : case Mips::F25: return 25; - case Mips::K0 : case Mips::F26: case Mips::D13: return 26; - case Mips::K1 : case Mips::F27: return 27; - case Mips::GP : case Mips::F28: case Mips::D14: return 28; - case Mips::SP : case Mips::F29: return 29; - case Mips::FP : case Mips::F30: case Mips::D15: return 30; - case Mips::RA : case Mips::F31: return 31; - default: llvm_unreachable("Unknown register number!"); + case Mips::ZERO: case Mips::ZERO_64: case Mips::F0: case Mips::D0_64: + case Mips::D0: + return 0; + case Mips::AT: case Mips::AT_64: case Mips::F1: case Mips::D1_64: + return 1; + case Mips::V0: case Mips::V0_64: case Mips::F2: case Mips::D2_64: + case Mips::D1: + return 2; + case Mips::V1: case Mips::V1_64: case Mips::F3: case Mips::D3_64: + return 3; + case Mips::A0: case Mips::A0_64: case Mips::F4: case Mips::D4_64: + case Mips::D2: + return 4; + case Mips::A1: case Mips::A1_64: case Mips::F5: case Mips::D5_64: + return 5; + case Mips::A2: case Mips::A2_64: case Mips::F6: case Mips::D6_64: + case Mips::D3: + return 6; + case Mips::A3: case Mips::A3_64: case Mips::F7: case Mips::D7_64: + return 7; + case Mips::T0: case Mips::T0_64: case Mips::F8: case Mips::D8_64: + case Mips::D4: + return 8; + case Mips::T1: case Mips::T1_64: case Mips::F9: case Mips::D9_64: + return 9; + case Mips::T2: case Mips::T2_64: case Mips::F10: case Mips::D10_64: + case Mips::D5: + return 10; + case Mips::T3: case Mips::T3_64: case Mips::F11: case Mips::D11_64: + return 11; + case Mips::T4: case Mips::T4_64: case Mips::F12: case Mips::D12_64: + case Mips::D6: + return 12; + case Mips::T5: case Mips::T5_64: case Mips::F13: case Mips::D13_64: + return 13; + case Mips::T6: case Mips::T6_64: case Mips::F14: case Mips::D14_64: + case Mips::D7: + return 14; + case Mips::T7: case Mips::T7_64: case Mips::F15: case Mips::D15_64: + return 15; + case Mips::S0: case Mips::S0_64: case Mips::F16: case Mips::D16_64: + case Mips::D8: + return 16; + case Mips::S1: case Mips::S1_64: case Mips::F17: case Mips::D17_64: + return 17; + case Mips::S2: case Mips::S2_64: case Mips::F18: case Mips::D18_64: + case Mips::D9: + return 18; + case Mips::S3: case Mips::S3_64: case Mips::F19: case Mips::D19_64: + return 19; + case Mips::S4: case Mips::S4_64: case Mips::F20: case Mips::D20_64: + case Mips::D10: + return 20; + case Mips::S5: case Mips::S5_64: case Mips::F21: case Mips::D21_64: + return 21; + case Mips::S6: case Mips::S6_64: case Mips::F22: case Mips::D22_64: + case Mips::D11: + return 22; + case Mips::S7: case Mips::S7_64: case Mips::F23: case Mips::D23_64: + return 23; + case Mips::T8: case Mips::T8_64: case Mips::F24: case Mips::D24_64: + case Mips::D12: + return 24; + case Mips::T9: case Mips::T9_64: case Mips::F25: case Mips::D25_64: + return 25; + case Mips::K0: case Mips::K0_64: case Mips::F26: case Mips::D26_64: + case Mips::D13: + return 26; + case Mips::K1: case Mips::K1_64: case Mips::F27: case Mips::D27_64: + return 27; + case Mips::GP: case Mips::GP_64: case Mips::F28: case Mips::D28_64: + case Mips::D14: + return 28; + case Mips::SP: case Mips::SP_64: case Mips::F29: case Mips::D29_64: + return 29; + case Mips::FP: case Mips::FP_64: case Mips::F30: case Mips::D30_64: + case Mips::D15: + return 30; + case Mips::RA: case Mips::RA_64: case Mips::F31: case Mips::D31_64: + return 31; + default: llvm_unreachable("Unknown register number!"); } return 0; // Not reached } @@ -101,7 +148,7 @@ getCalleeSavedRegs(const MachineFunction *MF) const { // Mips callee-save register range is $16-$23, $f20-$f30 static const unsigned SingleFloatOnlyCalleeSavedRegs[] = { - Mips::F30, Mips::F29, Mips::F28, Mips::F27, Mips::F26, + Mips::F31, Mips::F30, Mips::F29, Mips::F28, Mips::F27, Mips::F26, Mips::F25, Mips::F24, Mips::F23, Mips::F22, Mips::F21, Mips::F20, Mips::RA, Mips::FP, Mips::S7, Mips::S6, Mips::S5, Mips::S4, Mips::S3, Mips::S2, Mips::S1, Mips::S0, 0 @@ -113,31 +160,71 @@ getCalleeSavedRegs(const MachineFunction *MF) const Mips::S3, Mips::S2, Mips::S1, Mips::S0, 0 }; + static const unsigned N32CalleeSavedRegs[] = { + Mips::D31_64, Mips::D29_64, Mips::D27_64, Mips::D25_64, Mips::D23_64, + Mips::D21_64, + Mips::RA_64, Mips::FP_64, Mips::GP_64, Mips::S7_64, Mips::S6_64, + Mips::S5_64, Mips::S4_64, Mips::S3_64, Mips::S2_64, Mips::S1_64, + Mips::S0_64, 0 + }; + + static const unsigned N64CalleeSavedRegs[] = { + Mips::D31_64, Mips::D30_64, Mips::D29_64, Mips::D28_64, Mips::D27_64, + Mips::D26_64, Mips::D25_64, Mips::D24_64, + Mips::RA_64, Mips::FP_64, Mips::GP_64, Mips::S7_64, Mips::S6_64, + Mips::S5_64, Mips::S4_64, Mips::S3_64, Mips::S2_64, Mips::S1_64, + Mips::S0_64, 0 + }; + if (Subtarget.isSingleFloat()) return SingleFloatOnlyCalleeSavedRegs; - else + else if (!Subtarget.hasMips64()) return Mips32CalleeSavedRegs; + else if (Subtarget.isABI_N32()) + return N32CalleeSavedRegs; + + assert(Subtarget.isABI_N64()); + return N64CalleeSavedRegs; } BitVector MipsRegisterInfo:: getReservedRegs(const MachineFunction &MF) const { + static const unsigned ReservedCPURegs[] = { + Mips::ZERO, Mips::AT, Mips::K0, Mips::K1, + Mips::GP, Mips::SP, Mips::FP, Mips::RA, 0 + }; + + static const unsigned ReservedCPU64Regs[] = { + Mips::ZERO_64, Mips::AT_64, Mips::K0_64, Mips::K1_64, + Mips::GP_64, Mips::SP_64, Mips::FP_64, Mips::RA_64, 0 + }; + BitVector Reserved(getNumRegs()); - Reserved.set(Mips::ZERO); - Reserved.set(Mips::AT); - Reserved.set(Mips::K0); - Reserved.set(Mips::K1); - Reserved.set(Mips::GP); - Reserved.set(Mips::SP); - Reserved.set(Mips::FP); - Reserved.set(Mips::RA); - Reserved.set(Mips::F31); - Reserved.set(Mips::D15); - - // SRV4 requires that odd register can't be used. - if (!Subtarget.isSingleFloat() && !Subtarget.isMips32()) - for (unsigned FReg=(Mips::F0)+1; FReg < Mips::F30; FReg+=2) - Reserved.set(FReg); + typedef TargetRegisterClass::iterator RegIter; + + for (const unsigned *Reg = ReservedCPURegs; *Reg; ++Reg) + Reserved.set(*Reg); + if (Subtarget.hasMips64()) { + for (const unsigned *Reg = ReservedCPU64Regs; *Reg; ++Reg) + Reserved.set(*Reg); + + // Reserve all registers in AFGR64. + for (RegIter Reg = Mips::AFGR64RegisterClass->begin(); + Reg != Mips::AFGR64RegisterClass->end(); ++Reg) + Reserved.set(*Reg); + } + else { + // Reserve all registers in CPU64Regs & FGR64. + for (RegIter Reg = Mips::CPU64RegsRegisterClass->begin(); + Reg != Mips::CPU64RegsRegisterClass->end(); ++Reg) + Reserved.set(*Reg); + + for (RegIter Reg = Mips::FGR64RegisterClass->begin(); + Reg != Mips::FGR64RegisterClass->end(); ++Reg) + Reserved.set(*Reg); + } + return Reserved; } @@ -245,11 +332,6 @@ eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, } unsigned MipsRegisterInfo:: -getRARegister() const { - return Mips::RA; -} - -unsigned MipsRegisterInfo:: getFrameRegister(const MachineFunction &MF) const { const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); @@ -267,12 +349,3 @@ getEHHandlerRegister() const { llvm_unreachable("What is the exception handler register"); return 0; } - -int MipsRegisterInfo:: -getDwarfRegNum(unsigned RegNum, bool isEH) const { - return MipsGenRegisterInfo::getDwarfRegNumFull(RegNum, 0); -} - -int MipsRegisterInfo::getLLVMRegNum(unsigned DwarfRegNo, bool isEH) const { - return MipsGenRegisterInfo::getLLVMRegNumFull(DwarfRegNo,0); -} diff --git a/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.h b/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.h index 646369b..67e57dd 100644 --- a/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.h +++ b/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.h @@ -57,15 +57,11 @@ struct MipsRegisterInfo : public MipsGenRegisterInfo { void processFunctionBeforeFrameFinalized(MachineFunction &MF) const; /// Debug information queries. - unsigned getRARegister() const; unsigned getFrameRegister(const MachineFunction &MF) const; /// Exception handling queries. unsigned getEHExceptionRegister() const; unsigned getEHHandlerRegister() const; - - int getDwarfRegNum(unsigned RegNum, bool isEH) const; - int getLLVMRegNum(unsigned RegNum, bool isEH) const; }; } // end namespace llvm diff --git a/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.td b/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.td index f0db518..925ad9e 100644 --- a/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.td +++ b/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.td @@ -10,6 +10,11 @@ //===----------------------------------------------------------------------===// // Declarations that describe the MIPS register file //===----------------------------------------------------------------------===// +let Namespace = "Mips" in { +def sub_fpeven : SubRegIndex; +def sub_fpodd : SubRegIndex; +def sub_32 : SubRegIndex; +} // We have banks of 32 registers each. class MipsReg<string n> : Register<n> { @@ -28,22 +33,31 @@ class MipsGPRReg<bits<5> num, string n> : MipsReg<n> { let Num = num; } +// Mips 64-bit CPU Registers +class Mips64GPRReg<bits<5> num, string n, list<Register> subregs> + : MipsRegWithSubRegs<n, subregs> { + let Num = num; + let SubRegIndices = [sub_32]; +} + // Mips 32-bit FPU Registers class FPR<bits<5> num, string n> : MipsReg<n> { let Num = num; } // Mips 64-bit (aliased) FPU Registers -let Namespace = "Mips" in { -def sub_fpeven : SubRegIndex; -def sub_fpodd : SubRegIndex; -} class AFPR<bits<5> num, string n, list<Register> subregs> : MipsRegWithSubRegs<n, subregs> { let Num = num; let SubRegIndices = [sub_fpeven, sub_fpodd]; } +class AFPR64<bits<5> num, string n, list<Register> subregs> + : MipsRegWithSubRegs<n, subregs> { + let Num = num; + let SubRegIndices = [sub_32]; +} + // Mips Hardware Registers class HWR<bits<5> num, string n> : MipsReg<n> { let Num = num; @@ -54,6 +68,7 @@ class HWR<bits<5> num, string n> : MipsReg<n> { //===----------------------------------------------------------------------===// let Namespace = "Mips" in { + // FIXME: Fix DwarfRegNum. // General Purpose Registers def ZERO : MipsGPRReg< 0, "ZERO">, DwarfRegNum<[0]>; @@ -89,6 +104,40 @@ let Namespace = "Mips" in { 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]>; + def AT_64 : Mips64GPRReg< 1, "AT", [AT]>; + def V0_64 : Mips64GPRReg< 2, "2", [V0]>; + def V1_64 : Mips64GPRReg< 3, "3", [V1]>; + def A0_64 : Mips64GPRReg< 4, "4", [A0]>; + def A1_64 : Mips64GPRReg< 5, "5", [A1]>; + def A2_64 : Mips64GPRReg< 6, "6", [A2]>; + def A3_64 : Mips64GPRReg< 7, "7", [A3]>; + def T0_64 : Mips64GPRReg< 8, "8", [T0]>; + def T1_64 : Mips64GPRReg< 9, "9", [T1]>; + def T2_64 : Mips64GPRReg< 10, "10", [T2]>; + def T3_64 : Mips64GPRReg< 11, "11", [T3]>; + def T4_64 : Mips64GPRReg< 12, "12", [T4]>; + def T5_64 : Mips64GPRReg< 13, "13", [T5]>; + def T6_64 : Mips64GPRReg< 14, "14", [T6]>; + def T7_64 : Mips64GPRReg< 15, "15", [T7]>; + def S0_64 : Mips64GPRReg< 16, "16", [S0]>; + def S1_64 : Mips64GPRReg< 17, "17", [S1]>; + def S2_64 : Mips64GPRReg< 18, "18", [S2]>; + def S3_64 : Mips64GPRReg< 19, "19", [S3]>; + def S4_64 : Mips64GPRReg< 20, "20", [S4]>; + def S5_64 : Mips64GPRReg< 21, "21", [S5]>; + def S6_64 : Mips64GPRReg< 22, "22", [S6]>; + def S7_64 : Mips64GPRReg< 23, "23", [S7]>; + def T8_64 : Mips64GPRReg< 24, "24", [T8]>; + def T9_64 : Mips64GPRReg< 25, "25", [T9]>; + def K0_64 : Mips64GPRReg< 26, "26", [K0]>; + def K1_64 : Mips64GPRReg< 27, "27", [K1]>; + def GP_64 : Mips64GPRReg< 28, "GP", [GP]>; + def SP_64 : Mips64GPRReg< 29, "SP", [SP]>; + def FP_64 : Mips64GPRReg< 30, "FP", [FP]>; + def RA_64 : Mips64GPRReg< 31, "RA", [RA]>; + /// Mips Single point precision FPU Registers def F0 : FPR< 0, "F0">, DwarfRegNum<[32]>; def F1 : FPR< 1, "F1">, DwarfRegNum<[33]>; @@ -142,10 +191,49 @@ let Namespace = "Mips" in { 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]>; + def D1_64 : AFPR64<1, "F1", [F1]>; + def D2_64 : AFPR64<2, "F2", [F2]>; + def D3_64 : AFPR64<3, "F3", [F3]>; + def D4_64 : AFPR64<4, "F4", [F4]>; + def D5_64 : AFPR64<5, "F5", [F5]>; + def D6_64 : AFPR64<6, "F6", [F6]>; + def D7_64 : AFPR64<7, "F7", [F7]>; + def D8_64 : AFPR64<8, "F8", [F8]>; + def D9_64 : AFPR64<9, "F9", [F9]>; + def D10_64 : AFPR64<10, "F10", [F10]>; + def D11_64 : AFPR64<11, "F11", [F11]>; + def D12_64 : AFPR64<12, "F12", [F12]>; + def D13_64 : AFPR64<13, "F13", [F13]>; + def D14_64 : AFPR64<14, "F14", [F14]>; + def D15_64 : AFPR64<15, "F15", [F15]>; + def D16_64 : AFPR64<16, "F16", [F16]>; + def D17_64 : AFPR64<17, "F17", [F17]>; + def D18_64 : AFPR64<18, "F18", [F18]>; + def D19_64 : AFPR64<19, "F19", [F19]>; + def D20_64 : AFPR64<20, "F20", [F20]>; + def D21_64 : AFPR64<21, "F21", [F21]>; + def D22_64 : AFPR64<22, "F22", [F22]>; + def D23_64 : AFPR64<23, "F23", [F23]>; + def D24_64 : AFPR64<24, "F24", [F24]>; + def D25_64 : AFPR64<25, "F25", [F25]>; + def D26_64 : AFPR64<26, "F26", [F26]>; + def D27_64 : AFPR64<27, "F27", [F27]>; + def D28_64 : AFPR64<28, "F28", [F28]>; + def D29_64 : AFPR64<29, "F29", [F29]>; + def D30_64 : AFPR64<30, "F30", [F30]>; + def D31_64 : AFPR64<31, "F31", [F31]>; + // Hi/Lo registers def HI : Register<"hi">, DwarfRegNum<[64]>; def LO : Register<"lo">, DwarfRegNum<[65]>; + let SubRegIndices = [sub_32] in { + def HI64 : RegisterWithSubRegs<"hi", [HI]>; + def LO64 : RegisterWithSubRegs<"lo", [LO]>; + } + // Status flags register def FCR31 : Register<"31">; @@ -167,6 +255,18 @@ def CPURegs : RegisterClass<"Mips", [i32], 32, (add // Reserved ZERO, AT, K0, K1, GP, SP, FP, RA)>; +def CPU64Regs : RegisterClass<"Mips", [i64], 64, (add + // 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, + // Callee save + S0_64, S1_64, S2_64, S3_64, S4_64, S5_64, S6_64, S7_64, + // Reserved + ZERO_64, AT_64, K0_64, K1_64, GP_64, SP_64, FP_64, RA_64)> { + let SubRegClasses = [(CPURegs sub_32)]; +} + // 64bit fp: // * FGR64 - 32 64-bit registers // * AFGR64 - 16 32-bit even registers (32-bit FP Mode) @@ -182,17 +282,22 @@ def AFGR64 : RegisterClass<"Mips", [f64], 64, (add // Not preserved across procedure calls D2, D3, D4, D5, D8, D9, // Callee save - D10, D11, D12, D13, D14, - // Reserved - D15)> { + D10, D11, D12, D13, D14, D15)> { let SubRegClasses = [(FGR32 sub_fpeven, sub_fpodd)]; } +def FGR64 : RegisterClass<"Mips", [f64], 64, (sequence "D%u_64", 0, 31)> { + let SubRegClasses = [(FGR32 sub_32)]; +} + // Condition Register for floating point operations def CCR : RegisterClass<"Mips", [i32], 32, (add FCR31)>; // 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)]; +} // Hardware registers def HWRegs : RegisterClass<"Mips", [i32], 32, (add HWR29)>; diff --git a/contrib/llvm/lib/Target/Mips/MipsRelocations.h b/contrib/llvm/lib/Target/Mips/MipsRelocations.h new file mode 100644 index 0000000..66d1bfd --- /dev/null +++ b/contrib/llvm/lib/Target/Mips/MipsRelocations.h @@ -0,0 +1,41 @@ +//===- MipsRelocations.h - Mips Code Relocations ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// +// +// This file defines the Mips target-specific relocation types +// (for relocation-model=static). +// +//===---------------------------------------------------------------------===// + +#ifndef MIPSRELOCATIONS_H_ +#define MIPSRELOCATIONS_H_ + +#include "llvm/CodeGen/MachineRelocation.h" + +namespace llvm { + namespace Mips{ + enum RelocationType { + // reloc_mips_branch - pc relative relocation for branches. The lower 18 + // bits of the difference between the branch target and the branch + // instruction, shifted right by 2. + reloc_mips_branch = 1, + + // reloc_mips_hi - upper 16 bits of the address (modified by +1 if the + // lower 16 bits of the address is negative). + reloc_mips_hi = 2, + + // reloc_mips_lo - lower 16 bits of the address. + reloc_mips_lo = 3, + + // reloc_mips_26 - lower 28 bits of the address, shifted right by 2. + reloc_mips_26 = 4 + }; + } +} + +#endif /* MIPSRELOCATIONS_H_ */ diff --git a/contrib/llvm/lib/Target/Mips/MipsSubtarget.cpp b/contrib/llvm/lib/Target/Mips/MipsSubtarget.cpp index 6eee333..016d449 100644 --- a/contrib/llvm/lib/Target/Mips/MipsSubtarget.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsSubtarget.cpp @@ -13,7 +13,7 @@ #include "MipsSubtarget.h" #include "Mips.h" -#include "llvm/Target/TargetRegistry.h" +#include "llvm/Support/TargetRegistry.h" #define GET_SUBTARGETINFO_TARGET_DESC #define GET_SUBTARGETINFO_CTOR @@ -24,15 +24,14 @@ using namespace llvm; MipsSubtarget::MipsSubtarget(const std::string &TT, const std::string &CPU, const std::string &FS, bool little) : MipsGenSubtargetInfo(TT, CPU, FS), - MipsArchVersion(Mips1), MipsABI(O32), IsLittle(little), IsSingleFloat(false), - IsFP64bit(false), IsGP64bit(false), HasVFPU(false), IsLinux(true), - HasSEInReg(false), HasCondMov(false), HasMulDivAdd(false), HasMinMax(false), - HasSwap(false), HasBitCount(false) + 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) { std::string CPUName = CPU; if (CPUName.empty()) - CPUName = "mips1"; - MipsArchVersion = Mips1; + CPUName = "mips32r1"; // Parse features string. ParseSubtargetFeatures(CPUName, FS); @@ -40,23 +39,16 @@ MipsSubtarget::MipsSubtarget(const std::string &TT, const std::string &CPU, // Initialize scheduling itinerary for the specified CPU. InstrItins = getInstrItineraryForCPU(CPUName); + // Set MipsABI if it hasn't been set yet. + if (MipsABI == UnknownABI) + MipsABI = hasMips64() ? N64 : O32; + + // Check if Architecture and ABI are compatible. + assert(((!hasMips64() && (isABI_O32() || isABI_EABI())) || + (hasMips64() && (isABI_N32() || isABI_N64()))) && + "Invalid Arch & ABI pair."); + // Is the target system Linux ? if (TT.find("linux") == std::string::npos) IsLinux = false; - - // When only the target triple is specified and is - // a allegrex target, set the features. We also match - // big and little endian allegrex cores (dont really - // know if a big one exists) - if (TT.find("mipsallegrex") != std::string::npos || - TT.find("psp") != std::string::npos) { - MipsABI = EABI; - IsSingleFloat = true; - MipsArchVersion = Mips2; - HasVFPU = true; // Enables Allegrex Vector FPU (not supported yet) - HasSEInReg = true; - HasBitCount = true; - HasSwap = true; - HasCondMov = true; - } } diff --git a/contrib/llvm/lib/Target/Mips/MipsSubtarget.h b/contrib/llvm/lib/Target/Mips/MipsSubtarget.h index 533d4af..d9dddad 100644 --- a/contrib/llvm/lib/Target/Mips/MipsSubtarget.h +++ b/contrib/llvm/lib/Target/Mips/MipsSubtarget.h @@ -27,14 +27,15 @@ class StringRef; class MipsSubtarget : public MipsGenSubtargetInfo { public: + // NOTE: O64 will not be supported. enum MipsABIEnum { - O32, O64, N32, N64, EABI + UnknownABI, O32, N32, N64, EABI }; protected: enum MipsArchEnum { - Mips1, Mips2, Mips3, Mips4, Mips32, Mips32r2 + Mips32, Mips32r2, Mips64, Mips64r2 }; // Mips architecture version @@ -90,6 +91,8 @@ public: /// Only O32 and EABI supported right now. bool isABI_EABI() const { return MipsABI == EABI; } + bool isABI_N64() const { return MipsABI == N64; } + bool isABI_N32() const { return MipsABI == N32; } bool isABI_O32() const { return MipsABI == O32; } unsigned getTargetABI() const { return MipsABI; } @@ -102,9 +105,11 @@ public: /// subtarget options. Definition of function is auto generated by tblgen. void ParseSubtargetFeatures(StringRef CPU, StringRef FS); - bool isMips1() const { return MipsArchVersion == Mips1; } - bool isMips32() const { return MipsArchVersion >= Mips32; } - bool isMips32r2() const { return MipsArchVersion == Mips32r2; } + bool hasMips32() const { return MipsArchVersion >= Mips32; } + bool hasMips32r2() const { return MipsArchVersion == Mips32r2 || + MipsArchVersion == Mips64r2; } + bool hasMips64() const { return MipsArchVersion >= Mips64; } + bool hasMips64r2() const { return MipsArchVersion == Mips64r2; } bool isLittle() const { return IsLittle; } bool isFP64bit() const { return IsFP64bit; } diff --git a/contrib/llvm/lib/Target/Mips/MipsTargetMachine.cpp b/contrib/llvm/lib/Target/Mips/MipsTargetMachine.cpp index 20b9f4e..6480da3 100644 --- a/contrib/llvm/lib/Target/Mips/MipsTargetMachine.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsTargetMachine.cpp @@ -14,13 +14,15 @@ #include "Mips.h" #include "MipsTargetMachine.h" #include "llvm/PassManager.h" -#include "llvm/Target/TargetRegistry.h" +#include "llvm/Support/TargetRegistry.h" using namespace llvm; extern "C" void LLVMInitializeMipsTarget() { // Register the target. - RegisterTargetMachine<MipsTargetMachine> X(TheMipsTarget); + RegisterTargetMachine<MipsebTargetMachine> X(TheMipsTarget); RegisterTargetMachine<MipselTargetMachine> Y(TheMipselTarget); + RegisterTargetMachine<Mips64ebTargetMachine> A(TheMips64Target); + RegisterTargetMachine<Mips64elTargetMachine> B(TheMips64elTarget); } // DataLayout --> Big-endian, 32-bit pointer/ABI/alignment @@ -31,30 +33,47 @@ extern "C" void LLVMInitializeMipsTarget() { // an easier handling. // Using CodeModel::Large enables different CALL behavior. MipsTargetMachine:: -MipsTargetMachine(const Target &T, const std::string &TT, - const std::string &CPU, const std::string &FS, - bool isLittle=false): - LLVMTargetMachine(T, TT, CPU, FS), +MipsTargetMachine(const Target &T, StringRef TT, + StringRef CPU, StringRef FS, + Reloc::Model RM, CodeModel::Model CM, + bool isLittle): + LLVMTargetMachine(T, TT, CPU, FS, RM, CM), Subtarget(TT, CPU, FS, isLittle), - DataLayout(isLittle ? - std::string("e-p:32:32:32-i8:8:32-i16:16:32-i64:64:64-n32") : - std::string("E-p:32:32:32-i8:8:32-i16:16:32-i64:64:64-n32")), + DataLayout(isLittle ? + (Subtarget.isABI_N64() ? + "e-p:64:64:64-i8:8:32-i16:16:32-i64:64:64-f128:128:128-n32" : + "e-p:32:32:32-i8:8:32-i16:16:32-i64:64:64-n32") : + (Subtarget.isABI_N64() ? + "E-p:64:64:64-i8:8:32-i16:16:32-i64:64:64-f128:128:128-n32" : + "E-p:32:32:32-i8:8:32-i16:16:32-i64:64:64-n32")), InstrInfo(*this), FrameLowering(Subtarget), - TLInfo(*this), TSInfo(*this) { - // Abicall enables PIC by default - if (getRelocationModel() == Reloc::Default) { - if (Subtarget.isABI_O32()) - setRelocationModel(Reloc::PIC_); - else - setRelocationModel(Reloc::Static); - } + TLInfo(*this), TSInfo(*this), JITInfo() { } +MipsebTargetMachine:: +MipsebTargetMachine(const Target &T, StringRef TT, + StringRef CPU, StringRef FS, + Reloc::Model RM, CodeModel::Model CM) : + MipsTargetMachine(T, TT, CPU, FS, RM, CM, false) {} + MipselTargetMachine:: -MipselTargetMachine(const Target &T, const std::string &TT, - const std::string &CPU, const std::string &FS) : - MipsTargetMachine(T, TT, CPU, FS, true) {} +MipselTargetMachine(const Target &T, StringRef TT, + StringRef CPU, StringRef FS, + Reloc::Model RM, CodeModel::Model CM) : + MipsTargetMachine(T, TT, CPU, FS, RM, CM, true) {} + +Mips64ebTargetMachine:: +Mips64ebTargetMachine(const Target &T, StringRef TT, + StringRef CPU, StringRef FS, + Reloc::Model RM, CodeModel::Model CM) : + MipsTargetMachine(T, TT, CPU, FS, RM, CM, false) {} + +Mips64elTargetMachine:: +Mips64elTargetMachine(const Target &T, StringRef TT, + StringRef CPU, StringRef FS, + Reloc::Model RM, CodeModel::Model CM) : + MipsTargetMachine(T, TT, CPU, FS, RM, CM, true) {} // Install an instruction selector pass using // the ISelDag to gen Mips code. @@ -77,7 +96,10 @@ addPreEmitPass(PassManagerBase &PM, CodeGenOpt::Level OptLevel) bool MipsTargetMachine:: addPreRegAlloc(PassManagerBase &PM, CodeGenOpt::Level OptLevel) { - PM.add(createMipsEmitGPRestorePass(*this)); + // Do not restore $gp if target is Mips64. + // In N32/64, $gp is a callee-saved register. + if (!Subtarget.hasMips64()) + PM.add(createMipsEmitGPRestorePass(*this)); return true; } @@ -86,3 +108,12 @@ addPostRegAlloc(PassManagerBase &PM, CodeGenOpt::Level OptLevel) { PM.add(createMipsExpandPseudoPass(*this)); return true; } + +bool MipsTargetMachine::addCodeEmitter(PassManagerBase &PM, + CodeGenOpt::Level OptLevel, + JITCodeEmitter &JCE) { + // Machine code emitter pass for Mips. + PM.add(createMipsJITCodeEmitterPass(*this, JCE)); + return false; +} + diff --git a/contrib/llvm/lib/Target/Mips/MipsTargetMachine.h b/contrib/llvm/lib/Target/Mips/MipsTargetMachine.h index a021af2..118ed10 100644 --- a/contrib/llvm/lib/Target/Mips/MipsTargetMachine.h +++ b/contrib/llvm/lib/Target/Mips/MipsTargetMachine.h @@ -22,6 +22,7 @@ #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetFrameLowering.h" +#include "MipsJITInfo.h" namespace llvm { class formatted_raw_ostream; @@ -33,9 +34,12 @@ namespace llvm { MipsFrameLowering FrameLowering; MipsTargetLowering TLInfo; MipsSelectionDAGInfo TSInfo; + MipsJITInfo JITInfo; + public: - MipsTargetMachine(const Target &T, const std::string &TT, - const std::string &CPU, const std::string &FS, + MipsTargetMachine(const Target &T, StringRef TT, + StringRef CPU, StringRef FS, + Reloc::Model RM, CodeModel::Model CM, bool isLittle); virtual const MipsInstrInfo *getInstrInfo() const @@ -46,6 +50,9 @@ namespace llvm { { return &Subtarget; } virtual const TargetData *getTargetData() const { return &DataLayout;} + virtual MipsJITInfo *getJITInfo() + { return &JITInfo; } + virtual const MipsRegisterInfo *getRegisterInfo() const { return &InstrInfo.getRegisterInfo(); @@ -67,16 +74,47 @@ namespace llvm { virtual bool addPreRegAlloc(PassManagerBase &PM, CodeGenOpt::Level OptLevel); virtual bool addPostRegAlloc(PassManagerBase &, CodeGenOpt::Level); + virtual bool addCodeEmitter(PassManagerBase &PM, + CodeGenOpt::Level OptLevel, + JITCodeEmitter &JCE); + }; -/// MipselTargetMachine - Mipsel target machine. +/// MipsebTargetMachine - Mips32 big endian target machine. +/// +class MipsebTargetMachine : public MipsTargetMachine { +public: + MipsebTargetMachine(const Target &T, StringRef TT, + StringRef CPU, StringRef FS, + Reloc::Model RM, CodeModel::Model CM); +}; + +/// MipselTargetMachine - Mips32 little endian target machine. /// class MipselTargetMachine : public MipsTargetMachine { public: - MipselTargetMachine(const Target &T, const std::string &TT, - const std::string &CPU, const std::string &FS); + MipselTargetMachine(const Target &T, StringRef TT, + StringRef CPU, StringRef FS, + Reloc::Model RM, CodeModel::Model CM); }; +/// Mips64ebTargetMachine - Mips64 big endian target machine. +/// +class Mips64ebTargetMachine : public MipsTargetMachine { +public: + Mips64ebTargetMachine(const Target &T, StringRef TT, + StringRef CPU, StringRef FS, + Reloc::Model RM, CodeModel::Model CM); +}; + +/// Mips64elTargetMachine - Mips64 little endian target machine. +/// +class Mips64elTargetMachine : public MipsTargetMachine { +public: + Mips64elTargetMachine(const Target &T, StringRef TT, + StringRef CPU, StringRef FS, + Reloc::Model RM, CodeModel::Model CM); +}; } // End llvm namespace #endif diff --git a/contrib/llvm/lib/Target/Mips/MipsTargetObjectFile.cpp b/contrib/llvm/lib/Target/Mips/MipsTargetObjectFile.cpp index cf5d1b5..05c46f5 100644 --- a/contrib/llvm/lib/Target/Mips/MipsTargetObjectFile.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsTargetObjectFile.cpp @@ -79,7 +79,7 @@ IsGlobalInSmallSection(const GlobalValue *GV, const TargetMachine &TM, if (Kind.isMergeable1ByteCString()) return false; - const Type *Ty = GV->getType()->getElementType(); + Type *Ty = GV->getType()->getElementType(); return IsInSmallSection(TM.getTargetData()->getTypeAllocSize(Ty)); } diff --git a/contrib/llvm/lib/Target/Mips/TargetInfo/MipsTargetInfo.cpp b/contrib/llvm/lib/Target/Mips/TargetInfo/MipsTargetInfo.cpp index a8d6fe9..243632b 100644 --- a/contrib/llvm/lib/Target/Mips/TargetInfo/MipsTargetInfo.cpp +++ b/contrib/llvm/lib/Target/Mips/TargetInfo/MipsTargetInfo.cpp @@ -9,13 +9,23 @@ #include "Mips.h" #include "llvm/Module.h" -#include "llvm/Target/TargetRegistry.h" +#include "llvm/Support/TargetRegistry.h" using namespace llvm; Target llvm::TheMipsTarget, llvm::TheMipselTarget; +Target llvm::TheMips64Target, llvm::TheMips64elTarget; extern "C" void LLVMInitializeMipsTargetInfo() { - RegisterTarget<Triple::mips> X(TheMipsTarget, "mips", "Mips"); + RegisterTarget<Triple::mips, + /*HasJIT=*/true> X(TheMipsTarget, "mips", "Mips"); - RegisterTarget<Triple::mipsel> Y(TheMipselTarget, "mipsel", "Mipsel"); + RegisterTarget<Triple::mipsel, + /*HasJIT=*/true> Y(TheMipselTarget, "mipsel", "Mipsel"); + + RegisterTarget<Triple::mips64, + /*HasJIT=*/false> A(TheMips64Target, "mips64", "Mips64 [experimental]"); + + RegisterTarget<Triple::mips64el, + /*HasJIT=*/false> B(TheMips64elTarget, + "mips64el", "Mips64el [experimental]"); } |