diff options
Diffstat (limited to 'contrib/llvm/lib/Target/Blackfin')
33 files changed, 4285 insertions, 0 deletions
diff --git a/contrib/llvm/lib/Target/Blackfin/AsmPrinter/BlackfinAsmPrinter.cpp b/contrib/llvm/lib/Target/Blackfin/AsmPrinter/BlackfinAsmPrinter.cpp new file mode 100644 index 0000000..6ba258b --- /dev/null +++ b/contrib/llvm/lib/Target/Blackfin/AsmPrinter/BlackfinAsmPrinter.cpp @@ -0,0 +1,156 @@ +//===-- BlackfinAsmPrinter.cpp - Blackfin LLVM assembly writer ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains a printer that converts from our internal representation +// of machine-dependent LLVM code to GAS-format BLACKFIN assembly language. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "asm-printer" +#include "Blackfin.h" +#include "BlackfinInstrInfo.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Module.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Target/Mangler.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +namespace { + class BlackfinAsmPrinter : public AsmPrinter { + public: + BlackfinAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) + : AsmPrinter(TM, Streamer) {} + + virtual const char *getPassName() const { + return "Blackfin Assembly Printer"; + } + + void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O); + void printMemoryOperand(const MachineInstr *MI, int opNum, raw_ostream &O); + void printInstruction(const MachineInstr *MI, raw_ostream &O);// autogen'd. + static const char *getRegisterName(unsigned RegNo); + + void EmitInstruction(const MachineInstr *MI) { + SmallString<128> Str; + raw_svector_ostream OS(Str); + printInstruction(MI, OS); + OutStreamer.EmitRawText(OS.str()); + } + bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O); + bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O); + }; +} // end of anonymous namespace + +#include "BlackfinGenAsmWriter.inc" + +extern "C" void LLVMInitializeBlackfinAsmPrinter() { + RegisterAsmPrinter<BlackfinAsmPrinter> X(TheBlackfinTarget); +} + +void BlackfinAsmPrinter::printOperand(const MachineInstr *MI, int opNum, + raw_ostream &O) { + const MachineOperand &MO = MI->getOperand(opNum); + switch (MO.getType()) { + case MachineOperand::MO_Register: + assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) && + "Virtual registers should be already mapped!"); + O << getRegisterName(MO.getReg()); + break; + + case MachineOperand::MO_Immediate: + O << MO.getImm(); + break; + case MachineOperand::MO_MachineBasicBlock: + O << *MO.getMBB()->getSymbol(); + return; + case MachineOperand::MO_GlobalAddress: + O << *Mang->getSymbol(MO.getGlobal()); + printOffset(MO.getOffset(), O); + break; + case MachineOperand::MO_ExternalSymbol: + O << *GetExternalSymbolSymbol(MO.getSymbolName()); + break; + case MachineOperand::MO_ConstantPoolIndex: + O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_" + << MO.getIndex(); + break; + case MachineOperand::MO_JumpTableIndex: + O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() + << '_' << MO.getIndex(); + break; + default: + llvm_unreachable("<unknown operand type>"); + break; + } +} + +void BlackfinAsmPrinter::printMemoryOperand(const MachineInstr *MI, int opNum, + raw_ostream &O) { + printOperand(MI, opNum, O); + + if (MI->getOperand(opNum+1).isImm() && MI->getOperand(opNum+1).getImm() == 0) + return; + + O << " + "; + printOperand(MI, opNum+1, O); +} + +/// PrintAsmOperand - Print out an operand for an inline asm expression. +/// +bool BlackfinAsmPrinter::PrintAsmOperand(const MachineInstr *MI, + unsigned OpNo, unsigned AsmVariant, + const char *ExtraCode, + raw_ostream &O) { + if (ExtraCode && ExtraCode[0]) { + if (ExtraCode[1] != 0) return true; // Unknown modifier. + + switch (ExtraCode[0]) { + default: return true; // Unknown modifier. + case 'r': + break; + } + } + + printOperand(MI, OpNo, O); + + return false; +} + +bool BlackfinAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, + unsigned OpNo, + unsigned AsmVariant, + const char *ExtraCode, + raw_ostream &O) { + if (ExtraCode && ExtraCode[0]) + return true; // Unknown modifier + + O << '['; + printOperand(MI, OpNo, O); + O << ']'; + + return false; +} diff --git a/contrib/llvm/lib/Target/Blackfin/AsmPrinter/CMakeLists.txt b/contrib/llvm/lib/Target/Blackfin/AsmPrinter/CMakeLists.txt new file mode 100644 index 0000000..795aebf --- /dev/null +++ b/contrib/llvm/lib/Target/Blackfin/AsmPrinter/CMakeLists.txt @@ -0,0 +1,6 @@ +include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. ) + +add_llvm_library(LLVMBlackfinAsmPrinter + BlackfinAsmPrinter.cpp + ) +add_dependencies(LLVMBlackfinAsmPrinter BlackfinCodeGenTable_gen) diff --git a/contrib/llvm/lib/Target/Blackfin/AsmPrinter/Makefile b/contrib/llvm/lib/Target/Blackfin/AsmPrinter/Makefile new file mode 100644 index 0000000..a106a23 --- /dev/null +++ b/contrib/llvm/lib/Target/Blackfin/AsmPrinter/Makefile @@ -0,0 +1,16 @@ +##===- lib/Target/Blackfin/AsmPrinter/Makefile -------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../../../.. +LIBRARYNAME = LLVMBlackfinAsmPrinter + +# Hack: we need to include 'main' Blackfin target directory to grab private +# headers +CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common diff --git a/contrib/llvm/lib/Target/Blackfin/Blackfin.h b/contrib/llvm/lib/Target/Blackfin/Blackfin.h new file mode 100644 index 0000000..ec1fa86 --- /dev/null +++ b/contrib/llvm/lib/Target/Blackfin/Blackfin.h @@ -0,0 +1,38 @@ +//=== Blackfin.h - Top-level interface for Blackfin backend -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the entry points for global functions defined in the LLVM +// Blackfin back-end. +// +//===----------------------------------------------------------------------===// + +#ifndef TARGET_BLACKFIN_H +#define TARGET_BLACKFIN_H + +#include "llvm/Target/TargetMachine.h" + +namespace llvm { + + class FunctionPass; + class BlackfinTargetMachine; + + FunctionPass *createBlackfinISelDag(BlackfinTargetMachine &TM, + CodeGenOpt::Level OptLevel); + extern Target TheBlackfinTarget; + +} // end namespace llvm + +// Defines symbolic names for Blackfin registers. This defines a mapping from +// register name to register number. +#include "BlackfinGenRegisterNames.inc" + +// Defines symbolic names for the Blackfin instructions. +#include "BlackfinGenInstrNames.inc" + +#endif diff --git a/contrib/llvm/lib/Target/Blackfin/Blackfin.td b/contrib/llvm/lib/Target/Blackfin/Blackfin.td new file mode 100644 index 0000000..cd90962 --- /dev/null +++ b/contrib/llvm/lib/Target/Blackfin/Blackfin.td @@ -0,0 +1,202 @@ +//===- Blackfin.td - Describe the Blackfin Target Machine --*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Target-independent interfaces which we are implementing +//===----------------------------------------------------------------------===// + +include "llvm/Target/Target.td" + +//===----------------------------------------------------------------------===// +// Blackfin Subtarget features. +//===----------------------------------------------------------------------===// + +def FeatureSDRAM : SubtargetFeature<"sdram", "sdram", "true", + "Build for SDRAM">; + +def FeatureICPLB : SubtargetFeature<"icplb", "icplb", "true", + "Assume instruction cache lookaside buffers are enabled at runtime">; + +//===----------------------------------------------------------------------===// +// Bugs in the silicon becomes workarounds in the compiler. +// See http://www.analog.com/ for the full list of IC anomalies. +//===----------------------------------------------------------------------===// + +def WA_MI_SHIFT : SubtargetFeature<"mi-shift-anomaly","wa_mi_shift", "true", + "Work around 05000074 - " + "Multi-Issue Instruction with dsp32shiftimm and P-reg Store">; + +def WA_CSYNC : SubtargetFeature<"csync-anomaly","wa_csync", "true", + "Work around 05000244 - " + "If I-Cache Is On, CSYNC/SSYNC/IDLE Around Change of Control">; + +def WA_SPECLD : SubtargetFeature<"specld-anomaly","wa_specld", "true", + "Work around 05000245 - " + "Access in the Shadow of a Conditional Branch">; + +def WA_HWLOOP : SubtargetFeature<"hwloop-anomaly","wa_hwloop", "true", + "Work around 05000257 - " + "Interrupt/Exception During Short Hardware Loop">; + +def WA_MMR_STALL : SubtargetFeature<"mmr-stall-anomaly","wa_mmr_stall", "true", + "Work around 05000283 - " + "System MMR Write Is Stalled Indefinitely when Killed">; + +def WA_LCREGS : SubtargetFeature<"lcregs-anomaly","wa_lcregs", "true", + "Work around 05000312 - " + "SSYNC, CSYNC, or Loads to LT, LB and LC Registers Are Interrupted">; + +def WA_KILLED_MMR : SubtargetFeature<"killed-mmr-anomaly", + "wa_killed_mmr", "true", + "Work around 05000315 - " + "Killed System MMR Write Completes Erroneously on Next System MMR Access">; + +def WA_RETS : SubtargetFeature<"rets-anomaly", "wa_rets", "true", + "Work around 05000371 - " + "Possible RETS Register Corruption when Subroutine Is under 5 Cycles">; + +def WA_IND_CALL : SubtargetFeature<"ind-call-anomaly", "wa_ind_call", "true", + "Work around 05000426 - " + "Speculative Fetches of Indirect-Pointer Instructions">; + +//===----------------------------------------------------------------------===// +// Register File, Calling Conv, Instruction Descriptions +//===----------------------------------------------------------------------===// + +include "BlackfinRegisterInfo.td" +include "BlackfinCallingConv.td" +include "BlackfinIntrinsics.td" +include "BlackfinInstrInfo.td" + +def BlackfinInstrInfo : InstrInfo {} + +//===----------------------------------------------------------------------===// +// Blackfin processors supported. +//===----------------------------------------------------------------------===// + +class Proc<string Name, string Suffix, list<SubtargetFeature> Features> + : Processor<!strconcat(Name, Suffix), NoItineraries, Features>; + +def : Proc<"generic", "", []>; + +multiclass Core<string Name,string Suffix, + list<SubtargetFeature> Features> { + def : Proc<Name, Suffix, Features>; + def : Proc<Name, "", Features>; + def : Proc<Name, "-none", []>; +} + +multiclass CoreEdinburgh<string Name> + : Core<Name, "-0.6", [WA_MI_SHIFT, WA_SPECLD, WA_LCREGS]> { + def : Proc<Name, "-0.5", + [WA_MI_SHIFT, WA_SPECLD, WA_MMR_STALL, WA_LCREGS, WA_KILLED_MMR, + WA_RETS]>; + def : Proc<Name, "-0.4", + [WA_MI_SHIFT, WA_CSYNC, WA_SPECLD, WA_HWLOOP, WA_MMR_STALL, WA_LCREGS, + WA_KILLED_MMR, WA_RETS]>; + def : Proc<Name, "-0.3", + [WA_MI_SHIFT, WA_CSYNC, WA_SPECLD, WA_HWLOOP, WA_MMR_STALL, WA_LCREGS, + WA_KILLED_MMR, WA_RETS]>; + def : Proc<Name, "-any", + [WA_MI_SHIFT, WA_CSYNC, WA_SPECLD, WA_HWLOOP, WA_MMR_STALL, WA_LCREGS, + WA_KILLED_MMR, WA_RETS]>; +} +multiclass CoreBraemar<string Name> + : Core<Name, "-0.3", + [WA_MI_SHIFT, WA_SPECLD, WA_LCREGS, WA_RETS, WA_IND_CALL]> { + def : Proc<Name, "-0.2", + [WA_MI_SHIFT, WA_CSYNC, WA_SPECLD, WA_HWLOOP, WA_MMR_STALL, WA_LCREGS, + WA_KILLED_MMR, WA_RETS, WA_IND_CALL]>; + def : Proc<Name, "-any", + [WA_MI_SHIFT, WA_CSYNC, WA_SPECLD, WA_HWLOOP, WA_MMR_STALL, WA_LCREGS, + WA_KILLED_MMR, WA_RETS, WA_IND_CALL]>; +} +multiclass CoreStirling<string Name> + : Core<Name, "-0.5", [WA_MI_SHIFT, WA_SPECLD, WA_IND_CALL]> { + def : Proc<Name, "-0.4", + [WA_MI_SHIFT, WA_SPECLD, WA_LCREGS, WA_RETS, WA_IND_CALL]>; + def : Proc<Name, "-0.3", + [WA_MI_SHIFT, WA_SPECLD, WA_MMR_STALL, WA_LCREGS, WA_KILLED_MMR, + WA_RETS, WA_IND_CALL]>; + def : Proc<Name, "-any", + [WA_MI_SHIFT, WA_SPECLD, WA_MMR_STALL, WA_LCREGS, WA_KILLED_MMR, + WA_RETS, WA_IND_CALL]>; +} +multiclass CoreMoab<string Name> + : Core<Name, "-0.3", [WA_MI_SHIFT, WA_SPECLD, WA_IND_CALL]> { + def : Proc<Name, "-0.2", [WA_MI_SHIFT, WA_SPECLD, WA_IND_CALL]>; + def : Proc<Name, "-0.1", [WA_MI_SHIFT, WA_SPECLD, WA_RETS, WA_IND_CALL]>; + def : Proc<Name, "-0.0", + [WA_MI_SHIFT, WA_SPECLD, WA_LCREGS, WA_RETS, WA_IND_CALL]>; + def : Proc<Name, "-any", + [WA_MI_SHIFT, WA_SPECLD, WA_LCREGS, WA_RETS, WA_IND_CALL]>; +} +multiclass CoreTeton<string Name> + : Core<Name, "-0.5", + [WA_MI_SHIFT, WA_SPECLD, WA_MMR_STALL, WA_LCREGS, WA_KILLED_MMR, + WA_RETS, WA_IND_CALL]> { + def : Proc<Name, "-0.3", + [WA_MI_SHIFT, WA_CSYNC, WA_SPECLD, WA_HWLOOP, WA_MMR_STALL, WA_LCREGS, + WA_KILLED_MMR, WA_RETS, WA_IND_CALL]>; + def : Proc<Name, "-any", + [WA_MI_SHIFT, WA_CSYNC, WA_SPECLD, WA_HWLOOP, WA_MMR_STALL, WA_LCREGS, + WA_KILLED_MMR, WA_RETS, WA_IND_CALL]>; +} +multiclass CoreKookaburra<string Name> + : Core<Name, "-0.2", [WA_MI_SHIFT, WA_SPECLD, WA_IND_CALL]> { + def : Proc<Name, "-0.1", [WA_MI_SHIFT, WA_SPECLD, WA_RETS, WA_IND_CALL]>; + def : Proc<Name, "-0.0", [WA_MI_SHIFT, WA_SPECLD, WA_RETS, WA_IND_CALL]>; + def : Proc<Name, "-any", [WA_MI_SHIFT, WA_SPECLD, WA_RETS, WA_IND_CALL]>; +} +multiclass CoreMockingbird<string Name> + : Core<Name, "-0.1", [WA_MI_SHIFT, WA_SPECLD, WA_IND_CALL]> { + def : Proc<Name, "-0.0", [WA_MI_SHIFT, WA_SPECLD, WA_IND_CALL]>; + def : Proc<Name, "-any", [WA_MI_SHIFT, WA_SPECLD, WA_IND_CALL]>; +} +multiclass CoreBrodie<string Name> + : Core<Name, "-0.1", [WA_MI_SHIFT, WA_SPECLD, WA_IND_CALL]> { + def : Proc<Name, "-0.0", [WA_MI_SHIFT, WA_SPECLD, WA_IND_CALL]>; + def : Proc<Name, "-any", [WA_MI_SHIFT, WA_SPECLD, WA_IND_CALL]>; +} + +defm BF512 : CoreBrodie<"bf512">; +defm BF514 : CoreBrodie<"bf514">; +defm BF516 : CoreBrodie<"bf516">; +defm BF518 : CoreBrodie<"bf518">; +defm BF522 : CoreMockingbird<"bf522">; +defm BF523 : CoreKookaburra<"bf523">; +defm BF524 : CoreMockingbird<"bf524">; +defm BF525 : CoreKookaburra<"bf525">; +defm BF526 : CoreMockingbird<"bf526">; +defm BF527 : CoreKookaburra<"bf527">; +defm BF531 : CoreEdinburgh<"bf531">; +defm BF532 : CoreEdinburgh<"bf532">; +defm BF533 : CoreEdinburgh<"bf533">; +defm BF534 : CoreBraemar<"bf534">; +defm BF536 : CoreBraemar<"bf536">; +defm BF537 : CoreBraemar<"bf537">; +defm BF538 : CoreStirling<"bf538">; +defm BF539 : CoreStirling<"bf539">; +defm BF542 : CoreMoab<"bf542">; +defm BF544 : CoreMoab<"bf544">; +defm BF548 : CoreMoab<"bf548">; +defm BF549 : CoreMoab<"bf549">; +defm BF561 : CoreTeton<"bf561">; + +//===----------------------------------------------------------------------===// +// Declare the target which we are implementing +//===----------------------------------------------------------------------===// + +def Blackfin : Target { + // Pull in Instruction Info: + let InstructionSet = BlackfinInstrInfo; +} diff --git a/contrib/llvm/lib/Target/Blackfin/BlackfinCallingConv.td b/contrib/llvm/lib/Target/Blackfin/BlackfinCallingConv.td new file mode 100644 index 0000000..0abc84c --- /dev/null +++ b/contrib/llvm/lib/Target/Blackfin/BlackfinCallingConv.td @@ -0,0 +1,30 @@ +//===--- BlackfinCallingConv.td - Calling Conventions ------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This describes the calling conventions for the Blackfin architectures. +// +//===----------------------------------------------------------------------===// + +// Blackfin C Calling convention. +def CC_Blackfin : CallingConv<[ + CCIfType<[i16], CCPromoteToType<i32>>, + CCIfSRet<CCAssignToReg<[P0]>>, + CCAssignToReg<[R0, R1, R2]>, + CCAssignToStack<4, 4> +]>; + +//===----------------------------------------------------------------------===// +// Return Value Calling Conventions +//===----------------------------------------------------------------------===// + +// Blackfin C return-value convention. +def RetCC_Blackfin : CallingConv<[ + CCIfType<[i16], CCPromoteToType<i32>>, + CCAssignToReg<[R0, R1]> +]>; diff --git a/contrib/llvm/lib/Target/Blackfin/BlackfinISelDAGToDAG.cpp b/contrib/llvm/lib/Target/Blackfin/BlackfinISelDAGToDAG.cpp new file mode 100644 index 0000000..80ee107 --- /dev/null +++ b/contrib/llvm/lib/Target/Blackfin/BlackfinISelDAGToDAG.cpp @@ -0,0 +1,182 @@ +//===- BlackfinISelDAGToDAG.cpp - A dag to dag inst selector for Blackfin -===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines an instruction selector for the Blackfin target. +// +//===----------------------------------------------------------------------===// + +#include "Blackfin.h" +#include "BlackfinTargetMachine.h" +#include "BlackfinRegisterInfo.h" +#include "llvm/Intrinsics.h" +#include "llvm/CodeGen/SelectionDAGISel.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Instruction Selector Implementation +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +/// BlackfinDAGToDAGISel - Blackfin specific code to select blackfin machine +/// instructions for SelectionDAG operations. +namespace { + class BlackfinDAGToDAGISel : public SelectionDAGISel { + /// Subtarget - Keep a pointer to the Blackfin Subtarget around so that we + /// can make the right decision when generating code for different targets. + //const BlackfinSubtarget &Subtarget; + public: + BlackfinDAGToDAGISel(BlackfinTargetMachine &TM, CodeGenOpt::Level OptLevel) + : SelectionDAGISel(TM, OptLevel) {} + + virtual void PostprocessISelDAG(); + + virtual const char *getPassName() const { + return "Blackfin DAG->DAG Pattern Instruction Selection"; + } + + // Include the pieces autogenerated from the target description. +#include "BlackfinGenDAGISel.inc" + + private: + SDNode *Select(SDNode *N); + bool SelectADDRspii(SDNode *Op, SDValue Addr, + SDValue &Base, SDValue &Offset); + + // Walk the DAG after instruction selection, fixing register class issues. + void FixRegisterClasses(SelectionDAG &DAG); + + const BlackfinInstrInfo &getInstrInfo() { + return *static_cast<const BlackfinTargetMachine&>(TM).getInstrInfo(); + } + const BlackfinRegisterInfo *getRegisterInfo() { + return static_cast<const BlackfinTargetMachine&>(TM).getRegisterInfo(); + } + }; +} // end anonymous namespace + +FunctionPass *llvm::createBlackfinISelDag(BlackfinTargetMachine &TM, + CodeGenOpt::Level OptLevel) { + return new BlackfinDAGToDAGISel(TM, OptLevel); +} + +void BlackfinDAGToDAGISel::PostprocessISelDAG() { + FixRegisterClasses(*CurDAG); +} + +SDNode *BlackfinDAGToDAGISel::Select(SDNode *N) { + if (N->isMachineOpcode()) + return NULL; // Already selected. + + switch (N->getOpcode()) { + default: break; + case ISD::FrameIndex: { + // Selects to ADDpp FI, 0 which in turn will become ADDimm7 SP, imm or ADDpp + // SP, Px + int FI = cast<FrameIndexSDNode>(N)->getIndex(); + SDValue TFI = CurDAG->getTargetFrameIndex(FI, MVT::i32); + return CurDAG->SelectNodeTo(N, BF::ADDpp, MVT::i32, TFI, + CurDAG->getTargetConstant(0, MVT::i32)); + } + } + + return SelectCode(N); +} + +bool BlackfinDAGToDAGISel::SelectADDRspii(SDNode *Op, + SDValue Addr, + SDValue &Base, + SDValue &Offset) { + FrameIndexSDNode *FIN = 0; + if ((FIN = dyn_cast<FrameIndexSDNode>(Addr))) { + Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); + Offset = CurDAG->getTargetConstant(0, MVT::i32); + return true; + } + if (Addr.getOpcode() == ISD::ADD) { + ConstantSDNode *CN = 0; + if ((FIN = dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) && + (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) && + (CN->getSExtValue() % 4 == 0 && CN->getSExtValue() >= 0)) { + // Constant positive word offset from frame index + Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); + Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i32); + return true; + } + } + return false; +} + +static inline bool isCC(const TargetRegisterClass *RC) { + return RC == &BF::AnyCCRegClass || BF::AnyCCRegClass.hasSubClass(RC); +} + +static inline bool isDCC(const TargetRegisterClass *RC) { + return RC == &BF::DRegClass || BF::DRegClass.hasSubClass(RC) || isCC(RC); +} + +static void UpdateNodeOperand(SelectionDAG &DAG, + SDNode *N, + unsigned Num, + SDValue Val) { + SmallVector<SDValue, 8> ops(N->op_begin(), N->op_end()); + ops[Num] = Val; + SDNode *New = DAG.UpdateNodeOperands(N, ops.data(), ops.size()); + DAG.ReplaceAllUsesWith(N, New); +} + +// After instruction selection, insert COPY_TO_REGCLASS nodes to help in +// choosing the proper register classes. +void BlackfinDAGToDAGISel::FixRegisterClasses(SelectionDAG &DAG) { + const BlackfinInstrInfo &TII = getInstrInfo(); + const BlackfinRegisterInfo *TRI = getRegisterInfo(); + DAG.AssignTopologicalOrder(); + HandleSDNode Dummy(DAG.getRoot()); + + for (SelectionDAG::allnodes_iterator NI = DAG.allnodes_begin(); + NI != DAG.allnodes_end(); ++NI) { + if (NI->use_empty() || !NI->isMachineOpcode()) + continue; + const TargetInstrDesc &DefTID = TII.get(NI->getMachineOpcode()); + for (SDNode::use_iterator UI = NI->use_begin(); !UI.atEnd(); ++UI) { + if (!UI->isMachineOpcode()) + continue; + + if (UI.getUse().getResNo() >= DefTID.getNumDefs()) + continue; + const TargetRegisterClass *DefRC = + DefTID.OpInfo[UI.getUse().getResNo()].getRegClass(TRI); + + const TargetInstrDesc &UseTID = TII.get(UI->getMachineOpcode()); + if (UseTID.getNumDefs()+UI.getOperandNo() >= UseTID.getNumOperands()) + continue; + const TargetRegisterClass *UseRC = + UseTID.OpInfo[UseTID.getNumDefs()+UI.getOperandNo()].getRegClass(TRI); + if (!DefRC || !UseRC) + continue; + // We cannot copy CC <-> !(CC/D) + if ((isCC(DefRC) && !isDCC(UseRC)) || (isCC(UseRC) && !isDCC(DefRC))) { + SDNode *Copy = + DAG.getMachineNode(TargetOpcode::COPY_TO_REGCLASS, + NI->getDebugLoc(), + MVT::i32, + UI.getUse().get(), + DAG.getTargetConstant(BF::DRegClassID, MVT::i32)); + UpdateNodeOperand(DAG, *UI, UI.getOperandNo(), SDValue(Copy, 0)); + } + } + } + DAG.setRoot(Dummy.getValue()); +} + diff --git a/contrib/llvm/lib/Target/Blackfin/BlackfinISelLowering.cpp b/contrib/llvm/lib/Target/Blackfin/BlackfinISelLowering.cpp new file mode 100644 index 0000000..6e828e1 --- /dev/null +++ b/contrib/llvm/lib/Target/Blackfin/BlackfinISelLowering.cpp @@ -0,0 +1,618 @@ +//===- BlackfinISelLowering.cpp - Blackfin DAG Lowering Implementation ----===// +// +// 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 interfaces that Blackfin uses to lower LLVM code +// into a selection DAG. +// +//===----------------------------------------------------------------------===// + +#include "BlackfinISelLowering.h" +#include "BlackfinTargetMachine.h" +#include "llvm/Function.h" +#include "llvm/CodeGen/CallingConvLower.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" +#include "llvm/ADT/VectorExtras.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Calling Convention Implementation +//===----------------------------------------------------------------------===// + +#include "BlackfinGenCallingConv.inc" + +//===----------------------------------------------------------------------===// +// TargetLowering Implementation +//===----------------------------------------------------------------------===// + +BlackfinTargetLowering::BlackfinTargetLowering(TargetMachine &TM) + : TargetLowering(TM, new TargetLoweringObjectFileELF()) { + setShiftAmountType(MVT::i16); + setBooleanContents(ZeroOrOneBooleanContent); + setStackPointerRegisterToSaveRestore(BF::SP); + setIntDivIsCheap(false); + + // Set up the legal register classes. + addRegisterClass(MVT::i32, BF::DRegisterClass); + addRegisterClass(MVT::i16, BF::D16RegisterClass); + + computeRegisterProperties(); + + // Blackfin doesn't have i1 loads or stores + setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote); + setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote); + setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote); + + setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); + setOperationAction(ISD::JumpTable, MVT::i32, Custom); + + setOperationAction(ISD::SELECT_CC, MVT::Other, Expand); + setOperationAction(ISD::BR_JT, MVT::Other, Expand); + setOperationAction(ISD::BR_CC, MVT::Other, Expand); + + // i16 registers don't do much + setOperationAction(ISD::AND, MVT::i16, Promote); + setOperationAction(ISD::OR, MVT::i16, Promote); + setOperationAction(ISD::XOR, MVT::i16, Promote); + setOperationAction(ISD::CTPOP, MVT::i16, Promote); + // The expansion of CTLZ/CTTZ uses AND/OR, so we might as well promote + // immediately. + setOperationAction(ISD::CTLZ, MVT::i16, Promote); + setOperationAction(ISD::CTTZ, MVT::i16, Promote); + setOperationAction(ISD::SETCC, MVT::i16, Promote); + + // Blackfin has no division + setOperationAction(ISD::SDIV, MVT::i16, Expand); + setOperationAction(ISD::SDIV, MVT::i32, Expand); + setOperationAction(ISD::SDIVREM, MVT::i16, Expand); + setOperationAction(ISD::SDIVREM, MVT::i32, Expand); + setOperationAction(ISD::SREM, MVT::i16, Expand); + setOperationAction(ISD::SREM, MVT::i32, Expand); + setOperationAction(ISD::UDIV, MVT::i16, Expand); + setOperationAction(ISD::UDIV, MVT::i32, Expand); + setOperationAction(ISD::UDIVREM, MVT::i16, Expand); + setOperationAction(ISD::UDIVREM, MVT::i32, Expand); + setOperationAction(ISD::UREM, MVT::i16, Expand); + setOperationAction(ISD::UREM, MVT::i32, Expand); + + setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand); + setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand); + setOperationAction(ISD::MULHU, MVT::i32, Expand); + setOperationAction(ISD::MULHS, MVT::i32, Expand); + + // No carry-in operations. + setOperationAction(ISD::ADDE, MVT::i32, Custom); + setOperationAction(ISD::SUBE, MVT::i32, Custom); + + // Blackfin has no intrinsics for these particular operations. + setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand); + setOperationAction(ISD::BSWAP, MVT::i32, Expand); + + setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand); + setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand); + setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand); + + setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); + + // i32 has native CTPOP, but not CTLZ/CTTZ + setOperationAction(ISD::CTLZ, MVT::i32, Expand); + setOperationAction(ISD::CTTZ, MVT::i32, Expand); + + // READCYCLECOUNTER needs special type legalization. + setOperationAction(ISD::READCYCLECOUNTER, MVT::i64, Custom); + + setOperationAction(ISD::EH_LABEL, MVT::Other, Expand); + + // Use the default implementation. + setOperationAction(ISD::VACOPY, MVT::Other, Expand); + setOperationAction(ISD::VAEND, MVT::Other, Expand); + setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); + setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand); +} + +const char *BlackfinTargetLowering::getTargetNodeName(unsigned Opcode) const { + switch (Opcode) { + default: return 0; + case BFISD::CALL: return "BFISD::CALL"; + case BFISD::RET_FLAG: return "BFISD::RET_FLAG"; + case BFISD::Wrapper: return "BFISD::Wrapper"; + } +} + +MVT::SimpleValueType BlackfinTargetLowering::getSetCCResultType(EVT VT) const { + // SETCC always sets the CC register. Technically that is an i1 register, but + // that type is not legal, so we treat it as an i32 register. + return MVT::i32; +} + +SDValue BlackfinTargetLowering::LowerGlobalAddress(SDValue Op, + SelectionDAG &DAG) const { + DebugLoc DL = Op.getDebugLoc(); + const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal(); + + Op = DAG.getTargetGlobalAddress(GV, DL, MVT::i32); + return DAG.getNode(BFISD::Wrapper, DL, MVT::i32, Op); +} + +SDValue BlackfinTargetLowering::LowerJumpTable(SDValue Op, + SelectionDAG &DAG) const { + DebugLoc DL = Op.getDebugLoc(); + int JTI = cast<JumpTableSDNode>(Op)->getIndex(); + + Op = DAG.getTargetJumpTable(JTI, MVT::i32); + return DAG.getNode(BFISD::Wrapper, DL, MVT::i32, Op); +} + +SDValue +BlackfinTargetLowering::LowerFormalArguments(SDValue Chain, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl<ISD::InputArg> + &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl<SDValue> &InVals) + const { + + MachineFunction &MF = DAG.getMachineFunction(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + + SmallVector<CCValAssign, 16> ArgLocs; + CCState CCInfo(CallConv, isVarArg, getTargetMachine(), + ArgLocs, *DAG.getContext()); + CCInfo.AllocateStack(12, 4); // ABI requires 12 bytes stack space + CCInfo.AnalyzeFormalArguments(Ins, CC_Blackfin); + + for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { + CCValAssign &VA = ArgLocs[i]; + + if (VA.isRegLoc()) { + EVT RegVT = VA.getLocVT(); + TargetRegisterClass *RC = VA.getLocReg() == BF::P0 ? + BF::PRegisterClass : BF::DRegisterClass; + assert(RC->contains(VA.getLocReg()) && "Unexpected regclass in CCState"); + assert(RC->hasType(RegVT) && "Unexpected regclass in CCState"); + + unsigned Reg = MF.getRegInfo().createVirtualRegister(RC); + MF.getRegInfo().addLiveIn(VA.getLocReg(), Reg); + SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, RegVT); + + // If this is an 8 or 16-bit value, it is really passed promoted to 32 + // bits. Insert an assert[sz]ext to capture this, then truncate to the + // right size. + if (VA.getLocInfo() == CCValAssign::SExt) + ArgValue = DAG.getNode(ISD::AssertSext, dl, RegVT, ArgValue, + DAG.getValueType(VA.getValVT())); + else if (VA.getLocInfo() == CCValAssign::ZExt) + ArgValue = DAG.getNode(ISD::AssertZext, dl, RegVT, ArgValue, + DAG.getValueType(VA.getValVT())); + + if (VA.getLocInfo() != CCValAssign::Full) + ArgValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), ArgValue); + + InVals.push_back(ArgValue); + } else { + assert(VA.isMemLoc() && "CCValAssign must be RegLoc or MemLoc"); + unsigned ObjSize = VA.getLocVT().getStoreSize(); + int FI = MFI->CreateFixedObject(ObjSize, VA.getLocMemOffset(), true); + SDValue FIN = DAG.getFrameIndex(FI, MVT::i32); + InVals.push_back(DAG.getLoad(VA.getValVT(), dl, Chain, FIN, NULL, 0, + false, false, 0)); + } + } + + return Chain; +} + +SDValue +BlackfinTargetLowering::LowerReturn(SDValue Chain, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl<ISD::OutputArg> &Outs, + const SmallVectorImpl<SDValue> &OutVals, + DebugLoc dl, SelectionDAG &DAG) const { + + // CCValAssign - represent the assignment of the return value to locations. + SmallVector<CCValAssign, 16> RVLocs; + + // CCState - Info about the registers and stack slot. + CCState CCInfo(CallConv, isVarArg, DAG.getTarget(), + RVLocs, *DAG.getContext()); + + // Analize return values. + CCInfo.AnalyzeReturn(Outs, RetCC_Blackfin); + + // If this is the first return lowered for this function, add the regs to the + // liveout set for the function. + if (DAG.getMachineFunction().getRegInfo().liveout_empty()) { + for (unsigned i = 0; i != RVLocs.size(); ++i) + DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg()); + } + + SDValue Flag; + + // Copy the result values into the output registers. + for (unsigned i = 0; i != RVLocs.size(); ++i) { + CCValAssign &VA = RVLocs[i]; + assert(VA.isRegLoc() && "Can only return in registers!"); + SDValue Opi = OutVals[i]; + + // Expand to i32 if necessary + switch (VA.getLocInfo()) { + default: llvm_unreachable("Unknown loc info!"); + case CCValAssign::Full: break; + case CCValAssign::SExt: + Opi = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Opi); + break; + case CCValAssign::ZExt: + Opi = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Opi); + break; + case CCValAssign::AExt: + Opi = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Opi); + break; + } + Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), Opi, SDValue()); + // Guarantee that all emitted copies are stuck together with flags. + Flag = Chain.getValue(1); + } + + if (Flag.getNode()) { + return DAG.getNode(BFISD::RET_FLAG, dl, MVT::Other, Chain, Flag); + } else { + return DAG.getNode(BFISD::RET_FLAG, dl, MVT::Other, Chain); + } +} + +SDValue +BlackfinTargetLowering::LowerCall(SDValue Chain, SDValue Callee, + CallingConv::ID CallConv, bool isVarArg, + bool &isTailCall, + const SmallVectorImpl<ISD::OutputArg> &Outs, + const SmallVectorImpl<SDValue> &OutVals, + const SmallVectorImpl<ISD::InputArg> &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl<SDValue> &InVals) const { + // Blackfin target does not yet support tail call optimization. + isTailCall = false; + + // Analyze operands of the call, assigning locations to each operand. + SmallVector<CCValAssign, 16> ArgLocs; + CCState CCInfo(CallConv, isVarArg, DAG.getTarget(), ArgLocs, + *DAG.getContext()); + CCInfo.AllocateStack(12, 4); // ABI requires 12 bytes stack space + CCInfo.AnalyzeCallOperands(Outs, CC_Blackfin); + + // Get the size of the outgoing arguments stack space requirement. + unsigned ArgsSize = CCInfo.getNextStackOffset(); + + Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(ArgsSize, true)); + SmallVector<std::pair<unsigned, SDValue>, 8> RegsToPass; + SmallVector<SDValue, 8> MemOpChains; + + // Walk the register/memloc assignments, inserting copies/loads. + for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { + CCValAssign &VA = ArgLocs[i]; + SDValue Arg = OutVals[i]; + + // Promote the value if needed. + switch (VA.getLocInfo()) { + default: llvm_unreachable("Unknown loc info!"); + case CCValAssign::Full: break; + case CCValAssign::SExt: + Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg); + break; + case CCValAssign::ZExt: + Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg); + break; + case CCValAssign::AExt: + Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg); + break; + } + + // Arguments that can be passed on register must be kept at + // RegsToPass vector + if (VA.isRegLoc()) { + RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); + } else { + assert(VA.isMemLoc() && "CCValAssign must be RegLoc or MemLoc"); + int Offset = VA.getLocMemOffset(); + assert(Offset%4 == 0 && "Unaligned LocMemOffset"); + assert(VA.getLocVT()==MVT::i32 && "Illegal CCValAssign type"); + SDValue SPN = DAG.getCopyFromReg(Chain, dl, BF::SP, MVT::i32); + SDValue OffsetN = DAG.getIntPtrConstant(Offset); + OffsetN = DAG.getNode(ISD::ADD, dl, MVT::i32, SPN, OffsetN); + MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, OffsetN, + PseudoSourceValue::getStack(), + Offset, false, false, 0)); + } + } + + // Transform all store nodes into one single node because + // all store nodes are independent of each other. + if (!MemOpChains.empty()) + Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, + &MemOpChains[0], MemOpChains.size()); + + // Build a sequence of copy-to-reg nodes chained together with token + // chain and flag operands which copy the outgoing args into registers. + // The InFlag in necessary since all emited instructions must be + // stuck together. + SDValue InFlag; + for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { + Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first, + RegsToPass[i].second, InFlag); + InFlag = Chain.getValue(1); + } + + // If the callee is a GlobalAddress node (quite common, every direct call is) + // turn it into a TargetGlobalAddress node so that legalize doesn't hack it. + // Likewise ExternalSymbol -> TargetExternalSymbol. + if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) + Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i32); + else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee)) + Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32); + + std::vector<EVT> NodeTys; + NodeTys.push_back(MVT::Other); // Returns a chain + NodeTys.push_back(MVT::Flag); // Returns a flag for retval copy to use. + SDValue Ops[] = { Chain, Callee, InFlag }; + Chain = DAG.getNode(BFISD::CALL, dl, NodeTys, Ops, + InFlag.getNode() ? 3 : 2); + InFlag = Chain.getValue(1); + + Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(ArgsSize, true), + DAG.getIntPtrConstant(0, true), InFlag); + InFlag = Chain.getValue(1); + + // Assign locations to each value returned by this call. + SmallVector<CCValAssign, 16> RVLocs; + CCState RVInfo(CallConv, isVarArg, DAG.getTarget(), RVLocs, + *DAG.getContext()); + + RVInfo.AnalyzeCallResult(Ins, RetCC_Blackfin); + + // Copy all of the result registers out of their specified physreg. + for (unsigned i = 0; i != RVLocs.size(); ++i) { + CCValAssign &RV = RVLocs[i]; + unsigned Reg = RV.getLocReg(); + + Chain = DAG.getCopyFromReg(Chain, dl, Reg, + RVLocs[i].getLocVT(), InFlag); + SDValue Val = Chain.getValue(0); + InFlag = Chain.getValue(2); + Chain = Chain.getValue(1); + + // Callee is responsible for extending any i16 return values. + switch (RV.getLocInfo()) { + case CCValAssign::SExt: + Val = DAG.getNode(ISD::AssertSext, dl, RV.getLocVT(), Val, + DAG.getValueType(RV.getValVT())); + break; + case CCValAssign::ZExt: + Val = DAG.getNode(ISD::AssertZext, dl, RV.getLocVT(), Val, + DAG.getValueType(RV.getValVT())); + break; + default: + break; + } + + // Truncate to valtype + if (RV.getLocInfo() != CCValAssign::Full) + Val = DAG.getNode(ISD::TRUNCATE, dl, RV.getValVT(), Val); + InVals.push_back(Val); + } + + return Chain; +} + +// Expansion of ADDE / SUBE. This is a bit involved since blackfin doesn't have +// add-with-carry instructions. +SDValue BlackfinTargetLowering::LowerADDE(SDValue Op, SelectionDAG &DAG) const { + // Operands: lhs, rhs, carry-in (AC0 flag) + // Results: sum, carry-out (AC0 flag) + DebugLoc dl = Op.getDebugLoc(); + + unsigned Opcode = Op.getOpcode()==ISD::ADDE ? BF::ADD : BF::SUB; + + // zext incoming carry flag in AC0 to 32 bits + SDNode* CarryIn = DAG.getMachineNode(BF::MOVE_cc_ac0, dl, MVT::i32, + /* flag= */ Op.getOperand(2)); + CarryIn = DAG.getMachineNode(BF::MOVECC_zext, dl, MVT::i32, + SDValue(CarryIn, 0)); + + // Add operands, produce sum and carry flag + SDNode *Sum = DAG.getMachineNode(Opcode, dl, MVT::i32, MVT::Flag, + Op.getOperand(0), Op.getOperand(1)); + + // Store intermediate carry from Sum + SDNode* Carry1 = DAG.getMachineNode(BF::MOVE_cc_ac0, dl, MVT::i32, + /* flag= */ SDValue(Sum, 1)); + + // Add incoming carry, again producing an output flag + Sum = DAG.getMachineNode(Opcode, dl, MVT::i32, MVT::Flag, + SDValue(Sum, 0), SDValue(CarryIn, 0)); + + // Update AC0 with the intermediate carry, producing a flag. + SDNode *CarryOut = DAG.getMachineNode(BF::OR_ac0_cc, dl, MVT::Flag, + SDValue(Carry1, 0)); + + // Compose (i32, flag) pair + SDValue ops[2] = { SDValue(Sum, 0), SDValue(CarryOut, 0) }; + return DAG.getMergeValues(ops, 2, dl); +} + +SDValue BlackfinTargetLowering::LowerOperation(SDValue Op, + SelectionDAG &DAG) const { + switch (Op.getOpcode()) { + default: + Op.getNode()->dump(); + llvm_unreachable("Should not custom lower this!"); + case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG); + case ISD::GlobalTLSAddress: + llvm_unreachable("TLS not implemented for Blackfin."); + case ISD::JumpTable: return LowerJumpTable(Op, DAG); + // Frame & Return address. Currently unimplemented + case ISD::FRAMEADDR: return SDValue(); + case ISD::RETURNADDR: return SDValue(); + case ISD::ADDE: + case ISD::SUBE: return LowerADDE(Op, DAG); + } +} + +void +BlackfinTargetLowering::ReplaceNodeResults(SDNode *N, + SmallVectorImpl<SDValue> &Results, + SelectionDAG &DAG) const { + DebugLoc dl = N->getDebugLoc(); + switch (N->getOpcode()) { + default: + llvm_unreachable("Do not know how to custom type legalize this operation!"); + return; + case ISD::READCYCLECOUNTER: { + // The low part of the cycle counter is in CYCLES, the high part in + // CYCLES2. Reading CYCLES will latch the value of CYCLES2, so we must read + // CYCLES2 last. + SDValue TheChain = N->getOperand(0); + SDValue lo = DAG.getCopyFromReg(TheChain, dl, BF::CYCLES, MVT::i32); + SDValue hi = DAG.getCopyFromReg(lo.getValue(1), dl, BF::CYCLES2, MVT::i32); + // Use a buildpair to merge the two 32-bit values into a 64-bit one. + Results.push_back(DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, lo, hi)); + // Outgoing chain. If we were to use the chain from lo instead, it would be + // possible to entirely eliminate the CYCLES2 read in (i32 (trunc + // readcyclecounter)). Unfortunately this could possibly delay the CYCLES2 + // read beyond the next CYCLES read, leading to invalid results. + Results.push_back(hi.getValue(1)); + return; + } + } +} + +/// getFunctionAlignment - Return the Log2 alignment of this function. +unsigned BlackfinTargetLowering::getFunctionAlignment(const Function *F) const { + return 2; +} + +//===----------------------------------------------------------------------===// +// Blackfin Inline Assembly Support +//===----------------------------------------------------------------------===// + +/// getConstraintType - Given a constraint letter, return the type of +/// constraint it is for this target. +BlackfinTargetLowering::ConstraintType +BlackfinTargetLowering::getConstraintType(const std::string &Constraint) const { + if (Constraint.size() != 1) + return TargetLowering::getConstraintType(Constraint); + + switch (Constraint[0]) { + // Standard constraints + case 'r': + return C_RegisterClass; + + // Blackfin-specific constraints + case 'a': + case 'd': + case 'z': + case 'D': + case 'W': + case 'e': + case 'b': + case 'v': + case 'f': + case 'c': + case 't': + case 'u': + case 'k': + case 'x': + case 'y': + case 'w': + return C_RegisterClass; + case 'A': + case 'B': + case 'C': + case 'Z': + case 'Y': + return C_Register; + } + + // Not implemented: q0-q7, qA. Use {R2} etc instead + + return TargetLowering::getConstraintType(Constraint); +} + +/// getRegForInlineAsmConstraint - Return register no and class for a C_Register +/// constraint. +std::pair<unsigned, const TargetRegisterClass*> BlackfinTargetLowering:: +getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const { + typedef std::pair<unsigned, const TargetRegisterClass*> Pair; + using namespace BF; + + if (Constraint.size() != 1) + return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT); + + switch (Constraint[0]) { + // Standard constraints + case 'r': + return Pair(0U, VT == MVT::i16 ? D16RegisterClass : DPRegisterClass); + + // Blackfin-specific constraints + case 'a': return Pair(0U, PRegisterClass); + case 'd': return Pair(0U, DRegisterClass); + case 'e': return Pair(0U, AccuRegisterClass); + case 'A': return Pair(A0, AccuRegisterClass); + case 'B': return Pair(A1, AccuRegisterClass); + case 'b': return Pair(0U, IRegisterClass); + case 'v': return Pair(0U, BRegisterClass); + case 'f': return Pair(0U, MRegisterClass); + case 'C': return Pair(CC, JustCCRegisterClass); + case 'x': return Pair(0U, GRRegisterClass); + case 'w': return Pair(0U, ALLRegisterClass); + case 'Z': return Pair(P3, PRegisterClass); + case 'Y': return Pair(P1, PRegisterClass); + } + + // Not implemented: q0-q7, qA. Use {R2} etc instead. + // Constraints z, D, W, c, t, u, k, and y use non-existing classes, defer to + // getRegClassForInlineAsmConstraint() + + return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT); +} + +std::vector<unsigned> BlackfinTargetLowering:: +getRegClassForInlineAsmConstraint(const std::string &Constraint, EVT VT) const { + using namespace BF; + + if (Constraint.size() != 1) + return std::vector<unsigned>(); + + switch (Constraint[0]) { + case 'z': return make_vector<unsigned>(P0, P1, P2, 0); + case 'D': return make_vector<unsigned>(R0, R2, R4, R6, 0); + case 'W': return make_vector<unsigned>(R1, R3, R5, R7, 0); + case 'c': return make_vector<unsigned>(I0, I1, I2, I3, + B0, B1, B2, B3, + L0, L1, L2, L3, 0); + case 't': return make_vector<unsigned>(LT0, LT1, 0); + case 'u': return make_vector<unsigned>(LB0, LB1, 0); + case 'k': return make_vector<unsigned>(LC0, LC1, 0); + case 'y': return make_vector<unsigned>(RETS, RETN, RETI, RETX, RETE, + ASTAT, SEQSTAT, USP, 0); + } + + return std::vector<unsigned>(); +} + +bool BlackfinTargetLowering:: +isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const { + // The Blackfin target isn't yet aware of offsets. + return false; +} diff --git a/contrib/llvm/lib/Target/Blackfin/BlackfinISelLowering.h b/contrib/llvm/lib/Target/Blackfin/BlackfinISelLowering.h new file mode 100644 index 0000000..6bebcc3 --- /dev/null +++ b/contrib/llvm/lib/Target/Blackfin/BlackfinISelLowering.h @@ -0,0 +1,80 @@ +//===- BlackfinISelLowering.h - Blackfin DAG Lowering Interface -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the interfaces that Blackfin uses to lower LLVM code into a +// selection DAG. +// +//===----------------------------------------------------------------------===// + +#ifndef BLACKFIN_ISELLOWERING_H +#define BLACKFIN_ISELLOWERING_H + +#include "llvm/Target/TargetLowering.h" +#include "Blackfin.h" + +namespace llvm { + + namespace BFISD { + enum { + FIRST_NUMBER = ISD::BUILTIN_OP_END, + CALL, // A call instruction. + RET_FLAG, // Return with a flag operand. + Wrapper // Address wrapper + }; + } + + class BlackfinTargetLowering : public TargetLowering { + public: + BlackfinTargetLowering(TargetMachine &TM); + virtual MVT::SimpleValueType getSetCCResultType(EVT VT) const; + virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const; + virtual void ReplaceNodeResults(SDNode *N, + SmallVectorImpl<SDValue> &Results, + SelectionDAG &DAG) const; + + ConstraintType getConstraintType(const std::string &Constraint) const; + std::pair<unsigned, const TargetRegisterClass*> + getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const; + std::vector<unsigned> + getRegClassForInlineAsmConstraint(const std::string &Constraint, + EVT VT) const; + virtual bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const; + const char *getTargetNodeName(unsigned Opcode) const; + unsigned getFunctionAlignment(const Function *F) const; + + private: + SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerADDE(SDValue Op, SelectionDAG &DAG) const; + + virtual SDValue + LowerFormalArguments(SDValue Chain, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl<ISD::InputArg> &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl<SDValue> &InVals) const; + virtual SDValue + LowerCall(SDValue Chain, SDValue Callee, + CallingConv::ID CallConv, bool isVarArg, bool &isTailCall, + const SmallVectorImpl<ISD::OutputArg> &Outs, + const SmallVectorImpl<SDValue> &OutVals, + const SmallVectorImpl<ISD::InputArg> &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl<SDValue> &InVals) const; + + virtual SDValue + LowerReturn(SDValue Chain, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl<ISD::OutputArg> &Outs, + const SmallVectorImpl<SDValue> &OutVals, + DebugLoc dl, SelectionDAG &DAG) const; + }; +} // end namespace llvm + +#endif // BLACKFIN_ISELLOWERING_H diff --git a/contrib/llvm/lib/Target/Blackfin/BlackfinInstrFormats.td b/contrib/llvm/lib/Target/Blackfin/BlackfinInstrFormats.td new file mode 100644 index 0000000..d8e6e25 --- /dev/null +++ b/contrib/llvm/lib/Target/Blackfin/BlackfinInstrFormats.td @@ -0,0 +1,34 @@ +//===--- BlackfinInstrFormats.td ---------------------------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Instruction format superclass +//===----------------------------------------------------------------------===// + +class InstBfin<dag outs, dag ins, string asmstr, list<dag> pattern> + : Instruction { + field bits<32> Inst; + + let Namespace = "BF"; + + dag OutOperandList = outs; + dag InOperandList = ins; + let AsmString = asmstr; + let Pattern = pattern; +} + +// Single-word (16-bit) instructions +class F1<dag outs, dag ins, string asmstr, list<dag> pattern> + : InstBfin<outs, ins, asmstr, pattern> { +} + +// Double-word (32-bit) instructions +class F2<dag outs, dag ins, string asmstr, list<dag> pattern> + : InstBfin<outs, ins, asmstr, pattern> { +} diff --git a/contrib/llvm/lib/Target/Blackfin/BlackfinInstrInfo.cpp b/contrib/llvm/lib/Target/Blackfin/BlackfinInstrInfo.cpp new file mode 100644 index 0000000..a74d42d --- /dev/null +++ b/contrib/llvm/lib/Target/Blackfin/BlackfinInstrInfo.cpp @@ -0,0 +1,281 @@ +//===- BlackfinInstrInfo.cpp - Blackfin Instruction Information -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the Blackfin implementation of the TargetInstrInfo class. +// +//===----------------------------------------------------------------------===// + +#include "BlackfinInstrInfo.h" +#include "BlackfinSubtarget.h" +#include "Blackfin.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/Support/ErrorHandling.h" +#include "BlackfinGenInstrInfo.inc" + +using namespace llvm; + +BlackfinInstrInfo::BlackfinInstrInfo(BlackfinSubtarget &ST) + : TargetInstrInfoImpl(BlackfinInsts, array_lengthof(BlackfinInsts)), + RI(ST, *this), + Subtarget(ST) {} + +/// Return true if the instruction is a register to register move and +/// leave the source and dest operands in the passed parameters. +bool BlackfinInstrInfo::isMoveInstr(const MachineInstr &MI, + unsigned &SrcReg, + unsigned &DstReg, + unsigned &SrcSR, + unsigned &DstSR) const { + SrcSR = DstSR = 0; // No sub-registers. + switch (MI.getOpcode()) { + case BF::MOVE: + case BF::MOVE_ncccc: + case BF::MOVE_ccncc: + case BF::MOVECC_zext: + case BF::MOVECC_nz: + DstReg = MI.getOperand(0).getReg(); + SrcReg = MI.getOperand(1).getReg(); + return true; + case BF::SLL16i: + if (MI.getOperand(2).getImm()!=0) + return false; + DstReg = MI.getOperand(0).getReg(); + SrcReg = MI.getOperand(1).getReg(); + return true; + default: + return false; + } +} + +/// isLoadFromStackSlot - If the specified machine instruction is a direct +/// load from a stack slot, return the virtual or physical register number of +/// the destination along with the FrameIndex of the loaded stack slot. If +/// not, return 0. This predicate must return 0 if the instruction has +/// any side effects other than loading from the stack slot. +unsigned BlackfinInstrInfo::isLoadFromStackSlot(const MachineInstr *MI, + int &FrameIndex) const { + switch (MI->getOpcode()) { + default: break; + case BF::LOAD32fi: + case BF::LOAD16fi: + if (MI->getOperand(1).isFI() && + MI->getOperand(2).isImm() && + MI->getOperand(2).getImm() == 0) { + FrameIndex = MI->getOperand(1).getIndex(); + return MI->getOperand(0).getReg(); + } + break; + } + return 0; +} + +/// isStoreToStackSlot - If the specified machine instruction is a direct +/// store to a stack slot, return the virtual or physical register number of +/// the source reg along with the FrameIndex of the loaded stack slot. If +/// not, return 0. This predicate must return 0 if the instruction has +/// any side effects other than storing to the stack slot. +unsigned BlackfinInstrInfo::isStoreToStackSlot(const MachineInstr *MI, + int &FrameIndex) const { + switch (MI->getOpcode()) { + default: break; + case BF::STORE32fi: + case BF::STORE16fi: + if (MI->getOperand(1).isFI() && + MI->getOperand(2).isImm() && + MI->getOperand(2).getImm() == 0) { + FrameIndex = MI->getOperand(1).getIndex(); + return MI->getOperand(0).getReg(); + } + break; + } + return 0; +} + +unsigned BlackfinInstrInfo:: +InsertBranch(MachineBasicBlock &MBB, + MachineBasicBlock *TBB, + MachineBasicBlock *FBB, + const SmallVectorImpl<MachineOperand> &Cond, + DebugLoc DL) const { + // Shouldn't be a fall through. + assert(TBB && "InsertBranch must not be told to insert a fallthrough"); + assert((Cond.size() == 1 || Cond.size() == 0) && + "Branch conditions have one component!"); + + if (Cond.empty()) { + // Unconditional branch? + assert(!FBB && "Unconditional branch with multiple successors!"); + BuildMI(&MBB, DL, get(BF::JUMPa)).addMBB(TBB); + return 1; + } + + // Conditional branch. + llvm_unreachable("Implement conditional branches!"); +} + +void BlackfinInstrInfo::copyPhysReg(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, DebugLoc DL, + unsigned DestReg, unsigned SrcReg, + bool KillSrc) const { + if (BF::ALLRegClass.contains(DestReg, SrcReg)) { + BuildMI(MBB, I, DL, get(BF::MOVE), DestReg) + .addReg(SrcReg, getKillRegState(KillSrc)); + return; + } + + if (BF::D16RegClass.contains(DestReg, SrcReg)) { + BuildMI(MBB, I, DL, get(BF::SLL16i), DestReg) + .addReg(SrcReg, getKillRegState(KillSrc)) + .addImm(0); + return; + } + + if (BF::DRegClass.contains(DestReg)) { + if (SrcReg == BF::NCC) { + BuildMI(MBB, I, DL, get(BF::MOVENCC_z), DestReg) + .addReg(SrcReg, getKillRegState(KillSrc)); + BuildMI(MBB, I, DL, get(BF::BITTGL), DestReg).addReg(DestReg).addImm(0); + return; + } + if (SrcReg == BF::CC) { + BuildMI(MBB, I, DL, get(BF::MOVECC_zext), DestReg) + .addReg(SrcReg, getKillRegState(KillSrc)); + return; + } + } + + if (BF::DRegClass.contains(SrcReg)) { + if (DestReg == BF::NCC) { + BuildMI(MBB, I, DL, get(BF::SETEQri_not), DestReg) + .addReg(SrcReg, getKillRegState(KillSrc)).addImm(0); + return; + } + if (DestReg == BF::CC) { + BuildMI(MBB, I, DL, get(BF::MOVECC_nz), DestReg) + .addReg(SrcReg, getKillRegState(KillSrc)); + return; + } + } + + + if (DestReg == BF::NCC && SrcReg == BF::CC) { + BuildMI(MBB, I, DL, get(BF::MOVE_ncccc), DestReg) + .addReg(SrcReg, getKillRegState(KillSrc)); + return; + } + + if (DestReg == BF::CC && SrcReg == BF::NCC) { + BuildMI(MBB, I, DL, get(BF::MOVE_ccncc), DestReg) + .addReg(SrcReg, getKillRegState(KillSrc)); + return; + } + + llvm_unreachable("Bad reg-to-reg copy"); +} + +static bool inClass(const TargetRegisterClass &Test, + unsigned Reg, + const TargetRegisterClass *RC) { + if (TargetRegisterInfo::isPhysicalRegister(Reg)) + return Test.contains(Reg); + else + return &Test==RC || Test.hasSubClass(RC); +} + +void +BlackfinInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + unsigned SrcReg, + bool isKill, + int FI, + const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI) const { + DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc(); + + if (inClass(BF::DPRegClass, SrcReg, RC)) { + BuildMI(MBB, I, DL, get(BF::STORE32fi)) + .addReg(SrcReg, getKillRegState(isKill)) + .addFrameIndex(FI) + .addImm(0); + return; + } + + if (inClass(BF::D16RegClass, SrcReg, RC)) { + BuildMI(MBB, I, DL, get(BF::STORE16fi)) + .addReg(SrcReg, getKillRegState(isKill)) + .addFrameIndex(FI) + .addImm(0); + return; + } + + if (inClass(BF::AnyCCRegClass, SrcReg, RC)) { + BuildMI(MBB, I, DL, get(BF::STORE8fi)) + .addReg(SrcReg, getKillRegState(isKill)) + .addFrameIndex(FI) + .addImm(0); + return; + } + + llvm_unreachable((std::string("Cannot store regclass to stack slot: ")+ + RC->getName()).c_str()); +} + +void BlackfinInstrInfo:: +storeRegToAddr(MachineFunction &MF, + unsigned SrcReg, + bool isKill, + SmallVectorImpl<MachineOperand> &Addr, + const TargetRegisterClass *RC, + SmallVectorImpl<MachineInstr*> &NewMIs) const { + llvm_unreachable("storeRegToAddr not implemented"); +} + +void +BlackfinInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + unsigned DestReg, + int FI, + const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI) const { + DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc(); + if (inClass(BF::DPRegClass, DestReg, RC)) { + BuildMI(MBB, I, DL, get(BF::LOAD32fi), DestReg) + .addFrameIndex(FI) + .addImm(0); + return; + } + + if (inClass(BF::D16RegClass, DestReg, RC)) { + BuildMI(MBB, I, DL, get(BF::LOAD16fi), DestReg) + .addFrameIndex(FI) + .addImm(0); + return; + } + + if (inClass(BF::AnyCCRegClass, DestReg, RC)) { + BuildMI(MBB, I, DL, get(BF::LOAD8fi), DestReg) + .addFrameIndex(FI) + .addImm(0); + return; + } + + llvm_unreachable("Cannot load regclass from stack slot"); +} + +void BlackfinInstrInfo:: +loadRegFromAddr(MachineFunction &MF, + unsigned DestReg, + SmallVectorImpl<MachineOperand> &Addr, + const TargetRegisterClass *RC, + SmallVectorImpl<MachineInstr*> &NewMIs) const { + llvm_unreachable("loadRegFromAddr not implemented"); +} diff --git a/contrib/llvm/lib/Target/Blackfin/BlackfinInstrInfo.h b/contrib/llvm/lib/Target/Blackfin/BlackfinInstrInfo.h new file mode 100644 index 0000000..6c35917 --- /dev/null +++ b/contrib/llvm/lib/Target/Blackfin/BlackfinInstrInfo.h @@ -0,0 +1,82 @@ +//===- BlackfinInstrInfo.h - Blackfin Instruction Information ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the Blackfin implementation of the TargetInstrInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef BLACKFININSTRUCTIONINFO_H +#define BLACKFININSTRUCTIONINFO_H + +#include "llvm/Target/TargetInstrInfo.h" +#include "BlackfinRegisterInfo.h" + +namespace llvm { + + class BlackfinInstrInfo : public TargetInstrInfoImpl { + const BlackfinRegisterInfo RI; + const BlackfinSubtarget& Subtarget; + public: + explicit BlackfinInstrInfo(BlackfinSubtarget &ST); + + /// getRegisterInfo - TargetInstrInfo is a superset of MRegister info. As + /// such, whenever a client has an instance of instruction info, it should + /// always be able to get register info as well (through this method). + virtual const BlackfinRegisterInfo &getRegisterInfo() const { return RI; } + + virtual bool isMoveInstr(const MachineInstr &MI, + unsigned &SrcReg, unsigned &DstReg, + unsigned &SrcSubIdx, unsigned &DstSubIdx) const; + + virtual unsigned isLoadFromStackSlot(const MachineInstr *MI, + int &FrameIndex) const; + + virtual unsigned isStoreToStackSlot(const MachineInstr *MI, + int &FrameIndex) const; + + virtual unsigned + InsertBranch(MachineBasicBlock &MBB, + MachineBasicBlock *TBB, + MachineBasicBlock *FBB, + const SmallVectorImpl<MachineOperand> &Cond, + DebugLoc DL) const; + + virtual void copyPhysReg(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, DebugLoc DL, + unsigned DestReg, unsigned SrcReg, + bool KillSrc) const; + + virtual void storeRegToStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + unsigned SrcReg, bool isKill, + int FrameIndex, + const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI) const; + + virtual void storeRegToAddr(MachineFunction &MF, + unsigned SrcReg, bool isKill, + SmallVectorImpl<MachineOperand> &Addr, + const TargetRegisterClass *RC, + SmallVectorImpl<MachineInstr*> &NewMIs) const; + + virtual void loadRegFromStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + unsigned DestReg, int FrameIndex, + const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI) const; + + virtual void loadRegFromAddr(MachineFunction &MF, unsigned DestReg, + SmallVectorImpl<MachineOperand> &Addr, + const TargetRegisterClass *RC, + SmallVectorImpl<MachineInstr*> &NewMIs) const; + }; + +} // end namespace llvm + +#endif diff --git a/contrib/llvm/lib/Target/Blackfin/BlackfinInstrInfo.td b/contrib/llvm/lib/Target/Blackfin/BlackfinInstrInfo.td new file mode 100644 index 0000000..8034a7f --- /dev/null +++ b/contrib/llvm/lib/Target/Blackfin/BlackfinInstrInfo.td @@ -0,0 +1,862 @@ +//===- BlackfinInstrInfo.td - Target Description for Blackfin Target ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes the Blackfin instructions in TableGen format. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Instruction format superclass +//===----------------------------------------------------------------------===// + +include "BlackfinInstrFormats.td" + +// These are target-independent nodes, but have target-specific formats. +def SDT_BfinCallSeqStart : SDCallSeqStart<[ SDTCisVT<0, i32> ]>; +def SDT_BfinCallSeqEnd : SDCallSeqEnd<[ SDTCisVT<0, i32>, + SDTCisVT<1, i32> ]>; + +def BfinCallseqStart : SDNode<"ISD::CALLSEQ_START", SDT_BfinCallSeqStart, + [SDNPHasChain, SDNPOutFlag]>; +def BfinCallseqEnd : SDNode<"ISD::CALLSEQ_END", SDT_BfinCallSeqEnd, + [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>; + +def SDT_BfinCall : SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>; +def BfinCall : SDNode<"BFISD::CALL", SDT_BfinCall, + [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag, + SDNPVariadic]>; + +def BfinRet: SDNode<"BFISD::RET_FLAG", SDTNone, + [SDNPHasChain, SDNPOptInFlag]>; + +def BfinWrapper: SDNode<"BFISD::Wrapper", SDTIntUnaryOp>; + +//===----------------------------------------------------------------------===// +// Transformations +//===----------------------------------------------------------------------===// + +def trailingZeros_xform : SDNodeXForm<imm, [{ + return CurDAG->getTargetConstant(N->getAPIntValue().countTrailingZeros(), + MVT::i32); +}]>; + +def trailingOnes_xform : SDNodeXForm<imm, [{ + return CurDAG->getTargetConstant(N->getAPIntValue().countTrailingOnes(), + MVT::i32); +}]>; + +def LO16 : SDNodeXForm<imm, [{ + return CurDAG->getTargetConstant((unsigned short)N->getZExtValue(), MVT::i16); +}]>; + +def HI16 : SDNodeXForm<imm, [{ + // Transformation function: shift the immediate value down into the low bits. + return CurDAG->getTargetConstant((unsigned)N->getZExtValue() >> 16, MVT::i16); +}]>; + +//===----------------------------------------------------------------------===// +// Immediates +//===----------------------------------------------------------------------===// + +def imm3 : PatLeaf<(imm), [{return isInt<3>(N->getSExtValue());}]>; +def uimm3 : PatLeaf<(imm), [{return isUInt<3>(N->getZExtValue());}]>; +def uimm4 : PatLeaf<(imm), [{return isUInt<4>(N->getZExtValue());}]>; +def uimm5 : PatLeaf<(imm), [{return isUInt<5>(N->getZExtValue());}]>; + +def uimm5m2 : PatLeaf<(imm), [{ + uint64_t value = N->getZExtValue(); + return value % 2 == 0 && isUInt<5>(value); +}]>; + +def uimm6m4 : PatLeaf<(imm), [{ + uint64_t value = N->getZExtValue(); + return value % 4 == 0 && isUInt<6>(value); +}]>; + +def imm7 : PatLeaf<(imm), [{return isInt<7>(N->getSExtValue());}]>; +def imm16 : PatLeaf<(imm), [{return isInt<16>(N->getSExtValue());}]>; +def uimm16 : PatLeaf<(imm), [{return isUInt<16>(N->getZExtValue());}]>; + +def ximm16 : PatLeaf<(imm), [{ + int64_t value = N->getSExtValue(); + return value < (1<<16) && value >= -(1<<15); +}]>; + +def imm17m2 : PatLeaf<(imm), [{ + int64_t value = N->getSExtValue(); + return value % 2 == 0 && isInt<17>(value); +}]>; + +def imm18m4 : PatLeaf<(imm), [{ + int64_t value = N->getSExtValue(); + return value % 4 == 0 && isInt<18>(value); +}]>; + +// 32-bit bitmask transformed to a bit number +def uimm5mask : Operand<i32>, PatLeaf<(imm), [{ + return isPowerOf2_32(N->getZExtValue()); +}], trailingZeros_xform>; + +// 32-bit inverse bitmask transformed to a bit number +def uimm5imask : Operand<i32>, PatLeaf<(imm), [{ + return isPowerOf2_32(~N->getZExtValue()); +}], trailingOnes_xform>; + +//===----------------------------------------------------------------------===// +// Operands +//===----------------------------------------------------------------------===// + +def calltarget : Operand<iPTR>; + +def brtarget : Operand<OtherVT>; + +// Addressing modes +def ADDRspii : ComplexPattern<i32, 2, "SelectADDRspii", [add, frameindex], []>; + +// Address operands +def MEMii : Operand<i32> { + let PrintMethod = "printMemoryOperand"; + let MIOperandInfo = (ops i32imm, i32imm); +} + +//===----------------------------------------------------------------------===// +// Instructions +//===----------------------------------------------------------------------===// + +// Pseudo instructions. +class Pseudo<dag outs, dag ins, string asmstr, list<dag> pattern> + : InstBfin<outs, ins, asmstr, pattern>; + +let Defs = [SP], Uses = [SP] in { +def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt), + "${:comment}ADJCALLSTACKDOWN $amt", + [(BfinCallseqStart timm:$amt)]>; +def ADJCALLSTACKUP : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), + "${:comment}ADJCALLSTACKUP $amt1 $amt2", + [(BfinCallseqEnd timm:$amt1, timm:$amt2)]>; +} + +//===----------------------------------------------------------------------===// +// Table C-9. Program Flow Control Instructions +//===----------------------------------------------------------------------===// + +let isBranch = 1, isTerminator = 1 in { + +let isIndirectBranch = 1 in +def JUMPp : F1<(outs), (ins P:$target), + "JUMP ($target);", + [(brind P:$target)]>; + +// TODO JUMP (PC-P) + +// NOTE: assembler chooses between JUMP.S and JUMP.L +def JUMPa : F1<(outs), (ins brtarget:$target), + "jump $target;", + [(br bb:$target)]>; + +def JUMPcc : F1<(outs), (ins AnyCC:$cc, brtarget:$target), + "if $cc jump $target;", + [(brcond AnyCC:$cc, bb:$target)]>; +} + +let isCall = 1, + Defs = [R0, R1, R2, R3, P0, P1, P2, LB0, LB1, LC0, LC1, RETS, ASTAT] in { +def CALLa: F1<(outs), (ins calltarget:$func, variable_ops), + "call $func;", []>; +def CALLp: F1<(outs), (ins P:$func, variable_ops), + "call ($func);", [(BfinCall P:$func)]>; +} + +let isReturn = 1, + isTerminator = 1, + isBarrier = 1, + Uses = [RETS] in +def RTS: F1<(outs), (ins), "rts;", [(BfinRet)]>; + +//===----------------------------------------------------------------------===// +// Table C-10. Load / Store Instructions +//===----------------------------------------------------------------------===// + +// Immediate constant loads + +// sext immediate, i32 D/P regs +def LOADimm7: F1<(outs DP:$dst), (ins i32imm:$src), + "$dst = $src (x);", + [(set DP:$dst, imm7:$src)]>; + +// zext immediate, i32 reg groups 0-3 +def LOADuimm16: F2<(outs GR:$dst), (ins i32imm:$src), + "$dst = $src (z);", + [(set GR:$dst, uimm16:$src)]>; + +// sext immediate, i32 reg groups 0-3 +def LOADimm16: F2<(outs GR:$dst), (ins i32imm:$src), + "$dst = $src (x);", + [(set GR:$dst, imm16:$src)]>; + +// Pseudo-instruction for loading a general 32-bit constant. +def LOAD32imm: Pseudo<(outs GR:$dst), (ins i32imm:$src), + "$dst.h = ($src >> 16); $dst.l = ($src & 0xffff);", + [(set GR:$dst, imm:$src)]>; + +def LOAD32sym: Pseudo<(outs GR:$dst), (ins i32imm:$src), + "$dst.h = $src; $dst.l = $src;", []>; + + +// 16-bit immediate, i16 reg groups 0-3 +def LOAD16i: F2<(outs GR16:$dst), (ins i16imm:$src), + "$dst = $src;", []>; + +def : Pat<(BfinWrapper (i32 tglobaladdr:$addr)), + (LOAD32sym tglobaladdr:$addr)>; + +def : Pat<(BfinWrapper (i32 tjumptable:$addr)), + (LOAD32sym tjumptable:$addr)>; + +// We cannot copy from GR16 to D16, and codegen wants to insert copies if we +// emit GR16 instructions. As a hack, we use this fake instruction instead. +def LOAD16i_d16: F2<(outs D16:$dst), (ins i16imm:$src), + "$dst = $src;", + [(set D16:$dst, ximm16:$src)]>; + +// Memory loads with patterns + +def LOAD32p: F1<(outs DP:$dst), (ins P:$ptr), + "$dst = [$ptr];", + [(set DP:$dst, (load P:$ptr))]>; + +// Pseudo-instruction for loading a stack slot +def LOAD32fi: Pseudo<(outs DP:$dst), (ins MEMii:$mem), + "${:comment}FI $dst = [$mem];", + [(set DP:$dst, (load ADDRspii:$mem))]>; + +// Note: Expands to multiple insns +def LOAD16fi: Pseudo<(outs D16:$dst), (ins MEMii:$mem), + "${:comment}FI $dst = [$mem];", + [(set D16:$dst, (load ADDRspii:$mem))]>; + +// Pseudo-instruction for loading a stack slot, used for AnyCC regs. +// Replaced with Load D + CC=D +def LOAD8fi: Pseudo<(outs AnyCC:$dst), (ins MEMii:$mem), + "${:comment}FI $dst = B[$mem];", + [(set AnyCC:$dst, (load ADDRspii:$mem))]>; + +def LOAD32p_uimm6m4: F1<(outs DP:$dst), (ins P:$ptr, i32imm:$off), + "$dst = [$ptr + $off];", + [(set DP:$dst, (load (add P:$ptr, uimm6m4:$off)))]>; + +def LOAD32p_imm18m4: F2<(outs DP:$dst), (ins P:$ptr, i32imm:$off), + "$dst = [$ptr + $off];", + [(set DP:$dst, (load (add P:$ptr, imm18m4:$off)))]>; + +def LOAD32p_16z: F1<(outs D:$dst), (ins P:$ptr), + "$dst = W[$ptr] (z);", + [(set D:$dst, (zextloadi16 P:$ptr))]>; + +def : Pat<(i32 (extloadi16 P:$ptr)),(LOAD32p_16z P:$ptr)>; + +def LOAD32p_uimm5m2_16z: F1<(outs D:$dst), (ins P:$ptr, i32imm:$off), + "$dst = w[$ptr + $off] (z);", + [(set D:$dst, (zextloadi16 (add P:$ptr, + uimm5m2:$off)))]>; + +def : Pat<(i32 (extloadi16 (add P:$ptr, uimm5m2:$off))), + (LOAD32p_uimm5m2_16z P:$ptr, imm:$off)>; + +def LOAD32p_imm17m2_16z: F1<(outs D:$dst), (ins P:$ptr, i32imm:$off), + "$dst = w[$ptr + $off] (z);", + [(set D:$dst, + (zextloadi16 (add P:$ptr, imm17m2:$off)))]>; + +def : Pat<(i32 (extloadi16 (add P:$ptr, imm17m2:$off))), + (LOAD32p_imm17m2_16z P:$ptr, imm:$off)>; + +def LOAD32p_16s: F1<(outs D:$dst), (ins P:$ptr), + "$dst = w[$ptr] (x);", + [(set D:$dst, (sextloadi16 P:$ptr))]>; + +def LOAD32p_uimm5m2_16s: F1<(outs D:$dst), (ins P:$ptr, i32imm:$off), + "$dst = w[$ptr + $off] (x);", + [(set D:$dst, + (sextloadi16 (add P:$ptr, uimm5m2:$off)))]>; + +def LOAD32p_imm17m2_16s: F1<(outs D:$dst), (ins P:$ptr, i32imm:$off), + "$dst = w[$ptr + $off] (x);", + [(set D:$dst, + (sextloadi16 (add P:$ptr, imm17m2:$off)))]>; + +def LOAD16pi: F1<(outs D16:$dst), (ins PI:$ptr), + "$dst = w[$ptr];", + [(set D16:$dst, (load PI:$ptr))]>; + +def LOAD32p_8z: F1<(outs D:$dst), (ins P:$ptr), + "$dst = B[$ptr] (z);", + [(set D:$dst, (zextloadi8 P:$ptr))]>; + +def : Pat<(i32 (extloadi8 P:$ptr)), (LOAD32p_8z P:$ptr)>; +def : Pat<(i16 (extloadi8 P:$ptr)), + (EXTRACT_SUBREG (LOAD32p_8z P:$ptr), lo16)>; +def : Pat<(i16 (zextloadi8 P:$ptr)), + (EXTRACT_SUBREG (LOAD32p_8z P:$ptr), lo16)>; + +def LOAD32p_imm16_8z: F1<(outs D:$dst), (ins P:$ptr, i32imm:$off), + "$dst = b[$ptr + $off] (z);", + [(set D:$dst, (zextloadi8 (add P:$ptr, imm16:$off)))]>; + +def : Pat<(i32 (extloadi8 (add P:$ptr, imm16:$off))), + (LOAD32p_imm16_8z P:$ptr, imm:$off)>; +def : Pat<(i16 (extloadi8 (add P:$ptr, imm16:$off))), + (EXTRACT_SUBREG (LOAD32p_imm16_8z P:$ptr, imm:$off), + lo16)>; +def : Pat<(i16 (zextloadi8 (add P:$ptr, imm16:$off))), + (EXTRACT_SUBREG (LOAD32p_imm16_8z P:$ptr, imm:$off), + lo16)>; + +def LOAD32p_8s: F1<(outs D:$dst), (ins P:$ptr), + "$dst = b[$ptr] (x);", + [(set D:$dst, (sextloadi8 P:$ptr))]>; + +def : Pat<(i16 (sextloadi8 P:$ptr)), + (EXTRACT_SUBREG (LOAD32p_8s P:$ptr), lo16)>; + +def LOAD32p_imm16_8s: F1<(outs D:$dst), (ins P:$ptr, i32imm:$off), + "$dst = b[$ptr + $off] (x);", + [(set D:$dst, (sextloadi8 (add P:$ptr, imm16:$off)))]>; + +def : Pat<(i16 (sextloadi8 (add P:$ptr, imm16:$off))), + (EXTRACT_SUBREG (LOAD32p_imm16_8s P:$ptr, imm:$off), + lo16)>; +// Memory loads without patterns + +let mayLoad = 1 in { + +multiclass LOAD_incdec<RegisterClass drc, RegisterClass prc, + string mem="", string suf=";"> { + def _inc : F1<(outs drc:$dst, prc:$ptr_wb), (ins prc:$ptr), + !strconcat(!subst("M", mem, "$dst = M[$ptr++]"), suf), []>; + def _dec : F1<(outs drc:$dst, prc:$ptr_wb), (ins prc:$ptr), + !strconcat(!subst("M", mem, "$dst = M[$ptr--]"), suf), []>; +} +multiclass LOAD_incdecpost<RegisterClass drc, RegisterClass prc, + string mem="", string suf=";"> + : LOAD_incdec<drc, prc, mem, suf> { + def _post : F1<(outs drc:$dst, prc:$ptr_wb), (ins prc:$ptr, prc:$off), + !strconcat(!subst("M", mem, "$dst = M[$ptr++$off]"), suf), []>; +} + +defm LOAD32p: LOAD_incdec<DP, P>; +defm LOAD32i: LOAD_incdec<D, I>; +defm LOAD8z32p: LOAD_incdec<D, P, "b", " (z);">; +defm LOAD8s32p: LOAD_incdec<D, P, "b", " (x);">; +defm LOADhi: LOAD_incdec<D16, I, "w">; +defm LOAD16z32p: LOAD_incdecpost<D, P, "w", " (z);">; +defm LOAD16s32p: LOAD_incdecpost<D, P, "w", " (x);">; + +def LOAD32p_post: F1<(outs D:$dst, P:$ptr_wb), (ins P:$ptr, P:$off), + "$dst = [$ptr ++ $off];", []>; + +// Note: $fp MUST be FP +def LOAD32fp_nimm7m4: F1<(outs DP:$dst), (ins P:$fp, i32imm:$off), + "$dst = [$fp - $off];", []>; + +def LOAD32i: F1<(outs D:$dst), (ins I:$ptr), + "$dst = [$ptr];", []>; +def LOAD32i_post: F1<(outs D:$dst, I:$ptr_wb), (ins I:$ptr, M:$off), + "$dst = [$ptr ++ $off];", []>; + + + +def LOADhp_post: F1<(outs D16:$dst, P:$ptr_wb), (ins P:$ptr, P:$off), + "$dst = w[$ptr ++ $off];", []>; + + +} + +// Memory stores with patterns +def STORE32p: F1<(outs), (ins DP:$val, P:$ptr), + "[$ptr] = $val;", + [(store DP:$val, P:$ptr)]>; + +// Pseudo-instructions for storing to a stack slot +def STORE32fi: Pseudo<(outs), (ins DP:$val, MEMii:$mem), + "${:comment}FI [$mem] = $val;", + [(store DP:$val, ADDRspii:$mem)]>; + +// Note: This stack-storing pseudo-instruction is expanded to multiple insns +def STORE16fi: Pseudo<(outs), (ins D16:$val, MEMii:$mem), + "${:comment}FI [$mem] = $val;", + [(store D16:$val, ADDRspii:$mem)]>; + +// Pseudo-instructions for storing AnyCC register to a stack slot. +// Replaced with D=CC + STORE byte +def STORE8fi: Pseudo<(outs), (ins AnyCC:$val, MEMii:$mem), + "${:comment}FI b[$mem] = $val;", + [(store AnyCC:$val, ADDRspii:$mem)]>; + +def STORE32p_uimm6m4: F1<(outs), (ins DP:$val, P:$ptr, i32imm:$off), + "[$ptr + $off] = $val;", + [(store DP:$val, (add P:$ptr, uimm6m4:$off))]>; + +def STORE32p_imm18m4: F1<(outs), (ins DP:$val, P:$ptr, i32imm:$off), + "[$ptr + $off] = $val;", + [(store DP:$val, (add P:$ptr, imm18m4:$off))]>; + +def STORE16pi: F1<(outs), (ins D16:$val, PI:$ptr), + "w[$ptr] = $val;", + [(store D16:$val, PI:$ptr)]>; + +def STORE8p: F1<(outs), (ins D:$val, P:$ptr), + "b[$ptr] = $val;", + [(truncstorei8 D:$val, P:$ptr)]>; + +def STORE8p_imm16: F1<(outs), (ins D:$val, P:$ptr, i32imm:$off), + "b[$ptr + $off] = $val;", + [(truncstorei8 D:$val, (add P:$ptr, imm16:$off))]>; + +let Constraints = "$ptr = $ptr_wb" in { + +multiclass STORE_incdec<RegisterClass drc, RegisterClass prc, + int off=4, string pre=""> { + def _inc : F1<(outs prc:$ptr_wb), (ins drc:$val, prc:$ptr), + !strconcat(pre, "[$ptr++] = $val;"), + [(set prc:$ptr_wb, (post_store drc:$val, prc:$ptr, off))]>; + def _dec : F1<(outs prc:$ptr_wb), (ins drc:$val, prc:$ptr), + !strconcat(pre, "[$ptr--] = $val;"), + [(set prc:$ptr_wb, (post_store drc:$val, prc:$ptr, + (ineg off)))]>; +} + +defm STORE32p: STORE_incdec<DP, P>; +defm STORE16i: STORE_incdec<D16, I, 2, "w">; +defm STORE8p: STORE_incdec<D, P, 1, "b">; + +def STORE32p_post: F1<(outs P:$ptr_wb), (ins D:$val, P:$ptr, P:$off), + "[$ptr ++ $off] = $val;", + [(set P:$ptr_wb, (post_store D:$val, P:$ptr, P:$off))]>; + +def STORE16p_post: F1<(outs P:$ptr_wb), (ins D16:$val, P:$ptr, P:$off), + "w[$ptr ++ $off] = $val;", + [(set P:$ptr_wb, (post_store D16:$val, P:$ptr, P:$off))]>; +} + +// Memory stores without patterns + +let mayStore = 1 in { + +// Note: only works for $fp == FP +def STORE32fp_nimm7m4: F1<(outs), (ins DP:$val, P:$fp, i32imm:$off), + "[$fp - $off] = $val;", []>; + +def STORE32i: F1<(outs), (ins D:$val, I:$ptr), + "[$ptr] = $val;", []>; + +def STORE32i_inc: F1<(outs I:$ptr_wb), (ins D:$val, I:$ptr), + "[$ptr++] = $val;", []>; + +def STORE32i_dec: F1<(outs I:$ptr_wb), (ins D:$val, I:$ptr), + "[$ptr--] = $val;", []>; + +def STORE32i_post: F1<(outs I:$ptr_wb), (ins D:$val, I:$ptr, M:$off), + "[$ptr ++ $off] = $val;", []>; +} + +def : Pat<(truncstorei16 D:$val, PI:$ptr), + (STORE16pi (EXTRACT_SUBREG (i32 (COPY_TO_REGCLASS D:$val, D)), + lo16), PI:$ptr)>; + +def : Pat<(truncstorei16 (srl D:$val, (i16 16)), PI:$ptr), + (STORE16pi (EXTRACT_SUBREG (i32 (COPY_TO_REGCLASS D:$val, D)), + hi16), PI:$ptr)>; + +def : Pat<(truncstorei8 D16L:$val, P:$ptr), + (STORE8p (INSERT_SUBREG (i32 (IMPLICIT_DEF)), + (i16 (COPY_TO_REGCLASS D16L:$val, D16L)), + lo16), + P:$ptr)>; + +//===----------------------------------------------------------------------===// +// Table C-11. Move Instructions. +//===----------------------------------------------------------------------===// + +def MOVE: F1<(outs ALL:$dst), (ins ALL:$src), + "$dst = $src;", + []>; + +let Constraints = "$src1 = $dst" in +def MOVEcc: F1<(outs DP:$dst), (ins DP:$src1, DP:$src2, AnyCC:$cc), + "if $cc $dst = $src2;", + [(set DP:$dst, (select AnyCC:$cc, DP:$src2, DP:$src1))]>; + +let Defs = [AZ, AN, AC0, V] in { +def MOVEzext: F1<(outs D:$dst), (ins D16L:$src), + "$dst = $src (z);", + [(set D:$dst, (zext D16L:$src))]>; + +def MOVEsext: F1<(outs D:$dst), (ins D16L:$src), + "$dst = $src (x);", + [(set D:$dst, (sext D16L:$src))]>; + +def MOVEzext8: F1<(outs D:$dst), (ins D:$src), + "$dst = $src.b (z);", + [(set D:$dst, (and D:$src, 0xff))]>; + +def MOVEsext8: F1<(outs D:$dst), (ins D:$src), + "$dst = $src.b (x);", + [(set D:$dst, (sext_inreg D:$src, i8))]>; + +} + +def : Pat<(sext_inreg D16L:$src, i8), + (EXTRACT_SUBREG (MOVEsext8 + (INSERT_SUBREG (i32 (IMPLICIT_DEF)), + D16L:$src, + lo16)), + lo16)>; + +def : Pat<(sext_inreg D:$src, i16), + (MOVEsext (EXTRACT_SUBREG D:$src, lo16))>; + +def : Pat<(and D:$src, 0xffff), + (MOVEzext (EXTRACT_SUBREG D:$src, lo16))>; + +def : Pat<(i32 (anyext D16L:$src)), + (INSERT_SUBREG (i32 (IMPLICIT_DEF)), + (i16 (COPY_TO_REGCLASS D16L:$src, D16L)), + lo16)>; + +// TODO Dreg = Dreg_byte (X/Z) + +// TODO Accumulator moves + +//===----------------------------------------------------------------------===// +// Table C-12. Stack Control Instructions +//===----------------------------------------------------------------------===// + +let Uses = [SP], Defs = [SP] in { +def PUSH: F1<(outs), (ins ALL:$src), + "[--sp] = $src;", []> { let mayStore = 1; } + +// NOTE: POP does not work for DP regs, use LOAD instead +def POP: F1<(outs ALL:$dst), (ins), + "$dst = [sp++];", []> { let mayLoad = 1; } +} + +// TODO: push/pop multiple + +def LINK: F2<(outs), (ins i32imm:$amount), + "link $amount;", []>; + +def UNLINK: F2<(outs), (ins), + "unlink;", []>; + +//===----------------------------------------------------------------------===// +// Table C-13. Control Code Bit Management Instructions +//===----------------------------------------------------------------------===// + +multiclass SETCC<PatFrag opnode, PatFrag invnode, string cond, string suf=";"> { + def dd : F1<(outs JustCC:$cc), (ins D:$a, D:$b), + !strconcat(!subst("XX", cond, "cc = $a XX $b"), suf), + [(set JustCC:$cc, (opnode D:$a, D:$b))]>; + + def ri : F1<(outs JustCC:$cc), (ins DP:$a, i32imm:$b), + !strconcat(!subst("XX", cond, "cc = $a XX $b"), suf), + [(set JustCC:$cc, (opnode DP:$a, imm3:$b))]>; + + def pp : F1<(outs JustCC:$cc), (ins P:$a, P:$b), + !strconcat(!subst("XX", cond, "cc = $a XX $b"), suf), + []>; + + def ri_not : F1<(outs NotCC:$cc), (ins DP:$a, i32imm:$b), + !strconcat(!subst("XX", cond, "cc = $a XX $b"), suf), + [(set NotCC:$cc, (invnode DP:$a, imm3:$b))]>; +} + +defm SETEQ : SETCC<seteq, setne, "==">; +defm SETLT : SETCC<setlt, setge, "<">; +defm SETLE : SETCC<setle, setgt, "<=">; +defm SETULT : SETCC<setult, setuge, "<", " (iu);">; +defm SETULE : SETCC<setule, setugt, "<=", " (iu);">; + +def SETNEdd : F1<(outs NotCC:$cc), (ins D:$a, D:$b), + "cc = $a == $b;", + [(set NotCC:$cc, (setne D:$a, D:$b))]>; + +def : Pat<(setgt D:$a, D:$b), (SETLTdd D:$b, D:$a)>; +def : Pat<(setge D:$a, D:$b), (SETLEdd D:$b, D:$a)>; +def : Pat<(setugt D:$a, D:$b), (SETULTdd D:$b, D:$a)>; +def : Pat<(setuge D:$a, D:$b), (SETULEdd D:$b, D:$a)>; + +// TODO: compare pointer for P-P comparisons +// TODO: compare accumulator + +let Defs = [AC0] in +def OR_ac0_cc : F1<(outs), (ins JustCC:$cc), + "ac0 \\|= cc;", []>; + +let Uses = [AC0] in +def MOVE_cc_ac0 : F1<(outs JustCC:$cc), (ins), + "cc = ac0;", []>; + +def MOVE_ccncc : F1<(outs JustCC:$cc), (ins NotCC:$sb), + "cc = !cc;", []>; + +def MOVE_ncccc : F1<(outs NotCC:$cc), (ins JustCC:$sb), + "cc = !cc;", []>; + +def MOVECC_zext : F1<(outs D:$dst), (ins JustCC:$cc), + "$dst = $cc;", []>; + +def MOVENCC_z : F1<(outs D:$dst), (ins NotCC:$cc), + "$dst = cc;", []>; + +def MOVECC_nz : F1<(outs AnyCC:$cc), (ins D:$src), + "cc = $src;", + [(set AnyCC:$cc, (setne D:$src, 0))]>; + +//===----------------------------------------------------------------------===// +// Table C-14. Logical Operations Instructions +//===----------------------------------------------------------------------===// + +def AND: F1<(outs D:$dst), (ins D:$src1, D:$src2), + "$dst = $src1 & $src2;", + [(set D:$dst, (and D:$src1, D:$src2))]>; + +def NOT: F1<(outs D:$dst), (ins D:$src), + "$dst = ~$src;", + [(set D:$dst, (not D:$src))]>; + +def OR: F1<(outs D:$dst), (ins D:$src1, D:$src2), + "$dst = $src1 \\| $src2;", + [(set D:$dst, (or D:$src1, D:$src2))]>; + +def XOR: F1<(outs D:$dst), (ins D:$src1, D:$src2), + "$dst = $src1 ^ $src2;", + [(set D:$dst, (xor D:$src1, D:$src2))]>; + +// missing: BXOR, BXORSHIFT + +//===----------------------------------------------------------------------===// +// Table C-15. Bit Operations Instructions +//===----------------------------------------------------------------------===// + +let Constraints = "$src1 = $dst" in { +def BITCLR: F1<(outs D:$dst), (ins D:$src1, uimm5imask:$src2), + "bitclr($dst, $src2);", + [(set D:$dst, (and D:$src1, uimm5imask:$src2))]>; + +def BITSET: F1<(outs D:$dst), (ins D:$src1, uimm5mask:$src2), + "bitset($dst, $src2);", + [(set D:$dst, (or D:$src1, uimm5mask:$src2))]>; + +def BITTGL: F1<(outs D:$dst), (ins D:$src1, uimm5mask:$src2), + "bittgl($dst, $src2);", + [(set D:$dst, (xor D:$src1, uimm5mask:$src2))]>; +} + +def BITTST: F1<(outs JustCC:$cc), (ins D:$src1, uimm5mask:$src2), + "cc = bittst($src1, $src2);", + [(set JustCC:$cc, (setne (and D:$src1, uimm5mask:$src2), + (i32 0)))]>; + +def NBITTST: F1<(outs JustCC:$cc), (ins D:$src1, uimm5mask:$src2), + "cc = !bittst($src1, $src2);", + [(set JustCC:$cc, (seteq (and D:$src1, uimm5mask:$src2), + (i32 0)))]>; + +// TODO: DEPOSIT, EXTRACT, BITMUX + +def ONES: F2<(outs D16L:$dst), (ins D:$src), + "$dst = ones $src;", + [(set D16L:$dst, (trunc (ctpop D:$src)))]>; + +def : Pat<(ctpop D:$src), (MOVEzext (ONES D:$src))>; + +//===----------------------------------------------------------------------===// +// Table C-16. Shift / Rotate Instructions +//===----------------------------------------------------------------------===// + +multiclass SHIFT32<SDNode opnode, string ops> { + def i : F1<(outs D:$dst), (ins D:$src, i16imm:$amount), + !subst("XX", ops, "$dst XX= $amount;"), + [(set D:$dst, (opnode D:$src, (i16 uimm5:$amount)))]>; + def r : F1<(outs D:$dst), (ins D:$src, D:$amount), + !subst("XX", ops, "$dst XX= $amount;"), + [(set D:$dst, (opnode D:$src, D:$amount))]>; +} + +let Defs = [AZ, AN, V, VS], + Constraints = "$src = $dst" in { +defm SRA : SHIFT32<sra, ">>>">; +defm SRL : SHIFT32<srl, ">>">; +defm SLL : SHIFT32<shl, "<<">; +} + +// TODO: automatic switching between 2-addr and 3-addr (?) + +let Defs = [AZ, AN, V, VS] in { +def SLLr16: F2<(outs D:$dst), (ins D:$src, D16L:$amount), + "$dst = lshift $src by $amount;", + [(set D:$dst, (shl D:$src, D16L:$amount))]>; + +// Arithmetic left-shift = saturing overflow. +def SLAr16: F2<(outs D:$dst), (ins D:$src, D16L:$amount), + "$dst = ashift $src by $amount;", + [(set D:$dst, (sra D:$src, (ineg D16L:$amount)))]>; + +def SRA16i: F1<(outs D16:$dst), (ins D16:$src, i16imm:$amount), + "$dst = $src >>> $amount;", + [(set D16:$dst, (sra D16:$src, (i16 uimm4:$amount)))]>; + +def SRL16i: F1<(outs D16:$dst), (ins D16:$src, i16imm:$amount), + "$dst = $src >> $amount;", + [(set D16:$dst, (srl D16:$src, (i16 uimm4:$amount)))]>; + +// Arithmetic left-shift = saturing overflow. +def SLA16r: F1<(outs D16:$dst), (ins D16:$src, D16L:$amount), + "$dst = ashift $src BY $amount;", + [(set D16:$dst, (srl D16:$src, (ineg D16L:$amount)))]>; + +def SLL16i: F1<(outs D16:$dst), (ins D16:$src, i16imm:$amount), + "$dst = $src << $amount;", + [(set D16:$dst, (shl D16:$src, (i16 uimm4:$amount)))]>; + +def SLL16r: F1<(outs D16:$dst), (ins D16:$src, D16L:$amount), + "$dst = lshift $src by $amount;", + [(set D16:$dst, (shl D16:$src, D16L:$amount))]>; + +} + +//===----------------------------------------------------------------------===// +// Table C-17. Arithmetic Operations Instructions +//===----------------------------------------------------------------------===// + +// TODO: ABS + +let Defs = [AZ, AN, AC0, V, VS] in { + +def ADD: F1<(outs D:$dst), (ins D:$src1, D:$src2), + "$dst = $src1 + $src2;", + [(set D:$dst, (add D:$src1, D:$src2))]>; + +def ADD16: F2<(outs D16:$dst), (ins D16:$src1, D16:$src2), + "$dst = $src1 + $src2;", + [(set D16:$dst, (add D16:$src1, D16:$src2))]>; + +let Constraints = "$src1 = $dst" in +def ADDimm7: F1<(outs D:$dst), (ins D:$src1, i32imm:$src2), + "$dst += $src2;", + [(set D:$dst, (add D:$src1, imm7:$src2))]>; + +def SUB: F1<(outs D:$dst), (ins D:$src1, D:$src2), + "$dst = $src1 - $src2;", + [(set D:$dst, (sub D:$src1, D:$src2))]>; + +def SUB16: F2<(outs D16:$dst), (ins D16:$src1, D16:$src2), + "$dst = $src1 - $src2;", + [(set D16:$dst, (sub D16:$src1, D16:$src2))]>; + +} + +def : Pat<(addc D:$src1, D:$src2), (ADD D:$src1, D:$src2)>; +def : Pat<(subc D:$src1, D:$src2), (SUB D:$src1, D:$src2)>; + +let Defs = [AZ, AN, V, VS] in +def NEG: F1<(outs D:$dst), (ins D:$src), + "$dst = -$src;", + [(set D:$dst, (ineg D:$src))]>; + +// No pattern, it would confuse isel to have two i32 = i32+i32 patterns +def ADDpp: F1<(outs P:$dst), (ins P:$src1, P:$src2), + "$dst = $src1 + $src2;", []>; + +let Constraints = "$src1 = $dst" in +def ADDpp_imm7: F1<(outs P:$dst), (ins P:$src1, i32imm:$src2), + "$dst += $src2;", []>; + +let Defs = [AZ, AN, V] in +def ADD_RND20: F2<(outs D16:$dst), (ins D:$src1, D:$src2), + "$dst = $src1 + $src2 (rnd20);", []>; + +let Defs = [V, VS] in { +def MUL16: F2<(outs D16:$dst), (ins D16:$src1, D16:$src2), + "$dst = $src1 * $src2 (is);", + [(set D16:$dst, (mul D16:$src1, D16:$src2))]>; + +def MULHS16: F2<(outs D16:$dst), (ins D16:$src1, D16:$src2), + "$dst = $src1 * $src2 (ih);", + [(set D16:$dst, (mulhs D16:$src1, D16:$src2))]>; + +def MULhh32s: F2<(outs D:$dst), (ins D16:$src1, D16:$src2), + "$dst = $src1 * $src2 (is);", + [(set D:$dst, (mul (sext D16:$src1), (sext D16:$src2)))]>; + +def MULhh32u: F2<(outs D:$dst), (ins D16:$src1, D16:$src2), + "$dst = $src1 * $src2 (is);", + [(set D:$dst, (mul (zext D16:$src1), (zext D16:$src2)))]>; +} + + +let Constraints = "$src1 = $dst" in +def MUL32: F1<(outs D:$dst), (ins D:$src1, D:$src2), + "$dst *= $src2;", + [(set D:$dst, (mul D:$src1, D:$src2))]>; + +//===----------------------------------------------------------------------===// +// Table C-18. External Exent Management Instructions +//===----------------------------------------------------------------------===// + +def IDLE : F1<(outs), (ins), "idle;", [(int_bfin_idle)]>; +def CSYNC : F1<(outs), (ins), "csync;", [(int_bfin_csync)]>; +def SSYNC : F1<(outs), (ins), "ssync;", [(int_bfin_ssync)]>; +def EMUEXCPT : F1<(outs), (ins), "emuexcpt;", []>; +def CLI : F1<(outs D:$mask), (ins), "cli $mask;", []>; +def STI : F1<(outs), (ins D:$mask), "sti $mask;", []>; +def RAISE : F1<(outs), (ins i32imm:$itr), "raise $itr;", []>; +def EXCPT : F1<(outs), (ins i32imm:$exc), "excpt $exc;", []>; +def NOP : F1<(outs), (ins), "nop;", []>; +def MNOP : F2<(outs), (ins), "mnop;", []>; +def ABORT : F1<(outs), (ins), "abort;", []>; + +//===----------------------------------------------------------------------===// +// Table C-19. Cache Control Instructions +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Table C-20. Video Pixel Operations Instructions +//===----------------------------------------------------------------------===// + +def ALIGN8 : F2<(outs D:$dst), (ins D:$src1, D:$src2), + "$dst = align8($src1, $src2);", + [(set D:$dst, (or (shl D:$src1, (i32 24)), + (srl D:$src2, (i32 8))))]>; + +def ALIGN16 : F2<(outs D:$dst), (ins D:$src1, D:$src2), + "$dst = align16($src1, $src2);", + [(set D:$dst, (or (shl D:$src1, (i32 16)), + (srl D:$src2, (i32 16))))]>; + +def ALIGN24 : F2<(outs D:$dst), (ins D:$src1, D:$src2), + "$dst = align16($src1, $src2);", + [(set D:$dst, (or (shl D:$src1, (i32 8)), + (srl D:$src2, (i32 24))))]>; + +def DISALGNEXCPT : F2<(outs), (ins), "disalignexcpt;", []>; + +// TODO: BYTEOP3P, BYTEOP16P, BYTEOP1P, BYTEOP2P, BYTEOP16M, SAA, +// BYTEPACK, BYTEUNPACK + +// Table C-21. Vector Operations Instructions + +// Patterns +def : Pat<(BfinCall (i32 tglobaladdr:$dst)), + (CALLa tglobaladdr:$dst)>; +def : Pat<(BfinCall (i32 texternalsym:$dst)), + (CALLa texternalsym:$dst)>; +def : Pat<(i16 (trunc D:$src)), + (EXTRACT_SUBREG (i32 (COPY_TO_REGCLASS D:$src, D)), lo16)>; diff --git a/contrib/llvm/lib/Target/Blackfin/BlackfinIntrinsicInfo.cpp b/contrib/llvm/lib/Target/Blackfin/BlackfinIntrinsicInfo.cpp new file mode 100644 index 0000000..34a8d38 --- /dev/null +++ b/contrib/llvm/lib/Target/Blackfin/BlackfinIntrinsicInfo.cpp @@ -0,0 +1,104 @@ +//===- BlackfinIntrinsicInfo.cpp - Intrinsic Information --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the Blackfin implementation of TargetIntrinsicInfo. +// +//===----------------------------------------------------------------------===// + +#include "BlackfinIntrinsicInfo.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/Intrinsics.h" +#include "llvm/Module.h" +#include "llvm/Type.h" +#include "llvm/Support/raw_ostream.h" +#include <cstring> + +using namespace llvm; + +namespace bfinIntrinsic { + + enum ID { + last_non_bfin_intrinsic = Intrinsic::num_intrinsics-1, +#define GET_INTRINSIC_ENUM_VALUES +#include "BlackfinGenIntrinsics.inc" +#undef GET_INTRINSIC_ENUM_VALUES + , num_bfin_intrinsics + }; + +} + +std::string BlackfinIntrinsicInfo::getName(unsigned IntrID, const Type **Tys, + unsigned numTys) const { + static const char *const names[] = { +#define GET_INTRINSIC_NAME_TABLE +#include "BlackfinGenIntrinsics.inc" +#undef GET_INTRINSIC_NAME_TABLE + }; + + assert(!isOverloaded(IntrID) && "Blackfin intrinsics are not overloaded"); + if (IntrID < Intrinsic::num_intrinsics) + return 0; + assert(IntrID < bfinIntrinsic::num_bfin_intrinsics && "Invalid intrinsic ID"); + + std::string Result(names[IntrID - Intrinsic::num_intrinsics]); + return Result; +} + +unsigned +BlackfinIntrinsicInfo::lookupName(const char *Name, unsigned Len) const { + if (Len < 5 || Name[4] != '.' || Name[0] != 'l' || Name[1] != 'l' + || Name[2] != 'v' || Name[3] != 'm') + return 0; // All intrinsics start with 'llvm.' + +#define GET_FUNCTION_RECOGNIZER +#include "BlackfinGenIntrinsics.inc" +#undef GET_FUNCTION_RECOGNIZER + return 0; +} + +bool BlackfinIntrinsicInfo::isOverloaded(unsigned IntrID) const { + // Overload Table + const bool OTable[] = { +#define GET_INTRINSIC_OVERLOAD_TABLE +#include "BlackfinGenIntrinsics.inc" +#undef GET_INTRINSIC_OVERLOAD_TABLE + }; + if (IntrID == 0) + return false; + else + return OTable[IntrID - Intrinsic::num_intrinsics]; +} + +/// This defines the "getAttributes(ID id)" method. +#define GET_INTRINSIC_ATTRIBUTES +#include "BlackfinGenIntrinsics.inc" +#undef GET_INTRINSIC_ATTRIBUTES + +static const FunctionType *getType(LLVMContext &Context, unsigned id) { + const Type *ResultTy = NULL; + std::vector<const Type*> ArgTys; + bool IsVarArg = false; + +#define GET_INTRINSIC_GENERATOR +#include "BlackfinGenIntrinsics.inc" +#undef GET_INTRINSIC_GENERATOR + + return FunctionType::get(ResultTy, ArgTys, IsVarArg); +} + +Function *BlackfinIntrinsicInfo::getDeclaration(Module *M, unsigned IntrID, + const Type **Tys, + unsigned numTy) const { + assert(!isOverloaded(IntrID) && "Blackfin intrinsics are not overloaded"); + AttrListPtr AList = getAttributes((bfinIntrinsic::ID) IntrID); + return cast<Function>(M->getOrInsertFunction(getName(IntrID), + getType(M->getContext(), IntrID), + AList)); +} diff --git a/contrib/llvm/lib/Target/Blackfin/BlackfinIntrinsicInfo.h b/contrib/llvm/lib/Target/Blackfin/BlackfinIntrinsicInfo.h new file mode 100644 index 0000000..7c4b5a9 --- /dev/null +++ b/contrib/llvm/lib/Target/Blackfin/BlackfinIntrinsicInfo.h @@ -0,0 +1,32 @@ +//===- BlackfinIntrinsicInfo.h - Blackfin Intrinsic Information -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the Blackfin implementation of TargetIntrinsicInfo. +// +//===----------------------------------------------------------------------===// +#ifndef BLACKFININTRINSICS_H +#define BLACKFININTRINSICS_H + +#include "llvm/Target/TargetIntrinsicInfo.h" + +namespace llvm { + + class BlackfinIntrinsicInfo : public TargetIntrinsicInfo { + public: + std::string getName(unsigned IntrID, const Type **Tys = 0, + unsigned numTys = 0) const; + unsigned lookupName(const char *Name, unsigned Len) const; + bool isOverloaded(unsigned IID) const; + Function *getDeclaration(Module *M, unsigned ID, const Type **Tys = 0, + unsigned numTys = 0) const; + }; + +} + +#endif diff --git a/contrib/llvm/lib/Target/Blackfin/BlackfinIntrinsics.td b/contrib/llvm/lib/Target/Blackfin/BlackfinIntrinsics.td new file mode 100644 index 0000000..ce21b08 --- /dev/null +++ b/contrib/llvm/lib/Target/Blackfin/BlackfinIntrinsics.td @@ -0,0 +1,34 @@ +//===- BlackfinIntrinsics.td - Defines Blackfin intrinsics -*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines all of the blackfin-specific intrinsics. +// +//===----------------------------------------------------------------------===// + +let TargetPrefix = "bfin", isTarget = 1 in { + +//===----------------------------------------------------------------------===// +// Core synchronisation etc. +// +// These intrinsics have sideeffects. Each represent a single instruction, but +// workarounds are sometimes required depending on the cpu. + +// Execute csync instruction with workarounds +def int_bfin_csync : GCCBuiltin<"__builtin_bfin_csync">, + Intrinsic<[]>; + +// Execute ssync instruction with workarounds +def int_bfin_ssync : GCCBuiltin<"__builtin_bfin_ssync">, + Intrinsic<[]>; + +// Execute idle instruction with workarounds +def int_bfin_idle : GCCBuiltin<"__builtin_bfin_idle">, + Intrinsic<[]>; + +} diff --git a/contrib/llvm/lib/Target/Blackfin/BlackfinMCAsmInfo.cpp b/contrib/llvm/lib/Target/Blackfin/BlackfinMCAsmInfo.cpp new file mode 100644 index 0000000..5b9d4a2 --- /dev/null +++ b/contrib/llvm/lib/Target/Blackfin/BlackfinMCAsmInfo.cpp @@ -0,0 +1,22 @@ +//===-- BlackfinMCAsmInfo.cpp - Blackfin asm properties -------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declarations of the BlackfinMCAsmInfo properties. +// +//===----------------------------------------------------------------------===// + +#include "BlackfinMCAsmInfo.h" + +using namespace llvm; + +BlackfinMCAsmInfo::BlackfinMCAsmInfo(const Target &T, StringRef TT) { + GlobalPrefix = "_"; + CommentString = "//"; + HasSetDirective = false; +} diff --git a/contrib/llvm/lib/Target/Blackfin/BlackfinMCAsmInfo.h b/contrib/llvm/lib/Target/Blackfin/BlackfinMCAsmInfo.h new file mode 100644 index 0000000..c372aa2 --- /dev/null +++ b/contrib/llvm/lib/Target/Blackfin/BlackfinMCAsmInfo.h @@ -0,0 +1,29 @@ +//===-- BlackfinMCAsmInfo.h - Blackfin asm properties ---------*- C++ -*--====// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the BlackfinMCAsmInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef BLACKFINTARGETASMINFO_H +#define BLACKFINTARGETASMINFO_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/MC/MCAsmInfo.h" + +namespace llvm { + class Target; + + struct BlackfinMCAsmInfo : public MCAsmInfo { + explicit BlackfinMCAsmInfo(const Target &T, StringRef TT); + }; + +} // namespace llvm + +#endif diff --git a/contrib/llvm/lib/Target/Blackfin/BlackfinRegisterInfo.cpp b/contrib/llvm/lib/Target/Blackfin/BlackfinRegisterInfo.cpp new file mode 100644 index 0000000..06e95de --- /dev/null +++ b/contrib/llvm/lib/Target/Blackfin/BlackfinRegisterInfo.cpp @@ -0,0 +1,443 @@ +//===- BlackfinRegisterInfo.cpp - Blackfin Register Information -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the Blackfin implementation of the TargetRegisterInfo +// class. +// +//===----------------------------------------------------------------------===// + +#include "Blackfin.h" +#include "BlackfinRegisterInfo.h" +#include "BlackfinSubtarget.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineLocation.h" +#include "llvm/CodeGen/RegisterScavenging.h" +#include "llvm/Target/TargetFrameInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Type.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/STLExtras.h" +using namespace llvm; + +BlackfinRegisterInfo::BlackfinRegisterInfo(BlackfinSubtarget &st, + const TargetInstrInfo &tii) + : BlackfinGenRegisterInfo(BF::ADJCALLSTACKDOWN, BF::ADJCALLSTACKUP), + Subtarget(st), + TII(tii) {} + +const unsigned* +BlackfinRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { + using namespace BF; + static const unsigned CalleeSavedRegs[] = { + FP, + R4, R5, R6, R7, + P3, P4, P5, + 0 }; + return CalleeSavedRegs; +} + +BitVector +BlackfinRegisterInfo::getReservedRegs(const MachineFunction &MF) const { + using namespace BF; + BitVector Reserved(getNumRegs()); + Reserved.set(AZ); + Reserved.set(AN); + Reserved.set(AQ); + Reserved.set(AC0); + Reserved.set(AC1); + Reserved.set(AV0); + Reserved.set(AV0S); + Reserved.set(AV1); + Reserved.set(AV1S); + Reserved.set(V); + Reserved.set(VS); + Reserved.set(CYCLES).set(CYCLES2); + Reserved.set(L0); + Reserved.set(L1); + Reserved.set(L2); + Reserved.set(L3); + Reserved.set(SP); + Reserved.set(RETS); + if (hasFP(MF)) + Reserved.set(FP); + return Reserved; +} + +// hasFP - Return true if the specified function should have a dedicated frame +// pointer register. This is true if the function has variable sized allocas or +// if frame pointer elimination is disabled. +bool BlackfinRegisterInfo::hasFP(const MachineFunction &MF) const { + const MachineFrameInfo *MFI = MF.getFrameInfo(); + return DisableFramePointerElim(MF) || + MFI->adjustsStack() || MFI->hasVarSizedObjects(); +} + +bool BlackfinRegisterInfo:: +requiresRegisterScavenging(const MachineFunction &MF) const { + return true; +} + +// Emit instructions to add delta to D/P register. ScratchReg must be of the +// same class as Reg (P). +void BlackfinRegisterInfo::adjustRegister(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + DebugLoc DL, + unsigned Reg, + unsigned ScratchReg, + int delta) const { + if (!delta) + return; + if (isInt<7>(delta)) { + BuildMI(MBB, I, DL, TII.get(BF::ADDpp_imm7), Reg) + .addReg(Reg) // No kill on two-addr operand + .addImm(delta); + return; + } + + // We must load delta into ScratchReg and add that. + loadConstant(MBB, I, DL, ScratchReg, delta); + if (BF::PRegClass.contains(Reg)) { + assert(BF::PRegClass.contains(ScratchReg) && + "ScratchReg must be a P register"); + BuildMI(MBB, I, DL, TII.get(BF::ADDpp), Reg) + .addReg(Reg, RegState::Kill) + .addReg(ScratchReg, RegState::Kill); + } else { + assert(BF::DRegClass.contains(Reg) && "Reg must be a D or P register"); + assert(BF::DRegClass.contains(ScratchReg) && + "ScratchReg must be a D register"); + BuildMI(MBB, I, DL, TII.get(BF::ADD), Reg) + .addReg(Reg, RegState::Kill) + .addReg(ScratchReg, RegState::Kill); + } +} + +// Emit instructions to load a constant into D/P register +void BlackfinRegisterInfo::loadConstant(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + DebugLoc DL, + unsigned Reg, + int value) const { + if (isInt<7>(value)) { + BuildMI(MBB, I, DL, TII.get(BF::LOADimm7), Reg).addImm(value); + return; + } + + if (isUInt<16>(value)) { + BuildMI(MBB, I, DL, TII.get(BF::LOADuimm16), Reg).addImm(value); + return; + } + + if (isInt<16>(value)) { + BuildMI(MBB, I, DL, TII.get(BF::LOADimm16), Reg).addImm(value); + return; + } + + // We must split into halves + BuildMI(MBB, I, DL, + TII.get(BF::LOAD16i), getSubReg(Reg, BF::hi16)) + .addImm((value >> 16) & 0xffff) + .addReg(Reg, RegState::ImplicitDefine); + BuildMI(MBB, I, DL, + TII.get(BF::LOAD16i), getSubReg(Reg, BF::lo16)) + .addImm(value & 0xffff) + .addReg(Reg, RegState::ImplicitKill) + .addReg(Reg, RegState::ImplicitDefine); +} + +void BlackfinRegisterInfo:: +eliminateCallFramePseudoInstr(MachineFunction &MF, + MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const { + if (!hasReservedCallFrame(MF)) { + int64_t Amount = I->getOperand(0).getImm(); + if (Amount != 0) { + assert(Amount%4 == 0 && "Unaligned call frame size"); + if (I->getOpcode() == BF::ADJCALLSTACKDOWN) { + adjustRegister(MBB, I, I->getDebugLoc(), BF::SP, BF::P1, -Amount); + } else { + assert(I->getOpcode() == BF::ADJCALLSTACKUP && + "Unknown call frame pseudo instruction"); + adjustRegister(MBB, I, I->getDebugLoc(), BF::SP, BF::P1, Amount); + } + } + } + MBB.erase(I); +} + +/// findScratchRegister - Find a 'free' register. Try for a call-clobbered +/// register first and then a spilled callee-saved register if that fails. +static unsigned findScratchRegister(MachineBasicBlock::iterator II, + RegScavenger *RS, + const TargetRegisterClass *RC, + int SPAdj) { + assert(RS && "Register scavenging must be on"); + unsigned Reg = RS->FindUnusedReg(RC); + if (Reg == 0) + Reg = RS->scavengeRegister(RC, II, SPAdj); + return Reg; +} + +unsigned +BlackfinRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, + int SPAdj, FrameIndexValue *Value, + RegScavenger *RS) const { + MachineInstr &MI = *II; + MachineBasicBlock &MBB = *MI.getParent(); + MachineFunction &MF = *MBB.getParent(); + DebugLoc DL = MI.getDebugLoc(); + + unsigned FIPos; + for (FIPos=0; !MI.getOperand(FIPos).isFI(); ++FIPos) { + assert(FIPos < MI.getNumOperands() && + "Instr doesn't have FrameIndex operand!"); + } + int FrameIndex = MI.getOperand(FIPos).getIndex(); + assert(FIPos+1 < MI.getNumOperands() && MI.getOperand(FIPos+1).isImm()); + int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex) + + MI.getOperand(FIPos+1).getImm(); + unsigned BaseReg = BF::FP; + if (hasFP(MF)) { + assert(SPAdj==0 && "Unexpected SP adjust in function with frame pointer"); + } else { + BaseReg = BF::SP; + Offset += MF.getFrameInfo()->getStackSize() + SPAdj; + } + + bool isStore = false; + + switch (MI.getOpcode()) { + case BF::STORE32fi: + isStore = true; + case BF::LOAD32fi: { + assert(Offset%4 == 0 && "Unaligned i32 stack access"); + assert(FIPos==1 && "Bad frame index operand"); + MI.getOperand(FIPos).ChangeToRegister(BaseReg, false); + MI.getOperand(FIPos+1).setImm(Offset); + if (isUInt<6>(Offset)) { + MI.setDesc(TII.get(isStore + ? BF::STORE32p_uimm6m4 + : BF::LOAD32p_uimm6m4)); + return 0; + } + if (BaseReg == BF::FP && isUInt<7>(-Offset)) { + MI.setDesc(TII.get(isStore + ? BF::STORE32fp_nimm7m4 + : BF::LOAD32fp_nimm7m4)); + MI.getOperand(FIPos+1).setImm(-Offset); + return 0; + } + if (isInt<18>(Offset)) { + MI.setDesc(TII.get(isStore + ? BF::STORE32p_imm18m4 + : BF::LOAD32p_imm18m4)); + return 0; + } + // Use RegScavenger to calculate proper offset... + MI.dump(); + llvm_unreachable("Stack frame offset too big"); + break; + } + case BF::ADDpp: { + assert(MI.getOperand(0).isReg() && "ADD instruction needs a register"); + unsigned DestReg = MI.getOperand(0).getReg(); + // We need to produce a stack offset in a P register. We emit: + // P0 = offset; + // P0 = BR + P0; + assert(FIPos==1 && "Bad frame index operand"); + loadConstant(MBB, II, DL, DestReg, Offset); + MI.getOperand(1).ChangeToRegister(DestReg, false, false, true); + MI.getOperand(2).ChangeToRegister(BaseReg, false); + break; + } + case BF::STORE16fi: + isStore = true; + case BF::LOAD16fi: { + assert(Offset%2 == 0 && "Unaligned i16 stack access"); + assert(FIPos==1 && "Bad frame index operand"); + // We need a P register to use as an address + unsigned ScratchReg = findScratchRegister(II, RS, &BF::PRegClass, SPAdj); + assert(ScratchReg && "Could not scavenge register"); + loadConstant(MBB, II, DL, ScratchReg, Offset); + BuildMI(MBB, II, DL, TII.get(BF::ADDpp), ScratchReg) + .addReg(ScratchReg, RegState::Kill) + .addReg(BaseReg); + MI.setDesc(TII.get(isStore ? BF::STORE16pi : BF::LOAD16pi)); + MI.getOperand(1).ChangeToRegister(ScratchReg, false, false, true); + MI.RemoveOperand(2); + break; + } + case BF::STORE8fi: { + // This is an AnyCC spill, we need a scratch register. + assert(FIPos==1 && "Bad frame index operand"); + MachineOperand SpillReg = MI.getOperand(0); + unsigned ScratchReg = findScratchRegister(II, RS, &BF::DRegClass, SPAdj); + assert(ScratchReg && "Could not scavenge register"); + if (SpillReg.getReg()==BF::NCC) { + BuildMI(MBB, II, DL, TII.get(BF::MOVENCC_z), ScratchReg) + .addOperand(SpillReg); + BuildMI(MBB, II, DL, TII.get(BF::BITTGL), ScratchReg) + .addReg(ScratchReg).addImm(0); + } else { + BuildMI(MBB, II, DL, TII.get(BF::MOVECC_zext), ScratchReg) + .addOperand(SpillReg); + } + // STORE D + MI.setDesc(TII.get(BF::STORE8p_imm16)); + MI.getOperand(0).ChangeToRegister(ScratchReg, false, false, true); + MI.getOperand(FIPos).ChangeToRegister(BaseReg, false); + MI.getOperand(FIPos+1).setImm(Offset); + break; + } + case BF::LOAD8fi: { + // This is an restore, we need a scratch register. + assert(FIPos==1 && "Bad frame index operand"); + MachineOperand SpillReg = MI.getOperand(0); + unsigned ScratchReg = findScratchRegister(II, RS, &BF::DRegClass, SPAdj); + assert(ScratchReg && "Could not scavenge register"); + MI.setDesc(TII.get(BF::LOAD32p_imm16_8z)); + MI.getOperand(0).ChangeToRegister(ScratchReg, true); + MI.getOperand(FIPos).ChangeToRegister(BaseReg, false); + MI.getOperand(FIPos+1).setImm(Offset); + ++II; + if (SpillReg.getReg()==BF::CC) { + // CC = D + BuildMI(MBB, II, DL, TII.get(BF::MOVECC_nz), BF::CC) + .addReg(ScratchReg, RegState::Kill); + } else { + // Restore NCC (CC = D==0) + BuildMI(MBB, II, DL, TII.get(BF::SETEQri_not), BF::NCC) + .addReg(ScratchReg, RegState::Kill) + .addImm(0); + } + break; + } + default: + llvm_unreachable("Cannot eliminate frame index"); + break; + } + return 0; +} + +void BlackfinRegisterInfo:: +processFunctionBeforeCalleeSavedScan(MachineFunction &MF, + RegScavenger *RS) const { + MachineFrameInfo *MFI = MF.getFrameInfo(); + const TargetRegisterClass *RC = BF::DPRegisterClass; + if (requiresRegisterScavenging(MF)) { + // Reserve a slot close to SP or frame pointer. + RS->setScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(), + RC->getAlignment(), + false)); + } +} + +void BlackfinRegisterInfo:: +processFunctionBeforeFrameFinalized(MachineFunction &MF) const { +} + +// Emit a prologue that sets up a stack frame. +// On function entry, R0-R2 and P0 may hold arguments. +// R3, P1, and P2 may be used as scratch registers +void BlackfinRegisterInfo::emitPrologue(MachineFunction &MF) const { + MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB + MachineBasicBlock::iterator MBBI = MBB.begin(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); + + int FrameSize = MFI->getStackSize(); + if (FrameSize%4) { + FrameSize = (FrameSize+3) & ~3; + MFI->setStackSize(FrameSize); + } + + if (!hasFP(MF)) { + assert(!MFI->adjustsStack() && + "FP elimination on a non-leaf function is not supported"); + adjustRegister(MBB, MBBI, dl, BF::SP, BF::P1, -FrameSize); + return; + } + + // emit a LINK instruction + if (FrameSize <= 0x3ffff) { + BuildMI(MBB, MBBI, dl, TII.get(BF::LINK)).addImm(FrameSize); + return; + } + + // Frame is too big, do a manual LINK: + // [--SP] = RETS; + // [--SP] = FP; + // FP = SP; + // P1 = -FrameSize; + // SP = SP + P1; + BuildMI(MBB, MBBI, dl, TII.get(BF::PUSH)) + .addReg(BF::RETS, RegState::Kill); + BuildMI(MBB, MBBI, dl, TII.get(BF::PUSH)) + .addReg(BF::FP, RegState::Kill); + BuildMI(MBB, MBBI, dl, TII.get(BF::MOVE), BF::FP) + .addReg(BF::SP); + loadConstant(MBB, MBBI, dl, BF::P1, -FrameSize); + BuildMI(MBB, MBBI, dl, TII.get(BF::ADDpp), BF::SP) + .addReg(BF::SP, RegState::Kill) + .addReg(BF::P1, RegState::Kill); + +} + +void BlackfinRegisterInfo::emitEpilogue(MachineFunction &MF, + MachineBasicBlock &MBB) const { + MachineFrameInfo *MFI = MF.getFrameInfo(); + MachineBasicBlock::iterator MBBI = prior(MBB.end()); + DebugLoc dl = MBBI->getDebugLoc(); + + int FrameSize = MFI->getStackSize(); + assert(FrameSize%4 == 0 && "Misaligned frame size"); + + if (!hasFP(MF)) { + assert(!MFI->adjustsStack() && + "FP elimination on a non-leaf function is not supported"); + adjustRegister(MBB, MBBI, dl, BF::SP, BF::P1, FrameSize); + return; + } + + // emit an UNLINK instruction + BuildMI(MBB, MBBI, dl, TII.get(BF::UNLINK)); +} + +unsigned BlackfinRegisterInfo::getRARegister() const { + return BF::RETS; +} + +unsigned +BlackfinRegisterInfo::getFrameRegister(const MachineFunction &MF) const { + return hasFP(MF) ? BF::FP : BF::SP; +} + +unsigned BlackfinRegisterInfo::getEHExceptionRegister() const { + llvm_unreachable("What is the exception register"); + return 0; +} + +unsigned BlackfinRegisterInfo::getEHHandlerRegister() const { + llvm_unreachable("What is the exception handler register"); + return 0; +} + +int BlackfinRegisterInfo::getDwarfRegNum(unsigned RegNum, bool isEH) const { + llvm_unreachable("What is the dwarf register number"); + return -1; +} + +#include "BlackfinGenRegisterInfo.inc" + diff --git a/contrib/llvm/lib/Target/Blackfin/BlackfinRegisterInfo.h b/contrib/llvm/lib/Target/Blackfin/BlackfinRegisterInfo.h new file mode 100644 index 0000000..ead0b4a --- /dev/null +++ b/contrib/llvm/lib/Target/Blackfin/BlackfinRegisterInfo.h @@ -0,0 +1,91 @@ +//===- BlackfinRegisterInfo.h - Blackfin Register Information ..-*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the Blackfin implementation of the TargetRegisterInfo +// class. +// +//===----------------------------------------------------------------------===// + +#ifndef BLACKFINREGISTERINFO_H +#define BLACKFINREGISTERINFO_H + +#include "llvm/Target/TargetRegisterInfo.h" +#include "BlackfinGenRegisterInfo.h.inc" + +namespace llvm { + + class BlackfinSubtarget; + class TargetInstrInfo; + class Type; + + struct BlackfinRegisterInfo : public BlackfinGenRegisterInfo { + BlackfinSubtarget &Subtarget; + const TargetInstrInfo &TII; + + BlackfinRegisterInfo(BlackfinSubtarget &st, const TargetInstrInfo &tii); + + /// Code Generation virtual methods... + const unsigned *getCalleeSavedRegs(const MachineFunction *MF = 0) const; + + BitVector getReservedRegs(const MachineFunction &MF) const; + + // getSubReg implemented by tablegen + + const TargetRegisterClass *getPointerRegClass(unsigned Kind = 0) const { + return &BF::PRegClass; + } + + bool hasFP(const MachineFunction &MF) const; + + // bool hasReservedCallFrame(MachineFunction &MF) const; + + bool requiresRegisterScavenging(const MachineFunction &MF) const; + + void eliminateCallFramePseudoInstr(MachineFunction &MF, + MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const; + + unsigned eliminateFrameIndex(MachineBasicBlock::iterator II, + int SPAdj, FrameIndexValue *Value = NULL, + RegScavenger *RS = NULL) const; + + void processFunctionBeforeCalleeSavedScan(MachineFunction &MF, + RegScavenger *RS) const; + + void processFunctionBeforeFrameFinalized(MachineFunction &MF) const; + + void emitPrologue(MachineFunction &MF) const; + void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const; + + unsigned getFrameRegister(const MachineFunction &MF) const; + unsigned getRARegister() const; + + // Exception handling queries. + unsigned getEHExceptionRegister() const; + unsigned getEHHandlerRegister() const; + + int getDwarfRegNum(unsigned RegNum, bool isEH) const; + + // Utility functions + void adjustRegister(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + DebugLoc DL, + unsigned Reg, + unsigned ScratchReg, + int delta) const; + void loadConstant(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + DebugLoc DL, + unsigned Reg, + int value) const; + }; + +} // end namespace llvm + +#endif diff --git a/contrib/llvm/lib/Target/Blackfin/BlackfinRegisterInfo.td b/contrib/llvm/lib/Target/Blackfin/BlackfinRegisterInfo.td new file mode 100644 index 0000000..e1cfae9 --- /dev/null +++ b/contrib/llvm/lib/Target/Blackfin/BlackfinRegisterInfo.td @@ -0,0 +1,365 @@ +//===- BlackfinRegisterInfo.td - Blackfin Register defs ----*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Declarations that describe the Blackfin register file +//===----------------------------------------------------------------------===// + +// Subregs are: +// 1: .L +// 2: .H +// 3: .W (32 low bits of 40-bit accu) +let Namespace = "BF" in { +def lo16 : SubRegIndex; +def hi16 : SubRegIndex; +def lo32 : SubRegIndex; +def hi32 : SubRegIndex; +} + +// Registers are identified with 3-bit group and 3-bit ID numbers. +class BlackfinReg<string n> : Register<n> { + field bits<3> Group; + field bits<3> Num; + let Namespace = "BF"; +} + +// Rc - 1-bit registers +class Rc<bits<5> bitno, string n> : BlackfinReg<n> { + field bits<5> BitNum = bitno; +} + +// Rs - 16-bit integer registers +class Rs<bits<3> group, bits<3> num, bits<1> hi, string n> : BlackfinReg<n> { + let Group = group; + let Num = num; + field bits<1> High = hi; +} + +// Ri - 32-bit integer registers with subregs +class Ri<bits<3> group, bits<3> num, string n> : BlackfinReg<n> { + let Group = group; + let Num = num; +} + +// Ra 40-bit accumulator registers +class Ra<bits<3> num, string n, list<Register> subs> : BlackfinReg<n> { + let SubRegs = subs; + let SubRegIndices = [hi32, lo32]; + let Group = 4; + let Num = num; +} + +// Two halves of 32-bit register +multiclass Rss<bits<3> group, bits<3> num, string n> { + def H : Rs<group, num, 1, !strconcat(n, ".h")>; + def L : Rs<group, num, 0, !strconcat(n, ".l")>; +} + +// Rii - 32-bit integer registers with subregs +class Rii<bits<3> group, bits<3> num, string n, list<Register> subs> + : BlackfinReg<n> { + let SubRegs = subs; + let SubRegIndices = [hi16, lo16]; + let Group = group; + let Num = num; +} + +// Status bits are all part of ASTAT +def AZ : Rc<0, "az">; +def AN : Rc<1, "an">; +def CC : Rc<5, "cc">, DwarfRegNum<[34]>; +def NCC : Rc<5, "!cc"> { let Aliases = [CC]; } +def AQ : Rc<6, "aq">; +def AC0 : Rc<12, "ac0">; +def AC1 : Rc<13, "ac1">; +def AV0 : Rc<16, "av0">; +def AV0S : Rc<17, "av0s">; +def AV1 : Rc<18, "av1">; +def AV1S : Rc<19, "av1s">; +def V : Rc<24, "v">; +def VS : Rc<25, "vs">; +// Skipped non-status bits: AC0_COPY, V_COPY, RND_MOD + +// Group 0: Integer registers +defm R0 : Rss<0, 0, "r0">; +def R0 : Rii<0, 0, "r0", [R0H, R0L]>, DwarfRegNum<[0]>; +defm R1 : Rss<0, 1, "r1">; +def R1 : Rii<0, 1, "r1", [R1H, R1L]>, DwarfRegNum<[1]>; +defm R2 : Rss<0, 2, "r2">; +def R2 : Rii<0, 2, "r2", [R2H, R2L]>, DwarfRegNum<[2]>; +defm R3 : Rss<0, 3, "r3">; +def R3 : Rii<0, 3, "r3", [R3H, R3L]>, DwarfRegNum<[3]>; +defm R4 : Rss<0, 4, "r4">; +def R4 : Rii<0, 4, "r4", [R4H, R4L]>, DwarfRegNum<[4]>; +defm R5 : Rss<0, 5, "r5">; +def R5 : Rii<0, 5, "r5", [R5H, R5L]>, DwarfRegNum<[5]>; +defm R6 : Rss<0, 6, "r6">; +def R6 : Rii<0, 6, "r6", [R6H, R6L]>, DwarfRegNum<[6]>; +defm R7 : Rss<0, 7, "r7">; +def R7 : Rii<0, 7, "r7", [R7H, R7L]>, DwarfRegNum<[7]>; + +// Group 1: Pointer registers +defm P0 : Rss<1, 0, "p0">; +def P0 : Rii<1, 0, "p0", [P0H, P0L]>, DwarfRegNum<[8]>; +defm P1 : Rss<1, 1, "p1">; +def P1 : Rii<1, 1, "p1", [P1H, P1L]>, DwarfRegNum<[9]>; +defm P2 : Rss<1, 2, "p2">; +def P2 : Rii<1, 2, "p2", [P2H, P2L]>, DwarfRegNum<[10]>; +defm P3 : Rss<1, 3, "p3">; +def P3 : Rii<1, 3, "p3", [P3H, P3L]>, DwarfRegNum<[11]>; +defm P4 : Rss<1, 4, "p4">; +def P4 : Rii<1, 4, "p4", [P4H, P4L]>, DwarfRegNum<[12]>; +defm P5 : Rss<1, 5, "p5">; +def P5 : Rii<1, 5, "p5", [P5H, P5L]>, DwarfRegNum<[13]>; +defm SP : Rss<1, 6, "sp">; +def SP : Rii<1, 6, "sp", [SPH, SPL]>, DwarfRegNum<[14]>; +defm FP : Rss<1, 7, "fp">; +def FP : Rii<1, 7, "fp", [FPH, FPL]>, DwarfRegNum<[15]>; + +// Group 2: Index registers +defm I0 : Rss<2, 0, "i0">; +def I0 : Rii<2, 0, "i0", [I0H, I0L]>, DwarfRegNum<[16]>; +defm I1 : Rss<2, 1, "i1">; +def I1 : Rii<2, 1, "i1", [I1H, I1L]>, DwarfRegNum<[17]>; +defm I2 : Rss<2, 2, "i2">; +def I2 : Rii<2, 2, "i2", [I2H, I2L]>, DwarfRegNum<[18]>; +defm I3 : Rss<2, 3, "i3">; +def I3 : Rii<2, 3, "i3", [I3H, I3L]>, DwarfRegNum<[19]>; +defm M0 : Rss<2, 4, "m0">; +def M0 : Rii<2, 4, "m0", [M0H, M0L]>, DwarfRegNum<[20]>; +defm M1 : Rss<2, 5, "m1">; +def M1 : Rii<2, 5, "m1", [M1H, M1L]>, DwarfRegNum<[21]>; +defm M2 : Rss<2, 6, "m2">; +def M2 : Rii<2, 6, "m2", [M2H, M2L]>, DwarfRegNum<[22]>; +defm M3 : Rss<2, 7, "m3">; +def M3 : Rii<2, 7, "m3", [M3H, M3L]>, DwarfRegNum<[23]>; + +// Group 3: Cyclic indexing registers +defm B0 : Rss<3, 0, "b0">; +def B0 : Rii<3, 0, "b0", [B0H, B0L]>, DwarfRegNum<[24]>; +defm B1 : Rss<3, 1, "b1">; +def B1 : Rii<3, 1, "b1", [B1H, B1L]>, DwarfRegNum<[25]>; +defm B2 : Rss<3, 2, "b2">; +def B2 : Rii<3, 2, "b2", [B2H, B2L]>, DwarfRegNum<[26]>; +defm B3 : Rss<3, 3, "b3">; +def B3 : Rii<3, 3, "b3", [B3H, B3L]>, DwarfRegNum<[27]>; +defm L0 : Rss<3, 4, "l0">; +def L0 : Rii<3, 4, "l0", [L0H, L0L]>, DwarfRegNum<[28]>; +defm L1 : Rss<3, 5, "l1">; +def L1 : Rii<3, 5, "l1", [L1H, L1L]>, DwarfRegNum<[29]>; +defm L2 : Rss<3, 6, "l2">; +def L2 : Rii<3, 6, "l2", [L2H, L2L]>, DwarfRegNum<[30]>; +defm L3 : Rss<3, 7, "l3">; +def L3 : Rii<3, 7, "l3", [L3H, L3L]>, DwarfRegNum<[31]>; + +// Accumulators +def A0X : Ri <4, 0, "a0.x">; +defm A0 : Rss<4, 1, "a0">; +def A0W : Rii<4, 1, "a0.w", [A0H, A0L]>, DwarfRegNum<[32]>; +def A0 : Ra <0, "a0", [A0X, A0W]>; + +def A1X : Ri <4, 2, "a1.x">; +defm A1 : Rss<4, 3, "a1">; +def A1W : Rii<4, 3, "a1.w", [A1H, A1L]>, DwarfRegNum<[33]>; +def A1 : Ra <2, "a1", [A1X, A1W]>; + +def RETS : Ri<4, 7, "rets">, DwarfRegNum<[35]>; +def RETI : Ri<7, 3, "reti">, DwarfRegNum<[36]>; +def RETX : Ri<7, 4, "retx">, DwarfRegNum<[37]>; +def RETN : Ri<7, 5, "retn">, DwarfRegNum<[38]>; +def RETE : Ri<7, 6, "rete">, DwarfRegNum<[39]>; + +def ASTAT : Ri<4, 6, "astat">, DwarfRegNum<[40]> { + let Aliases = [AZ, AN, CC, NCC, AQ, AC0, AC1, AV0, AV0S, AV1, AV1S, V, VS]; +} + +def SEQSTAT : Ri<7, 1, "seqstat">, DwarfRegNum<[41]>; +def USP : Ri<7, 0, "usp">, DwarfRegNum<[42]>; +def EMUDAT : Ri<7, 7, "emudat">, DwarfRegNum<[43]>; +def SYSCFG : Ri<7, 2, "syscfg">; +def CYCLES : Ri<6, 6, "cycles">; +def CYCLES2 : Ri<6, 7, "cycles2">; + +// Hardware loops +def LT0 : Ri<6, 1, "lt0">, DwarfRegNum<[44]>; +def LT1 : Ri<6, 4, "lt1">, DwarfRegNum<[45]>; +def LC0 : Ri<6, 0, "lc0">, DwarfRegNum<[46]>; +def LC1 : Ri<6, 3, "lc1">, DwarfRegNum<[47]>; +def LB0 : Ri<6, 2, "lb0">, DwarfRegNum<[48]>; +def LB1 : Ri<6, 5, "lb1">, DwarfRegNum<[49]>; + +// Register classes. +def D16 : RegisterClass<"BF", [i16], 16, + [R0H, R0L, R1H, R1L, R2H, R2L, R3H, R3L, + R4H, R4L, R5H, R5L, R6H, R6L, R7H, R7L]>; + +def D16L : RegisterClass<"BF", [i16], 16, + [R0L, R1L, R2L, R3L, R4L, R5L, R6L, R7L]>; + +def D16H : RegisterClass<"BF", [i16], 16, + [R0H, R1H, R2H, R3H, R4H, R5H, R6H, R7H]>; + +def P16 : RegisterClass<"BF", [i16], 16, + [P0H, P0L, P1H, P1L, P2H, P2L, P3H, P3L, + P4H, P4L, P5H, P5L, SPH, SPL, FPH, FPL]>; + +def P16L : RegisterClass<"BF", [i16], 16, + [P0L, P1L, P2L, P3L, P4L, P5L, SPL, FPL]>; + +def P16H : RegisterClass<"BF", [i16], 16, + [P0H, P1H, P2H, P3H, P4H, P5H, SPH, FPH]>; + +def DP16 : RegisterClass<"BF", [i16], 16, + [R0H, R0L, R1H, R1L, R2H, R2L, R3H, R3L, + R4H, R4L, R5H, R5L, R6H, R6L, R7H, R7L, + P0H, P0L, P1H, P1L, P2H, P2L, P3H, P3L, + P4H, P4L, P5H, P5L, SPH, SPL, FPH, FPL]>; + +def DP16L : RegisterClass<"BF", [i16], 16, + [R0L, R1L, R2L, R3L, R4L, R5L, R6L, R7L, + P0L, P1L, P2L, P3L, P4L, P5L, SPL, FPL]>; + +def DP16H : RegisterClass<"BF", [i16], 16, + [R0H, R1H, R2H, R3H, R4H, R5H, R6H, R7H, + P0H, P1H, P2H, P3H, P4H, P5H, SPH, FPH]>; + +def GR16 : RegisterClass<"BF", [i16], 16, + [R0H, R0L, R1H, R1L, R2H, R2L, R3H, R3L, + R4H, R4L, R5H, R5L, R6H, R6L, R7H, R7L, + P0H, P0L, P1H, P1L, P2H, P2L, P3H, P3L, + P4H, P4L, P5H, P5L, SPH, SPL, FPH, FPL, + I0H, I0L, I1H, I1L, I2H, I2L, I3H, I3L, + M0H, M0L, M1H, M1L, M2H, M2L, M3H, M3L, + B0H, B0L, B1H, B1L, B2H, B2L, B3H, B3L, + L0H, L0L, L1H, L1L, L2H, L2L, L3H, L3L]>; + +def D : RegisterClass<"BF", [i32], 32, [R0, R1, R2, R3, R4, R5, R6, R7]> { + let SubRegClasses = [(D16L lo16), (D16H hi16)]; +} + +def P : RegisterClass<"BF", [i32], 32, [P0, P1, P2, P3, P4, P5, FP, SP]> { + let SubRegClasses = [(P16L lo16), (P16H hi16)]; + let MethodProtos = [{ + iterator allocation_order_end(const MachineFunction &MF) const; + }]; + let MethodBodies = [{ + PClass::iterator + PClass::allocation_order_end(const MachineFunction &MF) const { + const TargetMachine &TM = MF.getTarget(); + const TargetRegisterInfo *RI = TM.getRegisterInfo(); + return allocation_order_begin(MF) + + (RI->hasFP(MF) ? 7 : 6); + } + }]; +} + +def I : RegisterClass<"BF", [i32], 32, [I0, I1, I2, I3]>; +def M : RegisterClass<"BF", [i32], 32, [M0, M1, M2, M3]>; +def B : RegisterClass<"BF", [i32], 32, [B0, B1, B2, B3]>; +def L : RegisterClass<"BF", [i32], 32, [L0, L1, L2, L3]>; + +def DP : RegisterClass<"BF", [i32], 32, + [R0, R1, R2, R3, R4, R5, R6, R7, + P0, P1, P2, P3, P4, P5, FP, SP]> { + let SubRegClasses = [(DP16L lo16), (DP16H hi16)]; + let MethodProtos = [{ + iterator allocation_order_end(const MachineFunction &MF) const; + }]; + let MethodBodies = [{ + DPClass::iterator + DPClass::allocation_order_end(const MachineFunction &MF) const { + const TargetMachine &TM = MF.getTarget(); + const TargetRegisterInfo *RI = TM.getRegisterInfo(); + return allocation_order_begin(MF) + + (RI->hasFP(MF) ? 15 : 14); + } + }]; +} + +def GR : RegisterClass<"BF", [i32], 32, + [R0, R1, R2, R3, R4, R5, R6, R7, + P0, P1, P2, P3, P4, P5, + I0, I1, I2, I3, M0, M1, M2, M3, + B0, B1, B2, B3, L0, L1, L2, L3, + FP, SP]> { + let MethodProtos = [{ + iterator allocation_order_end(const MachineFunction &MF) const; + }]; + let MethodBodies = [{ + GRClass::iterator + GRClass::allocation_order_end(const MachineFunction &MF) const { + const TargetMachine &TM = MF.getTarget(); + const TargetRegisterInfo *RI = TM.getRegisterInfo(); + return allocation_order_begin(MF) + + (RI->hasFP(MF) ? 31 : 30); + } + }]; +} + +def ALL : RegisterClass<"BF", [i32], 32, + [R0, R1, R2, R3, R4, R5, R6, R7, + P0, P1, P2, P3, P4, P5, + I0, I1, I2, I3, M0, M1, M2, M3, + B0, B1, B2, B3, L0, L1, L2, L3, + FP, SP, + A0X, A0W, A1X, A1W, ASTAT, RETS, + LC0, LT0, LB0, LC1, LT1, LB1, CYCLES, CYCLES2, + USP, SEQSTAT, SYSCFG, RETI, RETX, RETN, RETE, EMUDAT]> { + let MethodProtos = [{ + iterator allocation_order_end(const MachineFunction &MF) const; + }]; + let MethodBodies = [{ + ALLClass::iterator + ALLClass::allocation_order_end(const MachineFunction &MF) const { + const TargetMachine &TM = MF.getTarget(); + const TargetRegisterInfo *RI = TM.getRegisterInfo(); + return allocation_order_begin(MF) + + (RI->hasFP(MF) ? 31 : 30); + } + }]; +} + +def PI : RegisterClass<"BF", [i32], 32, + [P0, P1, P2, P3, P4, P5, I0, I1, I2, I3, FP, SP]> { + let MethodProtos = [{ + iterator allocation_order_end(const MachineFunction &MF) const; + }]; + let MethodBodies = [{ + PIClass::iterator + PIClass::allocation_order_end(const MachineFunction &MF) const { + const TargetMachine &TM = MF.getTarget(); + const TargetRegisterInfo *RI = TM.getRegisterInfo(); + return allocation_order_begin(MF) + + (RI->hasFP(MF) ? 11 : 10); + } + }]; +} + +// We are going to pretend that CC and !CC are 32-bit registers, even though +// they only can hold 1 bit. +let CopyCost = -1, Size = 8 in { +def JustCC : RegisterClass<"BF", [i32], 8, [CC]>; +def NotCC : RegisterClass<"BF", [i32], 8, [NCC]>; +def AnyCC : RegisterClass<"BF", [i32], 8, [CC, NCC]> { + let MethodProtos = [{ + iterator allocation_order_end(const MachineFunction &MF) const; + }]; + let MethodBodies = [{ + AnyCCClass::iterator + AnyCCClass::allocation_order_end(const MachineFunction &MF) const { + return allocation_order_begin(MF)+1; + } + }]; +} +def StatBit : RegisterClass<"BF", [i1], 8, + [AZ, AN, CC, AQ, AC0, AC1, AV0, AV0S, AV1, AV1S, V, VS]>; +} + +// Should be i40, but that isn't defined. It is not a legal type yet anyway. +def Accu : RegisterClass<"BF", [i64], 64, [A0, A1]>; diff --git a/contrib/llvm/lib/Target/Blackfin/BlackfinSelectionDAGInfo.cpp b/contrib/llvm/lib/Target/Blackfin/BlackfinSelectionDAGInfo.cpp new file mode 100644 index 0000000..a21f696 --- /dev/null +++ b/contrib/llvm/lib/Target/Blackfin/BlackfinSelectionDAGInfo.cpp @@ -0,0 +1,24 @@ +//===-- BlackfinSelectionDAGInfo.cpp - Blackfin SelectionDAG Info ---------===// +// +// 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 BlackfinSelectionDAGInfo class. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "blackfin-selectiondag-info" +#include "BlackfinTargetMachine.h" +using namespace llvm; + +BlackfinSelectionDAGInfo::BlackfinSelectionDAGInfo( + const BlackfinTargetMachine &TM) + : TargetSelectionDAGInfo(TM) { +} + +BlackfinSelectionDAGInfo::~BlackfinSelectionDAGInfo() { +} diff --git a/contrib/llvm/lib/Target/Blackfin/BlackfinSelectionDAGInfo.h b/contrib/llvm/lib/Target/Blackfin/BlackfinSelectionDAGInfo.h new file mode 100644 index 0000000..f1ce348 --- /dev/null +++ b/contrib/llvm/lib/Target/Blackfin/BlackfinSelectionDAGInfo.h @@ -0,0 +1,31 @@ +//===-- BlackfinSelectionDAGInfo.h - Blackfin SelectionDAG Info -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the Blackfin subclass for TargetSelectionDAGInfo. +// +//===----------------------------------------------------------------------===// + +#ifndef BLACKFINSELECTIONDAGINFO_H +#define BLACKFINSELECTIONDAGINFO_H + +#include "llvm/Target/TargetSelectionDAGInfo.h" + +namespace llvm { + +class BlackfinTargetMachine; + +class BlackfinSelectionDAGInfo : public TargetSelectionDAGInfo { +public: + explicit BlackfinSelectionDAGInfo(const BlackfinTargetMachine &TM); + ~BlackfinSelectionDAGInfo(); +}; + +} + +#endif diff --git a/contrib/llvm/lib/Target/Blackfin/BlackfinSubtarget.cpp b/contrib/llvm/lib/Target/Blackfin/BlackfinSubtarget.cpp new file mode 100644 index 0000000..e104c52 --- /dev/null +++ b/contrib/llvm/lib/Target/Blackfin/BlackfinSubtarget.cpp @@ -0,0 +1,36 @@ +//===- BlackfinSubtarget.cpp - BLACKFIN Subtarget Information -------------===// +// +// 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 blackfin specific subclass of TargetSubtarget. +// +//===----------------------------------------------------------------------===// + +#include "BlackfinSubtarget.h" +#include "BlackfinGenSubtarget.inc" + +using namespace llvm; + +BlackfinSubtarget::BlackfinSubtarget(const std::string &TT, + const std::string &FS) + : sdram(false), + icplb(false), + wa_mi_shift(false), + wa_csync(false), + wa_specld(false), + wa_mmr_stall(false), + wa_lcregs(false), + wa_hwloop(false), + wa_ind_call(false), + wa_killed_mmr(false), + wa_rets(false) +{ + std::string CPU = "generic"; + // Parse features string. + ParseSubtargetFeatures(FS, CPU); +} diff --git a/contrib/llvm/lib/Target/Blackfin/BlackfinSubtarget.h b/contrib/llvm/lib/Target/Blackfin/BlackfinSubtarget.h new file mode 100644 index 0000000..d667fe2 --- /dev/null +++ b/contrib/llvm/lib/Target/Blackfin/BlackfinSubtarget.h @@ -0,0 +1,45 @@ +//===- BlackfinSubtarget.h - Define Subtarget for the Blackfin -*- C++ -*-====// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the BLACKFIN specific subclass of TargetSubtarget. +// +//===----------------------------------------------------------------------===// + +#ifndef BLACKFIN_SUBTARGET_H +#define BLACKFIN_SUBTARGET_H + +#include "llvm/Target/TargetSubtarget.h" +#include <string> + +namespace llvm { + + class BlackfinSubtarget : public TargetSubtarget { + bool sdram; + bool icplb; + bool wa_mi_shift; + bool wa_csync; + bool wa_specld; + bool wa_mmr_stall; + bool wa_lcregs; + bool wa_hwloop; + bool wa_ind_call; + bool wa_killed_mmr; + bool wa_rets; + public: + BlackfinSubtarget(const std::string &TT, const std::string &FS); + + /// ParseSubtargetFeatures - Parses features string setting specified + /// subtarget options. Definition of function is auto generated by tblgen. + std::string ParseSubtargetFeatures(const std::string &FS, + const std::string &CPU); + }; + +} // end namespace llvm + +#endif diff --git a/contrib/llvm/lib/Target/Blackfin/BlackfinTargetMachine.cpp b/contrib/llvm/lib/Target/Blackfin/BlackfinTargetMachine.cpp new file mode 100644 index 0000000..66a2f68 --- /dev/null +++ b/contrib/llvm/lib/Target/Blackfin/BlackfinTargetMachine.cpp @@ -0,0 +1,43 @@ +//===-- BlackfinTargetMachine.cpp - Define TargetMachine for Blackfin -----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// +//===----------------------------------------------------------------------===// + +#include "BlackfinTargetMachine.h" +#include "Blackfin.h" +#include "BlackfinMCAsmInfo.h" +#include "llvm/PassManager.h" +#include "llvm/Target/TargetRegistry.h" + +using namespace llvm; + +extern "C" void LLVMInitializeBlackfinTarget() { + RegisterTargetMachine<BlackfinTargetMachine> X(TheBlackfinTarget); + RegisterAsmInfo<BlackfinMCAsmInfo> Y(TheBlackfinTarget); + +} + +BlackfinTargetMachine::BlackfinTargetMachine(const Target &T, + const std::string &TT, + const std::string &FS) + : LLVMTargetMachine(T, TT), + DataLayout("e-p:32:32-i64:32-f64:32-n32"), + Subtarget(TT, FS), + TLInfo(*this), + TSInfo(*this), + InstrInfo(Subtarget), + FrameInfo(TargetFrameInfo::StackGrowsDown, 4, 0) { +} + +bool BlackfinTargetMachine::addInstSelector(PassManagerBase &PM, + CodeGenOpt::Level OptLevel) { + PM.add(createBlackfinISelDag(*this, OptLevel)); + return false; +} diff --git a/contrib/llvm/lib/Target/Blackfin/BlackfinTargetMachine.h b/contrib/llvm/lib/Target/Blackfin/BlackfinTargetMachine.h new file mode 100644 index 0000000..a63aa54 --- /dev/null +++ b/contrib/llvm/lib/Target/Blackfin/BlackfinTargetMachine.h @@ -0,0 +1,64 @@ +//===-- BlackfinTargetMachine.h - TargetMachine for Blackfin ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the Blackfin specific subclass of TargetMachine. +// +//===----------------------------------------------------------------------===// + +#ifndef BLACKFINTARGETMACHINE_H +#define BLACKFINTARGETMACHINE_H + +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetFrameInfo.h" +#include "BlackfinInstrInfo.h" +#include "BlackfinSubtarget.h" +#include "BlackfinISelLowering.h" +#include "BlackfinSelectionDAGInfo.h" +#include "BlackfinIntrinsicInfo.h" + +namespace llvm { + + class BlackfinTargetMachine : public LLVMTargetMachine { + const TargetData DataLayout; + BlackfinSubtarget Subtarget; + BlackfinTargetLowering TLInfo; + BlackfinSelectionDAGInfo TSInfo; + BlackfinInstrInfo InstrInfo; + TargetFrameInfo FrameInfo; + BlackfinIntrinsicInfo IntrinsicInfo; + public: + BlackfinTargetMachine(const Target &T, const std::string &TT, + const std::string &FS); + + virtual const BlackfinInstrInfo *getInstrInfo() const { return &InstrInfo; } + virtual const TargetFrameInfo *getFrameInfo() const { return &FrameInfo; } + virtual const BlackfinSubtarget *getSubtargetImpl() const { + return &Subtarget; + } + virtual const BlackfinRegisterInfo *getRegisterInfo() const { + return &InstrInfo.getRegisterInfo(); + } + virtual const BlackfinTargetLowering* getTargetLowering() const { + return &TLInfo; + } + virtual const BlackfinSelectionDAGInfo* getSelectionDAGInfo() const { + return &TSInfo; + } + virtual const TargetData *getTargetData() const { return &DataLayout; } + virtual bool addInstSelector(PassManagerBase &PM, + CodeGenOpt::Level OptLevel); + const TargetIntrinsicInfo *getIntrinsicInfo() const { + return &IntrinsicInfo; + } + }; + +} // end namespace llvm + +#endif diff --git a/contrib/llvm/lib/Target/Blackfin/CMakeLists.txt b/contrib/llvm/lib/Target/Blackfin/CMakeLists.txt new file mode 100644 index 0000000..f8847d0 --- /dev/null +++ b/contrib/llvm/lib/Target/Blackfin/CMakeLists.txt @@ -0,0 +1,24 @@ +set(LLVM_TARGET_DEFINITIONS Blackfin.td) + +tablegen(BlackfinGenRegisterInfo.h.inc -gen-register-desc-header) +tablegen(BlackfinGenRegisterNames.inc -gen-register-enums) +tablegen(BlackfinGenRegisterInfo.inc -gen-register-desc) +tablegen(BlackfinGenInstrNames.inc -gen-instr-enums) +tablegen(BlackfinGenInstrInfo.inc -gen-instr-desc) +tablegen(BlackfinGenAsmWriter.inc -gen-asm-writer) +tablegen(BlackfinGenDAGISel.inc -gen-dag-isel) +tablegen(BlackfinGenSubtarget.inc -gen-subtarget) +tablegen(BlackfinGenCallingConv.inc -gen-callingconv) +tablegen(BlackfinGenIntrinsics.inc -gen-tgt-intrinsic) + +add_llvm_target(BlackfinCodeGen + BlackfinInstrInfo.cpp + BlackfinIntrinsicInfo.cpp + BlackfinISelDAGToDAG.cpp + BlackfinISelLowering.cpp + BlackfinMCAsmInfo.cpp + BlackfinRegisterInfo.cpp + BlackfinSubtarget.cpp + BlackfinTargetMachine.cpp + BlackfinSelectionDAGInfo.cpp + ) diff --git a/contrib/llvm/lib/Target/Blackfin/Makefile b/contrib/llvm/lib/Target/Blackfin/Makefile new file mode 100644 index 0000000..339bef9 --- /dev/null +++ b/contrib/llvm/lib/Target/Blackfin/Makefile @@ -0,0 +1,24 @@ +##===- lib/Target/Blackfin/Makefile ------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../.. +LIBRARYNAME = LLVMBlackfinCodeGen +TARGET = Blackfin + +# Make sure that tblgen is run, first thing. +BUILT_SOURCES = BlackfinGenRegisterInfo.h.inc BlackfinGenRegisterNames.inc \ + BlackfinGenRegisterInfo.inc BlackfinGenInstrNames.inc \ + BlackfinGenInstrInfo.inc BlackfinGenAsmWriter.inc \ + BlackfinGenDAGISel.inc BlackfinGenSubtarget.inc \ + BlackfinGenCallingConv.inc BlackfinGenIntrinsics.inc + +DIRS = AsmPrinter TargetInfo + +include $(LEVEL)/Makefile.common + diff --git a/contrib/llvm/lib/Target/Blackfin/README.txt b/contrib/llvm/lib/Target/Blackfin/README.txt new file mode 100644 index 0000000..b4c8227 --- /dev/null +++ b/contrib/llvm/lib/Target/Blackfin/README.txt @@ -0,0 +1,244 @@ +//===-- README.txt - Notes for Blackfin Target ------------------*- org -*-===// + +* Condition codes +** DONE Problem with asymmetric SETCC operations +The instruction + + CC = R0 < 2 + +is not symmetric - there is no R0 > 2 instruction. On the other hand, IF CC +JUMP can take both CC and !CC as a condition. We cannot pattern-match (brcond +(not cc), target), the DAG optimizer removes that kind of thing. + +This is handled by creating a pseudo-register NCC that aliases CC. Register +classes JustCC and NotCC are used to control the inversion of CC. + +** DONE CC as an i32 register +The AnyCC register class pretends to hold i32 values. It can only represent the +values 0 and 1, but we can copy to and from the D class. This hack makes it +possible to represent the setcc instruction without having i1 as a legal type. + +In most cases, the CC register is set by a "CC = .." or BITTST instruction, and +then used in a conditional branch or move. The code generator thinks it is +moving 32 bits, but the value stays in CC. In other cases, the result of a +comparison is actually used as am i32 number, and CC will be copied to a D +register. + +* Stack frames +** TODO Use Push/Pop instructions +We should use the push/pop instructions when saving callee-saved +registers. The are smaller, and we may even use push multiple instructions. + +** TODO requiresRegisterScavenging +We need more intelligence in determining when the scavenger is needed. We +should keep track of: +- Spilling D16 registers +- Spilling AnyCC registers + +* Assembler +** TODO Implement PrintGlobalVariable +** TODO Remove LOAD32sym +It's a hack combining two instructions by concatenation. + +* Inline Assembly + +These are the GCC constraints from bfin/constraints.md: + +| Code | Register class | LLVM | +|-------+-------------------------------------------+------| +| a | P | C | +| d | D | C | +| z | Call clobbered P (P0, P1, P2) | X | +| D | EvenD | X | +| W | OddD | X | +| e | Accu | C | +| A | A0 | S | +| B | A1 | S | +| b | I | C | +| v | B | C | +| f | M | C | +| c | Circular I, B, L | X | +| C | JustCC | S | +| t | LoopTop | X | +| u | LoopBottom | X | +| k | LoopCount | X | +| x | GR | C | +| y | RET*, ASTAT, SEQSTAT, USP | X | +| w | ALL | C | +| Z | The FD-PIC GOT pointer (P3) | S | +| Y | The FD-PIC function pointer register (P1) | S | +| q0-q7 | R0-R7 individually | | +| qA | P0 | | +|-------+-------------------------------------------+------| +| Code | Constant | | +|-------+-------------------------------------------+------| +| J | 1<<N, N<32 | | +| Ks3 | imm3 | | +| Ku3 | uimm3 | | +| Ks4 | imm4 | | +| Ku4 | uimm4 | | +| Ks5 | imm5 | | +| Ku5 | uimm5 | | +| Ks7 | imm7 | | +| KN7 | -imm7 | | +| Ksh | imm16 | | +| Kuh | uimm16 | | +| L | ~(1<<N) | | +| M1 | 0xff | | +| M2 | 0xffff | | +| P0-P4 | 0-4 | | +| PA | Macflag, not M | | +| PB | Macflag, only M | | +| Q | Symbol | | + +** TODO Support all register classes +* DAG combiner +** Create test case for each Illegal SETCC case +The DAG combiner may someimes produce illegal i16 SETCC instructions. + +*** TODO SETCC (ctlz x), 5) == const +*** TODO SETCC (and load, const) == const +*** DONE SETCC (zext x) == const +*** TODO SETCC (sext x) == const + +* Instruction selection +** TODO Better imediate constants +Like ARM, build constants as small imm + shift. + +** TODO Implement cycle counter +We have CYCLES and CYCLES2 registers, but the readcyclecounter intrinsic wants +to return i64, and the code generator doesn't know how to legalize that. + +** TODO Instruction alternatives +Some instructions come in different variants for example: + + D = D + D + P = P + P + +Cross combinations are not allowed: + + P = D + D (bad) + +Similarly for the subreg pseudo-instructions: + + D16L = EXTRACT_SUBREG D16, bfin_subreg_lo16 + P16L = EXTRACT_SUBREG P16, bfin_subreg_lo16 + +We want to take advantage of the alternative instructions. This could be done by +changing the DAG after instruction selection. + + +** Multipatterns for load/store +We should try to identify multipatterns for load and store instructions. The +available instruction matrix is a bit irregular. + +Loads: + +| Addr | D | P | D 16z | D 16s | D16 | D 8z | D 8s | +|------------+---+---+-------+-------+-----+------+------| +| P | * | * | * | * | * | * | * | +| P++ | * | * | * | * | | * | * | +| P-- | * | * | * | * | | * | * | +| P+uimm5m2 | | | * | * | | | | +| P+uimm6m4 | * | * | | | | | | +| P+imm16 | | | | | | * | * | +| P+imm17m2 | | | * | * | | | | +| P+imm18m4 | * | * | | | | | | +| P++P | * | | * | * | * | | | +| FP-uimm7m4 | * | * | | | | | | +| I | * | | | | * | | | +| I++ | * | | | | * | | | +| I-- | * | | | | * | | | +| I++M | * | | | | | | | + +Stores: + +| Addr | D | P | D16H | D16L | D 8 | +|------------+---+---+------+------+-----| +| P | * | * | * | * | * | +| P++ | * | * | | * | * | +| P-- | * | * | | * | * | +| P+uimm5m2 | | | | * | | +| P+uimm6m4 | * | * | | | | +| P+imm16 | | | | | * | +| P+imm17m2 | | | | * | | +| P+imm18m4 | * | * | | | | +| P++P | * | | * | * | | +| FP-uimm7m4 | * | * | | | | +| I | * | | * | * | | +| I++ | * | | * | * | | +| I-- | * | | * | * | | +| I++M | * | | | | | + +* Workarounds and features +Blackfin CPUs have bugs. Each model comes in a number of silicon revisions with +different bugs. We learn about the CPU model from the -mcpu switch. + +** Interpretation of -mcpu value +- -mcpu=bf527 refers to the latest known BF527 revision +- -mcpu=bf527-0.2 refers to silicon rev. 0.2 +- -mcpu=bf527-any refers to all known revisions +- -mcpu=bf527-none disables all workarounds + +The -mcpu setting affects the __SILICON_REVISION__ macro and enabled workarounds: + +| -mcpu | __SILICON_REVISION__ | Workarounds | +|------------+----------------------+--------------------| +| bf527 | Def Latest | Specific to latest | +| bf527-1.3 | Def 0x0103 | Specific to 1.3 | +| bf527-any | Def 0xffff | All bf527-x.y | +| bf527-none | Undefined | None | + +These are the known cores and revisions: + +| Core | Silicon | Processors | +|-------------+--------------------+-------------------------| +| Edinburgh | 0.3, 0.4, 0.5, 0.6 | BF531 BF532 BF533 | +| Braemar | 0.2, 0.3 | BF534 BF536 BF537 | +| Stirling | 0.3, 0.4, 0.5 | BF538 BF539 | +| Moab | 0.0, 0.1, 0.2 | BF542 BF544 BF548 BF549 | +| Teton | 0.3, 0.5 | BF561 | +| Kookaburra | 0.0, 0.1, 0.2 | BF523 BF525 BF527 | +| Mockingbird | 0.0, 0.1 | BF522 BF524 BF526 | +| Brodie | 0.0, 0.1 | BF512 BF514 BF516 BF518 | + + +** Compiler implemented workarounds +Most workarounds are implemented in header files and source code using the +__ADSPBF527__ macros. A few workarounds require compiler support. + +| Anomaly | Macro | GCC Switch | +|----------+--------------------------------+------------------| +| Any | __WORKAROUNDS_ENABLED | | +| 05000074 | WA_05000074 | | +| 05000244 | __WORKAROUND_SPECULATIVE_SYNCS | -mcsync-anomaly | +| 05000245 | __WORKAROUND_SPECULATIVE_LOADS | -mspecld-anomaly | +| 05000257 | WA_05000257 | | +| 05000283 | WA_05000283 | | +| 05000312 | WA_LOAD_LCREGS | | +| 05000315 | WA_05000315 | | +| 05000371 | __WORKAROUND_RETS | | +| 05000426 | __WORKAROUND_INDIRECT_CALLS | Not -micplb | + +** GCC feature switches +| Switch | Description | +|---------------------------+----------------------------------------| +| -msim | Use simulator runtime | +| -momit-leaf-frame-pointer | Omit frame pointer for leaf functions | +| -mlow64k | | +| -mcsync-anomaly | | +| -mspecld-anomaly | | +| -mid-shared-library | | +| -mleaf-id-shared-library | | +| -mshared-library-id= | | +| -msep-data | Enable separate data segment | +| -mlong-calls | Use indirect calls | +| -mfast-fp | | +| -mfdpic | | +| -minline-plt | | +| -mstack-check-l1 | Do stack checking in L1 scratch memory | +| -mmulticore | Enable multicore support | +| -mcorea | Build for Core A | +| -mcoreb | Build for Core B | +| -msdram | Build for SDRAM | +| -micplb | Assume ICPLBs are enabled at runtime. | diff --git a/contrib/llvm/lib/Target/Blackfin/TargetInfo/BlackfinTargetInfo.cpp b/contrib/llvm/lib/Target/Blackfin/TargetInfo/BlackfinTargetInfo.cpp new file mode 100644 index 0000000..402e0af --- /dev/null +++ b/contrib/llvm/lib/Target/Blackfin/TargetInfo/BlackfinTargetInfo.cpp @@ -0,0 +1,21 @@ +//===-- BlackfinTargetInfo.cpp - Blackfin Target Implementation -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Blackfin.h" +#include "llvm/Module.h" +#include "llvm/Target/TargetRegistry.h" + +using namespace llvm; + +Target llvm::TheBlackfinTarget; + +extern "C" void LLVMInitializeBlackfinTargetInfo() { + RegisterTarget<Triple::bfin> X(TheBlackfinTarget, "bfin", + "Analog Devices Blackfin [experimental]"); +} diff --git a/contrib/llvm/lib/Target/Blackfin/TargetInfo/CMakeLists.txt b/contrib/llvm/lib/Target/Blackfin/TargetInfo/CMakeLists.txt new file mode 100644 index 0000000..5ca8060 --- /dev/null +++ b/contrib/llvm/lib/Target/Blackfin/TargetInfo/CMakeLists.txt @@ -0,0 +1,7 @@ +include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. ) + +add_llvm_library(LLVMBlackfinInfo + BlackfinTargetInfo.cpp + ) + +add_dependencies(LLVMBlackfinInfo BlackfinCodeGenTable_gen) diff --git a/contrib/llvm/lib/Target/Blackfin/TargetInfo/Makefile b/contrib/llvm/lib/Target/Blackfin/TargetInfo/Makefile new file mode 100644 index 0000000..c49cfbe --- /dev/null +++ b/contrib/llvm/lib/Target/Blackfin/TargetInfo/Makefile @@ -0,0 +1,15 @@ +##===- lib/Target/Blackfin/TargetInfo/Makefile -------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../../../.. +LIBRARYNAME = LLVMBlackfinInfo + +# Hack: we need to include 'main' target directory to grab private headers +CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common |