diff options
Diffstat (limited to 'lib/Target/Mips')
46 files changed, 2583 insertions, 961 deletions
diff --git a/lib/Target/Mips/Android.mk b/lib/Target/Mips/Android.mk new file mode 100644 index 0000000..acd2150 --- /dev/null +++ b/lib/Target/Mips/Android.mk @@ -0,0 +1,67 @@ +LOCAL_PATH := $(call my-dir) + +mips_codegen_TBLGEN_TABLES := \ + MipsGenRegisterInfo.inc \ + MipsGenInstrInfo.inc \ + MipsGenCodeEmitter.inc \ + MipsGenMCCodeEmitter.inc \ + MipsGenAsmWriter.inc \ + MipsGenDAGISel.inc \ + MipsGenCallingConv.inc \ + MipsGenSubtargetInfo.inc + +mips_codegen_SRC_FILES := \ + MipsAsmPrinter.cpp \ + MipsCodeEmitter.cpp \ + MipsDelaySlotFiller.cpp \ + MipsEmitGPRestore.cpp \ + MipsExpandPseudo.cpp \ + MipsJITInfo.cpp \ + MipsInstrInfo.cpp \ + MipsISelDAGToDAG.cpp \ + MipsISelLowering.cpp \ + MipsFrameLowering.cpp \ + MipsMCInstLower.cpp \ + MipsRegisterInfo.cpp \ + MipsSubtarget.cpp \ + MipsTargetMachine.cpp \ + MipsTargetObjectFile.cpp \ + MipsSelectionDAGInfo.cpp + +# For the host +# ===================================================== +include $(CLEAR_VARS) +include $(CLEAR_TBLGEN_VARS) + +LOCAL_MODULE:= libLLVMMipsCodeGen +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := $(mips_codegen_SRC_FILES) +LOCAL_C_INCLUDES := $(LOCAL_PATH)/MCTargetDesc + +TBLGEN_TABLES := $(mips_codegen_TBLGEN_TABLES) + +include $(LLVM_HOST_BUILD_MK) +include $(LLVM_TBLGEN_RULES_MK) +include $(LLVM_GEN_INTRINSICS_MK) +include $(BUILD_HOST_STATIC_LIBRARY) + +# For the device only +# ===================================================== +ifeq ($(TARGET_ARCH),mips) +include $(CLEAR_VARS) +include $(CLEAR_TBLGEN_VARS) + +LOCAL_MODULE:= libLLVMMipsCodeGen +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := $(mips_codegen_SRC_FILES) +LOCAL_C_INCLUDES := $(LOCAL_PATH)/MCTargetDesc + +TBLGEN_TABLES := $(mips_codegen_TBLGEN_TABLES) + +include $(LLVM_DEVICE_BUILD_MK) +include $(LLVM_TBLGEN_RULES_MK) +include $(LLVM_GEN_INTRINSICS_MK) +include $(BUILD_STATIC_LIBRARY) +endif diff --git a/lib/Target/Mips/CMakeLists.txt b/lib/Target/Mips/CMakeLists.txt index 71391f3..a13c0e8 100644 --- a/lib/Target/Mips/CMakeLists.txt +++ b/lib/Target/Mips/CMakeLists.txt @@ -1,12 +1,13 @@ set(LLVM_TARGET_DEFINITIONS Mips.td) -llvm_tablegen(MipsGenRegisterInfo.inc -gen-register-info) -llvm_tablegen(MipsGenInstrInfo.inc -gen-instr-info) -llvm_tablegen(MipsGenCodeEmitter.inc -gen-emitter) -llvm_tablegen(MipsGenAsmWriter.inc -gen-asm-writer) -llvm_tablegen(MipsGenDAGISel.inc -gen-dag-isel) -llvm_tablegen(MipsGenCallingConv.inc -gen-callingconv) -llvm_tablegen(MipsGenSubtargetInfo.inc -gen-subtarget) +tablegen(LLVM MipsGenRegisterInfo.inc -gen-register-info) +tablegen(LLVM MipsGenInstrInfo.inc -gen-instr-info) +tablegen(LLVM MipsGenCodeEmitter.inc -gen-emitter) +tablegen(LLVM MipsGenMCCodeEmitter.inc -gen-emitter -mc-emitter) +tablegen(LLVM MipsGenAsmWriter.inc -gen-asm-writer) +tablegen(LLVM MipsGenDAGISel.inc -gen-dag-isel) +tablegen(LLVM MipsGenCallingConv.inc -gen-callingconv) +tablegen(LLVM MipsGenSubtargetInfo.inc -gen-subtarget) add_public_tablegen_target(MipsCommonTableGen) add_llvm_target(MipsCodeGen @@ -21,7 +22,6 @@ add_llvm_target(MipsCodeGen MipsISelLowering.cpp MipsFrameLowering.cpp MipsMCInstLower.cpp - MipsMCSymbolRefExpr.cpp MipsRegisterInfo.cpp MipsSubtarget.cpp MipsTargetMachine.cpp @@ -29,19 +29,6 @@ add_llvm_target(MipsCodeGen MipsSelectionDAGInfo.cpp ) -add_llvm_library_dependencies(LLVMMipsCodeGen - LLVMAsmPrinter - LLVMCodeGen - LLVMCore - LLVMMC - LLVMMipsAsmPrinter - LLVMMipsDesc - LLVMMipsInfo - LLVMSelectionDAG - LLVMSupport - LLVMTarget - ) - add_subdirectory(InstPrinter) add_subdirectory(TargetInfo) add_subdirectory(MCTargetDesc) diff --git a/lib/Target/Mips/InstPrinter/Android.mk b/lib/Target/Mips/InstPrinter/Android.mk new file mode 100644 index 0000000..6e9a537 --- /dev/null +++ b/lib/Target/Mips/InstPrinter/Android.mk @@ -0,0 +1,43 @@ +LOCAL_PATH := $(call my-dir) + +mips_asm_printer_TBLGEN_TABLES := \ + MipsGenAsmWriter.inc + +mips_asm_printer_SRC_FILES := \ + MipsInstPrinter.cpp + +# For the host +# ===================================================== +include $(CLEAR_VARS) +include $(CLEAR_TBLGEN_VARS) + +LOCAL_MODULE:= libLLVMMipsAsmPrinter +LOCAL_MODULE_TAGS := optional + +TBLGEN_TABLES := $(mips_asm_printer_TBLGEN_TABLES) +TBLGEN_TD_DIR := $(LOCAL_PATH)/.. + +LOCAL_SRC_FILES := $(mips_asm_printer_SRC_FILES) +LOCAL_C_INCLUDES += $(LOCAL_PATH)/.. + +include $(LLVM_HOST_BUILD_MK) +include $(LLVM_TBLGEN_RULES_MK) +include $(BUILD_HOST_STATIC_LIBRARY) + +# For the device only +# ===================================================== +include $(CLEAR_VARS) +include $(CLEAR_TBLGEN_VARS) + +LOCAL_MODULE:= libLLVMMipsAsmPrinter +LOCAL_MODULE_TAGS := optional + +TBLGEN_TABLES := $(mips_asm_printer_TBLGEN_TABLES) +TBLGEN_TD_DIR := $(LOCAL_PATH)/.. + +LOCAL_SRC_FILES := $(mips_asm_printer_SRC_FILES) +LOCAL_C_INCLUDES += $(LOCAL_PATH)/.. + +include $(LLVM_DEVICE_BUILD_MK) +include $(LLVM_TBLGEN_RULES_MK) +include $(BUILD_STATIC_LIBRARY) diff --git a/lib/Target/Mips/InstPrinter/CMakeLists.txt b/lib/Target/Mips/InstPrinter/CMakeLists.txt index c45b35d..3e9fbf1 100644 --- a/lib/Target/Mips/InstPrinter/CMakeLists.txt +++ b/lib/Target/Mips/InstPrinter/CMakeLists.txt @@ -4,9 +4,4 @@ add_llvm_library(LLVMMipsAsmPrinter MipsInstPrinter.cpp ) -add_llvm_library_dependencies(LLVMMipsAsmPrinter - LLVMMC - LLVMSupport - ) - add_dependencies(LLVMMipsAsmPrinter MipsCommonTableGen) diff --git a/lib/Target/Mips/InstPrinter/LLVMBuild.txt b/lib/Target/Mips/InstPrinter/LLVMBuild.txt new file mode 100644 index 0000000..317057b --- /dev/null +++ b/lib/Target/Mips/InstPrinter/LLVMBuild.txt @@ -0,0 +1,23 @@ +;===- ./lib/Target/Mips/InstPrinter/LLVMBuild.txt --------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Library +name = MipsAsmPrinter +parent = Mips +required_libraries = MC Support +add_to_library_groups = Mips diff --git a/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp b/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp index 3dafc61..3e9c46a 100644 --- a/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp +++ b/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp @@ -13,11 +13,12 @@ #define DEBUG_TYPE "asm-printer" #include "MipsInstPrinter.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" +#include "llvm/MC/MCSymbol.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/ADT/StringExtras.h" using namespace llvm; #define GET_INSTRUCTION_NAME @@ -66,7 +67,7 @@ StringRef MipsInstPrinter::getOpcodeName(unsigned Opcode) const { } void MipsInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const { - OS << '$' << LowercaseString(getRegisterName(RegNo)); + OS << '$' << StringRef(getRegisterName(RegNo)).lower(); } void MipsInstPrinter::printInst(const MCInst *MI, raw_ostream &O, @@ -75,6 +76,59 @@ void MipsInstPrinter::printInst(const MCInst *MI, raw_ostream &O, printAnnotation(O, Annot); } +static void printExpr(const MCExpr *Expr, raw_ostream &OS) { + int Offset = 0; + const MCSymbolRefExpr *SRE; + + if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) { + SRE = dyn_cast<MCSymbolRefExpr>(BE->getLHS()); + const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(BE->getRHS()); + assert(SRE && CE && "Binary expression must be sym+const."); + Offset = CE->getValue(); + } + else if (!(SRE = dyn_cast<MCSymbolRefExpr>(Expr))) + assert(false && "Unexpected MCExpr type."); + + MCSymbolRefExpr::VariantKind Kind = SRE->getKind(); + + switch (Kind) { + default: assert(0 && "Invalid kind!"); + case MCSymbolRefExpr::VK_None: break; + case MCSymbolRefExpr::VK_Mips_GPREL: OS << "%gp_rel("; break; + case MCSymbolRefExpr::VK_Mips_GOT_CALL: OS << "%call16("; break; + case MCSymbolRefExpr::VK_Mips_GOT16: OS << "%got("; break; + case MCSymbolRefExpr::VK_Mips_GOT: OS << "%got("; break; + case MCSymbolRefExpr::VK_Mips_ABS_HI: OS << "%hi("; break; + case MCSymbolRefExpr::VK_Mips_ABS_LO: OS << "%lo("; break; + case MCSymbolRefExpr::VK_Mips_TLSGD: OS << "%tlsgd("; break; + case MCSymbolRefExpr::VK_Mips_TLSLDM: OS << "%tlsldm("; break; + case MCSymbolRefExpr::VK_Mips_DTPREL_HI:OS << "%dtprel_hi("; break; + case MCSymbolRefExpr::VK_Mips_DTPREL_LO:OS << "%dtprel_lo("; break; + case MCSymbolRefExpr::VK_Mips_GOTTPREL: OS << "%gottprel("; break; + case MCSymbolRefExpr::VK_Mips_TPREL_HI: OS << "%tprel_hi("; break; + case MCSymbolRefExpr::VK_Mips_TPREL_LO: OS << "%tprel_lo("; break; + case MCSymbolRefExpr::VK_Mips_GPOFF_HI: OS << "%hi(%neg(%gp_rel("; break; + case MCSymbolRefExpr::VK_Mips_GPOFF_LO: OS << "%lo(%neg(%gp_rel("; break; + case MCSymbolRefExpr::VK_Mips_GOT_DISP: OS << "%got_disp("; break; + case MCSymbolRefExpr::VK_Mips_GOT_PAGE: OS << "%got_page("; break; + case MCSymbolRefExpr::VK_Mips_GOT_OFST: OS << "%got_ofst("; break; + } + + OS << SRE->getSymbol(); + + if (Offset) { + if (Offset > 0) + OS << '+'; + OS << Offset; + } + + if ((Kind == MCSymbolRefExpr::VK_Mips_GPOFF_HI) || + (Kind == MCSymbolRefExpr::VK_Mips_GPOFF_LO)) + OS << ")))"; + else if (Kind != MCSymbolRefExpr::VK_None) + OS << ')'; +} + void MipsInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O) { const MCOperand &Op = MI->getOperand(OpNo); @@ -89,7 +143,7 @@ void MipsInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, } assert(Op.isExpr() && "unknown operand kind in printOperand"); - O << *Op.getExpr(); + printExpr(Op.getExpr(), O); } void MipsInstPrinter::printUnsignedImm(const MCInst *MI, int opNum, diff --git a/lib/Target/Mips/LLVMBuild.txt b/lib/Target/Mips/LLVMBuild.txt new file mode 100644 index 0000000..bcd32bc --- /dev/null +++ b/lib/Target/Mips/LLVMBuild.txt @@ -0,0 +1,33 @@ +;===- ./lib/Target/Mips/LLVMBuild.txt --------------------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[common] +subdirectories = InstPrinter MCTargetDesc TargetInfo + +[component_0] +type = TargetGroup +name = Mips +parent = Target +has_asmprinter = 1 +has_jit = 1 + +[component_1] +type = Library +name = MipsCodeGen +parent = Mips +required_libraries = AsmPrinter CodeGen Core MC MipsAsmPrinter MipsDesc MipsInfo SelectionDAG Support Target +add_to_library_groups = Mips diff --git a/lib/Target/Mips/MCTargetDesc/Android.mk b/lib/Target/Mips/MCTargetDesc/Android.mk new file mode 100644 index 0000000..a728a80 --- /dev/null +++ b/lib/Target/Mips/MCTargetDesc/Android.mk @@ -0,0 +1,53 @@ +LOCAL_PATH := $(call my-dir) + +mips_mc_desc_TBLGEN_TABLES := \ + MipsGenRegisterInfo.inc \ + MipsGenInstrInfo.inc \ + MipsGenMCCodeEmitter.inc \ + MipsGenSubtargetInfo.inc + +mips_mc_desc_SRC_FILES := \ + MipsAsmBackend.cpp \ + MipsMCAsmInfo.cpp \ + MipsMCCodeEmitter.cpp \ + MipsMCTargetDesc.cpp + +# For the host +# ===================================================== +include $(CLEAR_VARS) +include $(CLEAR_TBLGEN_VARS) + +LOCAL_MODULE:= libLLVMMipsDesc +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := $(mips_mc_desc_SRC_FILES) +LOCAL_C_INCLUDES := $(LOCAL_PATH)/.. + +TBLGEN_TD_DIR := $(LOCAL_PATH)/.. +TBLGEN_TABLES := $(mips_mc_desc_TBLGEN_TABLES) + +include $(LLVM_HOST_BUILD_MK) +include $(LLVM_TBLGEN_RULES_MK) +include $(LLVM_GEN_INTRINSICS_MK) +include $(BUILD_HOST_STATIC_LIBRARY) + +# For the device only +# ===================================================== +ifeq ($(TARGET_ARCH),mips) +include $(CLEAR_VARS) +include $(CLEAR_TBLGEN_VARS) + +LOCAL_MODULE:= libLLVMMipsDesc +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := $(mips_mc_desc_SRC_FILES) +LOCAL_C_INCLUDES := $(LOCAL_PATH)/.. + +TBLGEN_TD_DIR := $(LOCAL_PATH)/.. +TBLGEN_TABLES := $(mips_mc_desc_TBLGEN_TABLES) + +include $(LLVM_DEVICE_BUILD_MK) +include $(LLVM_TBLGEN_RULES_MK) +include $(LLVM_GEN_INTRINSICS_MK) +include $(BUILD_STATIC_LIBRARY) +endif diff --git a/lib/Target/Mips/MCTargetDesc/CMakeLists.txt b/lib/Target/Mips/MCTargetDesc/CMakeLists.txt index 2ceb5c9..0eb0a55 100644 --- a/lib/Target/Mips/MCTargetDesc/CMakeLists.txt +++ b/lib/Target/Mips/MCTargetDesc/CMakeLists.txt @@ -5,11 +5,4 @@ add_llvm_library(LLVMMipsDesc MipsMCTargetDesc.cpp ) -add_llvm_library_dependencies(LLVMMipsDesc - LLVMMC - LLVMMipsAsmPrinter - LLVMMipsInfo - LLVMSupport - ) - add_dependencies(LLVMMipsDesc MipsCommonTableGen) diff --git a/lib/Target/Mips/MCTargetDesc/LLVMBuild.txt b/lib/Target/Mips/MCTargetDesc/LLVMBuild.txt new file mode 100644 index 0000000..29f5da6 --- /dev/null +++ b/lib/Target/Mips/MCTargetDesc/LLVMBuild.txt @@ -0,0 +1,23 @@ +;===- ./lib/Target/Mips/MCTargetDesc/LLVMBuild.txt -------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Library +name = MipsDesc +parent = Mips +required_libraries = MC MipsAsmPrinter MipsInfo Support +add_to_library_groups = Mips diff --git a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp index f190ec4..60ff4fe 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp @@ -1,5 +1,21 @@ +//===-- MipsASMBackend.cpp - ---------===// +// +// 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 MipsAsmBackend and MipsELFObjectWriter classes. +// +//===----------------------------------------------------------------------===// +// + +#include "MipsFixupKinds.h" #include "MCTargetDesc/MipsMCTargetDesc.h" #include "llvm/ADT/Twine.h" +#include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCDirectives.h" #include "llvm/MC/MCELFObjectWriter.h" @@ -8,15 +24,52 @@ #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; +// Prepare value for the target space for it +static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) { + + // Add/subtract and shift + switch (Kind) { + default: + return 0; + case FK_GPRel_4: + case FK_Data_4: + case Mips::fixup_Mips_LO16: + break; + case Mips::fixup_Mips_PC16: + // So far we are only using this type for branches. + // For branches we start 1 instruction after the branch + // so the displacement will be one instruction size less. + Value -= 4; + // The displacement is then divided by 4 to give us an 18 bit + // address range. + Value >>= 2; + break; + case Mips::fixup_Mips_26: + // So far we are only using this type for jumps. + // The displacement is then divided by 4 to give us an 28 bit + // address range. + Value >>= 2; + break; + case Mips::fixup_Mips_HI16: + case Mips::fixup_Mips_GOT_Local: + // Get the higher 16-bits. Also add 1 if bit 15 is 1. + Value = (Value >> 16) + ((Value & 0x8000) != 0); + break; + } + + return Value; +} + namespace { + class MipsELFObjectWriter : public MCELFObjectTargetWriter { public: MipsELFObjectWriter(bool is64Bit, Triple::OSType OSType, uint16_t EMachine, @@ -27,18 +80,76 @@ public: class MipsAsmBackend : public MCAsmBackend { public: - MipsAsmBackend(const Target &T) - : MCAsmBackend() {} - - unsigned getNumFixupKinds() const { - return 1; //tbd - } + MipsAsmBackend(const Target &T) : MCAsmBackend() {} /// 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 { + MCFixupKind Kind = Fixup.getKind(); + Value = adjustFixupValue((unsigned)Kind, Value); + + if (!Value) + return; // Doesn't change encoding. + + unsigned Offset = Fixup.getOffset(); + // FIXME: The below code will not work across endian models + // How many bytes/bits are we fixing up? + unsigned NumBytes = ((getFixupKindInfo(Kind).TargetSize-1)/8)+1; + uint64_t Mask = ((uint64_t)1 << getFixupKindInfo(Kind).TargetSize) - 1; + + // Grab current value, if any, from bits. + uint64_t CurVal = 0; + for (unsigned i = 0; i != NumBytes; ++i) + CurVal |= ((uint8_t)Data[Offset + i]) << (i * 8); + + CurVal = (CurVal & ~Mask) | ((CurVal + Value) & Mask); + + // Write out the bytes back to the code/data bits. + // First the unaffected bits and then the fixup. + for (unsigned i = 0; i != NumBytes; ++i) { + Data[Offset + i] = uint8_t((CurVal >> (i * 8)) & 0xff); + } +} + + unsigned getNumFixupKinds() const { return Mips::NumTargetFixupKinds; } + + const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const { + const static MCFixupKindInfo Infos[Mips::NumTargetFixupKinds] = { + // This table *must* be in same the order of fixup_* kinds in + // MipsFixupKinds.h. + // + // name offset bits flags + { "fixup_Mips_16", 0, 16, 0 }, + { "fixup_Mips_32", 0, 32, 0 }, + { "fixup_Mips_REL32", 0, 32, 0 }, + { "fixup_Mips_26", 0, 26, 0 }, + { "fixup_Mips_HI16", 0, 16, 0 }, + { "fixup_Mips_LO16", 0, 16, 0 }, + { "fixup_Mips_GPREL16", 0, 16, 0 }, + { "fixup_Mips_LITERAL", 0, 16, 0 }, + { "fixup_Mips_GOT_Global", 0, 16, 0 }, + { "fixup_Mips_GOT_Local", 0, 16, 0 }, + { "fixup_Mips_PC16", 0, 16, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_Mips_CALL16", 0, 16, 0 }, + { "fixup_Mips_GPREL32", 0, 32, 0 }, + { "fixup_Mips_SHIFT5", 6, 5, 0 }, + { "fixup_Mips_SHIFT6", 6, 5, 0 }, + { "fixup_Mips_64", 0, 64, 0 }, + { "fixup_Mips_TLSGD", 0, 16, 0 }, + { "fixup_Mips_GOTTPREL", 0, 16, 0 }, + { "fixup_Mips_TPREL_HI", 0, 16, 0 }, + { "fixup_Mips_TPREL_LO", 0, 16, 0 }, + { "fixup_Mips_Branch_PCRel", 0, 16, MCFixupKindInfo::FKF_IsPCRel } + }; + + if (Kind < FirstTargetFixupKind) + return MCAsmBackend::getFixupKindInfo(Kind); + + assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && + "Invalid kind!"); + return Infos[Kind - FirstTargetFixupKind]; } /// @name Target Relaxation Interfaces @@ -52,24 +163,35 @@ public: return false; } - /// RelaxInstruction - Relax the instruction in the given fragment to the next - /// wider instruction. + /// fixupNeedsRelaxation - Target specific predicate for whether a given + /// fixup requires the associated instruction to be relaxed. + bool fixupNeedsRelaxation(const MCFixup &Fixup, + uint64_t Value, + const MCInstFragment *DF, + const MCAsmLayout &Layout) const { + // FIXME. + assert(0 && "RelaxInstruction() unimplemented"); + return false; + } + + /// RelaxInstruction - Relax the instruction in the given fragment + /// to the next wider instruction. /// - /// \param Inst - The instruction to relax, which may be the same as the - /// output. + /// \param 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. + /// 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; + return true; } }; @@ -106,7 +228,7 @@ public: return new MipsELFObjectWriter(false, OSType, ELF::EM_MIPS, false); } }; -} +} // namespace MCAsmBackend *llvm::createMipsAsmBackend(const Target &T, StringRef TT) { Triple TheTriple(TT); diff --git a/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h b/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h index f7a6fa9..00fc5df 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h +++ b/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h @@ -19,6 +19,96 @@ #include "llvm/Support/ErrorHandling.h" namespace llvm { + +/// MipsII - This namespace holds all of the target specific flags that +/// instruction info tracks. +/// +namespace MipsII { + /// Target Operand Flag enum. + enum TOF { + //===------------------------------------------------------------------===// + // Mips Specific MachineOperand flags. + + MO_NO_FLAG, + + /// MO_GOT16 - Represents the offset into the global offset table at which + /// the address the relocation entry symbol resides during execution. + MO_GOT16, + MO_GOT, + + /// MO_GOT_CALL - Represents the offset into the global offset table at + /// which the address of a call site relocation entry symbol resides + /// during execution. This is different from the above since this flag + /// can only be present in call instructions. + MO_GOT_CALL, + + /// MO_GPREL - Represents the offset from the current gp value to be used + /// for the relocatable object file being produced. + MO_GPREL, + + /// MO_ABS_HI/LO - Represents the hi or low part of an absolute symbol + /// address. + MO_ABS_HI, + MO_ABS_LO, + + /// MO_TLSGD - Represents the offset into the global offset table at which + // the module ID and TSL block offset reside during execution (General + // Dynamic TLS). + MO_TLSGD, + + /// MO_TLSLDM - Represents the offset into the global offset table at which + // the module ID and TSL block offset reside during execution (Local + // Dynamic TLS). + MO_TLSLDM, + MO_DTPREL_HI, + MO_DTPREL_LO, + + /// MO_GOTTPREL - Represents the offset from the thread pointer (Initial + // Exec TLS). + MO_GOTTPREL, + + /// MO_TPREL_HI/LO - Represents the hi and low part of the offset from + // the thread pointer (Local Exec TLS). + MO_TPREL_HI, + MO_TPREL_LO, + + // N32/64 Flags. + MO_GPOFF_HI, + MO_GPOFF_LO, + MO_GOT_DISP, + MO_GOT_PAGE, + MO_GOT_OFST + }; + + 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 + }; +} + + /// getMipsRegisterNumbering - Given the enum value for some register, /// return the number that it corresponds to. inline static unsigned getMipsRegisterNumbering(unsigned RegEnum) @@ -98,6 +188,7 @@ inline static unsigned getMipsRegisterNumbering(unsigned RegEnum) case Mips::D14: return 28; case Mips::SP: case Mips::SP_64: case Mips::F29: case Mips::D29_64: + case Mips::HWR29: return 29; case Mips::FP: case Mips::FP_64: case Mips::F30: case Mips::D30_64: case Mips::D15: diff --git a/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h b/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h index 20890ed..a56c002 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h +++ b/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h @@ -14,74 +14,82 @@ namespace llvm { namespace Mips { - enum Fixups { - // fixup_Mips_xxx - R_MIPS_NONE - fixup_Mips_NONE = FirstTargetFixupKind, + // Although most of the current fixup types reflect a unique relocation + // one can have multiple fixup types for a given relocation and thus need + // to be uniquely named. + // + // This table *must* be in the save order of + // MCFixupKindInfo Infos[Mips::NumTargetFixupKinds] + // in MipsAsmBackend.cpp. + // + enum Fixups { + // Branch fixups resulting in R_MIPS_16. + fixup_Mips_16 = FirstTargetFixupKind, - // fixup_Mips_xxx - R_MIPS_16. - fixup_Mips_16, + // Pure 32 bit data fixup resulting in - R_MIPS_32. + fixup_Mips_32, - // fixup_Mips_xxx - R_MIPS_32. - fixup_Mips_32, + // Full 32 bit data relative data fixup resulting in - R_MIPS_REL32. + fixup_Mips_REL32, - // fixup_Mips_xxx - R_MIPS_REL32. - fixup_Mips_REL32, + // Jump 26 bit fixup resulting in - R_MIPS_26. + fixup_Mips_26, - // fixup_Mips_xxx - R_MIPS_26. - fixup_Mips_26, + // Pure upper 16 bit fixup resulting in - R_MIPS_HI16. + fixup_Mips_HI16, - // fixup_Mips_xxx - R_MIPS_HI16. - fixup_Mips_HI16, + // Pure lower 16 bit fixup resulting in - R_MIPS_LO16. + fixup_Mips_LO16, - // fixup_Mips_xxx - R_MIPS_LO16. - fixup_Mips_LO16, + // 16 bit fixup for GP offest resulting in - R_MIPS_GPREL16. + fixup_Mips_GPREL16, - // fixup_Mips_xxx - R_MIPS_GPREL16. - fixup_Mips_GPREL16, + // 16 bit literal fixup resulting in - R_MIPS_LITERAL. + fixup_Mips_LITERAL, - // fixup_Mips_xxx - R_MIPS_LITERAL. - fixup_Mips_LITERAL, + // Global symbol fixup resulting in - R_MIPS_GOT16. + fixup_Mips_GOT_Global, - // fixup_Mips_xxx - R_MIPS_GOT16. - fixup_Mips_GOT16, + // Local symbol fixup resulting in - R_MIPS_GOT16. + fixup_Mips_GOT_Local, - // fixup_Mips_xxx - R_MIPS_PC16. - fixup_Mips_PC16, + // PC relative branch fixup resulting in - R_MIPS_PC16. + fixup_Mips_PC16, - // fixup_Mips_xxx - R_MIPS_CALL16. - fixup_Mips_CALL16, + // resulting in - R_MIPS_CALL16. + fixup_Mips_CALL16, - // fixup_Mips_xxx - R_MIPS_GPREL32. - fixup_Mips_GPREL32, + // resulting in - R_MIPS_GPREL32. + fixup_Mips_GPREL32, - // fixup_Mips_xxx - R_MIPS_SHIFT5. - fixup_Mips_SHIFT5, + // resulting in - R_MIPS_SHIFT5. + fixup_Mips_SHIFT5, - // fixup_Mips_xxx - R_MIPS_SHIFT6. - fixup_Mips_SHIFT6, + // resulting in - R_MIPS_SHIFT6. + fixup_Mips_SHIFT6, - // fixup_Mips_xxx - R_MIPS_64. - fixup_Mips_64, + // Pure 64 bit data fixup resulting in - R_MIPS_64. + fixup_Mips_64, - // fixup_Mips_xxx - R_MIPS_TLS_GD. - fixup_Mips_TLSGD, + // resulting in - R_MIPS_TLS_GD. + fixup_Mips_TLSGD, - // fixup_Mips_xxx - R_MIPS_TLS_GOTTPREL. - fixup_Mips_GOTTPREL, + // resulting in - R_MIPS_TLS_GOTTPREL. + fixup_Mips_GOTTPREL, - // fixup_Mips_xxx - R_MIPS_TLS_TPREL_HI16. - fixup_Mips_TPREL_HI, + // resulting in - R_MIPS_TLS_TPREL_HI16. + fixup_Mips_TPREL_HI, - // fixup_Mips_xxx - R_MIPS_TLS_TPREL_LO16. - fixup_Mips_TPREL_LO, + // resulting in - R_MIPS_TLS_TPREL_LO16. + fixup_Mips_TPREL_LO, - // fixup_Mips_xxx - yyy. // This should become R_MIPS_PC16 - fixup_Mips_Branch_PCRel, + // PC relative branch fixup resulting in - R_MIPS_PC16 + fixup_Mips_Branch_PCRel, - // Marker - LastTargetFixupKind, - NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind - }; + // Marker + LastTargetFixupKind, + NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind + }; } // namespace Mips } // namespace llvm diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp index d66de23..463dcfe 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp @@ -12,16 +12,18 @@ //===----------------------------------------------------------------------===// // #define DEBUG_TYPE "mccodeemitter" +#include "MCTargetDesc/MipsBaseInfo.h" +#include "MCTargetDesc/MipsFixupKinds.h" +#include "MCTargetDesc/MipsMCTargetDesc.h" +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/Statistic.h" #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; @@ -31,22 +33,237 @@ class MipsMCCodeEmitter : public MCCodeEmitter { void operator=(const MipsMCCodeEmitter &); // DO NOT IMPLEMENT const MCInstrInfo &MCII; const MCSubtargetInfo &STI; + MCContext &Ctx; public: MipsMCCodeEmitter(const MCInstrInfo &mcii, const MCSubtargetInfo &sti, - MCContext &ctx) - : MCII(mcii), STI(sti) {} + MCContext &ctx) : MCII(mcii), STI(sti) , Ctx(ctx) {} ~MipsMCCodeEmitter() {} - void EncodeInstruction(const MCInst &MI, raw_ostream &OS, - SmallVectorImpl<MCFixup> &Fixups) const { + void EmitByte(unsigned char C, raw_ostream &OS) const { + OS << (char)C; + } + + void EmitInstruction(uint64_t Val, unsigned Size, raw_ostream &OS) const { + // Output the instruction encoding in little endian byte order. + for (unsigned i = 0; i != Size; ++i) { + EmitByte(Val & 255, OS); + Val >>= 8; + } } + + void EncodeInstruction(const MCInst &MI, raw_ostream &OS, + SmallVectorImpl<MCFixup> &Fixups) const; + + // getBinaryCodeForInstr - TableGen'erated function for getting the + // binary encoding for an instruction. + unsigned getBinaryCodeForInstr(const MCInst &MI, + SmallVectorImpl<MCFixup> &Fixups) const; + + // getBranchJumpOpValue - Return binary encoding of the jump + // target operand. If the machine operand requires relocation, + // record the relocation and return zero. + unsigned getJumpTargetOpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups) const; + + // getBranchTargetOpValue - Return binary encoding of the branch + // target operand. If the machine operand requires relocation, + // record the relocation and return zero. + unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups) const; + + // getMachineOpValue - Return binary encoding of operand. If the machin + // operand requires relocation, record the relocation and return zero. + unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO, + SmallVectorImpl<MCFixup> &Fixups) const; + + unsigned getMemEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups) const; + unsigned getSizeExtEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups) const; + unsigned getSizeInsEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups) const; + }; // class MipsMCCodeEmitter } // namespace MCCodeEmitter *llvm::createMipsMCCodeEmitter(const MCInstrInfo &MCII, const MCSubtargetInfo &STI, - MCContext &Ctx) { + MCContext &Ctx) +{ return new MipsMCCodeEmitter(MCII, STI, Ctx); } + +/// EncodeInstruction - Emit the instruction. +/// Size the instruction (currently only 4 bytes +void MipsMCCodeEmitter:: +EncodeInstruction(const MCInst &MI, raw_ostream &OS, + SmallVectorImpl<MCFixup> &Fixups) const +{ + uint32_t Binary = getBinaryCodeForInstr(MI, Fixups); + + // Check for unimplemented opcodes. + // Unfortunately in MIPS both NOT and SLL will come in with Binary == 0 + // so we have to special check for them. + unsigned Opcode = MI.getOpcode(); + if ((Opcode != Mips::NOP) && (Opcode != Mips::SLL) && !Binary) + llvm_unreachable("unimplemented opcode in EncodeInstruction()"); + + const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); + uint64_t TSFlags = Desc.TSFlags; + + // Pseudo instructions don't get encoded and shouldn't be here + // in the first place! + if ((TSFlags & MipsII::FormMask) == MipsII::Pseudo) + llvm_unreachable("Pseudo opcode found in EncodeInstruction()"); + + // For now all instructions are 4 bytes + int Size = 4; // FIXME: Have Desc.getSize() return the correct value! + + EmitInstruction(Binary, Size, OS); +} + +/// getBranchTargetOpValue - Return binary encoding of the branch +/// target operand. If the machine operand requires relocation, +/// record the relocation and return zero. +unsigned MipsMCCodeEmitter:: +getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups) const { + + const MCOperand &MO = MI.getOperand(OpNo); + assert(MO.isExpr() && "getBranchTargetOpValue expects only expressions"); + + const MCExpr *Expr = MO.getExpr(); + Fixups.push_back(MCFixup::Create(0, Expr, + MCFixupKind(Mips::fixup_Mips_PC16))); + return 0; +} + +/// getJumpTargetOpValue - Return binary encoding of the jump +/// target operand. If the machine operand requires relocation, +/// record the relocation and return zero. +unsigned MipsMCCodeEmitter:: +getJumpTargetOpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups) const { + + const MCOperand &MO = MI.getOperand(OpNo); + assert(MO.isExpr() && "getJumpTargetOpValue expects only expressions"); + + const MCExpr *Expr = MO.getExpr(); + Fixups.push_back(MCFixup::Create(0, Expr, + MCFixupKind(Mips::fixup_Mips_26))); + return 0; +} + +/// getMachineOpValue - Return binary encoding of operand. If the machine +/// operand requires relocation, record the relocation and return zero. +unsigned MipsMCCodeEmitter:: +getMachineOpValue(const MCInst &MI, const MCOperand &MO, + SmallVectorImpl<MCFixup> &Fixups) const { + if (MO.isReg()) { + unsigned Reg = MO.getReg(); + unsigned RegNo = getMipsRegisterNumbering(Reg); + return RegNo; + } else if (MO.isImm()) { + return static_cast<unsigned>(MO.getImm()); + } else if (MO.isFPImm()) { + return static_cast<unsigned>(APFloat(MO.getFPImm()) + .bitcastToAPInt().getHiBits(32).getLimitedValue()); + } else if (MO.isExpr()) { + const MCExpr *Expr = MO.getExpr(); + MCExpr::ExprKind Kind = Expr->getKind(); + unsigned Ret = 0; + + if (Kind == MCExpr::Binary) { + const MCBinaryExpr *BE = static_cast<const MCBinaryExpr*>(Expr); + Expr = BE->getLHS(); + Kind = Expr->getKind(); + const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(BE->getRHS()); + assert((Kind == MCExpr::SymbolRef) && CE && + "Binary expression must be sym+const."); + Ret = CE->getValue(); + } + + if (Kind == MCExpr::SymbolRef) { + Mips::Fixups FixupKind; + switch(cast<MCSymbolRefExpr>(Expr)->getKind()) { + case MCSymbolRefExpr::VK_Mips_GPREL: + FixupKind = Mips::fixup_Mips_GPREL16; + break; + case MCSymbolRefExpr::VK_Mips_GOT_CALL: + FixupKind = Mips::fixup_Mips_CALL16; + break; + case MCSymbolRefExpr::VK_Mips_GOT16: + FixupKind = Mips::fixup_Mips_GOT_Global; + break; + case MCSymbolRefExpr::VK_Mips_GOT: + FixupKind = Mips::fixup_Mips_GOT_Local; + break; + case MCSymbolRefExpr::VK_Mips_ABS_HI: + FixupKind = Mips::fixup_Mips_HI16; + break; + case MCSymbolRefExpr::VK_Mips_ABS_LO: + FixupKind = Mips::fixup_Mips_LO16; + break; + case MCSymbolRefExpr::VK_Mips_TLSGD: + FixupKind = Mips::fixup_Mips_TLSGD; + break; + case MCSymbolRefExpr::VK_Mips_GOTTPREL: + FixupKind = Mips::fixup_Mips_GOTTPREL; + break; + case MCSymbolRefExpr::VK_Mips_TPREL_HI: + FixupKind = Mips::fixup_Mips_TPREL_HI; + break; + case MCSymbolRefExpr::VK_Mips_TPREL_LO: + FixupKind = Mips::fixup_Mips_TPREL_LO; + break; + default: + return Ret; + } // switch + Fixups.push_back(MCFixup::Create(0, Expr, MCFixupKind(FixupKind))); + } // if SymbolRef + // All of the information is in the fixup. + return Ret; + } + llvm_unreachable("Unable to encode MCOperand!"); + // Not reached + return 0; +} + +/// getMemEncoding - Return binary encoding of memory related operand. +/// If the offset operand requires relocation, record the relocation. +unsigned +MipsMCCodeEmitter::getMemEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups) const { + // Base register is encoded in bits 20-16, offset is encoded in bits 15-0. + assert(MI.getOperand(OpNo).isReg()); + unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),Fixups) << 16; + unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups); + + return (OffBits & 0xFFFF) | RegBits; +} + +unsigned +MipsMCCodeEmitter::getSizeExtEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups) const { + assert(MI.getOperand(OpNo).isImm()); + unsigned SizeEncoding = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups); + return SizeEncoding - 1; +} + +// FIXME: should be called getMSBEncoding +// +unsigned +MipsMCCodeEmitter::getSizeInsEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups) const { + assert(MI.getOperand(OpNo-1).isImm()); + assert(MI.getOperand(OpNo).isImm()); + unsigned Position = getMachineOpValue(MI, MI.getOperand(OpNo-1), Fixups); + unsigned Size = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups); + + return Position + Size - 1; +} + +#include "MipsGenMCCodeEmitter.inc" + diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp index 1f9e3dd..1fec88a 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#include "MipsMCTargetDesc.h" #include "MipsMCAsmInfo.h" +#include "MipsMCTargetDesc.h" #include "InstPrinter/MipsInstPrinter.h" #include "llvm/MC/MachineLocation.h" #include "llvm/MC/MCCodeGenInfo.h" @@ -63,11 +63,12 @@ static MCAsmInfo *createMipsMCAsmInfo(const Target &T, StringRef TT) { } static MCCodeGenInfo *createMipsMCCodeGenInfo(StringRef TT, Reloc::Model RM, - CodeModel::Model CM) { + CodeModel::Model CM, + CodeGenOpt::Level OL) { MCCodeGenInfo *X = new MCCodeGenInfo(); if (RM == Reloc::Default) RM = Reloc::PIC_; - X->InitMCCodeGenInfo(RM, CM); + X->InitMCCodeGenInfo(RM, CM, OL); return X; } @@ -140,6 +141,9 @@ extern "C" void LLVMInitializeMipsTargetMC() { TargetRegistry::RegisterMCAsmBackend(TheMips64Target, createMipsAsmBackend); TargetRegistry::RegisterMCAsmBackend(TheMips64elTarget, createMipsAsmBackend); + TargetRegistry::RegisterMCCodeEmitter(TheMipsTarget, createMipsMCCodeEmitter); + TargetRegistry::RegisterMCCodeEmitter(TheMipselTarget, createMipsMCCodeEmitter); + // Register the MC subtarget info. TargetRegistry::RegisterMCSubtargetInfo(TheMipsTarget, createMipsMCSubtargetInfo); diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h b/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h index 7a0042a..fc43d2d 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h +++ b/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h @@ -16,12 +16,14 @@ namespace llvm { class MCAsmBackend; -class MCInstrInfo; class MCCodeEmitter; class MCContext; +class MCInstrInfo; +class MCObjectWriter; class MCSubtargetInfo; class StringRef; class Target; +class raw_ostream; extern Target TheMipsTarget; extern Target TheMipselTarget; @@ -33,6 +35,7 @@ MCCodeEmitter *createMipsMCCodeEmitter(const MCInstrInfo &MCII, 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/lib/Target/Mips/Makefile b/lib/Target/Mips/Makefile index d72693c..94f7c18 100644 --- a/lib/Target/Mips/Makefile +++ b/lib/Target/Mips/Makefile @@ -15,7 +15,7 @@ TARGET = Mips BUILT_SOURCES = MipsGenRegisterInfo.inc MipsGenInstrInfo.inc \ MipsGenAsmWriter.inc MipsGenCodeEmitter.inc \ MipsGenDAGISel.inc MipsGenCallingConv.inc \ - MipsGenSubtargetInfo.inc + MipsGenSubtargetInfo.inc MipsGenMCCodeEmitter.inc DIRS = InstPrinter TargetInfo MCTargetDesc diff --git a/lib/Target/Mips/Mips.td b/lib/Target/Mips/Mips.td index 39c2c16..e9e0f60 100644 --- a/lib/Target/Mips/Mips.td +++ b/lib/Target/Mips/Mips.td @@ -79,9 +79,9 @@ def FeatureMips64r2 : SubtargetFeature<"mips64r2", "MipsArchVersion", class Proc<string Name, list<SubtargetFeature> Features> : Processor<Name, MipsGenericItineraries, Features>; -def : Proc<"mips32r1", [FeatureMips32]>; -def : Proc<"4ke", [FeatureMips32r2]>; -def : Proc<"mips64r1", [FeatureMips64]>; +def : Proc<"mips32", [FeatureMips32]>; +def : Proc<"mips32r2", [FeatureMips32r2]>; +def : Proc<"mips64", [FeatureMips64]>; def : Proc<"mips64r2", [FeatureMips64r2]>; def MipsAsmWriter : AsmWriter { diff --git a/lib/Target/Mips/Mips64InstrInfo.td b/lib/Target/Mips/Mips64InstrInfo.td index 05470d5..2996986 100644 --- a/lib/Target/Mips/Mips64InstrInfo.td +++ b/lib/Target/Mips/Mips64InstrInfo.td @@ -25,17 +25,30 @@ def uimm16_64 : Operand<i64> { // Transformation Function - get Imm - 32. def Subtract32 : SDNodeXForm<imm, [{ - return getI32Imm((unsigned)N->getZExtValue() - 32); + return getImm(N, (unsigned)N->getZExtValue() - 32); }]>; // shamt field must fit in 5 bits. def immZExt5_64 : ImmLeaf<i64, [{return Imm == (Imm & 0x1f);}]>; // imm32_63 predicate - True if imm is in range [32, 63]. -def imm32_63 : ImmLeaf<i64, +def imm32_63 : ImmLeaf<i32, [{return (int32_t)Imm >= 32 && (int32_t)Imm < 64;}], Subtract32>; +// Is a 32-bit int. +def immSExt32 : ImmLeaf<i64, [{return isInt<32>(Imm);}]>; + +// Transformation Function - get the higher 16 bits. +def HIGHER : SDNodeXForm<imm, [{ + return getImm(N, (N->getZExtValue() >> 32) & 0xFFFF); +}]>; + +// Transformation Function - get the highest 16 bits. +def HIGHEST : SDNodeXForm<imm, [{ + return getImm(N, (N->getZExtValue() >> 48) & 0xFFFF); +}]>; + //===----------------------------------------------------------------------===// // Instructions specific format //===----------------------------------------------------------------------===// @@ -43,20 +56,66 @@ def imm32_63 : ImmLeaf<i64, // 64-bit shift instructions. class shift_rotate_imm64<bits<6> func, bits<5> isRotate, string instr_asm, SDNode OpNode>: - shift_rotate_imm<func, isRotate, instr_asm, OpNode, immZExt5_64, shamt_64, + shift_rotate_imm<func, isRotate, instr_asm, OpNode, immZExt5, shamt, CPU64Regs>; class shift_rotate_imm64_32<bits<6> func, bits<5> isRotate, string instr_asm, SDNode OpNode>: - shift_rotate_imm<func, isRotate, instr_asm, OpNode, imm32_63, shamt_64, + shift_rotate_imm<func, isRotate, instr_asm, OpNode, imm32_63, shamt, CPU64Regs>; +// Jump and Link (Call) +let isCall=1, hasDelaySlot=1, + // All calls clobber the non-callee saved registers... + Defs = [AT, V0, V1, A0, A1, A2, A3, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, + K0, K1, D0, D1, D2, D3, D4, D5, D6, D7, D8, D9], Uses = [GP] in { + class JumpLink64<bits<6> op, string instr_asm>: + FJ<op, (outs), (ins calltarget64:$target, variable_ops), + !strconcat(instr_asm, "\t$target"), [(MipsJmpLink imm:$target)], + IIBranch>; + + class JumpLinkReg64<bits<6> op, bits<6> func, string instr_asm>: + FR<op, func, (outs), (ins CPU64Regs:$rs, variable_ops), + !strconcat(instr_asm, "\t$rs"), + [(MipsJmpLink CPU64Regs:$rs)], IIBranch> { + let rt = 0; + let rd = 31; + let shamt = 0; + } + + class BranchLink64<string instr_asm>: + FI<0x1, (outs), (ins CPU64Regs:$rs, brtarget:$imm16, variable_ops), + !strconcat(instr_asm, "\t$rs, $imm16"), [], IIBranch>; +} + // Mul, Div class Mult64<bits<6> func, string instr_asm, InstrItinClass itin>: Mult<func, instr_asm, itin, CPU64Regs, [HI64, LO64]>; class Div64<SDNode op, bits<6> func, string instr_asm, InstrItinClass itin>: Div<op, func, instr_asm, itin, CPU64Regs, [HI64, LO64]>; +multiclass Atomic2Ops64<PatFrag Op, string Opstr> { + def #NAME# : Atomic2Ops<Op, Opstr, CPU64Regs, CPURegs>, Requires<[NotN64]>; + def _P8 : Atomic2Ops<Op, Opstr, CPU64Regs, CPU64Regs>, Requires<[IsN64]>; +} + +multiclass AtomicCmpSwap64<PatFrag Op, string Width> { + def #NAME# : AtomicCmpSwap<Op, Width, CPU64Regs, CPURegs>, Requires<[NotN64]>; + def _P8 : AtomicCmpSwap<Op, Width, CPU64Regs, CPU64Regs>, + Requires<[IsN64]>; +} + +let usesCustomInserter = 1, Predicates = [HasMips64] in { + defm ATOMIC_LOAD_ADD_I64 : Atomic2Ops64<atomic_load_add_64, "load_add_64">; + defm ATOMIC_LOAD_SUB_I64 : Atomic2Ops64<atomic_load_sub_64, "load_sub_64">; + defm ATOMIC_LOAD_AND_I64 : Atomic2Ops64<atomic_load_and_64, "load_and_64">; + defm ATOMIC_LOAD_OR_I64 : Atomic2Ops64<atomic_load_or_64, "load_or_64">; + defm ATOMIC_LOAD_XOR_I64 : Atomic2Ops64<atomic_load_xor_64, "load_xor_64">; + defm ATOMIC_LOAD_NAND_I64 : Atomic2Ops64<atomic_load_nand_64, "load_nand_64">; + defm ATOMIC_SWAP_I64 : Atomic2Ops64<atomic_swap_64, "swap_64">; + defm ATOMIC_CMP_SWAP_I64 : AtomicCmpSwap64<atomic_cmp_swap_64, "64">; +} + //===----------------------------------------------------------------------===// // Instruction definition //===----------------------------------------------------------------------===// @@ -69,6 +128,7 @@ 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>; +def LUi64 : LoadUpper<0x0f, "lui", CPU64Regs, uimm16_64>; /// Arithmetic Instructions (3-Operand, R-Type) def DADDu : ArithLogicR<0x00, 0x2d, "daddu", add, IIAlu, CPU64Regs, 1>; @@ -121,7 +181,16 @@ defm USW64 : StoreM64<0x2b, "usw", truncstorei32_u, 1>; defm ULD : LoadM64<0x37, "uld", load_u, 1>; defm USD : StoreM64<0x3f, "usd", store_u, 1>; +/// Load-linked, Store-conditional +def LLD : LLBase<0x34, "lld", CPU64Regs, mem>, Requires<[NotN64]>; +def LLD_P8 : LLBase<0x34, "lld", CPU64Regs, mem64>, Requires<[IsN64]>; +def SCD : SCBase<0x3c, "scd", CPU64Regs, mem>, Requires<[NotN64]>; +def SCD_P8 : SCBase<0x3c, "scd", CPU64Regs, mem64>, Requires<[IsN64]>; + /// Jump and Branch Instructions +def JR64 : JumpFR<0x00, 0x08, "jr", CPU64Regs>; +def JAL64 : JumpLink64<0x03, "jal">; +def JALR64 : JumpLinkReg64<0x00, 0x09, "jalr">; def BEQ64 : CBranch<0x04, "beq", seteq, CPU64Regs>; def BNE64 : CBranch<0x05, "bne", setne, CPU64Regs>; def BGEZ64 : CBranchZero<0x01, 1, "bgez", setge, CPU64Regs>; @@ -144,6 +213,23 @@ def MFLO64 : MoveFromLOHI<0x12, "mflo", CPU64Regs, [LO64]>; def DCLZ : CountLeading0<0x24, "dclz", CPU64Regs>; def DCLO : CountLeading1<0x25, "dclo", CPU64Regs>; +def LEA_ADDiu64 : EffectiveAddress<"addiu\t$rt, $addr", CPU64Regs, mem_ea_64>; + +let Uses = [SP_64] in +def DynAlloc64 : EffectiveAddress<"daddiu\t$rt, $addr", CPU64Regs, mem_ea_64>, + Requires<[IsN64]>; + +def RDHWR64 : ReadHardware<CPU64Regs, HWRegs64>; + +def DEXT : ExtBase<3, "dext", CPU64Regs>; +def DINS : InsBase<7, "dins", CPU64Regs>; + +def DSLL64_32 : FR<0x3c, 0x00, (outs CPU64Regs:$rd), (ins CPURegs:$rt), + "dsll32\t$rd, $rt, 0", [], IIAlu>; + +def SLL64_32 : FR<0x0, 0x00, (outs CPU64Regs:$rd), (ins CPURegs:$rt), + "sll\t$rd, $rt, 0", [], IIAlu>; + //===----------------------------------------------------------------------===// // Arbitrary patterns that map to one or more instructions //===----------------------------------------------------------------------===// @@ -154,14 +240,57 @@ def : Pat<(i64 immSExt16:$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]>; +// 32-bit immediates +def : Pat<(i64 immSExt32:$imm), + (ORi64 (LUi64 (HI16 imm:$imm)), (LO16 imm:$imm))>; + +// Arbitrary immediates +def : Pat<(i64 imm:$imm), + (ORi64 (DSLL (ORi64 (DSLL (ORi64 (LUi64 (HIGHEST imm:$imm)), + (HIGHER imm:$imm)), 16), (HI16 imm:$imm)), 16), + (LO16 imm:$imm))>; + +// extended loads +let Predicates = [NotN64] in { + def : Pat<(extloadi32_a addr:$a), (DSRL32 (DSLL32 (LW64 addr:$a), 0), 0)>; + def : Pat<(zextloadi32_u addr:$a), (DSRL32 (DSLL32 (ULW64 addr:$a), 0), 0)>; +} +let Predicates = [IsN64] in { + def : Pat<(extloadi32_a addr:$a), (DSRL32 (DSLL32 (LW64_P8 addr:$a), 0), 0)>; + def : Pat<(zextloadi32_u addr:$a), + (DSRL32 (DSLL32 (ULW64_P8 addr:$a), 0), 0)>; +} // hi/lo relocs -def : Pat<(i64 (MipsLo tglobaladdr:$in)), (DADDiu ZERO_64, tglobaladdr:$in)>; +def : Pat<(MipsHi tglobaladdr:$in), (LUi64 tglobaladdr:$in)>; +def : Pat<(MipsHi tblockaddress:$in), (LUi64 tblockaddress:$in)>; +def : Pat<(MipsHi tjumptable:$in), (LUi64 tjumptable:$in)>; +def : Pat<(MipsHi tconstpool:$in), (LUi64 tconstpool:$in)>; +def : Pat<(MipsHi tglobaltlsaddr:$in), (LUi64 tglobaltlsaddr:$in)>; + +def : Pat<(MipsLo tglobaladdr:$in), (DADDiu ZERO_64, tglobaladdr:$in)>; +def : Pat<(MipsLo tblockaddress:$in), (DADDiu ZERO_64, tblockaddress:$in)>; +def : Pat<(MipsLo tjumptable:$in), (DADDiu ZERO_64, tjumptable:$in)>; +def : Pat<(MipsLo tconstpool:$in), (DADDiu ZERO_64, tconstpool:$in)>; +def : Pat<(MipsLo tglobaltlsaddr:$in), (DADDiu ZERO_64, tglobaltlsaddr:$in)>; + +def : Pat<(add CPU64Regs:$hi, (MipsLo tglobaladdr:$lo)), + (DADDiu CPU64Regs:$hi, tglobaladdr:$lo)>; +def : Pat<(add CPU64Regs:$hi, (MipsLo tblockaddress:$lo)), + (DADDiu CPU64Regs:$hi, tblockaddress:$lo)>; +def : Pat<(add CPU64Regs:$hi, (MipsLo tjumptable:$lo)), + (DADDiu CPU64Regs:$hi, tjumptable:$lo)>; +def : Pat<(add CPU64Regs:$hi, (MipsLo tconstpool:$lo)), + (DADDiu CPU64Regs:$hi, tconstpool:$lo)>; +def : Pat<(add CPU64Regs:$hi, (MipsLo tglobaltlsaddr:$lo)), + (DADDiu CPU64Regs:$hi, tglobaltlsaddr:$lo)>; + +def : WrapperPat<tglobaladdr, DADDiu, GP_64>; +def : WrapperPat<tconstpool, DADDiu, GP_64>; +def : WrapperPat<texternalsym, DADDiu, GP_64>; +def : WrapperPat<tblockaddress, DADDiu, GP_64>; +def : WrapperPat<tjumptable, DADDiu, GP_64>; +def : WrapperPat<tglobaltlsaddr, DADDiu, GP_64>; defm : BrcondPats<CPU64Regs, BEQ64, BNE64, SLT64, SLTu64, SLTi64, SLTiu64, ZERO_64>; @@ -172,3 +301,14 @@ defm : SetlePats<CPU64Regs, SLT64, SLTu64>; defm : SetgtPats<CPU64Regs, SLT64, SLTu64>; defm : SetgePats<CPU64Regs, SLT64, SLTu64>; defm : SetgeImmPats<CPU64Regs, SLTi64, SLTiu64>; + +// select MipsDynAlloc +def : Pat<(MipsDynAlloc addr:$f), (DynAlloc64 addr:$f)>, Requires<[IsN64]>; + +// truncate +def : Pat<(i32 (trunc CPU64Regs:$src)), + (SLL (EXTRACT_SUBREG CPU64Regs:$src, sub_32), 0)>, Requires<[IsN64]>; + +// 32-to-64-bit extension +def : Pat<(i64 (anyext CPURegs:$src)), (SLL64_32 CPURegs:$src)>; +def : Pat<(i64 (zext CPURegs:$src)), (DSRL32 (DSLL64_32 CPURegs:$src), 0)>; diff --git a/lib/Target/Mips/MipsAsmPrinter.cpp b/lib/Target/Mips/MipsAsmPrinter.cpp index 0e82681..a5505d3 100644 --- a/lib/Target/Mips/MipsAsmPrinter.cpp +++ b/lib/Target/Mips/MipsAsmPrinter.cpp @@ -13,13 +13,17 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "mips-asm-printer" -#include "MipsAsmPrinter.h" #include "Mips.h" +#include "MipsAsmPrinter.h" #include "MipsInstrInfo.h" #include "MipsMachineFunction.h" #include "MipsMCInstLower.h" -#include "MipsMCSymbolRefExpr.h" #include "InstPrinter/MipsInstPrinter.h" +#include "MCTargetDesc/MipsBaseInfo.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Analysis/DebugInfo.h" #include "llvm/BasicBlock.h" #include "llvm/Instructions.h" #include "llvm/CodeGen/MachineFunctionPass.h" @@ -27,20 +31,17 @@ #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineMemOperand.h" +#include "llvm/Instructions.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCSymbol.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/Target/Mangler.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetOptions.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; @@ -51,6 +52,12 @@ static bool isUnalignedLoadStore(unsigned Opc) { Opc == Mips::USW_P8 || Opc == Mips::USH_P8; } +static bool isDirective(unsigned Opc) { + return Opc == Mips::MACRO || Opc == Mips::NOMACRO || + Opc == Mips::REORDER || Opc == Mips::NOREORDER || + Opc == Mips::ATMACRO || Opc == Mips::NOAT; +} + void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) { SmallString<128> Str; raw_svector_ostream OS(Str); @@ -63,19 +70,45 @@ void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) { MipsMCInstLower MCInstLowering(Mang, *MF, *this); unsigned Opc = MI->getOpcode(); MCInst TmpInst0; + SmallVector<MCInst, 4> MCInsts; MCInstLowering.Lower(MI, TmpInst0); - + + if (!OutStreamer.hasRawTextSupport() && isDirective(Opc)) + return; + // 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); + if (OutStreamer.hasRawTextSupport()) { + MCInst Directive; + Directive.setOpcode(Mips::MACRO); + OutStreamer.EmitInstruction(Directive); + OutStreamer.EmitInstruction(TmpInst0); + Directive.setOpcode(Mips::NOMACRO); + OutStreamer.EmitInstruction(Directive); + } else { + MCInstLowering.LowerUnalignedLoadStore(MI, MCInsts); + for (SmallVector<MCInst, 4>::iterator I = MCInsts.begin(); I + != MCInsts.end(); ++I) + OutStreamer.EmitInstruction(*I); + } return; } + if (!OutStreamer.hasRawTextSupport()) { + // Lower CPLOAD and CPRESTORE + if (Opc == Mips::CPLOAD) + MCInstLowering.LowerCPLOAD(MI, MCInsts); + else if (Opc == Mips::CPRESTORE) + MCInstLowering.LowerCPRESTORE(MI, MCInsts); + + if (!MCInsts.empty()) { + for (SmallVector<MCInst, 4>::iterator I = MCInsts.begin(); + I != MCInsts.end(); ++I) + OutStreamer.EmitInstruction(*I); + return; + } + } + OutStreamer.EmitInstruction(TmpInst0); } @@ -177,7 +210,7 @@ void MipsAsmPrinter::printSavedRegsBitmask(raw_ostream &O) { void MipsAsmPrinter::printHex32(unsigned Value, raw_ostream &O) { O << "0x"; for (int i = 7; i >= 0; i--) - O << utohexstr((Value & (0xF << (i*4))) >> (i*4)); + O.write_hex((Value & (0xF << (i*4))) >> (i*4)); } //===----------------------------------------------------------------------===// @@ -192,10 +225,11 @@ void MipsAsmPrinter::emitFrameDirective() { unsigned returnReg = RI.getRARegister(); unsigned stackSize = MF->getFrameInfo()->getStackSize(); - OutStreamer.EmitRawText("\t.frame\t$" + - Twine(LowercaseString(MipsInstPrinter::getRegisterName(stackReg))) + + if (OutStreamer.hasRawTextSupport()) + OutStreamer.EmitRawText("\t.frame\t$" + + StringRef(MipsInstPrinter::getRegisterName(stackReg)).lower() + "," + Twine(stackSize) + ",$" + - Twine(LowercaseString(MipsInstPrinter::getRegisterName(returnReg)))); + StringRef(MipsInstPrinter::getRegisterName(returnReg)).lower()); } /// Emit Set directives. @@ -213,7 +247,8 @@ const char *MipsAsmPrinter::getCurrentABIString() const { } void MipsAsmPrinter::EmitFunctionEntryLabel() { - OutStreamer.EmitRawText("\t.ent\t" + Twine(CurrentFnSym->getName())); + if (OutStreamer.hasRawTextSupport()) + OutStreamer.EmitRawText("\t.ent\t" + Twine(CurrentFnSym->getName())); OutStreamer.EmitLabel(CurrentFnSym); } @@ -222,10 +257,12 @@ void MipsAsmPrinter::EmitFunctionEntryLabel() { void MipsAsmPrinter::EmitFunctionBodyStart() { emitFrameDirective(); - SmallString<128> Str; - raw_svector_ostream OS(Str); - printSavedRegsBitmask(OS); - OutStreamer.EmitRawText(OS.str()); + if (OutStreamer.hasRawTextSupport()) { + SmallString<128> Str; + raw_svector_ostream OS(Str); + printSavedRegsBitmask(OS); + OutStreamer.EmitRawText(OS.str()); + } } /// EmitFunctionBodyEnd - Targets can override this to emit stuff after @@ -234,12 +271,13 @@ void MipsAsmPrinter::EmitFunctionBodyEnd() { // There are instruction for this macros, but they must // always be at the function end, and we can't emit and // break with BB logic. - OutStreamer.EmitRawText(StringRef("\t.set\tmacro")); - OutStreamer.EmitRawText(StringRef("\t.set\treorder")); - OutStreamer.EmitRawText("\t.end\t" + Twine(CurrentFnSym->getName())); + if (OutStreamer.hasRawTextSupport()) { + OutStreamer.EmitRawText(StringRef("\t.set\tmacro")); + OutStreamer.EmitRawText(StringRef("\t.set\treorder")); + OutStreamer.EmitRawText("\t.end\t" + Twine(CurrentFnSym->getName())); + } } - /// isBlockOnlyReachableByFallthough - Return true if the basic block has /// exactly one predecessor and the control transfer mechanism between /// the predecessor and this block is a fall-through. @@ -277,9 +315,9 @@ bool MipsAsmPrinter::isBlockOnlyReachableByFallthrough(const MachineBasicBlock* // Otherwise, check the last instruction. // Check if the last terminator is an unconditional branch. MachineBasicBlock::const_iterator I = Pred->end(); - while (I != Pred->begin() && !(--I)->getDesc().isTerminator()) ; + while (I != Pred->begin() && !(--I)->isTerminator()) ; - return !I->getDesc().isBarrier(); + return !I->isBarrier(); } // Print out an operand for an inline asm expression. @@ -335,7 +373,7 @@ void MipsAsmPrinter::printOperand(const MachineInstr *MI, int opNum, switch (MO.getType()) { case MachineOperand::MO_Register: O << '$' - << LowercaseString(MipsInstPrinter::getRegisterName(MO.getReg())); + << StringRef(MipsInstPrinter::getRegisterName(MO.getReg())).lower(); break; case MachineOperand::MO_Immediate: @@ -420,18 +458,22 @@ void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) { // FIXME: Use SwitchSection. // Tell the assembler which ABI we are using - OutStreamer.EmitRawText("\t.section .mdebug." + Twine(getCurrentABIString())); + if (OutStreamer.hasRawTextSupport()) + OutStreamer.EmitRawText("\t.section .mdebug." + Twine(getCurrentABIString())); // TODO: handle O64 ABI - if (Subtarget->isABI_EABI()) { - if (Subtarget->isGP32bit()) - OutStreamer.EmitRawText(StringRef("\t.section .gcc_compiled_long32")); - else - OutStreamer.EmitRawText(StringRef("\t.section .gcc_compiled_long64")); + if (OutStreamer.hasRawTextSupport()) { + if (Subtarget->isABI_EABI()) { + if (Subtarget->isGP32bit()) + OutStreamer.EmitRawText(StringRef("\t.section .gcc_compiled_long32")); + else + OutStreamer.EmitRawText(StringRef("\t.section .gcc_compiled_long64")); + } } // return to previous section - OutStreamer.EmitRawText(StringRef("\t.previous")); + if (OutStreamer.hasRawTextSupport()) + OutStreamer.EmitRawText(StringRef("\t.previous")); } MachineLocation diff --git a/lib/Target/Mips/MipsAsmPrinter.h b/lib/Target/Mips/MipsAsmPrinter.h index 16461ff..f0c6626 100644 --- a/lib/Target/Mips/MipsAsmPrinter.h +++ b/lib/Target/Mips/MipsAsmPrinter.h @@ -27,9 +27,11 @@ class MachineBasicBlock; class Module; class LLVM_LIBRARY_VISIBILITY MipsAsmPrinter : public AsmPrinter { - const MipsSubtarget *Subtarget; - + public: + + const MipsSubtarget *Subtarget; + explicit MipsAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) : AsmPrinter(TM, Streamer) { Subtarget = &TM.getSubtarget<MipsSubtarget>(); diff --git a/lib/Target/Mips/MipsCallingConv.td b/lib/Target/Mips/MipsCallingConv.td index 0ae4ef6..3d973ce 100644 --- a/lib/Target/Mips/MipsCallingConv.td +++ b/lib/Target/Mips/MipsCallingConv.td @@ -35,8 +35,9 @@ def RetCC_MipsO32 : CallingConv<[ //===----------------------------------------------------------------------===// def CC_MipsN : CallingConv<[ - // FIXME: Handle byval, complex and float double parameters. - + // Handles byval parameters. + CCIfByVal<CCCustom<"CC_Mips64Byval">>, + // Promote i8/i16/i32 arguments to i64. CCIfType<[i8, i16, i32], CCPromoteToType<i64>>, @@ -63,6 +64,25 @@ def CC_MipsN : CallingConv<[ CCIfType<[f32], CCAssignToStack<4, 8>> ]>; +// N32/64 variable arguments. +// All arguments are passed in integer registers. +def CC_MipsN_VarArg : CallingConv<[ + // Handles byval parameters. + CCIfByVal<CCCustom<"CC_Mips64Byval">>, + + // Promote i8/i16/i32 arguments to i64. + CCIfType<[i8, i16, i32], CCPromoteToType<i64>>, + + CCIfType<[i64, f64], CCAssignToReg<[A0_64, A1_64, A2_64, A3_64, + T0_64, T1_64, T2_64, T3_64]>>, + + CCIfType<[f32], CCAssignToReg<[A0, A1, A2, A3, T0, T1, T2, T3]>>, + + // 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. diff --git a/lib/Target/Mips/MipsCodeEmitter.cpp b/lib/Target/Mips/MipsCodeEmitter.cpp index 23fabe3..6b26e24 100644 --- a/lib/Target/Mips/MipsCodeEmitter.cpp +++ b/lib/Target/Mips/MipsCodeEmitter.cpp @@ -18,18 +18,20 @@ #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 "MCTargetDesc/MipsBaseInfo.h" +#include "llvm/ADT/Statistic.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/MachineOperand.h" #include "llvm/CodeGen/Passes.h" -#include "llvm/ADT/Statistic.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/PassManager.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" @@ -37,8 +39,6 @@ #include <iomanip> #endif -#include "llvm/CodeGen/MachineOperand.h" - using namespace llvm; STATISTIC(NumEmitted, "Number of machine instructions emitted"); @@ -66,9 +66,9 @@ class MipsCodeEmitter : public MachineFunctionPass { 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_) { + 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); @@ -91,7 +91,7 @@ class MipsCodeEmitter : public MachineFunctionPass { /// 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; + 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; @@ -105,9 +105,21 @@ class MipsCodeEmitter : public MachineFunctionPass { unsigned getRelocation(const MachineInstr &MI, const MachineOperand &MO) const; + unsigned getJumpTargetOpValue(const MachineInstr &MI, unsigned OpNo) const; + + unsigned getBranchTargetOpValue(const MachineInstr &MI, unsigned OpNo) const; unsigned getMemEncoding(const MachineInstr &MI, unsigned OpNo) const; unsigned getSizeExtEncoding(const MachineInstr &MI, unsigned OpNo) const; unsigned getSizeInsEncoding(const MachineInstr &MI, unsigned OpNo) const; + + int emitULW(const MachineInstr &MI); + int emitUSW(const MachineInstr &MI); + int emitULH(const MachineInstr &MI); + int emitULHu(const MachineInstr &MI); + int emitUSH(const MachineInstr &MI); + + void emitGlobalAddressUnaligned(const GlobalValue *GV, unsigned Reloc, + int Offset) const; }; } @@ -132,7 +144,7 @@ bool MipsCodeEmitter::runOnMachineFunction(MachineFunction &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(); + for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); I != E; ++I) emitInstruction(*I); } @@ -149,30 +161,41 @@ unsigned MipsCodeEmitter::getRelocation(const MachineInstr &MI, if (Form == MipsII::FrmJ) return Mips::reloc_mips_26; if ((Form == MipsII::FrmI || Form == MipsII::FrmFI) - && MI.getDesc().isBranch()) + && MI.isBranch()) return Mips::reloc_mips_branch; if (Form == MipsII::FrmI && MI.getOpcode() == Mips::LUi) return Mips::reloc_mips_hi; return Mips::reloc_mips_lo; } +unsigned MipsCodeEmitter::getJumpTargetOpValue(const MachineInstr &MI, + unsigned OpNo) const { + // FIXME: implement + return 0; +} + +unsigned MipsCodeEmitter::getBranchTargetOpValue(const MachineInstr &MI, + unsigned OpNo) const { + // FIXME: implement + return 0; +} + unsigned MipsCodeEmitter::getMemEncoding(const MachineInstr &MI, - unsigned OpNo) const { + unsigned OpNo) const { // Base register is encoded in bits 20-16, offset is encoded in bits 15-0. assert(MI.getOperand(OpNo).isReg()); unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo)) << 16; - return - (getMachineOpValue(MI, MI.getOperand(OpNo+1)) & 0xFFFF) | RegBits; + return (getMachineOpValue(MI, MI.getOperand(OpNo+1)) & 0xFFFF) | RegBits; } unsigned MipsCodeEmitter::getSizeExtEncoding(const MachineInstr &MI, - unsigned OpNo) const { + unsigned OpNo) const { // size is encoded as size-1. return getMachineOpValue(MI, MI.getOperand(OpNo)) - 1; } unsigned MipsCodeEmitter::getSizeInsEncoding(const MachineInstr &MI, - unsigned OpNo) const { + unsigned OpNo) const { // size is encoded as pos+size-1. return getMachineOpValue(MI, MI.getOperand(OpNo-1)) + getMachineOpValue(MI, MI.getOperand(OpNo)) - 1; @@ -181,14 +204,20 @@ unsigned MipsCodeEmitter::getSizeInsEncoding(const MachineInstr &MI, /// 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 { + 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()) + else if (MO.isGlobal()) { + if (MI.getOpcode() == Mips::ULW || MI.getOpcode() == Mips::USW || + MI.getOpcode() == Mips::ULH || MI.getOpcode() == Mips::ULHu) + emitGlobalAddressUnaligned(MO.getGlobal(), getRelocation(MI, MO), 4); + else if (MI.getOpcode() == Mips::USH) + emitGlobalAddressUnaligned(MO.getGlobal(), getRelocation(MI, MO), 8); + else + 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)); @@ -202,9 +231,18 @@ unsigned MipsCodeEmitter::getMachineOpValue(const MachineInstr &MI, } void MipsCodeEmitter::emitGlobalAddress(const GlobalValue *GV, unsigned Reloc, - bool MayNeedFarStub) const { + bool MayNeedFarStub) const { + MCE.addRelocation(MachineRelocation::getGV(MCE.getCurrentPCOffset(), Reloc, + const_cast<GlobalValue *>(GV), 0, + MayNeedFarStub)); +} + +void MipsCodeEmitter::emitGlobalAddressUnaligned(const GlobalValue *GV, + unsigned Reloc, int Offset) const { MCE.addRelocation(MachineRelocation::getGV(MCE.getCurrentPCOffset(), Reloc, - const_cast<GlobalValue *>(GV), 0, MayNeedFarStub)); + const_cast<GlobalValue *>(GV), 0, false)); + MCE.addRelocation(MachineRelocation::getGV(MCE.getCurrentPCOffset() + Offset, + Reloc, const_cast<GlobalValue *>(GV), 0, false)); } void MipsCodeEmitter:: @@ -225,11 +263,108 @@ emitJumpTableAddress(unsigned JTIndex, unsigned Reloc) const { } void MipsCodeEmitter::emitMachineBasicBlock(MachineBasicBlock *BB, - unsigned Reloc) const { + unsigned Reloc) const { MCE.addRelocation(MachineRelocation::getBB(MCE.getCurrentPCOffset(), Reloc, BB)); } +int MipsCodeEmitter::emitUSW(const MachineInstr &MI) { + unsigned src = getMachineOpValue(MI, MI.getOperand(0)); + unsigned base = getMachineOpValue(MI, MI.getOperand(1)); + unsigned offset = getMachineOpValue(MI, MI.getOperand(2)); + // swr src, offset(base) + // swl src, offset+3(base) + MCE.emitWordLE( + (0x2e << 26) | (base << 21) | (src << 16) | (offset & 0xffff)); + MCE.emitWordLE( + (0x2a << 26) | (base << 21) | (src << 16) | ((offset+3) & 0xffff)); + return 2; +} + +int MipsCodeEmitter::emitULW(const MachineInstr &MI) { + unsigned dst = getMachineOpValue(MI, MI.getOperand(0)); + unsigned base = getMachineOpValue(MI, MI.getOperand(1)); + unsigned offset = getMachineOpValue(MI, MI.getOperand(2)); + unsigned at = 1; + if (dst != base) { + // lwr dst, offset(base) + // lwl dst, offset+3(base) + MCE.emitWordLE( + (0x26 << 26) | (base << 21) | (dst << 16) | (offset & 0xffff)); + MCE.emitWordLE( + (0x22 << 26) | (base << 21) | (dst << 16) | ((offset+3) & 0xffff)); + return 2; + } else { + // lwr at, offset(base) + // lwl at, offset+3(base) + // addu dst, at, $zero + MCE.emitWordLE( + (0x26 << 26) | (base << 21) | (at << 16) | (offset & 0xffff)); + MCE.emitWordLE( + (0x22 << 26) | (base << 21) | (at << 16) | ((offset+3) & 0xffff)); + MCE.emitWordLE( + (0x0 << 26) | (at << 21) | (0x0 << 16) | (dst << 11) | (0x0 << 6) | 0x21); + return 3; + } +} + +int MipsCodeEmitter::emitUSH(const MachineInstr &MI) { + unsigned src = getMachineOpValue(MI, MI.getOperand(0)); + unsigned base = getMachineOpValue(MI, MI.getOperand(1)); + unsigned offset = getMachineOpValue(MI, MI.getOperand(2)); + unsigned at = 1; + // sb src, offset(base) + // srl at,src,8 + // sb at, offset+1(base) + MCE.emitWordLE( + (0x28 << 26) | (base << 21) | (src << 16) | (offset & 0xffff)); + MCE.emitWordLE( + (0x0 << 26) | (0x0 << 21) | (src << 16) | (at << 11) | (0x8 << 6) | 0x2); + MCE.emitWordLE( + (0x28 << 26) | (base << 21) | (at << 16) | ((offset+1) & 0xffff)); + return 3; +} + +int MipsCodeEmitter::emitULH(const MachineInstr &MI) { + unsigned dst = getMachineOpValue(MI, MI.getOperand(0)); + unsigned base = getMachineOpValue(MI, MI.getOperand(1)); + unsigned offset = getMachineOpValue(MI, MI.getOperand(2)); + unsigned at = 1; + // lbu at, offset(base) + // lb dst, offset+1(base) + // sll dst,dst,8 + // or dst,dst,at + MCE.emitWordLE( + (0x24 << 26) | (base << 21) | (at << 16) | (offset & 0xffff)); + MCE.emitWordLE( + (0x20 << 26) | (base << 21) | (dst << 16) | ((offset+1) & 0xffff)); + MCE.emitWordLE( + (0x0 << 26) | (0x0 << 21) | (dst << 16) | (dst << 11) | (0x8 << 6) | 0x0); + MCE.emitWordLE( + (0x0 << 26) | (dst << 21) | (at << 16) | (dst << 11) | (0x0 << 6) | 0x25); + return 4; +} + +int MipsCodeEmitter::emitULHu(const MachineInstr &MI) { + unsigned dst = getMachineOpValue(MI, MI.getOperand(0)); + unsigned base = getMachineOpValue(MI, MI.getOperand(1)); + unsigned offset = getMachineOpValue(MI, MI.getOperand(2)); + unsigned at = 1; + // lbu at, offset(base) + // lbu dst, offset+1(base) + // sll dst,dst,8 + // or dst,dst,at + MCE.emitWordLE( + (0x24 << 26) | (base << 21) | (at << 16) | (offset & 0xffff)); + MCE.emitWordLE( + (0x24 << 26) | (base << 21) | (dst << 16) | ((offset+1) & 0xffff)); + MCE.emitWordLE( + (0x0 << 26) | (0x0 << 21) | (dst << 16) | (dst << 11) | (0x8 << 6) | 0x0); + MCE.emitWordLE( + (0x0 << 26) | (dst << 21) | (at << 16) | (dst << 11) | (0x0 << 6) | 0x25); + return 4; +} + void MipsCodeEmitter::emitInstruction(const MachineInstr &MI) { DEBUG(errs() << "JIT: " << (void*)MCE.getCurrentPCValue() << ":\t" << MI); @@ -239,11 +374,27 @@ void MipsCodeEmitter::emitInstruction(const MachineInstr &MI) { if ((MI.getDesc().TSFlags & MipsII::FormMask) == MipsII::Pseudo) return; - ++NumEmitted; // Keep track of the # of mi's emitted switch (MI.getOpcode()) { + case Mips::USW: + NumEmitted += emitUSW(MI); + break; + case Mips::ULW: + NumEmitted += emitULW(MI); + break; + case Mips::ULH: + NumEmitted += emitULH(MI); + break; + case Mips::ULHu: + NumEmitted += emitULHu(MI); + break; + case Mips::USH: + NumEmitted += emitUSH(MI); + break; + default: emitWordLE(getBinaryCodeForInstr(MI)); + ++NumEmitted; // Keep track of the # of mi's emitted break; } @@ -259,7 +410,7 @@ void MipsCodeEmitter::emitWordLE(unsigned Word) { /// createMipsJITCodeEmitterPass - Return a pass that emits the collected Mips /// code to the specified MCE object. FunctionPass *llvm::createMipsJITCodeEmitterPass(MipsTargetMachine &TM, - JITCodeEmitter &JCE) { + JITCodeEmitter &JCE) { return new MipsCodeEmitter(TM, JCE); } diff --git a/lib/Target/Mips/MipsDelaySlotFiller.cpp b/lib/Target/Mips/MipsDelaySlotFiller.cpp index be3b7a0..1d9e9b0 100644 --- a/lib/Target/Mips/MipsDelaySlotFiller.cpp +++ b/lib/Target/Mips/MipsDelaySlotFiller.cpp @@ -96,7 +96,7 @@ runOnMachineBasicBlock(MachineBasicBlock &MBB) { LastFiller = MBB.end(); for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I) - if (I->getDesc().hasDelaySlot()) { + if (I->hasDelaySlot()) { ++FilledSlots; Changed = true; @@ -146,7 +146,7 @@ bool Filler::findDelayInstr(MachineBasicBlock &MBB, || I->isInlineAsm() || I->isLabel() || FI == LastFiller - || I->getDesc().isPseudo() + || I->isPseudo() // // Should not allow: // ERET, DERET or WAIT, PAUSE. Need to add these to instruction @@ -174,16 +174,15 @@ bool Filler::delayHasHazard(MachineBasicBlock::iterator candidate, 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 (candidate->mayLoad()) { if (sawStore) return true; sawLoad = true; } - if (MCID.mayStore()) { + if (candidate->mayStore()) { if (sawStore) return true; sawStore = true; @@ -191,7 +190,7 @@ bool Filler::delayHasHazard(MachineBasicBlock::iterator candidate, return true; } - assert((!MCID.isCall() && !MCID.isReturn()) && + assert((!candidate->isCall() && !candidate->isReturn()) && "Cannot put calls or returns in delay slot."); for (unsigned i = 0, e = candidate->getNumOperands(); i!= e; ++i) { @@ -221,11 +220,11 @@ void Filler::insertDefsUses(MachineBasicBlock::iterator MI, 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(); + unsigned e = MI->isCall() || MI->isReturn() ? MCID.getNumOperands() : + MI->getNumOperands(); // Add RA to RegDefs to prevent users of RA from going into delay slot. - if (MCID.isCall()) + if (MI->isCall()) RegDefs.insert(Mips::RA); for (unsigned i = 0; i != e; ++i) { diff --git a/lib/Target/Mips/MipsFrameLowering.cpp b/lib/Target/Mips/MipsFrameLowering.cpp index 22d1e47..2466545 100644 --- a/lib/Target/Mips/MipsFrameLowering.cpp +++ b/lib/Target/Mips/MipsFrameLowering.cpp @@ -14,6 +14,7 @@ #include "MipsFrameLowering.h" #include "MipsInstrInfo.h" #include "MipsMachineFunction.h" +#include "MCTargetDesc/MipsBaseInfo.h" #include "llvm/Function.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" @@ -84,8 +85,8 @@ using namespace llvm; // if frame pointer elimination is disabled. bool MipsFrameLowering::hasFP(const MachineFunction &MF) const { const MachineFrameInfo *MFI = MF.getFrameInfo(); - return DisableFramePointerElim(MF) || MFI->hasVarSizedObjects() - || MFI->isFrameAddressTaken(); + return MF.getTarget().Options.DisableFramePointerElim(MF) || + MFI->hasVarSizedObjects() || MFI->isFrameAddressTaken(); } bool MipsFrameLowering::targetHandlesStackFrameRounding() const { @@ -149,6 +150,14 @@ void MipsFrameLowering::emitPrologue(MachineFunction &MF) const { unsigned NewReg = 0; int NewImm = 0; bool ATUsed; + unsigned GP = STI.isABI_N64() ? Mips::GP_64 : Mips::GP; + unsigned T9 = STI.isABI_N64() ? Mips::T9_64 : Mips::T9; + unsigned SP = STI.isABI_N64() ? Mips::SP_64 : Mips::SP; + unsigned FP = STI.isABI_N64() ? Mips::FP_64 : Mips::FP; + unsigned ZERO = STI.isABI_N64() ? Mips::ZERO_64 : Mips::ZERO; + unsigned ADDu = STI.isABI_N64() ? Mips::DADDu : Mips::ADDu; + unsigned ADDiu = STI.isABI_N64() ? Mips::DADDiu : Mips::ADDiu; + unsigned LUi = STI.isABI_N64() ? Mips::LUi64 : Mips::LUi; // First, compute final stack size. unsigned RegSize = STI.isGP32bit() ? 4 : 8; @@ -163,12 +172,26 @@ void MipsFrameLowering::emitPrologue(MachineFunction &MF) const { MFI->setStackSize(StackSize); BuildMI(MBB, MBBI, dl, TII.get(Mips::NOREORDER)); + BuildMI(MBB, MBBI, dl, TII.get(Mips::NOMACRO)); - // TODO: check need from GP here. + // Emit instructions that set $gp using the the value of $t9. + // O32 uses the directive .cpload while N32/64 requires three instructions to + // do this. + // TODO: Do not emit these instructions if no instructions use $gp. if (isPIC && STI.isABI_O32()) - BuildMI(MBB, MBBI, dl, TII.get(Mips::CPLOAD)) + BuildMI(MBB, llvm::prior(MBBI), dl, TII.get(Mips::CPLOAD)) .addReg(RegInfo->getPICCallReg()); - BuildMI(MBB, MBBI, dl, TII.get(Mips::NOMACRO)); + else if (STI.isABI_N64() || (isPIC && STI.isABI_N32())) { + // lui $28,%hi(%neg(%gp_rel(fname))) + // addu $28,$28,$25 + // addiu $28,$28,%lo(%neg(%gp_rel(fname))) + const GlobalValue *FName = MF.getFunction(); + BuildMI(MBB, MBBI, dl, TII.get(LUi), GP) + .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_HI); + BuildMI(MBB, MBBI, dl, TII.get(ADDu), GP).addReg(GP).addReg(T9); + BuildMI(MBB, MBBI, dl, TII.get(ADDiu), GP).addReg(GP) + .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_LO); + } // No need to allocate space on the stack. if (StackSize == 0 && !MFI->adjustsStack()) return; @@ -178,10 +201,8 @@ void MipsFrameLowering::emitPrologue(MachineFunction &MF) const { MachineLocation DstML, SrcML; // Adjust stack : addi sp, sp, (-imm) - ATUsed = expandRegLargeImmPair(Mips::SP, -StackSize, NewReg, NewImm, MBB, - MBBI); - BuildMI(MBB, MBBI, dl, TII.get(Mips::ADDiu), Mips::SP) - .addReg(NewReg).addImm(NewImm); + ATUsed = expandRegLargeImmPair(SP, -StackSize, NewReg, NewImm, MBB, MBBI); + BuildMI(MBB, MBBI, dl, TII.get(ADDiu), SP).addReg(NewReg).addImm(NewImm); // FIXME: change this when mips goes MC". if (ATUsed) @@ -241,14 +262,13 @@ void MipsFrameLowering::emitPrologue(MachineFunction &MF) const { // if framepointer enabled, set it to point to the stack pointer. if (hasFP(MF)) { // Insert instruction "move $fp, $sp" at this location. - BuildMI(MBB, MBBI, dl, TII.get(Mips::ADDu), Mips::FP) - .addReg(Mips::SP).addReg(Mips::ZERO); + BuildMI(MBB, MBBI, dl, TII.get(ADDu), FP).addReg(SP).addReg(ZERO); // emit ".cfi_def_cfa_register $fp" MCSymbol *SetFPLabel = MMI.getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::PROLOG_LABEL)).addSym(SetFPLabel); - DstML = MachineLocation(Mips::FP); + DstML = MachineLocation(FP); SrcML = MachineLocation(MachineLocation::VirtualFP); Moves.push_back(MachineMove(SetFPLabel, DstML, SrcML)); } @@ -272,6 +292,11 @@ void MipsFrameLowering::emitEpilogue(MachineFunction &MF, const MipsInstrInfo &TII = *static_cast<const MipsInstrInfo*>(MF.getTarget().getInstrInfo()); DebugLoc dl = MBBI->getDebugLoc(); + unsigned SP = STI.isABI_N64() ? Mips::SP_64 : Mips::SP; + unsigned FP = STI.isABI_N64() ? Mips::FP_64 : Mips::FP; + unsigned ZERO = STI.isABI_N64() ? Mips::ZERO_64 : Mips::ZERO; + unsigned ADDu = STI.isABI_N64() ? Mips::DADDu : Mips::ADDu; + unsigned ADDiu = STI.isABI_N64() ? Mips::DADDiu : Mips::ADDiu; // Get the number of bytes from FrameInfo unsigned StackSize = MFI->getStackSize(); @@ -289,16 +314,13 @@ void MipsFrameLowering::emitEpilogue(MachineFunction &MF, --I; // Insert instruction "move $sp, $fp" at this location. - BuildMI(MBB, I, dl, TII.get(Mips::ADDu), Mips::SP) - .addReg(Mips::FP).addReg(Mips::ZERO); + BuildMI(MBB, I, dl, TII.get(ADDu), SP).addReg(FP).addReg(ZERO); } // adjust stack : insert addi sp, sp, (imm) if (StackSize) { - ATUsed = expandRegLargeImmPair(Mips::SP, StackSize, NewReg, NewImm, MBB, - MBBI); - BuildMI(MBB, MBBI, dl, TII.get(Mips::ADDiu), Mips::SP) - .addReg(NewReg).addImm(NewImm); + ATUsed = expandRegLargeImmPair(SP, StackSize, NewReg, NewImm, MBB, MBBI); + BuildMI(MBB, MBBI, dl, TII.get(ADDiu), SP).addReg(NewReg).addImm(NewImm); // FIXME: change this when mips goes MC". if (ATUsed) @@ -310,13 +332,15 @@ void MipsFrameLowering:: processFunctionBeforeCalleeSavedScan(MachineFunction &MF, RegScavenger *RS) const { MachineRegisterInfo& MRI = MF.getRegInfo(); + unsigned RA = STI.isABI_N64() ? Mips::RA_64 : Mips::RA; + unsigned FP = STI.isABI_N64() ? Mips::FP_64 : Mips::FP; // FIXME: remove this code if register allocator can correctly mark // $fp and $ra used or unused. // Mark $fp and $ra as used or unused. if (hasFP(MF)) - MRI.setPhysRegUsed(Mips::FP); + MRI.setPhysRegUsed(FP); // The register allocator might determine $ra is used after seeing // instruction "jr $ra", but we do not want PrologEpilogInserter to insert @@ -324,7 +348,7 @@ processFunctionBeforeCalleeSavedScan(MachineFunction &MF, // To correct this, $ra is explicitly marked unused if there is no // function call. if (MF.getFrameInfo()->hasCalls()) - MRI.setPhysRegUsed(Mips::RA); + MRI.setPhysRegUsed(RA); else - MRI.setPhysRegUnused(Mips::RA); + MRI.setPhysRegUnused(RA); } diff --git a/lib/Target/Mips/MipsISelDAGToDAG.cpp b/lib/Target/Mips/MipsISelDAGToDAG.cpp index 9c831ed..b17239d 100644 --- a/lib/Target/Mips/MipsISelDAGToDAG.cpp +++ b/lib/Target/Mips/MipsISelDAGToDAG.cpp @@ -86,10 +86,9 @@ private: // Complex Pattern. bool SelectAddr(SDValue N, SDValue &Base, SDValue &Offset); - // getI32Imm - Return a target constant with the specified - // value, of type i32. - inline SDValue getI32Imm(unsigned Imm) { - return CurDAG->getTargetConstant(Imm, MVT::i32); + // getImm - Return a target constant with the specified value. + inline SDValue getImm(const SDNode *Node, unsigned Imm) { + return CurDAG->getTargetConstant(Imm, Node->getValueType(0)); } virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op, @@ -122,21 +121,16 @@ SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset) { } // on PIC code Load GA - if (TM.getRelocationModel() == Reloc::PIC_) { - if (Addr.getOpcode() == MipsISD::WrapperPIC) { - Base = CurDAG->getRegister(GPReg, ValTy); - Offset = Addr.getOperand(0); - return true; - } - } else { + if (Addr.getOpcode() == MipsISD::Wrapper) { + Base = CurDAG->getRegister(GPReg, ValTy); + Offset = Addr.getOperand(0); + return true; + } + + if (TM.getRelocationModel() != Reloc::PIC_) { if ((Addr.getOpcode() == ISD::TargetExternalSymbol || Addr.getOpcode() == ISD::TargetGlobalAddress)) return false; - else if (Addr.getOpcode() == ISD::TargetGlobalTLSAddress) { - Base = CurDAG->getRegister(GPReg, ValTy); - Offset = Addr; - return true; - } } // Addresses of the form FI+const or FI|const @@ -310,13 +304,24 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) { } case MipsISD::ThreadPointer: { - unsigned SrcReg = Mips::HWR29; - unsigned DestReg = Mips::V1; - SDNode *Rdhwr = CurDAG->getMachineNode(Mips::RDHWR, Node->getDebugLoc(), - Node->getValueType(0), CurDAG->getRegister(SrcReg, MVT::i32)); + EVT PtrVT = TLI.getPointerTy(); + unsigned RdhwrOpc, SrcReg, DestReg; + + if (PtrVT == MVT::i32) { + RdhwrOpc = Mips::RDHWR; + SrcReg = Mips::HWR29; + DestReg = Mips::V1; + } else { + RdhwrOpc = Mips::RDHWR64; + SrcReg = Mips::HWR29_64; + DestReg = Mips::V1_64; + } + + SDNode *Rdhwr = CurDAG->getMachineNode(RdhwrOpc, Node->getDebugLoc(), + Node->getValueType(0), CurDAG->getRegister(SrcReg, PtrVT)); SDValue Chain = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, DestReg, SDValue(Rdhwr, 0)); - SDValue ResNode = CurDAG->getCopyFromReg(Chain, dl, DestReg, MVT::i32); + SDValue ResNode = CurDAG->getCopyFromReg(Chain, dl, DestReg, PtrVT); ReplaceUses(SDValue(Node, 0), ResNode); return ResNode.getNode(); } diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index 5271332..c9b657c 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -24,6 +24,7 @@ #include "llvm/Intrinsics.h" #include "llvm/CallingConv.h" #include "InstPrinter/MipsInstPrinter.h" +#include "MCTargetDesc/MipsBaseInfo.h" #include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" @@ -39,11 +40,11 @@ using namespace llvm; // 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)) + if (!isShiftedMask_64(I)) return false; - Size = CountPopulation_32(I); - Pos = CountTrailingZeros_32(I); + Size = CountPopulation_64(I); + Pos = CountTrailingZeros_64(I); return true; } @@ -53,9 +54,6 @@ const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const { case MipsISD::Hi: return "MipsISD::Hi"; case MipsISD::Lo: return "MipsISD::Lo"; case MipsISD::GPRel: return "MipsISD::GPRel"; - case MipsISD::TlsGd: return "MipsISD::TlsGd"; - case MipsISD::TprelHi: return "MipsISD::TprelHi"; - case MipsISD::TprelLo: return "MipsISD::TprelLo"; case MipsISD::ThreadPointer: return "MipsISD::ThreadPointer"; case MipsISD::Ret: return "MipsISD::Ret"; case MipsISD::FPBrcond: return "MipsISD::FPBrcond"; @@ -71,7 +69,7 @@ const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const { case MipsISD::DivRemU: return "MipsISD::DivRemU"; case MipsISD::BuildPairF64: return "MipsISD::BuildPairF64"; case MipsISD::ExtractElementF64: return "MipsISD::ExtractElementF64"; - case MipsISD::WrapperPIC: return "MipsISD::WrapperPIC"; + case MipsISD::Wrapper: return "MipsISD::Wrapper"; case MipsISD::DynAlloc: return "MipsISD::DynAlloc"; case MipsISD::Sync: return "MipsISD::Sync"; case MipsISD::Ext: return "MipsISD::Ext"; @@ -84,7 +82,8 @@ MipsTargetLowering:: MipsTargetLowering(MipsTargetMachine &TM) : TargetLowering(TM, new MipsTargetObjectFile()), Subtarget(&TM.getSubtarget<MipsSubtarget>()), - HasMips64(Subtarget->hasMips64()), IsN64(Subtarget->isABI_N64()) { + HasMips64(Subtarget->hasMips64()), IsN64(Subtarget->isABI_N64()), + IsO32(Subtarget->isABI_O32()) { // Mips does not have i1 type, so use i32 for // setcc operations results (slt, sgt, ...). @@ -125,9 +124,13 @@ MipsTargetLowering(MipsTargetMachine &TM) setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); setOperationAction(ISD::GlobalAddress, MVT::i64, Custom); setOperationAction(ISD::BlockAddress, MVT::i32, Custom); + setOperationAction(ISD::BlockAddress, MVT::i64, Custom); setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom); + setOperationAction(ISD::GlobalTLSAddress, MVT::i64, Custom); setOperationAction(ISD::JumpTable, MVT::i32, Custom); + setOperationAction(ISD::JumpTable, MVT::i64, Custom); setOperationAction(ISD::ConstantPool, MVT::i32, Custom); + setOperationAction(ISD::ConstantPool, MVT::i64, Custom); setOperationAction(ISD::SELECT, MVT::f32, Custom); setOperationAction(ISD::SELECT, MVT::f64, Custom); setOperationAction(ISD::SELECT, MVT::i32, Custom); @@ -153,6 +156,10 @@ MipsTargetLowering(MipsTargetMachine &TM) setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); setOperationAction(ISD::CTPOP, MVT::i32, Expand); setOperationAction(ISD::CTTZ, MVT::i32, Expand); + setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i32, Expand); + setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i64, Expand); + setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i32, Expand); + setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i64, Expand); setOperationAction(ISD::ROTL, MVT::i32, Expand); setOperationAction(ISD::ROTL, MVT::i64, Expand); @@ -394,7 +401,8 @@ static SDValue PerformADDECombine(SDNode *N, SelectionDAG& DAG, if (DCI.isBeforeLegalize()) return SDValue(); - if (Subtarget->hasMips32() && SelectMadd(N, &DAG)) + if (Subtarget->hasMips32() && N->getValueType(0) == MVT::i32 && + SelectMadd(N, &DAG)) return SDValue(N, 0); return SDValue(); @@ -406,7 +414,8 @@ static SDValue PerformSUBECombine(SDNode *N, SelectionDAG& DAG, if (DCI.isBeforeLegalize()) return SDValue(); - if (Subtarget->hasMips32() && SelectMsub(N, &DAG)) + if (Subtarget->hasMips32() && N->getValueType(0) == MVT::i32 && + SelectMsub(N, &DAG)) return SDValue(N, 0); return SDValue(); @@ -549,20 +558,20 @@ static SDValue PerformANDCombine(SDNode *N, SelectionDAG& DAG, return SDValue(); SDValue ShiftRight = N->getOperand(0), Mask = N->getOperand(1); - + unsigned ShiftRightOpc = ShiftRight.getOpcode(); + // Op's first operand must be a shift right. - if (ShiftRight.getOpcode() != ISD::SRA && ShiftRight.getOpcode() != ISD::SRL) + if (ShiftRightOpc != ISD::SRA && ShiftRightOpc != 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 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)) @@ -570,10 +579,11 @@ static SDValue PerformANDCombine(SDNode *N, SelectionDAG& DAG, // 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) + EVT ValTy = N->getValueType(0); + if (SMPos != 0 || Pos + SMSize > ValTy.getSizeInBits()) return SDValue(); - return DAG.getNode(MipsISD::Ext, N->getDebugLoc(), MVT::i32, + return DAG.getNode(MipsISD::Ext, N->getDebugLoc(), ValTy, ShiftRight.getOperand(0), DAG.getConstant(Pos, MVT::i32), DAG.getConstant(SMSize, MVT::i32)); @@ -624,10 +634,11 @@ static SDValue PerformORCombine(SDNode *N, SelectionDAG& DAG, // Return if the shift amount and the first bit position of mask are not the // same. - if (Shamt != SMPos0) + EVT ValTy = N->getValueType(0); + if ((Shamt != SMPos0) || (SMPos0 + SMSize0 > ValTy.getSizeInBits())) return SDValue(); - return DAG.getNode(MipsISD::Ins, N->getDebugLoc(), MVT::i32, + return DAG.getNode(MipsISD::Ins, N->getDebugLoc(), ValTy, Shl.getOperand(0), DAG.getConstant(SMPos0, MVT::i32), DAG.getConstant(SMSize0, MVT::i32), @@ -793,60 +804,108 @@ MipsTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, assert(false && "Unexpected instr type to insert"); return NULL; case Mips::ATOMIC_LOAD_ADD_I8: + case Mips::ATOMIC_LOAD_ADD_I8_P8: return EmitAtomicBinaryPartword(MI, BB, 1, Mips::ADDu); case Mips::ATOMIC_LOAD_ADD_I16: + case Mips::ATOMIC_LOAD_ADD_I16_P8: return EmitAtomicBinaryPartword(MI, BB, 2, Mips::ADDu); case Mips::ATOMIC_LOAD_ADD_I32: + case Mips::ATOMIC_LOAD_ADD_I32_P8: return EmitAtomicBinary(MI, BB, 4, Mips::ADDu); + case Mips::ATOMIC_LOAD_ADD_I64: + case Mips::ATOMIC_LOAD_ADD_I64_P8: + return EmitAtomicBinary(MI, BB, 8, Mips::DADDu); case Mips::ATOMIC_LOAD_AND_I8: + case Mips::ATOMIC_LOAD_AND_I8_P8: return EmitAtomicBinaryPartword(MI, BB, 1, Mips::AND); case Mips::ATOMIC_LOAD_AND_I16: + case Mips::ATOMIC_LOAD_AND_I16_P8: return EmitAtomicBinaryPartword(MI, BB, 2, Mips::AND); case Mips::ATOMIC_LOAD_AND_I32: + case Mips::ATOMIC_LOAD_AND_I32_P8: return EmitAtomicBinary(MI, BB, 4, Mips::AND); + case Mips::ATOMIC_LOAD_AND_I64: + case Mips::ATOMIC_LOAD_AND_I64_P8: + return EmitAtomicBinary(MI, BB, 8, Mips::AND64); case Mips::ATOMIC_LOAD_OR_I8: + case Mips::ATOMIC_LOAD_OR_I8_P8: return EmitAtomicBinaryPartword(MI, BB, 1, Mips::OR); case Mips::ATOMIC_LOAD_OR_I16: + case Mips::ATOMIC_LOAD_OR_I16_P8: return EmitAtomicBinaryPartword(MI, BB, 2, Mips::OR); case Mips::ATOMIC_LOAD_OR_I32: + case Mips::ATOMIC_LOAD_OR_I32_P8: return EmitAtomicBinary(MI, BB, 4, Mips::OR); + case Mips::ATOMIC_LOAD_OR_I64: + case Mips::ATOMIC_LOAD_OR_I64_P8: + return EmitAtomicBinary(MI, BB, 8, Mips::OR64); case Mips::ATOMIC_LOAD_XOR_I8: + case Mips::ATOMIC_LOAD_XOR_I8_P8: return EmitAtomicBinaryPartword(MI, BB, 1, Mips::XOR); case Mips::ATOMIC_LOAD_XOR_I16: + case Mips::ATOMIC_LOAD_XOR_I16_P8: return EmitAtomicBinaryPartword(MI, BB, 2, Mips::XOR); case Mips::ATOMIC_LOAD_XOR_I32: + case Mips::ATOMIC_LOAD_XOR_I32_P8: return EmitAtomicBinary(MI, BB, 4, Mips::XOR); + case Mips::ATOMIC_LOAD_XOR_I64: + case Mips::ATOMIC_LOAD_XOR_I64_P8: + return EmitAtomicBinary(MI, BB, 8, Mips::XOR64); case Mips::ATOMIC_LOAD_NAND_I8: + case Mips::ATOMIC_LOAD_NAND_I8_P8: return EmitAtomicBinaryPartword(MI, BB, 1, 0, true); case Mips::ATOMIC_LOAD_NAND_I16: + case Mips::ATOMIC_LOAD_NAND_I16_P8: return EmitAtomicBinaryPartword(MI, BB, 2, 0, true); case Mips::ATOMIC_LOAD_NAND_I32: + case Mips::ATOMIC_LOAD_NAND_I32_P8: return EmitAtomicBinary(MI, BB, 4, 0, true); + case Mips::ATOMIC_LOAD_NAND_I64: + case Mips::ATOMIC_LOAD_NAND_I64_P8: + return EmitAtomicBinary(MI, BB, 8, 0, true); case Mips::ATOMIC_LOAD_SUB_I8: + case Mips::ATOMIC_LOAD_SUB_I8_P8: return EmitAtomicBinaryPartword(MI, BB, 1, Mips::SUBu); case Mips::ATOMIC_LOAD_SUB_I16: + case Mips::ATOMIC_LOAD_SUB_I16_P8: return EmitAtomicBinaryPartword(MI, BB, 2, Mips::SUBu); case Mips::ATOMIC_LOAD_SUB_I32: + case Mips::ATOMIC_LOAD_SUB_I32_P8: return EmitAtomicBinary(MI, BB, 4, Mips::SUBu); + case Mips::ATOMIC_LOAD_SUB_I64: + case Mips::ATOMIC_LOAD_SUB_I64_P8: + return EmitAtomicBinary(MI, BB, 8, Mips::DSUBu); case Mips::ATOMIC_SWAP_I8: + case Mips::ATOMIC_SWAP_I8_P8: return EmitAtomicBinaryPartword(MI, BB, 1, 0); case Mips::ATOMIC_SWAP_I16: + case Mips::ATOMIC_SWAP_I16_P8: return EmitAtomicBinaryPartword(MI, BB, 2, 0); case Mips::ATOMIC_SWAP_I32: + case Mips::ATOMIC_SWAP_I32_P8: return EmitAtomicBinary(MI, BB, 4, 0); + case Mips::ATOMIC_SWAP_I64: + case Mips::ATOMIC_SWAP_I64_P8: + return EmitAtomicBinary(MI, BB, 8, 0); case Mips::ATOMIC_CMP_SWAP_I8: + case Mips::ATOMIC_CMP_SWAP_I8_P8: return EmitAtomicCmpSwapPartword(MI, BB, 1); case Mips::ATOMIC_CMP_SWAP_I16: + case Mips::ATOMIC_CMP_SWAP_I16_P8: return EmitAtomicCmpSwapPartword(MI, BB, 2); case Mips::ATOMIC_CMP_SWAP_I32: + case Mips::ATOMIC_CMP_SWAP_I32_P8: return EmitAtomicCmpSwap(MI, BB, 4); + case Mips::ATOMIC_CMP_SWAP_I64: + case Mips::ATOMIC_CMP_SWAP_I64_P8: + return EmitAtomicCmpSwap(MI, BB, 8); } } @@ -856,13 +915,31 @@ MachineBasicBlock * MipsTargetLowering::EmitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB, unsigned Size, unsigned BinOpcode, bool Nand) const { - assert(Size == 4 && "Unsupported size for EmitAtomicBinary."); + assert((Size == 4 || Size == 8) && "Unsupported size for EmitAtomicBinary."); MachineFunction *MF = BB->getParent(); MachineRegisterInfo &RegInfo = MF->getRegInfo(); - const TargetRegisterClass *RC = getRegClassFor(MVT::i32); + const TargetRegisterClass *RC = getRegClassFor(MVT::getIntegerVT(Size * 8)); const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); DebugLoc dl = MI->getDebugLoc(); + unsigned LL, SC, AND, NOR, ZERO, BEQ; + + if (Size == 4) { + LL = IsN64 ? Mips::LL_P8 : Mips::LL; + SC = IsN64 ? Mips::SC_P8 : Mips::SC; + AND = Mips::AND; + NOR = Mips::NOR; + ZERO = Mips::ZERO; + BEQ = Mips::BEQ; + } + else { + LL = IsN64 ? Mips::LLD_P8 : Mips::LLD; + SC = IsN64 ? Mips::SCD_P8 : Mips::SCD; + AND = Mips::AND64; + NOR = Mips::NOR64; + ZERO = Mips::ZERO_64; + BEQ = Mips::BEQ64; + } unsigned OldVal = MI->getOperand(0).getReg(); unsigned Ptr = MI->getOperand(1).getReg(); @@ -900,23 +977,20 @@ MipsTargetLowering::EmitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB, // 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(LL), OldVal).addReg(Ptr).addImm(0); if (Nand) { // 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); + BuildMI(BB, dl, TII->get(AND), AndRes).addReg(OldVal).addReg(Incr); + BuildMI(BB, dl, TII->get(NOR), StoreVal).addReg(ZERO).addReg(AndRes); } else if (BinOpcode) { // <binop> storeval, oldval, incr BuildMI(BB, dl, TII->get(BinOpcode), StoreVal).addReg(OldVal).addReg(Incr); } else { StoreVal = Incr; } - BuildMI(BB, dl, TII->get(Mips::SC), Success) - .addReg(StoreVal).addReg(Ptr).addImm(0); - BuildMI(BB, dl, TII->get(Mips::BEQ)) - .addReg(Success).addReg(Mips::ZERO).addMBB(loopMBB); + BuildMI(BB, dl, TII->get(SC), Success).addReg(StoreVal).addReg(Ptr).addImm(0); + BuildMI(BB, dl, TII->get(BEQ)).addReg(Success).addReg(ZERO).addMBB(loopMBB); MI->eraseFromParent(); // The instruction is gone now. @@ -936,6 +1010,8 @@ MipsTargetLowering::EmitAtomicBinaryPartword(MachineInstr *MI, const TargetRegisterClass *RC = getRegClassFor(MVT::i32); const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); DebugLoc dl = MI->getDebugLoc(); + unsigned LL = IsN64 ? Mips::LL_P8 : Mips::LL; + unsigned SC = IsN64 ? Mips::SC_P8 : Mips::SC; unsigned Dest = MI->getOperand(0).getReg(); unsigned Ptr = MI->getOperand(1).getReg(); @@ -1027,7 +1103,7 @@ MipsTargetLowering::EmitAtomicBinaryPartword(MachineInstr *MI, // beq success,$0,loopMBB BB = loopMBB; - BuildMI(BB, dl, TII->get(Mips::LL), OldVal).addReg(AlignedAddr).addImm(0); + BuildMI(BB, dl, TII->get(LL), OldVal).addReg(AlignedAddr).addImm(0); if (Nand) { // and andres, oldval, incr2 // nor binopres, $0, andres @@ -1050,7 +1126,7 @@ MipsTargetLowering::EmitAtomicBinaryPartword(MachineInstr *MI, .addReg(OldVal).addReg(Mask2); BuildMI(BB, dl, TII->get(Mips::OR), StoreVal) .addReg(MaskedOldVal0).addReg(NewVal); - BuildMI(BB, dl, TII->get(Mips::SC), Success) + BuildMI(BB, dl, TII->get(SC), Success) .addReg(StoreVal).addReg(AlignedAddr).addImm(0); BuildMI(BB, dl, TII->get(Mips::BEQ)) .addReg(Success).addReg(Mips::ZERO).addMBB(loopMBB); @@ -1081,13 +1157,29 @@ MachineBasicBlock * MipsTargetLowering::EmitAtomicCmpSwap(MachineInstr *MI, MachineBasicBlock *BB, unsigned Size) const { - assert(Size == 4 && "Unsupported size for EmitAtomicCmpSwap."); + assert((Size == 4 || Size == 8) && "Unsupported size for EmitAtomicCmpSwap."); MachineFunction *MF = BB->getParent(); MachineRegisterInfo &RegInfo = MF->getRegInfo(); - const TargetRegisterClass *RC = getRegClassFor(MVT::i32); + const TargetRegisterClass *RC = getRegClassFor(MVT::getIntegerVT(Size * 8)); const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); DebugLoc dl = MI->getDebugLoc(); + unsigned LL, SC, ZERO, BNE, BEQ; + + if (Size == 4) { + LL = IsN64 ? Mips::LL_P8 : Mips::LL; + SC = IsN64 ? Mips::SC_P8 : Mips::SC; + ZERO = Mips::ZERO; + BNE = Mips::BNE; + BEQ = Mips::BEQ; + } + else { + LL = IsN64 ? Mips::LLD_P8 : Mips::LLD; + SC = IsN64 ? Mips::SCD_P8 : Mips::SCD; + ZERO = Mips::ZERO_64; + BNE = Mips::BNE64; + BEQ = Mips::BEQ64; + } unsigned Dest = MI->getOperand(0).getReg(); unsigned Ptr = MI->getOperand(1).getReg(); @@ -1126,18 +1218,18 @@ MipsTargetLowering::EmitAtomicCmpSwap(MachineInstr *MI, // ll dest, 0(ptr) // bne dest, oldval, exitMBB BB = loop1MBB; - BuildMI(BB, dl, TII->get(Mips::LL), Dest).addReg(Ptr).addImm(0); - BuildMI(BB, dl, TII->get(Mips::BNE)) + BuildMI(BB, dl, TII->get(LL), Dest).addReg(Ptr).addImm(0); + BuildMI(BB, dl, TII->get(BNE)) .addReg(Dest).addReg(OldVal).addMBB(exitMBB); // loop2MBB: // sc success, newval, 0(ptr) // beq success, $0, loop1MBB BB = loop2MBB; - BuildMI(BB, dl, TII->get(Mips::SC), Success) + BuildMI(BB, dl, TII->get(SC), Success) .addReg(NewVal).addReg(Ptr).addImm(0); - BuildMI(BB, dl, TII->get(Mips::BEQ)) - .addReg(Success).addReg(Mips::ZERO).addMBB(loop1MBB); + BuildMI(BB, dl, TII->get(BEQ)) + .addReg(Success).addReg(ZERO).addMBB(loop1MBB); MI->eraseFromParent(); // The instruction is gone now. @@ -1156,6 +1248,8 @@ MipsTargetLowering::EmitAtomicCmpSwapPartword(MachineInstr *MI, const TargetRegisterClass *RC = getRegClassFor(MVT::i32); const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); DebugLoc dl = MI->getDebugLoc(); + unsigned LL = IsN64 ? Mips::LL_P8 : Mips::LL; + unsigned SC = IsN64 ? Mips::SC_P8 : Mips::SC; unsigned Dest = MI->getOperand(0).getReg(); unsigned Ptr = MI->getOperand(1).getReg(); @@ -1246,7 +1340,7 @@ MipsTargetLowering::EmitAtomicCmpSwapPartword(MachineInstr *MI, // and maskedoldval0,oldval,mask // bne maskedoldval0,shiftedcmpval,sinkMBB BB = loop1MBB; - BuildMI(BB, dl, TII->get(Mips::LL), OldVal).addReg(AlignedAddr).addImm(0); + BuildMI(BB, dl, TII->get(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)) @@ -1262,7 +1356,7 @@ MipsTargetLowering::EmitAtomicCmpSwapPartword(MachineInstr *MI, .addReg(OldVal).addReg(Mask2); BuildMI(BB, dl, TII->get(Mips::OR), StoreVal) .addReg(MaskedOldVal1).addReg(ShiftedNewVal); - BuildMI(BB, dl, TII->get(Mips::SC), Success) + BuildMI(BB, dl, TII->get(SC), Success) .addReg(StoreVal).addReg(AlignedAddr).addImm(0); BuildMI(BB, dl, TII->get(Mips::BEQ)) .addReg(Success).addReg(Mips::ZERO).addMBB(loop1MBB); @@ -1294,6 +1388,7 @@ LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const { MachineFunction &MF = DAG.getMachineFunction(); MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); + unsigned SP = IsN64 ? Mips::SP_64 : Mips::SP; assert(getTargetMachine().getFrameLowering()->getStackAlignment() >= cast<ConstantSDNode>(Op.getOperand(2).getNode())->getZExtValue() && @@ -1305,20 +1400,19 @@ LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const DebugLoc dl = Op.getDebugLoc(); // Get a reference from Mips stack pointer - SDValue StackPointer = DAG.getCopyFromReg(Chain, dl, Mips::SP, MVT::i32); + SDValue StackPointer = DAG.getCopyFromReg(Chain, dl, SP, getPointerTy()); // Subtract the dynamic size from the actual stack size to // obtain the new stack size. - SDValue Sub = DAG.getNode(ISD::SUB, dl, MVT::i32, StackPointer, Size); + SDValue Sub = DAG.getNode(ISD::SUB, dl, getPointerTy(), StackPointer, Size); // The Sub result contains the new stack start address, so it // must be placed in the stack pointer register. - Chain = DAG.getCopyToReg(StackPointer.getValue(1), dl, Mips::SP, Sub, - SDValue()); + Chain = DAG.getCopyToReg(StackPointer.getValue(1), dl, SP, Sub, SDValue()); // This node always has two return values: a new stack pointer // value and a chain - SDVTList VTLs = DAG.getVTList(MVT::i32, MVT::Other); + SDVTList VTLs = DAG.getVTList(getPointerTy(), MVT::Other); SDValue Ptr = DAG.getFrameIndex(MipsFI->getDynAllocFI(), getPointerTy()); SDValue Ops[] = { Chain, Ptr, Chain.getValue(1) }; @@ -1396,12 +1490,12 @@ SDValue MipsTargetLowering::LowerGlobalAddress(SDValue Op, (GV->hasLocalLinkage() && !isa<Function>(GV))); unsigned GotFlag = IsN64 ? (HasGotOfst ? MipsII::MO_GOT_PAGE : MipsII::MO_GOT_DISP) : - MipsII::MO_GOT; + (HasGotOfst ? MipsII::MO_GOT : MipsII::MO_GOT16); SDValue GA = DAG.getTargetGlobalAddress(GV, dl, ValTy, 0, GotFlag); - GA = DAG.getNode(MipsISD::WrapperPIC, dl, ValTy, GA); + GA = DAG.getNode(MipsISD::Wrapper, dl, ValTy, GA); SDValue ResNode = DAG.getLoad(ValTy, dl, DAG.getEntryNode(), GA, MachinePointerInfo(), - false, false, 0); + false, false, false, 0); // On functions and global targets not internal linked only // a load from got/GP is necessary for PIC to work. if (!HasGotOfst) @@ -1419,7 +1513,7 @@ SDValue MipsTargetLowering::LowerBlockAddress(SDValue Op, // FIXME there isn't actually debug info here DebugLoc dl = Op.getDebugLoc(); - if (getTargetMachine().getRelocationModel() != Reloc::PIC_) { + if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && !IsN64) { // %hi/%lo relocation SDValue BAHi = DAG.getBlockAddress(BA, MVT::i32, true, MipsII::MO_ABS_HI); @@ -1430,24 +1524,25 @@ SDValue MipsTargetLowering::LowerBlockAddress(SDValue Op, return DAG.getNode(ISD::ADD, dl, MVT::i32, Hi, Lo); } - SDValue BAGOTOffset = DAG.getBlockAddress(BA, MVT::i32, true, - MipsII::MO_GOT); - BAGOTOffset = DAG.getNode(MipsISD::WrapperPIC, dl, MVT::i32, BAGOTOffset); - SDValue BALOOffset = DAG.getBlockAddress(BA, MVT::i32, true, - MipsII::MO_ABS_LO); - SDValue Load = DAG.getLoad(MVT::i32, dl, + EVT ValTy = Op.getValueType(); + unsigned GOTFlag = IsN64 ? MipsII::MO_GOT_PAGE : MipsII::MO_GOT; + unsigned OFSTFlag = IsN64 ? MipsII::MO_GOT_OFST : MipsII::MO_ABS_LO; + SDValue BAGOTOffset = DAG.getBlockAddress(BA, ValTy, true, GOTFlag); + BAGOTOffset = DAG.getNode(MipsISD::Wrapper, dl, ValTy, BAGOTOffset); + SDValue BALOOffset = DAG.getBlockAddress(BA, ValTy, true, OFSTFlag); + SDValue Load = DAG.getLoad(ValTy, dl, DAG.getEntryNode(), BAGOTOffset, - MachinePointerInfo(), false, false, 0); - SDValue Lo = DAG.getNode(MipsISD::Lo, dl, MVT::i32, BALOOffset); - return DAG.getNode(ISD::ADD, dl, MVT::i32, Load, Lo); + MachinePointerInfo(), false, false, false, 0); + SDValue Lo = DAG.getNode(MipsISD::Lo, dl, ValTy, BALOOffset); + return DAG.getNode(ISD::ADD, dl, ValTy, Load, Lo); } SDValue MipsTargetLowering:: LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const { - // If the relocation model is PIC, use the General Dynamic TLS Model, - // otherwise use the Initial Exec or Local Exec TLS Model. - // TODO: implement Local Dynamic TLS model + // If the relocation model is PIC, use the General Dynamic TLS Model or + // Local Dynamic TLS model, otherwise use the Initial Exec or + // Local Exec TLS Model. GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(Op); DebugLoc dl = GA->getDebugLoc(); @@ -1456,45 +1551,59 @@ LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const if (getTargetMachine().getRelocationModel() == Reloc::PIC_) { // General Dynamic TLS Model - SDValue TGA = DAG.getTargetGlobalAddress(GV, dl, MVT::i32, - 0, MipsII::MO_TLSGD); - SDValue Tlsgd = DAG.getNode(MipsISD::TlsGd, dl, MVT::i32, TGA); - SDValue GP = DAG.getRegister(Mips::GP, MVT::i32); - SDValue Argument = DAG.getNode(ISD::ADD, dl, MVT::i32, GP, Tlsgd); + bool LocalDynamic = GV->hasInternalLinkage(); + unsigned Flag = LocalDynamic ? MipsII::MO_TLSLDM :MipsII::MO_TLSGD; + SDValue TGA = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, Flag); + SDValue Argument = DAG.getNode(MipsISD::Wrapper, dl, PtrVT, TGA); + unsigned PtrSize = PtrVT.getSizeInBits(); + IntegerType *PtrTy = Type::getIntNTy(*DAG.getContext(), PtrSize); + + SDValue TlsGetAddr = DAG.getExternalSymbol("__tls_get_addr", PtrVT); ArgListTy Args; ArgListEntry Entry; Entry.Node = Argument; - Entry.Ty = (Type *) Type::getInt32Ty(*DAG.getContext()); + Entry.Ty = PtrTy; Args.push_back(Entry); + std::pair<SDValue, SDValue> CallResult = - LowerCallTo(DAG.getEntryNode(), - (Type *) Type::getInt32Ty(*DAG.getContext()), - false, false, false, false, 0, CallingConv::C, false, true, - DAG.getExternalSymbol("__tls_get_addr", PtrVT), Args, DAG, - dl); - - return CallResult.first; + LowerCallTo(DAG.getEntryNode(), PtrTy, + false, false, false, false, 0, CallingConv::C, false, true, + TlsGetAddr, Args, DAG, dl); + + SDValue Ret = CallResult.first; + + if (!LocalDynamic) + return Ret; + + SDValue TGAHi = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, + MipsII::MO_DTPREL_HI); + SDValue Hi = DAG.getNode(MipsISD::Hi, dl, PtrVT, TGAHi); + SDValue TGALo = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, + MipsII::MO_DTPREL_LO); + SDValue Lo = DAG.getNode(MipsISD::Lo, dl, PtrVT, TGALo); + SDValue Add = DAG.getNode(ISD::ADD, dl, PtrVT, Hi, Ret); + return DAG.getNode(ISD::ADD, dl, PtrVT, Add, Lo); } SDValue Offset; if (GV->isDeclaration()) { // Initial Exec TLS Model - SDValue TGA = DAG.getTargetGlobalAddress(GV, dl, MVT::i32, 0, + SDValue TGA = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, MipsII::MO_GOTTPREL); - Offset = DAG.getLoad(MVT::i32, dl, + TGA = DAG.getNode(MipsISD::Wrapper, dl, PtrVT, TGA); + Offset = DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), TGA, MachinePointerInfo(), - false, false, 0); + false, false, false, 0); } else { // Local Exec TLS Model - SDVTList VTs = DAG.getVTList(MVT::i32); - SDValue TGAHi = DAG.getTargetGlobalAddress(GV, dl, MVT::i32, 0, + SDValue TGAHi = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, MipsII::MO_TPREL_HI); - SDValue TGALo = DAG.getTargetGlobalAddress(GV, dl, MVT::i32, 0, + SDValue TGALo = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, MipsII::MO_TPREL_LO); - SDValue Hi = DAG.getNode(MipsISD::TprelHi, dl, VTs, &TGAHi, 1); - SDValue Lo = DAG.getNode(MipsISD::TprelLo, dl, MVT::i32, TGALo); - Offset = DAG.getNode(ISD::ADD, dl, MVT::i32, Hi, Lo); + SDValue Hi = DAG.getNode(MipsISD::Hi, dl, PtrVT, TGAHi); + SDValue Lo = DAG.getNode(MipsISD::Lo, dl, PtrVT, TGALo); + Offset = DAG.getNode(ISD::ADD, dl, PtrVT, Hi, Lo); } SDValue ThreadPointer = DAG.getNode(MipsISD::ThreadPointer, dl, PtrVT); @@ -1504,34 +1613,29 @@ LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const SDValue MipsTargetLowering:: LowerJumpTable(SDValue Op, SelectionDAG &DAG) const { - SDValue ResNode; - SDValue HiPart; + SDValue HiPart, JTI, JTILo; // FIXME there isn't actually debug info here DebugLoc dl = Op.getDebugLoc(); bool IsPIC = getTargetMachine().getRelocationModel() == Reloc::PIC_; - unsigned char OpFlag = IsPIC ? MipsII::MO_GOT : MipsII::MO_ABS_HI; - EVT PtrVT = Op.getValueType(); - JumpTableSDNode *JT = cast<JumpTableSDNode>(Op); + JumpTableSDNode *JT = cast<JumpTableSDNode>(Op); - SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT, OpFlag); - - if (!IsPIC) { - SDValue Ops[] = { JTI }; - HiPart = DAG.getNode(MipsISD::Hi, dl, DAG.getVTList(MVT::i32), Ops, 1); + if (!IsPIC && !IsN64) { + JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT, MipsII::MO_ABS_HI); + HiPart = DAG.getNode(MipsISD::Hi, dl, PtrVT, JTI); + JTILo = DAG.getTargetJumpTable(JT->getIndex(), PtrVT, MipsII::MO_ABS_LO); } else {// Emit Load from Global Pointer - JTI = DAG.getNode(MipsISD::WrapperPIC, dl, MVT::i32, JTI); - HiPart = DAG.getLoad(MVT::i32, dl, DAG.getEntryNode(), JTI, - MachinePointerInfo(), - false, false, 0); + unsigned GOTFlag = IsN64 ? MipsII::MO_GOT_PAGE : MipsII::MO_GOT; + unsigned OfstFlag = IsN64 ? MipsII::MO_GOT_OFST : MipsII::MO_ABS_LO; + JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT, GOTFlag); + JTI = DAG.getNode(MipsISD::Wrapper, dl, PtrVT, JTI); + HiPart = DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), JTI, + MachinePointerInfo(), false, false, false, 0); + JTILo = DAG.getTargetJumpTable(JT->getIndex(), PtrVT, OfstFlag); } - SDValue JTILo = DAG.getTargetJumpTable(JT->getIndex(), PtrVT, - MipsII::MO_ABS_LO); - SDValue Lo = DAG.getNode(MipsISD::Lo, dl, MVT::i32, JTILo); - ResNode = DAG.getNode(ISD::ADD, dl, MVT::i32, HiPart, Lo); - - return ResNode; + SDValue Lo = DAG.getNode(MipsISD::Lo, dl, PtrVT, JTILo); + return DAG.getNode(ISD::ADD, dl, PtrVT, HiPart, Lo); } SDValue MipsTargetLowering:: @@ -1562,16 +1666,19 @@ LowerConstantPool(SDValue Op, SelectionDAG &DAG) const SDValue Lo = DAG.getNode(MipsISD::Lo, dl, MVT::i32, CPLo); ResNode = DAG.getNode(ISD::ADD, dl, MVT::i32, HiPart, Lo); } else { - SDValue CP = DAG.getTargetConstantPool(C, MVT::i32, N->getAlignment(), - N->getOffset(), MipsII::MO_GOT); - CP = DAG.getNode(MipsISD::WrapperPIC, dl, MVT::i32, CP); - SDValue Load = DAG.getLoad(MVT::i32, dl, DAG.getEntryNode(), + EVT ValTy = Op.getValueType(); + unsigned GOTFlag = IsN64 ? MipsII::MO_GOT_PAGE : MipsII::MO_GOT; + unsigned OFSTFlag = IsN64 ? MipsII::MO_GOT_OFST : MipsII::MO_ABS_LO; + SDValue CP = DAG.getTargetConstantPool(C, ValTy, N->getAlignment(), + N->getOffset(), GOTFlag); + CP = DAG.getNode(MipsISD::Wrapper, dl, ValTy, CP); + SDValue Load = DAG.getLoad(ValTy, dl, DAG.getEntryNode(), CP, MachinePointerInfo::getConstantPool(), - false, false, 0); - SDValue CPLo = DAG.getTargetConstantPool(C, MVT::i32, N->getAlignment(), - N->getOffset(), MipsII::MO_ABS_LO); - SDValue Lo = DAG.getNode(MipsISD::Lo, dl, MVT::i32, CPLo); - ResNode = DAG.getNode(ISD::ADD, dl, MVT::i32, Load, Lo); + false, false, false, 0); + SDValue CPLo = DAG.getTargetConstantPool(C, ValTy, N->getAlignment(), + N->getOffset(), OFSTFlag); + SDValue Lo = DAG.getNode(MipsISD::Lo, dl, ValTy, CPLo); + ResNode = DAG.getNode(ISD::ADD, dl, ValTy, Load, Lo); } return ResNode; @@ -1592,21 +1699,29 @@ SDValue MipsTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) const { MachinePointerInfo(SV), false, false, 0); } - -static SDValue LowerFCOPYSIGN32(SDValue Op, SelectionDAG &DAG) { + +// Called if the size of integer registers is large enough to hold the whole +// floating point number. +static SDValue LowerFCOPYSIGNLargeIntReg(SDValue Op, SelectionDAG &DAG) { // FIXME: Use ext/ins instructions if target architecture is Mips32r2. + EVT ValTy = Op.getValueType(); + EVT IntValTy = MVT::getIntegerVT(ValTy.getSizeInBits()); + uint64_t Mask = (uint64_t)1 << (ValTy.getSizeInBits() - 1); DebugLoc dl = Op.getDebugLoc(); - SDValue Op0 = DAG.getNode(ISD::BITCAST, dl, MVT::i32, Op.getOperand(0)); - SDValue Op1 = DAG.getNode(ISD::BITCAST, dl, MVT::i32, Op.getOperand(1)); - SDValue And0 = DAG.getNode(ISD::AND, dl, MVT::i32, Op0, - DAG.getConstant(0x7fffffff, MVT::i32)); - SDValue And1 = DAG.getNode(ISD::AND, dl, MVT::i32, Op1, - DAG.getConstant(0x80000000, MVT::i32)); - SDValue Result = DAG.getNode(ISD::OR, dl, MVT::i32, And0, And1); - return DAG.getNode(ISD::BITCAST, dl, MVT::f32, Result); + SDValue Op0 = DAG.getNode(ISD::BITCAST, dl, IntValTy, Op.getOperand(0)); + SDValue Op1 = DAG.getNode(ISD::BITCAST, dl, IntValTy, Op.getOperand(1)); + SDValue And0 = DAG.getNode(ISD::AND, dl, IntValTy, Op0, + DAG.getConstant(Mask - 1, IntValTy)); + SDValue And1 = DAG.getNode(ISD::AND, dl, IntValTy, Op1, + DAG.getConstant(Mask, IntValTy)); + SDValue Result = DAG.getNode(ISD::OR, dl, IntValTy, And0, And1); + return DAG.getNode(ISD::BITCAST, dl, ValTy, Result); } -static SDValue LowerFCOPYSIGN64(SDValue Op, SelectionDAG &DAG, bool isLittle) { +// Called if the size of integer registers is not large enough to hold the whole +// floating point number (e.g. f64 & 32-bit integer register). +static SDValue +LowerFCOPYSIGNSmallIntReg(SDValue Op, SelectionDAG &DAG, bool isLittle) { // FIXME: // Use ext/ins instructions if target architecture is Mips32r2. // Eliminate redundant mfc1 and mtc1 instructions. @@ -1641,10 +1756,10 @@ SDValue MipsTargetLowering::LowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) assert(Ty == MVT::f32 || Ty == MVT::f64); - if (Ty == MVT::f32) - return LowerFCOPYSIGN32(Op, DAG); + if (Ty == MVT::f32 || HasMips64) + return LowerFCOPYSIGNLargeIntReg(Op, DAG); else - return LowerFCOPYSIGN64(Op, DAG, Subtarget->isLittle()); + return LowerFCOPYSIGNSmallIntReg(Op, DAG, Subtarget->isLittle()); } SDValue MipsTargetLowering:: @@ -1657,7 +1772,8 @@ LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const { MFI->setFrameAddressIsTaken(true); EVT VT = Op.getValueType(); DebugLoc dl = Op.getDebugLoc(); - SDValue FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, Mips::FP, VT); + SDValue FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, + IsN64 ? Mips::FP_64 : Mips::FP, VT); return FrameAddr; } @@ -1684,8 +1800,6 @@ SDValue MipsTargetLowering::LowerATOMIC_FENCE(SDValue Op, // Calling Convention Implementation //===----------------------------------------------------------------------===// -#include "MipsGenCallingConv.inc" - //===----------------------------------------------------------------------===// // TODO: Implement a generic logic using tblgen that can support this. // Mips O32 ABI rules: @@ -1792,6 +1906,70 @@ static bool CC_MipsO32(unsigned ValNo, MVT ValVT, return false; // CC must always match } +static const unsigned Mips64IntRegs[8] = + {Mips::A0_64, Mips::A1_64, Mips::A2_64, Mips::A3_64, + Mips::T0_64, Mips::T1_64, Mips::T2_64, Mips::T3_64}; +static const unsigned Mips64DPRegs[8] = + {Mips::D12_64, Mips::D13_64, Mips::D14_64, Mips::D15_64, + Mips::D16_64, Mips::D17_64, Mips::D18_64, Mips::D19_64}; + +static bool CC_Mips64Byval(unsigned ValNo, MVT ValVT, MVT LocVT, + CCValAssign::LocInfo LocInfo, + ISD::ArgFlagsTy ArgFlags, CCState &State) { + unsigned Align = std::max(ArgFlags.getByValAlign(), (unsigned)8); + unsigned Size = (ArgFlags.getByValSize() + 7) / 8 * 8; + unsigned FirstIdx = State.getFirstUnallocated(Mips64IntRegs, 8); + + assert(Align <= 16 && "Cannot handle alignments larger than 16."); + + // If byval is 16-byte aligned, the first arg register must be even. + if ((Align == 16) && (FirstIdx % 2)) { + State.AllocateReg(Mips64IntRegs[FirstIdx], Mips64DPRegs[FirstIdx]); + ++FirstIdx; + } + + // Mark the registers allocated. + for (unsigned I = FirstIdx; Size && (I < 8); Size -= 8, ++I) + State.AllocateReg(Mips64IntRegs[I], Mips64DPRegs[I]); + + // Allocate space on caller's stack. + unsigned Offset = State.AllocateStack(Size, Align); + + if (FirstIdx < 8) + State.addLoc(CCValAssign::getReg(ValNo, ValVT, Mips64IntRegs[FirstIdx], + LocVT, LocInfo)); + else + State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo)); + + return true; +} + +#include "MipsGenCallingConv.inc" + +static void +AnalyzeMips64CallOperands(CCState CCInfo, + const SmallVectorImpl<ISD::OutputArg> &Outs) { + unsigned NumOps = Outs.size(); + for (unsigned i = 0; i != NumOps; ++i) { + MVT ArgVT = Outs[i].VT; + ISD::ArgFlagsTy ArgFlags = Outs[i].Flags; + bool R; + + if (Outs[i].IsFixed) + R = CC_MipsN(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, CCInfo); + else + R = CC_MipsN_VarArg(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, CCInfo); + + if (R) { +#ifndef NDEBUG + dbgs() << "Call operand #" << i << " has unhandled type " + << EVT(ArgVT).getEVTString(); +#endif + llvm_unreachable(0); + } + } +} + //===----------------------------------------------------------------------===// // Call Calling Convention Implementation //===----------------------------------------------------------------------===// @@ -1830,8 +2008,8 @@ WriteByValArg(SDValue& ByValChain, SDValue Chain, DebugLoc dl, DAG.getConstant(Offset, MVT::i32)); SDValue LoadVal = DAG.getLoad(MVT::i32, dl, Chain, LoadPtr, MachinePointerInfo(), - false, false, std::min(ByValAlign, - (unsigned )4)); + false, false, false, std::min(ByValAlign, + (unsigned )4)); MemOpChains.push_back(LoadVal.getValue(1)); unsigned DstReg = O32IntRegs[LocMemOffset / 4]; RegsToPass.push_back(std::make_pair(DstReg, LoadVal)); @@ -1900,6 +2078,94 @@ WriteByValArg(SDValue& ByValChain, SDValue Chain, DebugLoc dl, MachinePointerInfo(0), MachinePointerInfo(0)); } +// Copy Mips64 byVal arg to registers and stack. +void static +PassByValArg64(SDValue& ByValChain, SDValue Chain, DebugLoc dl, + SmallVector<std::pair<unsigned, SDValue>, 16>& RegsToPass, + SmallVector<SDValue, 8>& MemOpChains, int& LastFI, + MachineFrameInfo *MFI, SelectionDAG &DAG, SDValue Arg, + const CCValAssign &VA, const ISD::ArgFlagsTy& Flags, + EVT PtrTy, bool isLittle) { + unsigned ByValSize = Flags.getByValSize(); + unsigned Alignment = std::min(Flags.getByValAlign(), (unsigned)8); + bool IsRegLoc = VA.isRegLoc(); + unsigned Offset = 0; // Offset in # of bytes from the beginning of struct. + unsigned LocMemOffset = 0; + unsigned MemCpySize = ByValSize; + + if (!IsRegLoc) + LocMemOffset = VA.getLocMemOffset(); + else { + const unsigned *Reg = std::find(Mips64IntRegs, Mips64IntRegs + 8, + VA.getLocReg()); + const unsigned *RegEnd = Mips64IntRegs + 8; + + // Copy double words to registers. + for (; (Reg != RegEnd) && (ByValSize >= Offset + 8); ++Reg, Offset += 8) { + SDValue LoadPtr = DAG.getNode(ISD::ADD, dl, PtrTy, Arg, + DAG.getConstant(Offset, PtrTy)); + SDValue LoadVal = DAG.getLoad(MVT::i64, dl, Chain, LoadPtr, + MachinePointerInfo(), false, false, false, + Alignment); + MemOpChains.push_back(LoadVal.getValue(1)); + RegsToPass.push_back(std::make_pair(*Reg, LoadVal)); + } + + // Return if the struct has been fully copied. + if (!(MemCpySize = ByValSize - Offset)) + return; + + // If there is an argument register available, copy the remainder of the + // byval argument with sub-doubleword loads and shifts. + if (Reg != RegEnd) { + assert((ByValSize < Offset + 8) && + "Size of the remainder should be smaller than 8-byte."); + SDValue Val; + for (unsigned LoadSize = 4; Offset < ByValSize; LoadSize /= 2) { + unsigned RemSize = ByValSize - Offset; + + if (RemSize < LoadSize) + continue; + + SDValue LoadPtr = DAG.getNode(ISD::ADD, dl, PtrTy, Arg, + DAG.getConstant(Offset, PtrTy)); + SDValue LoadVal = + DAG.getExtLoad(ISD::ZEXTLOAD, dl, MVT::i64, Chain, LoadPtr, + MachinePointerInfo(), MVT::getIntegerVT(LoadSize * 8), + false, false, Alignment); + MemOpChains.push_back(LoadVal.getValue(1)); + + // Offset in number of bits from double word boundary. + unsigned OffsetDW = (Offset % 8) * 8; + unsigned Shamt = isLittle ? OffsetDW : 64 - (OffsetDW + LoadSize * 8); + SDValue Shift = DAG.getNode(ISD::SHL, dl, MVT::i64, LoadVal, + DAG.getConstant(Shamt, MVT::i32)); + + Val = Val.getNode() ? DAG.getNode(ISD::OR, dl, MVT::i64, Val, Shift) : + Shift; + Offset += LoadSize; + Alignment = std::min(Alignment, LoadSize); + } + + RegsToPass.push_back(std::make_pair(*Reg, Val)); + return; + } + } + + assert(MemCpySize && "MemCpySize must not be zero."); + + // Create a fixed object on stack at offset LocMemOffset and copy + // remainder of byval arg to it with memcpy. + SDValue Src = DAG.getNode(ISD::ADD, dl, PtrTy, Arg, + DAG.getConstant(Offset, PtrTy)); + LastFI = MFI->CreateFixedObject(MemCpySize, LocMemOffset, true); + SDValue Dst = DAG.getFrameIndex(LastFI, PtrTy); + ByValChain = DAG.getMemcpy(ByValChain, dl, Dst, Src, + DAG.getConstant(MemCpySize, PtrTy), Alignment, + /*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. @@ -1926,8 +2192,10 @@ MipsTargetLowering::LowerCall(SDValue InChain, SDValue Callee, CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), getTargetMachine(), ArgLocs, *DAG.getContext()); - if (Subtarget->isABI_O32()) + if (IsO32) CCInfo.AnalyzeCallOperands(Outs, CC_MipsO32); + else if (HasMips64) + AnalyzeMips64CallOperands(CCInfo, Outs); else CCInfo.AnalyzeCallOperands(Outs, CC_Mips); @@ -1944,7 +2212,7 @@ MipsTargetLowering::LowerCall(SDValue InChain, SDValue Callee, // If this is the first call, create a stack frame object that points to // a location to which .cprestore saves $gp. - if (IsPIC && !MipsFI->getGPFI()) + if (IsO32 && IsPIC && !MipsFI->getGPFI()) MipsFI->setGPFI(MFI->CreateFixedObject(4, 0, true)); // Get the frame index of the stack frame object that points to the location @@ -1954,7 +2222,7 @@ MipsTargetLowering::LowerCall(SDValue InChain, SDValue Callee, // Update size of the maximum argument space. // For O32, a minimum of four words (16 bytes) of argument space is // allocated. - if (Subtarget->isABI_O32()) + if (IsO32) NextStackOffset = std::max(NextStackOffset, (unsigned)16); unsigned MaxCallFrameSize = MipsFI->getMaxCallFrameSize(); @@ -1969,7 +2237,7 @@ MipsTargetLowering::LowerCall(SDValue InChain, SDValue Callee, NextStackOffset = (NextStackOffset + StackAlignment - 1) / StackAlignment * StackAlignment; - if (IsPIC) + if (MipsFI->needGPSaveRestore()) MFI->setObjectOffset(MipsFI->getGPFI(), NextStackOffset); MFI->setObjectOffset(DynAllocFI, NextStackOffset); @@ -1985,15 +2253,33 @@ MipsTargetLowering::LowerCall(SDValue InChain, SDValue Callee, for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { SDValue Arg = OutVals[i]; CCValAssign &VA = ArgLocs[i]; + MVT ValVT = VA.getValVT(), LocVT = VA.getLocVT(); + ISD::ArgFlagsTy Flags = Outs[i].Flags; + // ByVal Arg. + if (Flags.isByVal()) { + assert(Flags.getByValSize() && + "ByVal args of size 0 should have been ignored by front-end."); + if (IsO32) + WriteByValArg(ByValChain, Chain, dl, RegsToPass, MemOpChains, LastFI, + MFI, DAG, Arg, VA, Flags, getPointerTy(), + Subtarget->isLittle()); + else + PassByValArg64(ByValChain, Chain, dl, RegsToPass, MemOpChains, LastFI, + MFI, DAG, Arg, VA, Flags, getPointerTy(), + Subtarget->isLittle()); + continue; + } + // Promote the value if needed. switch (VA.getLocInfo()) { default: llvm_unreachable("Unknown loc info!"); case CCValAssign::Full: - if (Subtarget->isABI_O32() && VA.isRegLoc()) { - if (VA.getValVT() == MVT::f32 && VA.getLocVT() == MVT::i32) - Arg = DAG.getNode(ISD::BITCAST, dl, MVT::i32, Arg); - if (VA.getValVT() == MVT::f64 && VA.getLocVT() == MVT::i32) { + if (VA.isRegLoc()) { + if ((ValVT == MVT::f32 && LocVT == MVT::i32) || + (ValVT == MVT::f64 && LocVT == MVT::i64)) + Arg = DAG.getNode(ISD::BITCAST, dl, LocVT, Arg); + else if (ValVT == MVT::f64 && LocVT == MVT::i32) { SDValue Lo = DAG.getNode(MipsISD::ExtractElementF64, dl, MVT::i32, Arg, DAG.getConstant(0, MVT::i32)); SDValue Hi = DAG.getNode(MipsISD::ExtractElementF64, dl, MVT::i32, @@ -2009,13 +2295,13 @@ MipsTargetLowering::LowerCall(SDValue InChain, SDValue Callee, } break; case CCValAssign::SExt: - Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg); + Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, LocVT, Arg); break; case CCValAssign::ZExt: - Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg); + Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, LocVT, Arg); break; case CCValAssign::AExt: - Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg); + Arg = DAG.getNode(ISD::ANY_EXTEND, dl, LocVT, Arg); break; } @@ -2029,20 +2315,8 @@ MipsTargetLowering::LowerCall(SDValue InChain, SDValue Callee, // Register can't get to this point... assert(VA.isMemLoc()); - // ByVal Arg. - ISD::ArgFlagsTy Flags = Outs[i].Flags; - if (Flags.isByVal()) { - assert(Subtarget->isABI_O32() && - "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(ByValChain, Chain, dl, RegsToPass, MemOpChains, LastFI, MFI, - DAG, Arg, VA, Flags, getPointerTy(), Subtarget->isLittle()); - continue; - } - // Create the frame index object for this incoming parameter - LastFI = MFI->CreateFixedObject(VA.getValVT().getSizeInBits()/8, + LastFI = MFI->CreateFixedObject(ValVT.getSizeInBits()/8, VA.getLocMemOffset(), true); SDValue PtrOff = DAG.getFrameIndex(LastFI, getPointerTy()); @@ -2074,52 +2348,67 @@ MipsTargetLowering::LowerCall(SDValue InChain, SDValue Callee, // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol // node so that legalize doesn't hack it. - unsigned char OpFlag = IsPIC ? MipsII::MO_GOT_CALL : MipsII::MO_NO_FLAG; - bool LoadSymAddr = false; + unsigned char OpFlag; + bool IsPICCall = (IsN64 || IsPIC); // true if calls are translated to jalr $25 + bool GlobalOrExternal = false; SDValue CalleeLo; if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) { - if (IsPIC && G->getGlobal()->hasInternalLinkage()) { - Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, - getPointerTy(), 0,MipsII:: MO_GOT); + if (IsPICCall && G->getGlobal()->hasInternalLinkage()) { + OpFlag = IsO32 ? MipsII::MO_GOT : MipsII::MO_GOT_PAGE; + unsigned char LoFlag = IsO32 ? MipsII::MO_ABS_LO : MipsII::MO_GOT_OFST; + Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, getPointerTy(), 0, + OpFlag); CalleeLo = DAG.getTargetGlobalAddress(G->getGlobal(), dl, getPointerTy(), - 0, MipsII::MO_ABS_LO); + 0, LoFlag); } else { + OpFlag = IsPICCall ? MipsII::MO_GOT_CALL : MipsII::MO_NO_FLAG; Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, getPointerTy(), 0, OpFlag); } - LoadSymAddr = true; + GlobalOrExternal = true; } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) { + if (IsN64 || (!IsO32 && IsPIC)) + OpFlag = MipsII::MO_GOT_DISP; + else if (!IsPIC) // !N64 && static + OpFlag = MipsII::MO_NO_FLAG; + else // O32 & PIC + OpFlag = MipsII::MO_GOT_CALL; Callee = DAG.getTargetExternalSymbol(S->getSymbol(), - getPointerTy(), OpFlag); - LoadSymAddr = true; + getPointerTy(), OpFlag); + GlobalOrExternal = true; } SDValue InFlag; // Create nodes that load address of callee and copy it to T9 - if (IsPIC) { - if (LoadSymAddr) { + if (IsPICCall) { + if (GlobalOrExternal) { // Load callee address - Callee = DAG.getNode(MipsISD::WrapperPIC, dl, MVT::i32, Callee); - SDValue LoadValue = DAG.getLoad(MVT::i32, dl, DAG.getEntryNode(), Callee, - MachinePointerInfo::getGOT(), - false, false, 0); + Callee = DAG.getNode(MipsISD::Wrapper, dl, getPointerTy(), Callee); + SDValue LoadValue = DAG.getLoad(getPointerTy(), dl, DAG.getEntryNode(), + Callee, MachinePointerInfo::getGOT(), + false, false, false, 0); // Use GOT+LO if callee has internal linkage. if (CalleeLo.getNode()) { - SDValue Lo = DAG.getNode(MipsISD::Lo, dl, MVT::i32, CalleeLo); - Callee = DAG.getNode(ISD::ADD, dl, MVT::i32, LoadValue, Lo); + SDValue Lo = DAG.getNode(MipsISD::Lo, dl, getPointerTy(), CalleeLo); + Callee = DAG.getNode(ISD::ADD, dl, getPointerTy(), LoadValue, Lo); } else Callee = LoadValue; } + } + // T9 should contain the address of the callee function if + // -reloction-model=pic or it is an indirect call. + if (IsPICCall || !GlobalOrExternal) { // copy to T9 - Chain = DAG.getCopyToReg(Chain, dl, Mips::T9, Callee, SDValue(0, 0)); + unsigned T9Reg = IsN64 ? Mips::T9_64 : Mips::T9; + Chain = DAG.getCopyToReg(Chain, dl, T9Reg, Callee, SDValue(0, 0)); InFlag = Chain.getValue(1); - Callee = DAG.getRegister(Mips::T9, MVT::i32); + Callee = DAG.getRegister(T9Reg, getPointerTy()); } // Build a sequence of copy-to-reg nodes chained together with token @@ -2218,6 +2507,45 @@ static void ReadByValArg(MachineFunction &MF, SDValue Chain, DebugLoc dl, } } +// Create frame object on stack and copy registers used for byval passing to it. +static unsigned +CopyMips64ByValRegs(MachineFunction &MF, SDValue Chain, DebugLoc dl, + std::vector<SDValue>& OutChains, SelectionDAG &DAG, + const CCValAssign &VA, const ISD::ArgFlagsTy& Flags, + MachineFrameInfo *MFI, bool IsRegLoc, + SmallVectorImpl<SDValue> &InVals, MipsFunctionInfo *MipsFI, + EVT PtrTy) { + const unsigned *Reg = Mips64IntRegs + 8; + int FOOffset; // Frame object offset from virtual frame pointer. + + if (IsRegLoc) { + Reg = std::find(Mips64IntRegs, Mips64IntRegs + 8, VA.getLocReg()); + FOOffset = (Reg - Mips64IntRegs) * 8 - 8 * 8; + } + else + FOOffset = VA.getLocMemOffset(); + + // Create frame object. + unsigned NumRegs = (Flags.getByValSize() + 7) / 8; + unsigned LastFI = MFI->CreateFixedObject(NumRegs * 8, FOOffset, true); + SDValue FIN = DAG.getFrameIndex(LastFI, PtrTy); + InVals.push_back(FIN); + + // Copy arg registers. + for (unsigned I = 0; (Reg != Mips64IntRegs + 8) && (I < NumRegs); + ++Reg, ++I) { + unsigned VReg = AddLiveIn(MF, *Reg, Mips::CPU64RegsRegisterClass); + SDValue StorePtr = DAG.getNode(ISD::ADD, dl, PtrTy, FIN, + DAG.getConstant(I * 8, PtrTy)); + SDValue Store = DAG.getStore(Chain, dl, DAG.getRegister(VReg, MVT::i64), + StorePtr, MachinePointerInfo(), false, + false, 0); + OutChains.push_back(Store); + } + + return LastFI; +} + /// LowerFormalArguments - transform physical registers into virtual registers /// and generate load operations for arguments places on the stack. SDValue @@ -2243,7 +2571,7 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), getTargetMachine(), ArgLocs, *DAG.getContext()); - if (Subtarget->isABI_O32()) + if (IsO32) CCInfo.AnalyzeFormalArguments(Ins, CC_MipsO32); else CCInfo.AnalyzeFormalArguments(Ins, CC_Mips); @@ -2252,9 +2580,29 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { CCValAssign &VA = ArgLocs[i]; + EVT ValVT = VA.getValVT(); + ISD::ArgFlagsTy Flags = Ins[i].Flags; + bool IsRegLoc = VA.isRegLoc(); + + if (Flags.isByVal()) { + assert(Flags.getByValSize() && + "ByVal args of size 0 should have been ignored by front-end."); + if (IsO32) { + unsigned NumWords = (Flags.getByValSize() + 3) / 4; + LastFI = MFI->CreateFixedObject(NumWords * 4, VA.getLocMemOffset(), + true); + SDValue FIN = DAG.getFrameIndex(LastFI, getPointerTy()); + InVals.push_back(FIN); + ReadByValArg(MF, Chain, dl, OutChains, DAG, NumWords, FIN, VA, Flags); + } else // N32/64 + LastFI = CopyMips64ByValRegs(MF, Chain, dl, OutChains, DAG, VA, Flags, + MFI, IsRegLoc, InVals, MipsFI, + getPointerTy()); + continue; + } // Arguments stored on registers - if (VA.isRegLoc()) { + if (IsRegLoc) { EVT RegVT = VA.getLocVT(); unsigned ArgReg = VA.getLocReg(); TargetRegisterClass *RC = 0; @@ -2286,23 +2634,22 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, Opcode = ISD::AssertZext; if (Opcode) ArgValue = DAG.getNode(Opcode, dl, RegVT, ArgValue, - DAG.getValueType(VA.getValVT())); - ArgValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), ArgValue); + DAG.getValueType(ValVT)); + ArgValue = DAG.getNode(ISD::TRUNCATE, dl, ValVT, ArgValue); } - // Handle O32 ABI cases: i32->f32 and (i32,i32)->f64 - if (Subtarget->isABI_O32()) { - if (RegVT == MVT::i32 && VA.getValVT() == MVT::f32) - ArgValue = DAG.getNode(ISD::BITCAST, dl, MVT::f32, ArgValue); - if (RegVT == MVT::i32 && VA.getValVT() == MVT::f64) { - unsigned Reg2 = AddLiveIn(DAG.getMachineFunction(), - getNextIntArgReg(ArgReg), RC); - SDValue ArgValue2 = DAG.getCopyFromReg(Chain, dl, Reg2, RegVT); - if (!Subtarget->isLittle()) - std::swap(ArgValue, ArgValue2); - ArgValue = DAG.getNode(MipsISD::BuildPairF64, dl, MVT::f64, - ArgValue, ArgValue2); - } + // Handle floating point arguments passed in integer registers. + if ((RegVT == MVT::i32 && ValVT == MVT::f32) || + (RegVT == MVT::i64 && ValVT == MVT::f64)) + ArgValue = DAG.getNode(ISD::BITCAST, dl, ValVT, ArgValue); + else if (IsO32 && RegVT == MVT::i32 && ValVT == MVT::f64) { + unsigned Reg2 = AddLiveIn(DAG.getMachineFunction(), + getNextIntArgReg(ArgReg), RC); + SDValue ArgValue2 = DAG.getCopyFromReg(Chain, dl, Reg2, RegVT); + if (!Subtarget->isLittle()) + std::swap(ArgValue, ArgValue2); + ArgValue = DAG.getNode(MipsISD::BuildPairF64, dl, MVT::f64, + ArgValue, ArgValue2); } InVals.push_back(ArgValue); @@ -2311,32 +2658,15 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, // sanity check assert(VA.isMemLoc()); - ISD::ArgFlagsTy Flags = Ins[i].Flags; - - if (Flags.isByVal()) { - assert(Subtarget->isABI_O32() && - "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."); - unsigned NumWords = (Flags.getByValSize() + 3) / 4; - LastFI = MFI->CreateFixedObject(NumWords * 4, VA.getLocMemOffset(), - true); - SDValue FIN = DAG.getFrameIndex(LastFI, getPointerTy()); - InVals.push_back(FIN); - ReadByValArg(MF, Chain, dl, OutChains, DAG, NumWords, FIN, VA, Flags); - - continue; - } - // The stack pointer offset is relative to the caller stack frame. - LastFI = MFI->CreateFixedObject(VA.getValVT().getSizeInBits()/8, + LastFI = MFI->CreateFixedObject(ValVT.getSizeInBits()/8, VA.getLocMemOffset(), true); // Create load nodes to retrieve arguments from the stack SDValue FIN = DAG.getFrameIndex(LastFI, getPointerTy()); - InVals.push_back(DAG.getLoad(VA.getValVT(), dl, Chain, FIN, + InVals.push_back(DAG.getLoad(ValVT, dl, Chain, FIN, MachinePointerInfo::getFixedStack(LastFI), - false, false, 0)); + false, false, false, 0)); } } @@ -2353,24 +2683,40 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Copy, Chain); } - if (isVarArg && Subtarget->isABI_O32()) { + if (isVarArg) { + unsigned NumOfRegs = IsO32 ? 4 : 8; + const unsigned *ArgRegs = IsO32 ? O32IntRegs : Mips64IntRegs; + unsigned Idx = CCInfo.getFirstUnallocated(ArgRegs, NumOfRegs); + int FirstRegSlotOffset = IsO32 ? 0 : -64 ; // offset of $a0's slot. + TargetRegisterClass *RC + = IsO32 ? Mips::CPURegsRegisterClass : Mips::CPU64RegsRegisterClass; + unsigned RegSize = RC->getSize(); + int RegSlotOffset = FirstRegSlotOffset + Idx * RegSize; + + // Offset of the first variable argument from stack pointer. + int FirstVaArgOffset; + + if (IsO32 || (Idx == NumOfRegs)) { + FirstVaArgOffset = + (CCInfo.getNextStackOffset() + RegSize - 1) / RegSize * RegSize; + } else + FirstVaArgOffset = RegSlotOffset; + // Record the frame index of the first variable argument // which is a value necessary to VASTART. - unsigned NextStackOffset = CCInfo.getNextStackOffset(); - assert(NextStackOffset % 4 == 0 && - "NextStackOffset must be aligned to 4-byte boundaries."); - LastFI = MFI->CreateFixedObject(4, NextStackOffset, true); + LastFI = MFI->CreateFixedObject(RegSize, FirstVaArgOffset, true); MipsFI->setVarArgsFrameIndex(LastFI); - // If NextStackOffset is smaller than o32's 16-byte reserved argument area, - // copy the integer registers that have not been used for argument passing - // to the caller's stack frame. - for (; NextStackOffset < 16; NextStackOffset += 4) { - TargetRegisterClass *RC = Mips::CPURegsRegisterClass; - unsigned Idx = NextStackOffset / 4; - unsigned Reg = AddLiveIn(DAG.getMachineFunction(), O32IntRegs[Idx], RC); - SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, MVT::i32); - LastFI = MFI->CreateFixedObject(4, NextStackOffset, true); + // Copy the integer registers that have not been used for argument passing + // to the argument register save area. For O32, the save area is allocated + // in the caller's stack frame, while for N32/64, it is allocated in the + // callee's stack frame. + for (int StackOffset = RegSlotOffset; + Idx < NumOfRegs; ++Idx, StackOffset += RegSize) { + unsigned Reg = AddLiveIn(DAG.getMachineFunction(), ArgRegs[Idx], RC); + SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, + MVT::getIntegerVT(RegSize * 8)); + LastFI = MFI->CreateFixedObject(RegSize, StackOffset, true); SDValue PtrOff = DAG.getFrameIndex(LastFI, getPointerTy()); OutChains.push_back(DAG.getStore(Chain, dl, ArgValue, PtrOff, MachinePointerInfo(), diff --git a/lib/Target/Mips/MipsISelLowering.h b/lib/Target/Mips/MipsISelLowering.h index 4be3fed..81d093f 100644 --- a/lib/Target/Mips/MipsISelLowering.h +++ b/lib/Target/Mips/MipsISelLowering.h @@ -40,13 +40,6 @@ namespace llvm { // Handle gp_rel (small data/bss sections) relocation. GPRel, - // General Dynamic TLS - TlsGd, - - // Local Exec TLS - TprelHi, - TprelLo, - // Thread Pointer ThreadPointer, @@ -79,7 +72,7 @@ namespace llvm { BuildPairF64, ExtractElementF64, - WrapperPIC, + Wrapper, DynAlloc, @@ -98,6 +91,8 @@ namespace llvm { public: explicit MipsTargetLowering(MipsTargetMachine &TM); + virtual MVT getShiftAmountTy(EVT LHSTy) const { return MVT::i32; } + virtual bool allowsUnalignedMemoryAccesses (EVT VT) const; /// LowerOperation - Provide custom lowering hooks for some operations. @@ -115,7 +110,7 @@ namespace llvm { // Subtarget Info const MipsSubtarget *Subtarget; - bool HasMips64, IsN64; + bool HasMips64, IsN64, IsO32; // Lower Operand helpers SDValue LowerCallResult(SDValue Chain, SDValue InFlag, diff --git a/lib/Target/Mips/MipsInstrFPU.td b/lib/Target/Mips/MipsInstrFPU.td index 62cee12..7638f54 100644 --- a/lib/Target/Mips/MipsInstrFPU.td +++ b/lib/Target/Mips/MipsInstrFPU.td @@ -183,6 +183,14 @@ def MTC1 : FFRGPR<0x04, (outs FGR32:$fs), (ins CPURegs:$rt), "mtc1\t$rt, $fs", [(set FGR32:$fs, (bitconvert CPURegs:$rt))]>; +def DMFC1 : FFRGPR<0x01, (outs CPU64Regs:$rt), (ins FGR64:$fs), + "dmfc1\t$rt, $fs", + [(set CPU64Regs:$rt, (bitconvert FGR64:$fs))]>; + +def DMTC1 : FFRGPR<0x05, (outs FGR64:$fs), (ins CPU64Regs:$rt), + "dmtc1\t$rt, $fs", + [(set FGR64:$fs, (bitconvert CPU64Regs:$rt))]>; + def FMOV_S : FFR1<0x6, 16, "mov", "s", FGR32, FGR32>; def FMOV_D32 : FFR1<0x6, 17, "mov", "d", AFGR64, AFGR64>, Requires<[NotFP64bit]>; @@ -259,16 +267,16 @@ def MIPS_FCOND_NGE : PatLeaf<(i32 13)>; def MIPS_FCOND_LE : PatLeaf<(i32 14)>; def MIPS_FCOND_NGT : PatLeaf<(i32 15)>; +class FCMP<bits<5> fmt, RegisterClass RC, string typestr> : + FCC<fmt, (outs), (ins RC:$fs, RC:$ft, condcode:$cc), + !strconcat("c.$cc.", typestr, "\t$fs, $ft"), + [(MipsFPCmp RC:$fs, RC:$ft, imm:$cc)]>; + /// Floating Point Compare let Defs=[FCR31] in { - def FCMP_S32 : FCC<0x10, (outs), (ins FGR32:$fs, FGR32:$ft, condcode:$cc), - "c.$cc.s\t$fs, $ft", - [(MipsFPCmp FGR32:$fs, FGR32:$ft, imm:$cc)]>; - - def FCMP_D32 : FCC<0x11, (outs), (ins AFGR64:$fs, AFGR64:$ft, condcode:$cc), - "c.$cc.d\t$fs, $ft", - [(MipsFPCmp AFGR64:$fs, AFGR64:$ft, imm:$cc)]>, - Requires<[NotFP64bit]>; + def FCMP_S32 : FCMP<0x10, FGR32, "s">; + def FCMP_D32 : FCMP<0x11, AFGR64, "d">, Requires<[NotFP64bit]>; + def FCMP_D64 : FCMP<0x11, FGR64, "d">, Requires<[IsFP64bit]>; } //===----------------------------------------------------------------------===// @@ -309,13 +317,28 @@ def : Pat<(f32 fpimm0), (MTC1 ZERO)>; def : Pat<(f32 fpimm0neg), (FNEG_S (MTC1 ZERO))>; 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_S FGR32:$src))>; -def : Pat<(i32 (fp_to_sint AFGR64:$src)), (MFC1 (TRUNC_W_D32 AFGR64:$src))>; let Predicates = [NotFP64bit] in { + def : Pat<(f64 (sint_to_fp CPURegs:$src)), (CVT_D32_W (MTC1 CPURegs:$src))>; + def : Pat<(i32 (fp_to_sint AFGR64:$src)), (MFC1 (TRUNC_W_D32 AFGR64:$src))>; def : Pat<(f32 (fround AFGR64:$src)), (CVT_S_D32 AFGR64:$src)>; def : Pat<(f64 (fextend FGR32:$src)), (CVT_D32_S FGR32:$src)>; } +let Predicates = [IsFP64bit] in { + def : Pat<(f64 fpimm0), (DMTC1 ZERO_64)>; + def : Pat<(f64 fpimm0neg), (FNEG_D64 (DMTC1 ZERO_64))>; + + def : Pat<(f64 (sint_to_fp CPURegs:$src)), (CVT_D64_W (MTC1 CPURegs:$src))>; + def : Pat<(f32 (sint_to_fp CPU64Regs:$src)), + (CVT_S_L (DMTC1 CPU64Regs:$src))>; + def : Pat<(f64 (sint_to_fp CPU64Regs:$src)), + (CVT_D64_L (DMTC1 CPU64Regs:$src))>; + + def : Pat<(i32 (fp_to_sint FGR64:$src)), (MFC1 (TRUNC_W_D64 FGR64:$src))>; + def : Pat<(i64 (fp_to_sint FGR64:$src)), (DMFC1 (TRUNC_L_D64 FGR64:$src))>; + + def : Pat<(f32 (fround FGR64:$src)), (CVT_S_D64 FGR64:$src)>; + def : Pat<(f64 (fextend FGR32:$src)), (CVT_D64_S FGR32:$src)>; +}
\ No newline at end of file diff --git a/lib/Target/Mips/MipsInstrFormats.td b/lib/Target/Mips/MipsInstrFormats.td index e1725fa..21a1862 100644 --- a/lib/Target/Mips/MipsInstrFormats.td +++ b/lib/Target/Mips/MipsInstrFormats.td @@ -115,7 +115,7 @@ 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, +class BranchBase<bits<6> op, dag outs, dag ins, string asmstr, list<dag> pattern, InstrItinClass itin>: MipsInst<outs, ins, asmstr, pattern, itin, FrmI> { diff --git a/lib/Target/Mips/MipsInstrInfo.cpp b/lib/Target/Mips/MipsInstrInfo.cpp index 559943a..ea101f7 100644 --- a/lib/Target/Mips/MipsInstrInfo.cpp +++ b/lib/Target/Mips/MipsInstrInfo.cpp @@ -29,8 +29,8 @@ using namespace llvm; MipsInstrInfo::MipsInstrInfo(MipsTargetMachine &tm) : MipsGenInstrInfo(Mips::ADJCALLSTACKDOWN, Mips::ADJCALLSTACKUP), TM(tm), IsN64(TM.getSubtarget<MipsSubtarget>().isABI_N64()), - RI(*TM.getSubtargetImpl(), *this) {} - + RI(*TM.getSubtargetImpl(), *this), + UncondBrOpc(TM.getRelocationModel() == Reloc::PIC_ ? Mips::B : Mips::J) {} const MipsRegisterInfo &MipsInstrInfo::getRegisterInfo() const { return RI; @@ -131,6 +131,8 @@ copyPhysReg(MachineBasicBlock &MBB, Opc = Mips::FMOV_S; else if (Mips::AFGR64RegClass.contains(DestReg, SrcReg)) Opc = Mips::FMOV_D32; + else if (Mips::FGR64RegClass.contains(DestReg, SrcReg)) + Opc = Mips::FMOV_D64; else if (Mips::CCRRegClass.contains(DestReg, SrcReg)) Opc = Mips::MOVCCRToCCR; else if (Mips::CPU64RegsRegClass.contains(DestReg)) { // Copy to CPU64 Reg. @@ -140,12 +142,16 @@ copyPhysReg(MachineBasicBlock &MBB, Opc = Mips::MFHI64, SrcReg = 0; else if (SrcReg == Mips::LO64) Opc = Mips::MFLO64, SrcReg = 0; + else if (Mips::FGR64RegClass.contains(SrcReg)) + Opc = Mips::DMFC1; } 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; + else if (Mips::FGR64RegClass.contains(DestReg)) + Opc = Mips::DMTC1; } assert(Opc && "Cannot copy registers"); @@ -230,7 +236,8 @@ static unsigned GetAnalyzableBrOpc(unsigned Opc) { 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 == Mips::BC1T || Opc == Mips::BC1F || Opc == Mips::B || + Opc == Mips::J) ? Opc : 0; } @@ -314,7 +321,7 @@ bool MipsInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, // If there is only one terminator instruction, process it. if (!SecondLastOpc) { // Unconditional branch - if (LastOpc == Mips::J) { + if (LastOpc == UncondBrOpc) { TBB = LastInst->getOperand(0).getMBB(); return false; } @@ -331,7 +338,7 @@ bool MipsInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, // If second to last instruction is an unconditional branch, // analyze it and remove the last instruction. - if (SecondLastOpc == Mips::J) { + if (SecondLastOpc == UncondBrOpc) { // Return if the last instruction cannot be removed. if (!AllowModify) return true; @@ -343,7 +350,7 @@ bool MipsInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, // Conditional branch followed by an unconditional branch. // The last one must be unconditional. - if (LastOpc != Mips::J) + if (LastOpc != UncondBrOpc) return true; AnalyzeCondBr(SecondLastInst, SecondLastOpc, TBB, Cond); @@ -385,14 +392,14 @@ InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, // Two-way Conditional branch. if (FBB) { BuildCondBr(MBB, TBB, DL, Cond); - BuildMI(&MBB, DL, get(Mips::J)).addMBB(FBB); + BuildMI(&MBB, DL, get(UncondBrOpc)).addMBB(FBB); return 2; } // One way branch. // Unconditional branch. if (Cond.empty()) - BuildMI(&MBB, DL, get(Mips::J)).addMBB(TBB); + BuildMI(&MBB, DL, get(UncondBrOpc)).addMBB(TBB); else // Conditional branch. BuildCondBr(MBB, TBB, DL, Cond); return 1; diff --git a/lib/Target/Mips/MipsInstrInfo.h b/lib/Target/Mips/MipsInstrInfo.h index 271d248..70cc2cf 100644 --- a/lib/Target/Mips/MipsInstrInfo.h +++ b/lib/Target/Mips/MipsInstrInfo.h @@ -30,90 +30,11 @@ namespace Mips { unsigned GetOppositeBranchOpc(unsigned Opc); } -/// MipsII - This namespace holds all of the target specific flags that -/// instruction info tracks. -/// -namespace MipsII { - /// Target Operand Flag enum. - enum TOF { - //===------------------------------------------------------------------===// - // Mips Specific MachineOperand flags. - - MO_NO_FLAG, - - /// MO_GOT - Represents the offset into the global offset table at which - /// the address the relocation entry symbol resides during execution. - MO_GOT, - - /// MO_GOT_CALL - Represents the offset into the global offset table at - /// which the address of a call site relocation entry symbol resides - /// during execution. This is different from the above since this flag - /// can only be present in call instructions. - MO_GOT_CALL, - - /// MO_GPREL - Represents the offset from the current gp value to be used - /// for the relocatable object file being produced. - MO_GPREL, - - /// MO_ABS_HI/LO - Represents the hi or low part of an absolute symbol - /// address. - MO_ABS_HI, - MO_ABS_LO, - - /// MO_TLSGD - Represents the offset into the global offset table at which - // the module ID and TSL block offset reside during execution (General - // Dynamic TLS). - MO_TLSGD, - - /// MO_GOTTPREL - Represents the offset from the thread pointer (Initial - // Exec TLS). - MO_GOTTPREL, - - /// MO_TPREL_HI/LO - Represents the hi and low part of the offset from - // the thread pointer (Local Exec TLS). - MO_TPREL_HI, - MO_TPREL_LO, - - // N32/64 Flags. - MO_GPOFF_HI, - MO_GPOFF_LO, - MO_GOT_DISP, - MO_GOT_PAGE, - MO_GOT_OFST - }; - - 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; + unsigned UncondBrOpc; public: explicit MipsInstrInfo(MipsTargetMachine &TM); diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td index fd99b13..9fcc5fd 100644 --- a/lib/Target/Mips/MipsInstrInfo.td +++ b/lib/Target/Mips/MipsInstrInfo.td @@ -39,8 +39,8 @@ def SDT_MipsDivRem : SDTypeProfile<0, 2, def SDT_MipsThreadPointer : SDTypeProfile<1, 0, [SDTCisPtrTy<0>]>; -def SDT_MipsDynAlloc : SDTypeProfile<1, 1, [SDTCisVT<0, i32>, - SDTCisVT<1, iPTR>]>; +def SDT_MipsDynAlloc : SDTypeProfile<1, 1, [SDTCisVT<0, iPTR>, + SDTCisSameAs<0, 1>]>; def SDT_Sync : SDTypeProfile<0, 1, [SDTCisVT<0, i32>]>; def SDT_Ext : SDTypeProfile<1, 3, [SDTCisInt<0>, SDTCisSameAs<0, 1>, @@ -107,7 +107,7 @@ def MipsDivRemU : SDNode<"MipsISD::DivRemU", SDT_MipsDivRem, // movn %got(d)($gp), %got(c)($gp), $4 // This instruction is illegal since movn can take only register operands. -def MipsWrapperPIC : SDNode<"MipsISD::WrapperPIC", SDTIntUnaryOp>; +def MipsWrapper : SDNode<"MipsISD::Wrapper", SDTIntUnaryOp>; // Pointer to dynamically allocated stack area. def MipsDynAlloc : SDNode<"MipsISD::DynAlloc", SDT_MipsDynAlloc, @@ -132,14 +132,25 @@ def NotMips64 : Predicate<"!Subtarget.hasMips64()">; def HasMips64r2 : Predicate<"Subtarget.hasMips64r2()">; def IsN64 : Predicate<"Subtarget.isABI_N64()">; def NotN64 : Predicate<"!Subtarget.isABI_N64()">; +def RelocStatic : Predicate<"TM.getRelocationModel() == Reloc::Static">; +def RelocPIC : Predicate<"TM.getRelocationModel() == Reloc::PIC_">; //===----------------------------------------------------------------------===// // Mips Operand, Complex Patterns and Transformations Definitions. //===----------------------------------------------------------------------===// // Instruction operand types -def brtarget : Operand<OtherVT>; -def calltarget : Operand<i32>; +def jmptarget : Operand<OtherVT> { + let EncoderMethod = "getJumpTargetOpValue"; +} +def brtarget : Operand<OtherVT> { + let EncoderMethod = "getBranchTargetOpValue"; + let OperandType = "OPERAND_PCREL"; +} +def calltarget : Operand<iPTR> { + let EncoderMethod = "getJumpTargetOpValue"; +} +def calltarget64: Operand<i64>; def simm16 : Operand<i32>; def simm16_64 : Operand<i64>; def shamt : Operand<i32>; @@ -167,6 +178,12 @@ def mem_ea : Operand<i32> { let EncoderMethod = "getMemEncoding"; } +def mem_ea_64 : Operand<i64> { + let PrintMethod = "printMemOperandEA"; + let MIOperandInfo = (ops CPU64Regs, simm16_64); + let EncoderMethod = "getMemEncoding"; +} + // size operand of ext instruction def size_ext : Operand<i32> { let EncoderMethod = "getSizeExtEncoding"; @@ -179,12 +196,12 @@ def size_ins : Operand<i32> { // Transformation Function - get the lower 16 bits. def LO16 : SDNodeXForm<imm, [{ - return getI32Imm((unsigned)N->getZExtValue() & 0xFFFF); + return getImm(N, N->getZExtValue() & 0xFFFF); }]>; // Transformation Function - get the higher 16 bits. def HI16 : SDNodeXForm<imm, [{ - return getI32Imm((unsigned)N->getZExtValue() >> 16); + return getImm(N, (N->getZExtValue() >> 16) & 0xFFFF); }]>; // Node immediate fits as 16-bit sign extended on target immediate. @@ -327,15 +344,15 @@ class shift_rotate_imm32<bits<6> func, bits<5> isRotate, string instr_asm, class shift_rotate_reg<bits<6> func, bits<5> isRotate, string instr_asm, SDNode OpNode, RegisterClass RC>: - FR<0x00, func, (outs RC:$rd), (ins RC:$rs, RC:$rt), + FR<0x00, func, (outs RC:$rd), (ins CPURegs:$rs, RC:$rt), !strconcat(instr_asm, "\t$rd, $rt, $rs"), - [(set RC:$rd, (OpNode RC:$rt, RC:$rs))], IIAlu> { + [(set RC:$rd, (OpNode RC:$rt, CPURegs:$rs))], IIAlu> { let shamt = isRotate; } // Load Upper Imediate -class LoadUpper<bits<6> op, string instr_asm>: - FI<op, (outs CPURegs:$rt), (ins uimm16:$imm16), +class LoadUpper<bits<6> op, string instr_asm, RegisterClass RC, Operand Imm>: + FI<op, (outs RC:$rt), (ins Imm:$imm16), !strconcat(instr_asm, "\t$rt, $imm16"), [], IIAlu> { let rs = 0; } @@ -365,6 +382,14 @@ class StoreM<bits<6> op, string instr_asm, PatFrag OpNode, RegisterClass RC, let isPseudo = Pseudo; } +// Unaligned Memory Load/Store +let canFoldAsLoad = 1 in +class LoadUnAlign<bits<6> op, RegisterClass RC, Operand MemOpnd>: + FMem<op, (outs RC:$rt), (ins MemOpnd:$addr), "", [], IILoad> {} + +class StoreUnAlign<bits<6> op, RegisterClass RC, Operand MemOpnd>: + FMem<op, (outs), (ins RC:$rt, MemOpnd:$addr), "", [], IIStore> {} + // 32-bit load. multiclass LoadM32<bits<6> op, string instr_asm, PatFrag OpNode, bit Pseudo = 0> { @@ -383,6 +408,13 @@ multiclass LoadM64<bits<6> op, string instr_asm, PatFrag OpNode, Requires<[IsN64]>; } +// 32-bit load. +multiclass LoadUnAlign32<bits<6> op> { + def #NAME# : LoadUnAlign<op, CPURegs, mem>, + Requires<[NotN64]>; + def _P8 : LoadUnAlign<op, CPURegs, mem64>, + Requires<[IsN64]>; +} // 32-bit store. multiclass StoreM32<bits<6> op, string instr_asm, PatFrag OpNode, bit Pseudo = 0> { @@ -401,11 +433,19 @@ multiclass StoreM64<bits<6> op, string instr_asm, PatFrag OpNode, Requires<[IsN64]>; } +// 32-bit store. +multiclass StoreUnAlign32<bits<6> op> { + def #NAME# : StoreUnAlign<op, CPURegs, mem>, + Requires<[NotN64]>; + def _P8 : StoreUnAlign<op, CPURegs, mem64>, + Requires<[IsN64]>; +} + // Conditional Branch class CBranch<bits<6> op, string instr_asm, PatFrag cond_op, RegisterClass RC>: - CBranchBase<op, (outs), (ins RC:$rs, RC:$rt, brtarget:$imm16), - !strconcat(instr_asm, "\t$rs, $rt, $imm16"), - [(brcond (i32 (cond_op RC:$rs, RC:$rt)), bb:$imm16)], IIBranch> { + BranchBase<op, (outs), (ins RC:$rs, RC:$rt, brtarget:$imm16), + !strconcat(instr_asm, "\t$rs, $rt, $imm16"), + [(brcond (i32 (cond_op RC:$rs, RC:$rt)), bb:$imm16)], IIBranch> { let isBranch = 1; let isTerminator = 1; let hasDelaySlot = 1; @@ -413,9 +453,9 @@ class CBranch<bits<6> op, string instr_asm, PatFrag cond_op, RegisterClass RC>: class CBranchZero<bits<6> op, bits<5> _rt, string instr_asm, PatFrag cond_op, RegisterClass RC>: - CBranchBase<op, (outs), (ins RC:$rs, brtarget:$imm16), - !strconcat(instr_asm, "\t$rs, $imm16"), - [(brcond (i32 (cond_op RC:$rs, 0)), bb:$imm16)], IIBranch> { + BranchBase<op, (outs), (ins RC:$rs, brtarget:$imm16), + !strconcat(instr_asm, "\t$rs, $imm16"), + [(brcond (i32 (cond_op RC:$rs, 0)), bb:$imm16)], IIBranch> { let rt = _rt; let isBranch = 1; let isTerminator = 1; @@ -439,16 +479,35 @@ class SetCC_I<bits<6> op, string instr_asm, PatFrag cond_op, Operand Od, [(set CPURegs:$rt, (cond_op RC:$rs, imm_type:$imm16))], IIAlu>; -// Unconditional branch -let isBranch=1, isTerminator=1, isBarrier=1, hasDelaySlot = 1 in +// Jump class JumpFJ<bits<6> op, string instr_asm>: - FJ<op, (outs), (ins brtarget:$target), - !strconcat(instr_asm, "\t$target"), [(br bb:$target)], IIBranch>; + FJ<op, (outs), (ins jmptarget:$target), + !strconcat(instr_asm, "\t$target"), [(br bb:$target)], IIBranch> { + let isBranch=1; + let isTerminator=1; + let isBarrier=1; + let hasDelaySlot = 1; + let Predicates = [RelocStatic]; +} + +// Unconditional branch +class UncondBranch<bits<6> op, string instr_asm>: + BranchBase<op, (outs), (ins brtarget:$imm16), + !strconcat(instr_asm, "\t$imm16"), [(br bb:$imm16)], IIBranch> { + let rs = 0; + let rt = 0; + let isBranch = 1; + let isTerminator = 1; + let isBarrier = 1; + let hasDelaySlot = 1; + let Predicates = [RelocPIC]; +} -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:$rs), - !strconcat(instr_asm, "\t$rs"), [(brind CPURegs:$rs)], IIBranch> { +let isBranch=1, isTerminator=1, isBarrier=1, rd=0, hasDelaySlot = 1, + isIndirectBranch = 1 in +class JumpFR<bits<6> op, bits<6> func, string instr_asm, RegisterClass RC>: + FR<op, func, (outs), (ins RC:$rs), + !strconcat(instr_asm, "\t$rs"), [(brind RC:$rs)], IIBranch> { let rt = 0; let rd = 0; let shamt = 0; @@ -525,9 +584,9 @@ class MoveToLOHI<bits<6> func, string instr_asm, RegisterClass RC, let Defs = DefRegs; } -class EffectiveAddress<string instr_asm> : - FMem<0x09, (outs CPURegs:$rt), (ins mem_ea:$addr), - instr_asm, [(set CPURegs:$rt, addr:$addr)], IIAlu>; +class EffectiveAddress<string instr_asm, RegisterClass RC, Operand Mem> : + FMem<0x09, (outs RC:$rt), (ins Mem:$addr), + instr_asm, [(set RC:$rt, addr:$addr)], IIAlu>; // Count Leading Ones/Zeros in Word class CountLeading0<bits<6> func, string instr_asm, RegisterClass RC>: @@ -569,38 +628,75 @@ class ByteSwap<bits<6> func, bits<5> sa, string instr_asm>: } // Read Hardware -class ReadHardware: FR<0x1f, 0x3b, (outs CPURegs:$rt), (ins HWRegs:$rd), - "rdhwr\t$rt, $rd", [], IIAlu> { +class ReadHardware<RegisterClass CPURegClass, RegisterClass HWRegClass> + : FR<0x1f, 0x3b, (outs CPURegClass:$rt), (ins HWRegClass:$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]> { +class ExtBase<bits<6> _funct, string instr_asm, RegisterClass RC>: + FR<0x1f, _funct, (outs RC:$rt), (ins RC:$rs, uimm16:$pos, size_ext:$sz), + !strconcat(instr_asm, " $rt, $rs, $pos, $sz"), + [(set RC:$rt, (MipsExt RC:$rs, imm:$pos, imm:$sz))], NoItinerary> { bits<5> pos; bits<5> sz; let rd = sz; let shamt = pos; + let Predicates = [HasMips32r2]; +} + +class InsBase<bits<6> _funct, string instr_asm, RegisterClass RC>: + FR<0x1f, _funct, (outs RC:$rt), + (ins RC:$rs, uimm16:$pos, size_ins:$sz, RC:$src), + !strconcat(instr_asm, " $rt, $rs, $pos, $sz"), + [(set RC:$rt, (MipsIns RC:$rs, imm:$pos, imm:$sz, RC:$src))], + NoItinerary> { + bits<5> pos; + bits<5> sz; + let rd = sz; + let shamt = pos; + let Predicates = [HasMips32r2]; + let Constraints = "$src = $rt"; } // 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), +class Atomic2Ops<PatFrag Op, string Opstr, RegisterClass DRC, + RegisterClass PRC> : + MipsPseudo<(outs DRC:$dst), (ins PRC:$ptr, DRC:$incr), !strconcat("atomic_", Opstr, "\t$dst, $ptr, $incr"), - [(set CPURegs:$dst, - (Op CPURegs:$ptr, CPURegs:$incr))]>; + [(set DRC:$dst, (Op PRC:$ptr, DRC:$incr))]>; + +multiclass Atomic2Ops32<PatFrag Op, string Opstr> { + def #NAME# : Atomic2Ops<Op, Opstr, CPURegs, CPURegs>, Requires<[NotN64]>; + def _P8 : Atomic2Ops<Op, Opstr, CPURegs, CPU64Regs>, Requires<[IsN64]>; +} // 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))]>; +class AtomicCmpSwap<PatFrag Op, string Width, RegisterClass DRC, + RegisterClass PRC> : + MipsPseudo<(outs DRC:$dst), (ins PRC:$ptr, DRC:$cmp, DRC:$swap), + !strconcat("atomic_cmp_swap_", Width, "\t$dst, $ptr, $cmp, $swap"), + [(set DRC:$dst, (Op PRC:$ptr, DRC:$cmp, DRC:$swap))]>; + +multiclass AtomicCmpSwap32<PatFrag Op, string Width> { + def #NAME# : AtomicCmpSwap<Op, Width, CPURegs, CPURegs>, Requires<[NotN64]>; + def _P8 : AtomicCmpSwap<Op, Width, CPURegs, CPU64Regs>, Requires<[IsN64]>; +} + +class LLBase<bits<6> Opc, string opstring, RegisterClass RC, Operand Mem> : + FMem<Opc, (outs RC:$rt), (ins Mem:$addr), + !strconcat(opstring, "\t$rt, $addr"), [], IILoad> { + let mayLoad = 1; +} + +class SCBase<bits<6> Opc, string opstring, RegisterClass RC, Operand Mem> : + FMem<Opc, (outs RC:$dst), (ins RC:$rt, Mem:$addr), + !strconcat(opstring, "\t$rt, $addr"), [], IIStore> { + let mayStore = 1; + let Constraints = "$rt = $dst"; +} //===----------------------------------------------------------------------===// // Pseudo instructions @@ -636,32 +732,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 : 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">; + defm ATOMIC_LOAD_ADD_I8 : Atomic2Ops32<atomic_load_add_8, "load_add_8">; + defm ATOMIC_LOAD_ADD_I16 : Atomic2Ops32<atomic_load_add_16, "load_add_16">; + defm ATOMIC_LOAD_ADD_I32 : Atomic2Ops32<atomic_load_add_32, "load_add_32">; + defm ATOMIC_LOAD_SUB_I8 : Atomic2Ops32<atomic_load_sub_8, "load_sub_8">; + defm ATOMIC_LOAD_SUB_I16 : Atomic2Ops32<atomic_load_sub_16, "load_sub_16">; + defm ATOMIC_LOAD_SUB_I32 : Atomic2Ops32<atomic_load_sub_32, "load_sub_32">; + defm ATOMIC_LOAD_AND_I8 : Atomic2Ops32<atomic_load_and_8, "load_and_8">; + defm ATOMIC_LOAD_AND_I16 : Atomic2Ops32<atomic_load_and_16, "load_and_16">; + defm ATOMIC_LOAD_AND_I32 : Atomic2Ops32<atomic_load_and_32, "load_and_32">; + defm ATOMIC_LOAD_OR_I8 : Atomic2Ops32<atomic_load_or_8, "load_or_8">; + defm ATOMIC_LOAD_OR_I16 : Atomic2Ops32<atomic_load_or_16, "load_or_16">; + defm ATOMIC_LOAD_OR_I32 : Atomic2Ops32<atomic_load_or_32, "load_or_32">; + defm ATOMIC_LOAD_XOR_I8 : Atomic2Ops32<atomic_load_xor_8, "load_xor_8">; + defm ATOMIC_LOAD_XOR_I16 : Atomic2Ops32<atomic_load_xor_16, "load_xor_16">; + defm ATOMIC_LOAD_XOR_I32 : Atomic2Ops32<atomic_load_xor_32, "load_xor_32">; + defm ATOMIC_LOAD_NAND_I8 : Atomic2Ops32<atomic_load_nand_8, "load_nand_8">; + defm ATOMIC_LOAD_NAND_I16 : Atomic2Ops32<atomic_load_nand_16, "load_nand_16">; + defm ATOMIC_LOAD_NAND_I32 : Atomic2Ops32<atomic_load_nand_32, "load_nand_32">; + + defm ATOMIC_SWAP_I8 : Atomic2Ops32<atomic_swap_8, "swap_8">; + defm ATOMIC_SWAP_I16 : Atomic2Ops32<atomic_swap_16, "swap_16">; + defm ATOMIC_SWAP_I32 : Atomic2Ops32<atomic_swap_32, "swap_32">; + + defm ATOMIC_CMP_SWAP_I8 : AtomicCmpSwap32<atomic_cmp_swap_8, "8">; + defm ATOMIC_CMP_SWAP_I16 : AtomicCmpSwap32<atomic_cmp_swap_16, "16">; + defm ATOMIC_CMP_SWAP_I32 : AtomicCmpSwap32<atomic_cmp_swap_32, "32">; } //===----------------------------------------------------------------------===// @@ -680,7 +776,7 @@ 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">; +def LUi : LoadUpper<0x0f, "lui", CPURegs, uimm16>; /// Arithmetic Instructions (3-Operand, R-Type) def ADDu : ArithLogicR<0x00, 0x21, "addu", add, IIAlu, CPURegs, 1>; @@ -726,6 +822,12 @@ defm ULW : LoadM32<0x23, "ulw", load_u, 1>; defm USH : StoreM32<0x29, "ush", truncstorei16_u, 1>; defm USW : StoreM32<0x2b, "usw", store_u, 1>; +/// Primitives for unaligned +defm LWL : LoadUnAlign32<0x22>; +defm LWR : LoadUnAlign32<0x26>; +defm SWL : StoreUnAlign32<0x2A>; +defm SWR : StoreUnAlign32<0x2E>; + let hasSideEffects = 1 in def SYNC : MipsInst<(outs), (ins i32imm:$stype), "sync $stype", [(MipsSync imm:$stype)], NoItinerary, FrmOther> @@ -738,19 +840,17 @@ def SYNC : MipsInst<(outs), (ins i32imm:$stype), "sync $stype", } /// Load-linked, Store-conditional -let mayLoad = 1 in - def LL : FMem<0x30, (outs CPURegs:$rt), (ins mem:$addr), - "ll\t$rt, $addr", [], IILoad>; -let mayStore = 1, Constraints = "$rt = $dst" in - def SC : FMem<0x38, (outs CPURegs:$dst), (ins CPURegs:$rt, mem:$addr), - "sc\t$rt, $addr", [], IIStore>; +def LL : LLBase<0x30, "ll", CPURegs, mem>, Requires<[NotN64]>; +def LL_P8 : LLBase<0x30, "ll", CPURegs, mem64>, Requires<[IsN64]>; +def SC : SCBase<0x38, "sc", CPURegs, mem>, Requires<[NotN64]>; +def SC_P8 : SCBase<0x38, "sc", CPURegs, mem64>, Requires<[IsN64]>; /// Jump and Branch Instructions def J : JumpFJ<0x02, "j">; -let isIndirectBranch = 1 in - def JR : JumpFR<0x00, 0x08, "jr">; +def JR : JumpFR<0x00, 0x08, "jr", CPURegs>; def JAL : JumpLink<0x03, "jal">; def JALR : JumpLinkReg<0x00, 0x09, "jalr">; +def B : UncondBranch<0x04, "b">; def BEQ : CBranch<0x04, "beq", seteq, CPURegs>; def BNE : CBranch<0x05, "bne", setne, CPURegs>; def BGEZ : CBranchZero<0x01, 1, "bgez", setge, CPURegs>; @@ -798,13 +898,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$rt, $addr">; +def LEA_ADDiu : EffectiveAddress<"addiu\t$rt, $addr", CPURegs, mem_ea>; // 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$rt, $addr">; +def DynAlloc : EffectiveAddress<"addiu\t$rt, $addr", CPURegs, mem_ea>; // MADD*/MSUB* def MADD : MArithR<0, "madd", MipsMAdd, 1>; @@ -817,21 +917,10 @@ def MSUBU : MArithR<5, "msubu", MipsMSubu>; def MUL : ArithLogicR<0x1c, 0x02, "mul", mul, IIImul, CPURegs, 1>, Requires<[HasMips32]>; -def RDHWR : ReadHardware; +def RDHWR : ReadHardware<CPURegs, HWRegs>; -def EXT : ExtIns<0, "ext", (outs CPURegs:$rt), - (ins CPURegs:$rs, uimm16:$pos, size_ext:$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, size_ins:$sz, CPURegs:$src), - [(set CPURegs:$rt, - (MipsIns CPURegs:$rs, immZExt5:$pos, immZExt5:$sz, - CPURegs:$src))], - NoItinerary>; +def EXT : ExtBase<0, "ext", CPURegs>; +def INS : InsBase<4, "ins", CPURegs>; //===----------------------------------------------------------------------===// // Arbitrary patterns that map to one or more instructions @@ -866,22 +955,26 @@ 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<(MipsHi tjumptable:$in), (LUi tjumptable:$in)>; +def : Pat<(MipsHi tconstpool:$in), (LUi tconstpool:$in)>; +def : Pat<(MipsHi tglobaltlsaddr:$in), (LUi tglobaltlsaddr:$in)>; + def : Pat<(MipsLo tglobaladdr:$in), (ADDiu ZERO, tglobaladdr:$in)>; def : Pat<(MipsLo tblockaddress:$in), (ADDiu ZERO, tblockaddress:$in)>; +def : Pat<(MipsLo tjumptable:$in), (ADDiu ZERO, tjumptable:$in)>; +def : Pat<(MipsLo tconstpool:$in), (ADDiu ZERO, tconstpool:$in)>; +def : Pat<(MipsLo tglobaltlsaddr:$in), (ADDiu ZERO, tglobaltlsaddr:$in)>; + def : Pat<(add CPURegs:$hi, (MipsLo tglobaladdr:$lo)), (ADDiu CPURegs:$hi, tglobaladdr:$lo)>; def : Pat<(add CPURegs:$hi, (MipsLo tblockaddress:$lo)), (ADDiu CPURegs:$hi, tblockaddress:$lo)>; - -def : Pat<(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)>; +def : Pat<(add CPURegs:$hi, (MipsLo tglobaltlsaddr:$lo)), + (ADDiu CPURegs:$hi, tglobaltlsaddr:$lo)>; // gp_rel relocs def : Pat<(add CPURegs:$gp, (MipsGPRel tglobaladdr:$in)), @@ -889,26 +982,17 @@ def : Pat<(add CPURegs:$gp, (MipsGPRel tglobaladdr:$in)), def : Pat<(add CPURegs:$gp, (MipsGPRel tconstpool:$in)), (ADDiu CPURegs:$gp, tconstpool:$in)>; -// tlsgd -def : Pat<(add CPURegs:$gp, (MipsTlsGd tglobaltlsaddr:$in)), - (ADDiu CPURegs:$gp, 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)>; - // wrapper_pic -class WrapperPICPat<SDNode node>: - Pat<(MipsWrapperPIC node:$in), - (ADDiu GP, node:$in)>; - -def : WrapperPICPat<tglobaladdr>; -def : WrapperPICPat<tconstpool>; -def : WrapperPICPat<texternalsym>; -def : WrapperPICPat<tblockaddress>; -def : WrapperPICPat<tjumptable>; +class WrapperPat<SDNode node, Instruction ADDiuOp, Register GPReg>: + Pat<(MipsWrapper node:$in), + (ADDiuOp GPReg, node:$in)>; + +def : WrapperPat<tglobaladdr, ADDiu, GP>; +def : WrapperPat<tconstpool, ADDiu, GP>; +def : WrapperPat<texternalsym, ADDiu, GP>; +def : WrapperPat<tblockaddress, ADDiu, GP>; +def : WrapperPat<tjumptable, ADDiu, GP>; +def : WrapperPat<tglobaltlsaddr, ADDiu, GP>; // Mips does not have "not", so we expand our way def : Pat<(not CPURegs:$in), diff --git a/lib/Target/Mips/MipsJITInfo.cpp b/lib/Target/Mips/MipsJITInfo.cpp index 28c2b48..a0ee722 100644 --- a/lib/Target/Mips/MipsJITInfo.cpp +++ b/lib/Target/Mips/MipsJITInfo.cpp @@ -57,11 +57,11 @@ void MipsCompilationCallback(); ".globl " ASMPREFIX "MipsCompilationCallback\n" ASMPREFIX "MipsCompilationCallback:\n" ".ent " ASMPREFIX "MipsCompilationCallback\n" - ".frame $29, 32, $31\n" + ".frame $sp, 32, $ra\n" ".set noreorder\n" ".cpload $t9\n" - "addiu $sp, $sp, -60\n" + "addiu $sp, $sp, -64\n" ".cprestore 16\n" // Save argument registers a0, a1, a2, a3, f12, f14 since they may contain @@ -76,8 +76,8 @@ void MipsCompilationCallback(); "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" + "sdc1 $f12, 48($sp)\n" + "sdc1 $f14, 56($sp)\n" // t8 points at the end of function stub. Pass the beginning of the stub // to the MipsCompilationCallbackC. @@ -92,9 +92,9 @@ void MipsCompilationCallback(); "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" + "ldc1 $f12, 48($sp)\n" + "ldc1 $f14, 56($sp)\n" + "addiu $sp, $sp, 64\n" // Jump to the (newly modified) stub to invoke the real function. "addiu $t8, $t8, -16\n" @@ -218,10 +218,16 @@ void MipsJITInfo::relocate(void *Function, MachineRelocation *MR, *((unsigned*) RelocPos) |= (unsigned) ResultPtr; break; - case Mips::reloc_mips_lo: - ResultPtr = ResultPtr & 0xffff; + case Mips::reloc_mips_lo: { + // Addend is needed for unaligned load/store instructions, where offset + // for the second load/store in the expanded instruction sequence must + // be modified by +1 or +3. Otherwise, Addend is 0. + int Addend = *((unsigned*) RelocPos) & 0xffff; + ResultPtr = (ResultPtr + Addend) & 0xffff; + *((unsigned*) RelocPos) &= 0xffff0000; *((unsigned*) RelocPos) |= (unsigned) ResultPtr; break; + } default: llvm_unreachable("ERROR: Unknown Mips relocation."); diff --git a/lib/Target/Mips/MipsMCInstLower.cpp b/lib/Target/Mips/MipsMCInstLower.cpp index 608a7d2..23486d3 100644 --- a/lib/Target/Mips/MipsMCInstLower.cpp +++ b/lib/Target/Mips/MipsMCInstLower.cpp @@ -12,16 +12,18 @@ // //===----------------------------------------------------------------------===// -#include "MipsMCInstLower.h" #include "MipsAsmPrinter.h" #include "MipsInstrInfo.h" -#include "MipsMCSymbolRefExpr.h" +#include "MipsMCInstLower.h" +#include "MCTargetDesc/MipsBaseInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineOperand.h" #include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" #include "llvm/Target/Mangler.h" + using namespace llvm; MipsMCInstLower::MipsMCInstLower(Mangler *mang, const MachineFunction &mf, @@ -31,64 +33,146 @@ MipsMCInstLower::MipsMCInstLower(Mangler *mang, const MachineFunction &mf, MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO, MachineOperandType MOTy, unsigned Offset) const { - MipsMCSymbolRefExpr::VariantKind Kind; + MCSymbolRefExpr::VariantKind Kind; const MCSymbol *Symbol; switch(MO.getTargetFlags()) { default: assert(0 && "Invalid target flag!"); - case MipsII::MO_NO_FLAG: Kind = MipsMCSymbolRefExpr::VK_Mips_None; break; - case MipsII::MO_GPREL: Kind = MipsMCSymbolRefExpr::VK_Mips_GPREL; break; - case MipsII::MO_GOT_CALL: Kind = MipsMCSymbolRefExpr::VK_Mips_GOT_CALL; break; - case MipsII::MO_GOT: Kind = MipsMCSymbolRefExpr::VK_Mips_GOT; break; - case MipsII::MO_ABS_HI: Kind = MipsMCSymbolRefExpr::VK_Mips_ABS_HI; break; - case MipsII::MO_ABS_LO: Kind = MipsMCSymbolRefExpr::VK_Mips_ABS_LO; break; - case MipsII::MO_TLSGD: Kind = MipsMCSymbolRefExpr::VK_Mips_TLSGD; break; - 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; + case MipsII::MO_NO_FLAG: Kind = MCSymbolRefExpr::VK_None; break; + case MipsII::MO_GPREL: Kind = MCSymbolRefExpr::VK_Mips_GPREL; break; + case MipsII::MO_GOT_CALL: Kind = MCSymbolRefExpr::VK_Mips_GOT_CALL; break; + case MipsII::MO_GOT16: Kind = MCSymbolRefExpr::VK_Mips_GOT16; break; + case MipsII::MO_GOT: Kind = MCSymbolRefExpr::VK_Mips_GOT; break; + case MipsII::MO_ABS_HI: Kind = MCSymbolRefExpr::VK_Mips_ABS_HI; break; + case MipsII::MO_ABS_LO: Kind = MCSymbolRefExpr::VK_Mips_ABS_LO; break; + case MipsII::MO_TLSGD: Kind = MCSymbolRefExpr::VK_Mips_TLSGD; break; + case MipsII::MO_TLSLDM: Kind = MCSymbolRefExpr::VK_Mips_TLSLDM; break; + case MipsII::MO_DTPREL_HI:Kind = MCSymbolRefExpr::VK_Mips_DTPREL_HI; break; + case MipsII::MO_DTPREL_LO:Kind = MCSymbolRefExpr::VK_Mips_DTPREL_LO; break; + case MipsII::MO_GOTTPREL: Kind = MCSymbolRefExpr::VK_Mips_GOTTPREL; break; + case MipsII::MO_TPREL_HI: Kind = MCSymbolRefExpr::VK_Mips_TPREL_HI; break; + case MipsII::MO_TPREL_LO: Kind = MCSymbolRefExpr::VK_Mips_TPREL_LO; break; + case MipsII::MO_GPOFF_HI: Kind = MCSymbolRefExpr::VK_Mips_GPOFF_HI; break; + case MipsII::MO_GPOFF_LO: Kind = MCSymbolRefExpr::VK_Mips_GPOFF_LO; break; + case MipsII::MO_GOT_DISP: Kind = MCSymbolRefExpr::VK_Mips_GOT_DISP; break; + case MipsII::MO_GOT_PAGE: Kind = MCSymbolRefExpr::VK_Mips_GOT_PAGE; break; + case MipsII::MO_GOT_OFST: Kind = MCSymbolRefExpr::VK_Mips_GOT_OFST; break; } switch (MOTy) { - case MachineOperand::MO_MachineBasicBlock: - Symbol = MO.getMBB()->getSymbol(); - break; - - case MachineOperand::MO_GlobalAddress: - Symbol = Mang->getSymbol(MO.getGlobal()); - break; - - case MachineOperand::MO_BlockAddress: - Symbol = AsmPrinter.GetBlockAddressSymbol(MO.getBlockAddress()); - break; - - case MachineOperand::MO_ExternalSymbol: - Symbol = AsmPrinter.GetExternalSymbolSymbol(MO.getSymbolName()); - break; - - case MachineOperand::MO_JumpTableIndex: - Symbol = AsmPrinter.GetJTISymbol(MO.getIndex()); - break; - - case MachineOperand::MO_ConstantPoolIndex: - Symbol = AsmPrinter.GetCPISymbol(MO.getIndex()); - if (MO.getOffset()) - Offset += MO.getOffset(); - break; - - default: - llvm_unreachable("<unknown operand type>"); + case MachineOperand::MO_MachineBasicBlock: + Symbol = MO.getMBB()->getSymbol(); + break; + + case MachineOperand::MO_GlobalAddress: + Symbol = Mang->getSymbol(MO.getGlobal()); + break; + + case MachineOperand::MO_BlockAddress: + Symbol = AsmPrinter.GetBlockAddressSymbol(MO.getBlockAddress()); + break; + + case MachineOperand::MO_ExternalSymbol: + Symbol = AsmPrinter.GetExternalSymbolSymbol(MO.getSymbolName()); + break; + + case MachineOperand::MO_JumpTableIndex: + Symbol = AsmPrinter.GetJTISymbol(MO.getIndex()); + break; + + case MachineOperand::MO_ConstantPoolIndex: + Symbol = AsmPrinter.GetCPISymbol(MO.getIndex()); + if (MO.getOffset()) + Offset += MO.getOffset(); + break; + + default: + llvm_unreachable("<unknown operand type>"); + } + + const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::Create(Symbol, Kind, Ctx); + + if (!Offset) + return MCOperand::CreateExpr(MCSym); + + // Assume offset is never negative. + assert(Offset > 0); + + const MCConstantExpr *OffsetExpr = MCConstantExpr::Create(Offset, Ctx); + const MCBinaryExpr *AddExpr = MCBinaryExpr::CreateAdd(MCSym, OffsetExpr, Ctx); + return MCOperand::CreateExpr(AddExpr); +} + +// Lower ".cpload $reg" to +// "lui $gp, %hi(_gp_disp)" +// "addiu $gp, $gp, %lo(_gp_disp)" +// "addu $gp. $gp, $reg" +void MipsMCInstLower::LowerCPLOAD(const MachineInstr *MI, + SmallVector<MCInst, 4>& MCInsts) { + MCInst Lui, Addiu, Addu; + StringRef SymName("_gp_disp"); + const MCSymbol *Symbol = Ctx.GetOrCreateSymbol(SymName); + const MCSymbolRefExpr *MCSym; + + // lui $gp, %hi(_gp_disp) + Lui.setOpcode(Mips::LUi); + Lui.addOperand(MCOperand::CreateReg(Mips::GP)); + MCSym = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_Mips_ABS_HI, Ctx); + Lui.addOperand(MCOperand::CreateExpr(MCSym)); + MCInsts.push_back(Lui); + + // addiu $gp, $gp, %lo(_gp_disp) + Addiu.setOpcode(Mips::ADDiu); + Addiu.addOperand(MCOperand::CreateReg(Mips::GP)); + Addiu.addOperand(MCOperand::CreateReg(Mips::GP)); + MCSym = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_Mips_ABS_LO, Ctx); + Addiu.addOperand(MCOperand::CreateExpr(MCSym)); + MCInsts.push_back(Addiu); + + // addu $gp. $gp, $reg + Addu.setOpcode(Mips::ADDu); + Addu.addOperand(MCOperand::CreateReg(Mips::GP)); + Addu.addOperand(MCOperand::CreateReg(Mips::GP)); + const MachineOperand &MO = MI->getOperand(0); + assert(MO.isReg() && "CPLOAD's operand must be a register."); + Addu.addOperand(MCOperand::CreateReg(MO.getReg())); + MCInsts.push_back(Addu); +} + +// Lower ".cprestore offset" to "sw $gp, offset($sp)". +void MipsMCInstLower::LowerCPRESTORE(const MachineInstr *MI, + SmallVector<MCInst, 4>& MCInsts) { + const MachineOperand &MO = MI->getOperand(0); + assert(MO.isImm() && "CPRESTORE's operand must be an immediate."); + unsigned Offset = MO.getImm(), Reg = Mips::SP; + MCInst Sw; + + if (Offset >= 0x8000) { + unsigned Hi = (Offset >> 16) + ((Offset & 0x8000) != 0); + Offset &= 0xffff; + Reg = Mips::AT; + + // lui at,hi + // addu at,at,sp + MCInsts.resize(2); + MCInsts[0].setOpcode(Mips::LUi); + MCInsts[0].addOperand(MCOperand::CreateReg(Mips::AT)); + MCInsts[0].addOperand(MCOperand::CreateImm(Hi)); + MCInsts[1].setOpcode(Mips::ADDu); + MCInsts[1].addOperand(MCOperand::CreateReg(Mips::AT)); + MCInsts[1].addOperand(MCOperand::CreateReg(Mips::AT)); + MCInsts[1].addOperand(MCOperand::CreateReg(Mips::SP)); } - return MCOperand::CreateExpr(MipsMCSymbolRefExpr::Create(Kind, Symbol, Offset, - Ctx)); + Sw.setOpcode(Mips::SW); + Sw.addOperand(MCOperand::CreateReg(Mips::GP)); + Sw.addOperand(MCOperand::CreateReg(Reg)); + Sw.addOperand(MCOperand::CreateImm(Offset)); + MCInsts.push_back(Sw); } -MCOperand MipsMCInstLower::LowerOperand(const MachineOperand& MO) const { +MCOperand MipsMCInstLower::LowerOperand(const MachineOperand& MO, + unsigned offset) const { MachineOperandType MOTy = MO.getType(); switch (MOTy) { @@ -100,14 +184,14 @@ MCOperand MipsMCInstLower::LowerOperand(const MachineOperand& MO) const { if (MO.isImplicit()) break; return MCOperand::CreateReg(MO.getReg()); case MachineOperand::MO_Immediate: - return MCOperand::CreateImm(MO.getImm()); + return MCOperand::CreateImm(MO.getImm() + offset); 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 LowerSymbolOperand(MO, MOTy, offset); } return MCOperand(); @@ -124,3 +208,116 @@ void MipsMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { OutMI.addOperand(MCOp); } } + +void MipsMCInstLower::LowerUnalignedLoadStore(const MachineInstr *MI, + SmallVector<MCInst, + 4>& MCInsts) { + unsigned Opc = MI->getOpcode(); + MCInst instr1, instr2, instr3, move; + + bool two_instructions = false; + + assert(MI->getNumOperands() == 3); + assert(MI->getOperand(0).isReg()); + assert(MI->getOperand(1).isReg()); + + MCOperand target = LowerOperand(MI->getOperand(0)); + MCOperand base = LowerOperand(MI->getOperand(1)); + MCOperand atReg = MCOperand::CreateReg(Mips::AT); + MCOperand zeroReg = MCOperand::CreateReg(Mips::ZERO); + + MachineOperand unloweredName = MI->getOperand(2); + MCOperand name = LowerOperand(unloweredName); + + move.setOpcode(Mips::ADDu); + move.addOperand(target); + move.addOperand(atReg); + move.addOperand(zeroReg); + + switch (Opc) { + case Mips::ULW: { + // FIXME: only works for little endian right now + MCOperand adj_name = LowerOperand(unloweredName, 3); + if (base.getReg() == (target.getReg())) { + instr1.setOpcode(Mips::LWL); + instr1.addOperand(atReg); + instr1.addOperand(base); + instr1.addOperand(adj_name); + instr2.setOpcode(Mips::LWR); + instr2.addOperand(atReg); + instr2.addOperand(base); + instr2.addOperand(name); + instr3 = move; + } else { + two_instructions = true; + instr1.setOpcode(Mips::LWL); + instr1.addOperand(target); + instr1.addOperand(base); + instr1.addOperand(adj_name); + instr2.setOpcode(Mips::LWR); + instr2.addOperand(target); + instr2.addOperand(base); + instr2.addOperand(name); + } + break; + } + case Mips::ULHu: { + // FIXME: only works for little endian right now + MCOperand adj_name = LowerOperand(unloweredName, 1); + instr1.setOpcode(Mips::LBu); + instr1.addOperand(atReg); + instr1.addOperand(base); + instr1.addOperand(adj_name); + instr2.setOpcode(Mips::LBu); + instr2.addOperand(target); + instr2.addOperand(base); + instr2.addOperand(name); + instr3.setOpcode(Mips::INS); + instr3.addOperand(target); + instr3.addOperand(atReg); + instr3.addOperand(MCOperand::CreateImm(0x8)); + instr3.addOperand(MCOperand::CreateImm(0x18)); + break; + } + + case Mips::USW: { + // FIXME: only works for little endian right now + assert (base.getReg() != target.getReg()); + two_instructions = true; + MCOperand adj_name = LowerOperand(unloweredName, 3); + instr1.setOpcode(Mips::SWL); + instr1.addOperand(target); + instr1.addOperand(base); + instr1.addOperand(adj_name); + instr2.setOpcode(Mips::SWR); + instr2.addOperand(target); + instr2.addOperand(base); + instr2.addOperand(name); + break; + } + case Mips::USH: { + MCOperand adj_name = LowerOperand(unloweredName, 1); + instr1.setOpcode(Mips::SB); + instr1.addOperand(target); + instr1.addOperand(base); + instr1.addOperand(name); + instr2.setOpcode(Mips::SRL); + instr2.addOperand(atReg); + instr2.addOperand(target); + instr2.addOperand(MCOperand::CreateImm(8)); + instr3.setOpcode(Mips::SB); + instr3.addOperand(atReg); + instr3.addOperand(base); + instr3.addOperand(adj_name); + break; + } + default: + // FIXME: need to add others + assert(0 && "unaligned instruction not processed"); + } + + MCInsts.push_back(instr1); + MCInsts.push_back(instr2); + if (!two_instructions) MCInsts.push_back(instr3); +} + diff --git a/lib/Target/Mips/MipsMCInstLower.h b/lib/Target/Mips/MipsMCInstLower.h index 223f23a..1490c14 100644 --- a/lib/Target/Mips/MipsMCInstLower.h +++ b/lib/Target/Mips/MipsMCInstLower.h @@ -9,6 +9,7 @@ #ifndef MIPSMCINSTLOWER_H #define MIPSMCINSTLOWER_H +#include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/MachineOperand.h" #include "llvm/Support/Compiler.h" @@ -34,10 +35,14 @@ public: MipsMCInstLower(Mangler *mang, const MachineFunction &MF, MipsAsmPrinter &asmprinter); void Lower(const MachineInstr *MI, MCInst &OutMI) const; + void LowerCPLOAD(const MachineInstr *MI, SmallVector<MCInst, 4>& MCInsts); + void LowerCPRESTORE(const MachineInstr *MI, SmallVector<MCInst, 4>& MCInsts); + void LowerUnalignedLoadStore(const MachineInstr *MI, + SmallVector<MCInst, 4>& MCInsts); private: MCOperand LowerSymbolOperand(const MachineOperand &MO, MachineOperandType MOTy, unsigned Offset) const; - MCOperand LowerOperand(const MachineOperand& MO) const; + MCOperand LowerOperand(const MachineOperand& MO, unsigned offset = 0) const; }; } diff --git a/lib/Target/Mips/MipsMCSymbolRefExpr.cpp b/lib/Target/Mips/MipsMCSymbolRefExpr.cpp deleted file mode 100644 index a0a242c..0000000 --- a/lib/Target/Mips/MipsMCSymbolRefExpr.cpp +++ /dev/null @@ -1,70 +0,0 @@ -//===-- MipsMCSymbolRefExpr.cpp - Mips specific MC expression classes -----===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#define DEBUG_TYPE "mipsmcsymbolrefexpr" -#include "MipsMCSymbolRefExpr.h" -#include "llvm/MC/MCAssembler.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCSymbol.h" -using namespace llvm; - -const MipsMCSymbolRefExpr* -MipsMCSymbolRefExpr::Create(VariantKind Kind, const MCSymbol *Symbol, - int Offset, MCContext &Ctx) { - return new (Ctx) MipsMCSymbolRefExpr(Kind, Symbol, Offset); -} - -void MipsMCSymbolRefExpr::PrintImpl(raw_ostream &OS) const { - switch (Kind) { - default: assert(0 && "Invalid kind!"); - case VK_Mips_None: break; - case VK_Mips_GPREL: OS << "%gp_rel("; break; - case VK_Mips_GOT_CALL: OS << "%call16("; break; - case VK_Mips_GOT: OS << "%got("; break; - case VK_Mips_ABS_HI: OS << "%hi("; break; - case VK_Mips_ABS_LO: OS << "%lo("; break; - case VK_Mips_TLSGD: OS << "%tlsgd("; break; - 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; - - if (Offset) { - if (Offset > 0) - OS << '+'; - OS << Offset; - } - - if (Kind == VK_Mips_GPOFF_HI || Kind == VK_Mips_GPOFF_LO) - OS << ")))"; - else if (Kind != VK_Mips_None) - OS << ')'; -} - -bool -MipsMCSymbolRefExpr::EvaluateAsRelocatableImpl(MCValue &Res, - const MCAsmLayout *Layout) const { - return false; -} - -void MipsMCSymbolRefExpr::AddValueSymbols(MCAssembler *Asm) const { - Asm->getOrCreateSymbolData(*Symbol); -} - -const MCSection *MipsMCSymbolRefExpr::FindAssociatedSection() const { - return Symbol->isDefined() ? &Symbol->getSection() : NULL; -} - diff --git a/lib/Target/Mips/MipsMCSymbolRefExpr.h b/lib/Target/Mips/MipsMCSymbolRefExpr.h deleted file mode 100644 index 55e85a7..0000000 --- a/lib/Target/Mips/MipsMCSymbolRefExpr.h +++ /dev/null @@ -1,67 +0,0 @@ -//===-- MipsMCSymbolRefExpr.h - Mips specific MCSymbolRefExpr class -------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef MIPSMCSYMBOLREFEXPR_H -#define MIPSMCSYMBOLREFEXPR_H -#include "llvm/MC/MCExpr.h" - -namespace llvm { - -class MipsMCSymbolRefExpr : public MCTargetExpr { -public: - enum VariantKind { - VK_Mips_None, - VK_Mips_GPREL, - VK_Mips_GOT_CALL, - VK_Mips_GOT, - VK_Mips_ABS_HI, - VK_Mips_ABS_LO, - VK_Mips_TLSGD, - VK_Mips_GOTTPREL, - VK_Mips_TPREL_HI, - 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: - const VariantKind Kind; - const MCSymbol *Symbol; - int Offset; - - explicit MipsMCSymbolRefExpr(VariantKind _Kind, const MCSymbol *_Symbol, - int _Offset) - : Kind(_Kind), Symbol(_Symbol), Offset(_Offset) {} - -public: - static const MipsMCSymbolRefExpr *Create(VariantKind Kind, - const MCSymbol *Symbol, int Offset, - MCContext &Ctx); - - void PrintImpl(raw_ostream &OS) const; - bool EvaluateAsRelocatableImpl(MCValue &Res, - const MCAsmLayout *Layout) const; - void AddValueSymbols(MCAssembler *) const; - const MCSection *FindAssociatedSection() const; - - static bool classof(const MCExpr *E) { - return E->getKind() == MCExpr::Target; - } - - static bool classof(const MipsMCSymbolRefExpr *) { return true; } - - int getOffset() const { return Offset; } - void setOffset(int O) { Offset = O; } -}; -} // end namespace llvm - -#endif diff --git a/lib/Target/Mips/MipsRegisterInfo.cpp b/lib/Target/Mips/MipsRegisterInfo.cpp index f8c0fda..e5a0f08 100644 --- a/lib/Target/Mips/MipsRegisterInfo.cpp +++ b/lib/Target/Mips/MipsRegisterInfo.cpp @@ -125,6 +125,7 @@ getRegisterNumbering(unsigned RegEnum) case Mips::D14: return 28; case Mips::SP: case Mips::SP_64: case Mips::F29: case Mips::D29_64: + case Mips::HWR29: return 29; case Mips::FP: case Mips::FP_64: case Mips::F30: case Mips::D30_64: case Mips::D15: @@ -191,23 +192,23 @@ 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 + Mips::GP, Mips::SP, Mips::FP, Mips::RA }; 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 + Mips::GP_64, Mips::SP_64, Mips::FP_64, Mips::RA_64 }; BitVector Reserved(getNumRegs()); typedef TargetRegisterClass::iterator RegIter; - for (const unsigned *Reg = ReservedCPURegs; *Reg; ++Reg) - Reserved.set(*Reg); + for (unsigned I = 0; I < array_lengthof(ReservedCPURegs); ++I) + Reserved.set(ReservedCPURegs[I]); if (Subtarget.hasMips64()) { - for (const unsigned *Reg = ReservedCPU64Regs; *Reg; ++Reg) - Reserved.set(*Reg); + for (unsigned I = 0; I < array_lengthof(ReservedCPU64Regs); ++I) + Reserved.set(ReservedCPU64Regs[I]); // Reserve all registers in AFGR64. for (RegIter Reg = Mips::AFGR64RegisterClass->begin(); @@ -285,7 +286,7 @@ eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, if (MipsFI->isOutArgFI(FrameIndex) || MipsFI->isDynAllocFI(FrameIndex) || (FrameIndex >= MinCSFI && FrameIndex <= MaxCSFI)) - FrameReg = Mips::SP; + FrameReg = Subtarget.isABI_N64() ? Mips::SP_64 : Mips::SP; else FrameReg = getFrameRegister(MF); @@ -334,8 +335,10 @@ eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, unsigned MipsRegisterInfo:: getFrameRegister(const MachineFunction &MF) const { const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); + bool IsN64 = Subtarget.isABI_N64(); - return TFI->hasFP(MF) ? Mips::FP : Mips::SP; + return TFI->hasFP(MF) ? (IsN64 ? Mips::FP_64 : Mips::FP) : + (IsN64 ? Mips::SP_64 : Mips::SP); } unsigned MipsRegisterInfo:: diff --git a/lib/Target/Mips/MipsRegisterInfo.td b/lib/Target/Mips/MipsRegisterInfo.td index 925ad9e..76ee2e6 100644 --- a/lib/Target/Mips/MipsRegisterInfo.td +++ b/lib/Target/Mips/MipsRegisterInfo.td @@ -239,6 +239,7 @@ let Namespace = "Mips" in { // Hardware register $29 def HWR29 : Register<"29">; + def HWR29_64 : Register<"29">; } //===----------------------------------------------------------------------===// @@ -301,3 +302,5 @@ def HILO64 : RegisterClass<"Mips", [i64], 64, (add HI64, LO64)> { // Hardware registers def HWRegs : RegisterClass<"Mips", [i32], 32, (add HWR29)>; +def HWRegs64 : RegisterClass<"Mips", [i64], 32, (add HWR29_64)>; + diff --git a/lib/Target/Mips/MipsSubtarget.cpp b/lib/Target/Mips/MipsSubtarget.cpp index 016d449..dc299f2 100644 --- a/lib/Target/Mips/MipsSubtarget.cpp +++ b/lib/Target/Mips/MipsSubtarget.cpp @@ -31,7 +31,7 @@ MipsSubtarget::MipsSubtarget(const std::string &TT, const std::string &CPU, { std::string CPUName = CPU; if (CPUName.empty()) - CPUName = "mips32r1"; + CPUName = "mips32"; // Parse features string. ParseSubtargetFeatures(CPUName, FS); diff --git a/lib/Target/Mips/MipsTargetMachine.cpp b/lib/Target/Mips/MipsTargetMachine.cpp index 6480da3..02887fa 100644 --- a/lib/Target/Mips/MipsTargetMachine.cpp +++ b/lib/Target/Mips/MipsTargetMachine.cpp @@ -34,51 +34,56 @@ extern "C" void LLVMInitializeMipsTarget() { // Using CodeModel::Large enables different CALL behavior. MipsTargetMachine:: MipsTargetMachine(const Target &T, StringRef TT, - StringRef CPU, StringRef FS, + StringRef CPU, StringRef FS, const TargetOptions &Options, Reloc::Model RM, CodeModel::Model CM, - bool isLittle): - LLVMTargetMachine(T, TT, CPU, FS, RM, CM), - Subtarget(TT, CPU, FS, isLittle), - 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), JITInfo() { + CodeGenOpt::Level OL, + bool isLittle) + : LLVMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL), + Subtarget(TT, CPU, FS, isLittle), + 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), 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) {} + StringRef CPU, StringRef FS, const TargetOptions &Options, + Reloc::Model RM, CodeModel::Model CM, + CodeGenOpt::Level OL) + : MipsTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {} MipselTargetMachine:: MipselTargetMachine(const Target &T, StringRef TT, - StringRef CPU, StringRef FS, - Reloc::Model RM, CodeModel::Model CM) : - MipsTargetMachine(T, TT, CPU, FS, RM, CM, true) {} + StringRef CPU, StringRef FS, const TargetOptions &Options, + Reloc::Model RM, CodeModel::Model CM, + CodeGenOpt::Level OL) + : MipsTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, 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) {} + StringRef CPU, StringRef FS, const TargetOptions &Options, + Reloc::Model RM, CodeModel::Model CM, + CodeGenOpt::Level OL) + : MipsTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, 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) {} + StringRef CPU, StringRef FS, const TargetOptions &Options, + Reloc::Model RM, CodeModel::Model CM, + CodeGenOpt::Level OL) + : MipsTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true) {} // Install an instruction selector pass using // the ISelDag to gen Mips code. bool MipsTargetMachine:: -addInstSelector(PassManagerBase &PM, CodeGenOpt::Level OptLevel) +addInstSelector(PassManagerBase &PM) { PM.add(createMipsISelDag(*this)); return false; @@ -88,14 +93,14 @@ addInstSelector(PassManagerBase &PM, CodeGenOpt::Level OptLevel) // machine code is emitted. return true if -print-machineinstrs should // print out the code after the passes. bool MipsTargetMachine:: -addPreEmitPass(PassManagerBase &PM, CodeGenOpt::Level OptLevel) +addPreEmitPass(PassManagerBase &PM) { PM.add(createMipsDelaySlotFillerPass(*this)); return true; } bool MipsTargetMachine:: -addPreRegAlloc(PassManagerBase &PM, CodeGenOpt::Level OptLevel) { +addPreRegAlloc(PassManagerBase &PM) { // Do not restore $gp if target is Mips64. // In N32/64, $gp is a callee-saved register. if (!Subtarget.hasMips64()) @@ -104,16 +109,14 @@ addPreRegAlloc(PassManagerBase &PM, CodeGenOpt::Level OptLevel) { } bool MipsTargetMachine:: -addPostRegAlloc(PassManagerBase &PM, CodeGenOpt::Level OptLevel) { +addPostRegAlloc(PassManagerBase &PM) { PM.add(createMipsExpandPseudoPass(*this)); return true; } bool MipsTargetMachine::addCodeEmitter(PassManagerBase &PM, - CodeGenOpt::Level OptLevel, - JITCodeEmitter &JCE) { + JITCodeEmitter &JCE) { // Machine code emitter pass for Mips. PM.add(createMipsJITCodeEmitterPass(*this, JCE)); return false; } - diff --git a/lib/Target/Mips/MipsTargetMachine.h b/lib/Target/Mips/MipsTargetMachine.h index 118ed10..6842373 100644 --- a/lib/Target/Mips/MipsTargetMachine.h +++ b/lib/Target/Mips/MipsTargetMachine.h @@ -38,8 +38,9 @@ namespace llvm { public: MipsTargetMachine(const Target &T, StringRef TT, - StringRef CPU, StringRef FS, + StringRef CPU, StringRef FS, const TargetOptions &Options, Reloc::Model RM, CodeModel::Model CM, + CodeGenOpt::Level OL, bool isLittle); virtual const MipsInstrInfo *getInstrInfo() const @@ -67,15 +68,11 @@ namespace llvm { } // Pass Pipeline Configuration - virtual bool addInstSelector(PassManagerBase &PM, - CodeGenOpt::Level OptLevel); - virtual bool addPreEmitPass(PassManagerBase &PM, - CodeGenOpt::Level OptLevel); - virtual bool addPreRegAlloc(PassManagerBase &PM, - CodeGenOpt::Level OptLevel); - virtual bool addPostRegAlloc(PassManagerBase &, CodeGenOpt::Level); + virtual bool addInstSelector(PassManagerBase &PM); + virtual bool addPreEmitPass(PassManagerBase &PM); + virtual bool addPreRegAlloc(PassManagerBase &PM); + virtual bool addPostRegAlloc(PassManagerBase &); virtual bool addCodeEmitter(PassManagerBase &PM, - CodeGenOpt::Level OptLevel, JITCodeEmitter &JCE); }; @@ -85,8 +82,9 @@ namespace llvm { class MipsebTargetMachine : public MipsTargetMachine { public: MipsebTargetMachine(const Target &T, StringRef TT, - StringRef CPU, StringRef FS, - Reloc::Model RM, CodeModel::Model CM); + StringRef CPU, StringRef FS, const TargetOptions &Options, + Reloc::Model RM, CodeModel::Model CM, + CodeGenOpt::Level OL); }; /// MipselTargetMachine - Mips32 little endian target machine. @@ -94,8 +92,9 @@ public: class MipselTargetMachine : public MipsTargetMachine { public: MipselTargetMachine(const Target &T, StringRef TT, - StringRef CPU, StringRef FS, - Reloc::Model RM, CodeModel::Model CM); + StringRef CPU, StringRef FS, const TargetOptions &Options, + Reloc::Model RM, CodeModel::Model CM, + CodeGenOpt::Level OL); }; /// Mips64ebTargetMachine - Mips64 big endian target machine. @@ -104,7 +103,9 @@ class Mips64ebTargetMachine : public MipsTargetMachine { public: Mips64ebTargetMachine(const Target &T, StringRef TT, StringRef CPU, StringRef FS, - Reloc::Model RM, CodeModel::Model CM); + const TargetOptions &Options, + Reloc::Model RM, CodeModel::Model CM, + CodeGenOpt::Level OL); }; /// Mips64elTargetMachine - Mips64 little endian target machine. @@ -113,7 +114,9 @@ class Mips64elTargetMachine : public MipsTargetMachine { public: Mips64elTargetMachine(const Target &T, StringRef TT, StringRef CPU, StringRef FS, - Reloc::Model RM, CodeModel::Model CM); + const TargetOptions &Options, + Reloc::Model RM, CodeModel::Model CM, + CodeGenOpt::Level OL); }; } // End llvm namespace diff --git a/lib/Target/Mips/TargetInfo/Android.mk b/lib/Target/Mips/TargetInfo/Android.mk new file mode 100644 index 0000000..e3f41bc --- /dev/null +++ b/lib/Target/Mips/TargetInfo/Android.mk @@ -0,0 +1,47 @@ +LOCAL_PATH := $(call my-dir) + +mips_target_info_TBLGEN_TABLES := \ + MipsGenInstrInfo.inc \ + MipsGenRegisterInfo.inc \ + MipsGenSubtargetInfo.inc + +mips_target_info_SRC_FILES := \ + MipsTargetInfo.cpp + +# For the host +# ===================================================== +include $(CLEAR_VARS) +include $(CLEAR_TBLGEN_VARS) + +LOCAL_MODULE:= libLLVMMipsInfo +LOCAL_MODULE_TAGS := optional + +TBLGEN_TABLES := $(mips_target_info_TBLGEN_TABLES) +TBLGEN_TD_DIR := $(LOCAL_PATH)/.. + +LOCAL_SRC_FILES := $(mips_target_info_SRC_FILES) +LOCAL_C_INCLUDES += $(LOCAL_PATH)/.. + +include $(LLVM_HOST_BUILD_MK) +include $(LLVM_TBLGEN_RULES_MK) +include $(BUILD_HOST_STATIC_LIBRARY) + +# For the device +# ===================================================== +ifeq ($(TARGET_ARCH),mips) +include $(CLEAR_VARS) +include $(CLEAR_TBLGEN_VARS) + +LOCAL_MODULE:= libLLVMMipsInfo +LOCAL_MODULE_TAGS := optional + +TBLGEN_TABLES := $(mips_target_info_TBLGEN_TABLES) +TBLGEN_TD_DIR := $(LOCAL_PATH)/.. + +LOCAL_SRC_FILES := $(mips_target_info_SRC_FILES) +LOCAL_C_INCLUDES += $(LOCAL_PATH)/.. + +include $(LLVM_DEVICE_BUILD_MK) +include $(LLVM_TBLGEN_RULES_MK) +include $(BUILD_STATIC_LIBRARY) +endif diff --git a/lib/Target/Mips/TargetInfo/CMakeLists.txt b/lib/Target/Mips/TargetInfo/CMakeLists.txt index 5692604..4172d00 100644 --- a/lib/Target/Mips/TargetInfo/CMakeLists.txt +++ b/lib/Target/Mips/TargetInfo/CMakeLists.txt @@ -4,10 +4,4 @@ add_llvm_library(LLVMMipsInfo MipsTargetInfo.cpp ) -add_llvm_library_dependencies(LLVMMipsInfo - LLVMMC - LLVMSupport - LLVMTarget - ) - add_dependencies(LLVMMipsInfo MipsCommonTableGen) diff --git a/lib/Target/Mips/TargetInfo/LLVMBuild.txt b/lib/Target/Mips/TargetInfo/LLVMBuild.txt new file mode 100644 index 0000000..2d42568 --- /dev/null +++ b/lib/Target/Mips/TargetInfo/LLVMBuild.txt @@ -0,0 +1,23 @@ +;===- ./lib/Target/Mips/TargetInfo/LLVMBuild.txt ---------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Library +name = MipsInfo +parent = Mips +required_libraries = MC Support Target +add_to_library_groups = Mips |
