diff --git a/lib/Target/PIC16/Makefile b/lib/Target/PIC16/Makefile new file mode 100644 index 00000000000..c429324cc2d --- /dev/null +++ b/lib/Target/PIC16/Makefile @@ -0,0 +1,21 @@ +##===- lib/Target/PIC16/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 = LLVMPIC16 +TARGET = PIC16 + +# Make sure that tblgen is run, first thing. +BUILT_SOURCES = PIC16GenRegisterInfo.h.inc PIC16GenRegisterNames.inc \ + PIC16GenRegisterInfo.inc PIC16GenInstrNames.inc \ + PIC16GenInstrInfo.inc PIC16GenAsmWriter.inc \ + PIC16GenDAGISel.inc PIC16GenCallingConv.inc \ + PIC16GenSubtarget.inc + +include $(LEVEL)/Makefile.common + diff --git a/lib/Target/PIC16/PIC16.h b/lib/Target/PIC16/PIC16.h new file mode 100644 index 00000000000..5c2a4cce828 --- /dev/null +++ b/lib/Target/PIC16/PIC16.h @@ -0,0 +1,38 @@ +//===-- PIC16.h - Top-level interface for PIC16 representation --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Bruno Cardoso Lopes and 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 PIC16 back-end. +// +//===----------------------------------------------------------------------===// + +#ifndef TARGET_PIC16_H +#define TARGET_PIC16_H + +#include + +namespace llvm { + class PIC16TargetMachine; + class FunctionPassManager; + class FunctionPass; + class MachineCodeEmitter; + + FunctionPass *createPIC16ISelDag(PIC16TargetMachine &TM); + FunctionPass *createPIC16CodePrinterPass(std::ostream &OS, + PIC16TargetMachine &TM); +} // end namespace llvm; + +// Defines symbolic names for PIC16 registers. This defines a mapping from +// register name to register number. +#include "PIC16GenRegisterNames.inc" + +// Defines symbolic names for the PIC16 instructions. +#include "PIC16GenInstrNames.inc" + +#endif diff --git a/lib/Target/PIC16/PIC16.td b/lib/Target/PIC16/PIC16.td new file mode 100644 index 00000000000..0ab4a3444f6 --- /dev/null +++ b/lib/Target/PIC16/PIC16.td @@ -0,0 +1,46 @@ +//===- PIC16.td - Describe the PIC16 Target Machine -----------*- tblgen -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// This is the top level entry point for the PIC16 target. +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Target-independent interfaces +//===----------------------------------------------------------------------===// + +include "../Target.td" + +//===----------------------------------------------------------------------===// +// Descriptions +//===----------------------------------------------------------------------===// + +include "PIC16RegisterInfo.td" +include "PIC16CallingConv.td" +include "PIC16InstrInfo.td" + +def PIC16InstrInfo : InstrInfo { + let TSFlagsFields = []; + let TSFlagsShifts = []; +} + + + +// Not currently supported, but work as SubtargetFeature placeholder. +def FeaturePIC16Old : SubtargetFeature<"pic16old", "IsPIC16Old", "true", + "PIC16 Old ISA Support">; + +//===----------------------------------------------------------------------===// +// PIC16 processors supported. +//===----------------------------------------------------------------------===// + +def : Processor<"generic", NoItineraries, []>; + +def PIC16 : Target { + let InstructionSet = PIC16InstrInfo; +} + diff --git a/lib/Target/PIC16/PIC16AsmPrinter.cpp b/lib/Target/PIC16/PIC16AsmPrinter.cpp new file mode 100644 index 00000000000..151fafc4c54 --- /dev/null +++ b/lib/Target/PIC16/PIC16AsmPrinter.cpp @@ -0,0 +1,569 @@ +//===-- PIC16AsmPrinter.cpp - PIC16 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 PIC16 assembly language. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "asm-printer" +#include "PIC16.h" +#include "PIC16TargetMachine.h" +#include "PIC16ConstantPoolValue.h" +#include "PIC16InstrInfo.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Module.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/Mangler.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Target/TargetAsmInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include + +using namespace llvm; + +STATISTIC(EmittedInsts, "Number of machine instrs printed"); + +namespace { + struct VISIBILITY_HIDDEN PIC16AsmPrinter : public AsmPrinter { + PIC16AsmPrinter(std::ostream &O, TargetMachine &TM, const TargetAsmInfo *T) + : AsmPrinter(O, TM, T) { + } + + + /// We name each basic block in a Function with a unique number, so + /// that we can consistently refer to them later. This is cleared + /// at the beginning of each call to runOnMachineFunction(). + /// + typedef std::map ValueMapTy; + ValueMapTy NumberForBB; + + /// Keeps the set of GlobalValues that require non-lazy-pointers for + /// indirect access. + std::set GVNonLazyPtrs; + + /// Keeps the set of external function GlobalAddresses that the asm + /// printer should generate stubs for. + std::set FnStubs; + + /// True if asm printer is printing a series of CONSTPOOL_ENTRY. + bool InCPMode; + + virtual const char *getPassName() const { + return "PIC16 Assembly Printer"; + } + + void printOperand(const MachineInstr *MI, int opNum, + const char *Modifier = 0); + + void printSOImmOperand(const MachineInstr *MI, int opNum); + + void printAddrModeOperand(const MachineInstr *MI, int OpNo); + + void printRegisterList(const MachineInstr *MI, int opNum); + void printCPInstOperand(const MachineInstr *MI, int opNum, + const char *Modifier); + + + bool printInstruction(const MachineInstr *MI); // autogenerated. + void emitFunctionStart(MachineFunction &F); + bool runOnMachineFunction(MachineFunction &F); + bool doInitialization(Module &M); + bool doFinalization(Module &M); + + virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV); + + void getAnalysisUsage(AnalysisUsage &AU) const; + + public: + void SwitchToTextSection(const char *NewSection, + const GlobalValue *GV = NULL); + void SwitchToDataSection(const char *NewSection, + const GlobalValue *GV = NULL); + void SwitchToDataOvrSection(const char *NewSection, + const GlobalValue *GV = NULL); + }; +} // end of anonymous namespace + +#include "PIC16GenAsmWriter.inc" + +/// createPIC16CodePrinterPass - Returns a pass that prints the PIC16 +/// assembly code for a MachineFunction to the given output stream, +/// using the given target machine description. This should work +/// regardless of whether the function is in SSA form. +/// +FunctionPass *llvm::createPIC16CodePrinterPass(std::ostream &o, + PIC16TargetMachine &tm) { + return new PIC16AsmPrinter(o, tm, tm.getTargetAsmInfo()); +} + +void PIC16AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const +{ + // Currently unimplemented. +} + + +void PIC16AsmPrinter :: +EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) +{ + printDataDirective(MCPV->getType()); + + PIC16ConstantPoolValue *ACPV = (PIC16ConstantPoolValue*)MCPV; + GlobalValue *GV = ACPV->getGV(); + std::string Name = GV ? Mang->getValueName(GV) : TAI->getGlobalPrefix(); + if (!GV) + Name += ACPV->getSymbol(); + if (ACPV->isNonLazyPointer()) { + GVNonLazyPtrs.insert(Name); + O << TAI->getPrivateGlobalPrefix() << Name << "$non_lazy_ptr"; + } else if (ACPV->isStub()) { + FnStubs.insert(Name); + O << TAI->getPrivateGlobalPrefix() << Name << "$stub"; + } else + O << Name; + if (ACPV->hasModifier()) O << "(" << ACPV->getModifier() << ")"; + + if (ACPV->getPCAdjustment() != 0) { + O << "-(" << TAI->getPrivateGlobalPrefix() << "PC" + << utostr(ACPV->getLabelId()) + << "+" << (unsigned)ACPV->getPCAdjustment(); + + if (ACPV->mustAddCurrentAddress()) + O << "-."; + + O << ")"; + } + O << "\n"; + + // If the constant pool value is a extern weak symbol, remember to emit + // the weak reference. + if (GV && GV->hasExternalWeakLinkage()) + ExtWeakSymbols.insert(GV); +} + +/// Emit the directives used by ASM on the start of functions +void PIC16AsmPrinter:: emitFunctionStart(MachineFunction &MF) +{ + // Print out the label for the function. + const Function *F = MF.getFunction(); + MachineFrameInfo *FrameInfo = MF.getFrameInfo(); + if (FrameInfo->hasStackObjects()) { + int indexBegin = FrameInfo->getObjectIndexBegin(); + int indexEnd = FrameInfo->getObjectIndexEnd(); + while (indexBegingetParent()->getModuleIdentifier().c_str(), + F); + + O << "\t\t" << CurrentFnName << "_" << indexBegin << " " << "RES" + << " " << FrameInfo->getObjectSize(indexBegin) << "\n" ; + indexBegin++; + } + } + SwitchToTextSection(CurrentFnName.c_str(), F); + O << "_" << CurrentFnName << ":" ; + O << "\n"; +} + + +/// runOnMachineFunction - This uses the printInstruction() +/// method to print assembly for each instruction. +/// +bool PIC16AsmPrinter:: +runOnMachineFunction(MachineFunction &MF) +{ + + // DW.SetModuleInfo(&getAnalysis()); + SetupMachineFunction(MF); + O << "\n"; + + // NOTE: we don't print out constant pools here, they are handled as + // instructions. + O << "\n"; + + // What's my mangled name? + CurrentFnName = Mang->getValueName(MF.getFunction()); + + // Emit the function start directives + emitFunctionStart(MF); + + // Emit pre-function debug information. + // DW.BeginFunction(&MF); + + // Print out code for the function. + for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); + I != E; ++I) { + // Print a label for the basic block. + if (I != MF.begin()) { + printBasicBlockLabel(I, true); + O << '\n'; + } + for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); + II != E; ++II) { + // Print the assembly for the instruction. + O << '\t'; + printInstruction(II); + ++EmittedInsts; + } + } + + // Emit post-function debug information. + // DW.EndFunction(); + + // We didn't modify anything. + return false; +} + +void PIC16AsmPrinter:: +printOperand(const MachineInstr *MI, int opNum, const char *Modifier) +{ + const MachineOperand &MO = MI->getOperand(opNum); + const TargetRegisterInfo &RI = *TM.getRegisterInfo(); + + switch (MO.getType()) + { + case MachineOperand::MO_Register: + { + if (TargetRegisterInfo::isPhysicalRegister(MO.getReg())) + O << RI.get(MO.getReg()).Name; + else + assert(0 && "not implemented"); + break; + } + case MachineOperand::MO_Immediate: + { + if (!Modifier || strcmp(Modifier, "no_hash") != 0) + O << "#"; + O << (int)MO.getImm(); + break; + } + case MachineOperand::MO_MachineBasicBlock: + { + printBasicBlockLabel(MO.getMBB()); + return; + } + case MachineOperand::MO_GlobalAddress: + { + O << Mang->getValueName(MO.getGlobal())<<'+'<getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() + << '_' << MO.getIndex(); + break; + } + case MachineOperand::MO_FrameIndex: + { + O << "_" << CurrentFnName + << '+' << MO.getIndex(); + break; + } + case MachineOperand::MO_JumpTableIndex: + { + O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() + << '_' << MO.getIndex(); + break; + } + default: + { + O << ""; abort (); + break; + } + } // end switch. +} + +static void +printSOImm(std::ostream &O, int64_t V, const TargetAsmInfo *TAI) +{ + assert(V < (1 << 12) && "Not a valid so_imm value!"); + unsigned Imm = V; + + O << Imm; +} + +/// printSOImmOperand - SOImm is 4-bit rotate amount in bits 8-11 with 8-bit +/// immediate in bits 0-7. +void PIC16AsmPrinter:: +printSOImmOperand(const MachineInstr *MI, int OpNum) +{ + const MachineOperand &MO = MI->getOperand(OpNum); + assert(MO.isImmediate() && "Not a valid so_imm value!"); + printSOImm(O, MO.getImm(), TAI); +} + + +void PIC16AsmPrinter:: printAddrModeOperand(const MachineInstr *MI, int Op) +{ + const MachineOperand &MO1 = MI->getOperand(Op); + const MachineOperand &MO2 = MI->getOperand(Op+1); + + if (MO2.isFrameIndex ()) { + printOperand(MI, Op+1); + return; + } + + if (!MO1.isRegister()) { // FIXME: This is for CP entries, but isn't right. + printOperand(MI, Op); + return; + } + + // If this is Stack Slot + if (MO1.isRegister()) { + if(strcmp(TM.getRegisterInfo()->get(MO1.getReg()).Name, "SP")==0) + { + O << CurrentFnName <<"_"<< MO2.getImm(); + return; + } + O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name; + O << "+"; + O << MO2.getImm(); + O << "]"; + return; + } + + O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name; + O << "]"; +} + + +void PIC16AsmPrinter:: printRegisterList(const MachineInstr *MI, int opNum) +{ + O << "{"; + for (unsigned i = opNum, e = MI->getNumOperands(); i != e; ++i) { + printOperand(MI, i); + if (i != e-1) O << ", "; + } + O << "}"; +} + +void PIC16AsmPrinter:: +printCPInstOperand(const MachineInstr *MI, int OpNo, const char *Modifier) +{ + assert(Modifier && "This operand only works with a modifier!"); + + // There are two aspects to a CONSTANTPOOL_ENTRY operand, the label and the + // data itself. + if (!strcmp(Modifier, "label")) { + unsigned ID = MI->getOperand(OpNo).getImm(); + O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() + << '_' << ID << ":\n"; + } else { + assert(!strcmp(Modifier, "cpentry") && "Unknown modifier for CPE"); + unsigned CPI = MI->getOperand(OpNo).getIndex(); + + const MachineConstantPoolEntry &MCPE = // Chasing pointers is fun? + MI->getParent()->getParent()->getConstantPool()->getConstants()[CPI]; + + if (MCPE.isMachineConstantPoolEntry()) + EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal); + else { + EmitGlobalConstant(MCPE.Val.ConstVal); + // remember to emit the weak reference + if (const GlobalValue *GV = dyn_cast(MCPE.Val.ConstVal)) + if (GV->hasExternalWeakLinkage()) + ExtWeakSymbols.insert(GV); + } + } +} + + +bool PIC16AsmPrinter:: doInitialization(Module &M) +{ + // Emit initial debug information. + // DW.BeginModule(&M); + + bool Result = AsmPrinter::doInitialization(M); + return Result; +} + +bool PIC16AsmPrinter:: doFinalization(Module &M) +{ + const TargetData *TD = TM.getTargetData(); + + for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) { + if (!I->hasInitializer()) // External global require no code + continue; + + if (EmitSpecialLLVMGlobal(I)) { + continue; + } + + std::string name = Mang->getValueName(I); + Constant *C = I->getInitializer(); + const Type *Type = C->getType(); + unsigned Size = TD->getABITypeSize(Type); + unsigned Align = TD->getPreferredAlignmentLog(I); + + const char *VisibilityDirective = NULL; + if (I->hasHiddenVisibility()) + VisibilityDirective = TAI->getHiddenDirective(); + else if (I->hasProtectedVisibility()) + VisibilityDirective = TAI->getProtectedDirective(); + + if (VisibilityDirective) + O << VisibilityDirective << name << "\n"; + + if (C->isNullValue()) { + if (I->hasExternalLinkage()) { + if (const char *Directive = TAI->getZeroFillDirective()) { + O << "\t.globl\t" << name << "\n"; + O << Directive << "__DATA__, __common, " << name << ", " + << Size << ", " << Align << "\n"; + continue; + } + } + + if (!I->hasSection() && + (I->hasInternalLinkage() || I->hasWeakLinkage() || + I->hasLinkOnceLinkage())) { + if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it. + if (!NoZerosInBSS && TAI->getBSSSection()) + SwitchToDataSection(M.getModuleIdentifier().c_str(), I); + else + SwitchToDataSection(TAI->getDataSection(), I); + if (TAI->getLCOMMDirective() != NULL) { + if (I->hasInternalLinkage()) { + O << TAI->getLCOMMDirective() << name << "," << Size; + } else + O << TAI->getCOMMDirective() << name << "," << Size; + } else { + if (I->hasInternalLinkage()) + O << "\t.local\t" << name << "\n"; + + O << TAI->getCOMMDirective() <<"\t" << name << " " <<"RES"<< " " + << Size; + O << "\n\t\tGLOBAL" <<" "<< name; + if (TAI->getCOMMDirectiveTakesAlignment()) + O << "," << (TAI->getAlignmentIsInBytes() ? (1 << Align) : Align); + } + continue; + } + } + + switch (I->getLinkage()) + { + case GlobalValue::AppendingLinkage: + { + // FIXME: appending linkage variables should go into a section of + // their name or something. For now, just emit them as external. + // Fall through + } + case GlobalValue::ExternalLinkage: + { + O << "\t.globl " << name << "\n"; + // FALL THROUGH + } + case GlobalValue::InternalLinkage: + { + if (I->isConstant()) { + const ConstantArray *CVA = dyn_cast(C); + if (TAI->getCStringSection() && CVA && CVA->isCString()) { + SwitchToDataSection(TAI->getCStringSection(), I); + break; + } + } + break; + } + default: + { + assert(0 && "Unknown linkage type!"); + break; + } + } // end switch. + + EmitAlignment(Align, I); + O << name << ":\t\t\t\t" << TAI->getCommentString() << " " << I->getName() + << "\n"; + + // If the initializer is a extern weak symbol, remember to emit the weak + // reference! + if (const GlobalValue *GV = dyn_cast(C)) + if (GV->hasExternalWeakLinkage()) + ExtWeakSymbols.insert(GV); + + EmitGlobalConstant(C); + O << '\n'; + } // end for. + + O << "\n "<< "END"; + return AsmPrinter::doFinalization(M); +} + +void PIC16AsmPrinter:: +SwitchToTextSection(const char *NewSection, const GlobalValue *GV) +{ + O << "\n"; + if (NewSection && *NewSection) { + std::string codeSection = "code_"; + codeSection += NewSection; + codeSection += " "; + codeSection += "CODE"; + AsmPrinter::SwitchToTextSection(codeSection.c_str(),GV); + } + else + AsmPrinter::SwitchToTextSection(NewSection,GV); +} + +void PIC16AsmPrinter:: +SwitchToDataSection(const char *NewSection, const GlobalValue *GV) +{ + //Need to append index for page + O << "\n"; + if (NewSection && *NewSection) { + std::string dataSection ="udata_"; + dataSection+=NewSection; + if (dataSection.substr(dataSection.length()-2).compare(".o") == 0) { + dataSection = dataSection.substr(0,dataSection.length()-2); + } + dataSection += " "; + dataSection += "UDATA"; + AsmPrinter::SwitchToDataSection(dataSection.c_str(),GV); + } + else + AsmPrinter::SwitchToDataSection(NewSection,GV); +} + +void PIC16AsmPrinter:: +SwitchToDataOvrSection(const char *NewSection, const GlobalValue *GV) +{ + O << "\n"; + if (NewSection && *NewSection) { + std::string dataSection = "frame_"; + dataSection += NewSection; + if (dataSection.substr(dataSection.length()-2).compare(".o") == 0) { + dataSection = dataSection.substr(0,dataSection.length()-2); + } + dataSection += "_"; + dataSection += CurrentFnName; + dataSection += " "; + dataSection += "UDATA_OVR"; + AsmPrinter::SwitchToDataSection(dataSection.c_str(),GV); + } + else + AsmPrinter::SwitchToDataSection(NewSection,GV); +} diff --git a/lib/Target/PIC16/PIC16CallingConv.td b/lib/Target/PIC16/PIC16CallingConv.td new file mode 100644 index 00000000000..bcd5f7c83dc --- /dev/null +++ b/lib/Target/PIC16/PIC16CallingConv.td @@ -0,0 +1,17 @@ +//===- PIC16CallingConv.td - Calling Conventions Sparc -----*- 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 PIC16 architectures. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Return Value Calling Conventions +//===----------------------------------------------------------------------===// + diff --git a/lib/Target/PIC16/PIC16ConstantPoolValue.cpp b/lib/Target/PIC16/PIC16ConstantPoolValue.cpp new file mode 100644 index 00000000000..6e324f9e4d6 --- /dev/null +++ b/lib/Target/PIC16/PIC16ConstantPoolValue.cpp @@ -0,0 +1,88 @@ +//===- PIC16ConstantPoolValue.cpp - PIC16 constantpool value --------------===// +// +// 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 PIC16 specific constantpool value class. +// +//===----------------------------------------------------------------------===// + +#include "PIC16ConstantPoolValue.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/GlobalValue.h" +#include "llvm/Type.h" +using namespace llvm; + +PIC16ConstantPoolValue::PIC16ConstantPoolValue(GlobalValue *gv, unsigned id, + PIC16CP::PIC16CPKind k, + unsigned char PCAdj, + const char *Modif, bool AddCA) + : MachineConstantPoolValue((const Type*)gv->getType()), + GV(gv), S(NULL), LabelId(id), Kind(k), PCAdjust(PCAdj), + Modifier(Modif), AddCurrentAddress(AddCA) {} + +PIC16ConstantPoolValue::PIC16ConstantPoolValue(const char *s, unsigned id, + PIC16CP::PIC16CPKind k, + unsigned char PCAdj, + const char *Modif, bool AddCA) + : MachineConstantPoolValue((const Type*)Type::Int32Ty), + GV(NULL), S(s), LabelId(id), Kind(k), PCAdjust(PCAdj), + Modifier(Modif), AddCurrentAddress(AddCA) {} + +PIC16ConstantPoolValue::PIC16ConstantPoolValue(GlobalValue *gv, + PIC16CP::PIC16CPKind k, + const char *Modif) + : MachineConstantPoolValue((const Type*)Type::Int32Ty), + GV(gv), S(NULL), LabelId(0), Kind(k), PCAdjust(0), + Modifier(Modif) {} + +int PIC16ConstantPoolValue::getExistingMachineCPValue(MachineConstantPool *CP, + unsigned Alignment) { + unsigned AlignMask = (1 << Alignment)-1; + const std::vector Constants = CP->getConstants(); + for (unsigned i = 0, e = Constants.size(); i != e; ++i) { + if (Constants[i].isMachineConstantPoolEntry() && + (Constants[i].Offset & AlignMask) == 0) { + PIC16ConstantPoolValue *CPV = + (PIC16ConstantPoolValue *)Constants[i].Val.MachineCPVal; + if (CPV->GV == GV && + CPV->S == S && + CPV->LabelId == LabelId && + CPV->Kind == Kind && + CPV->PCAdjust == PCAdjust) + return i; + } + } + + return -1; +} + +void +PIC16ConstantPoolValue::AddSelectionDAGCSEId(FoldingSetNodeID &ID) { + ID.AddPointer(GV); + ID.AddPointer(S); + ID.AddInteger(LabelId); + ID.AddInteger((unsigned)Kind); + ID.AddInteger(PCAdjust); +} + +void PIC16ConstantPoolValue::print(std::ostream &O) const { + if (GV) + O << GV->getName(); + else + O << S; + if (isNonLazyPointer()) O << "$non_lazy_ptr"; + else if (isStub()) O << "$stub"; + if (Modifier) O << "(" << Modifier << ")"; + if (PCAdjust != 0) { + O << "-(LPIC" << LabelId << "+" + << (unsigned)PCAdjust; + if (AddCurrentAddress) + O << "-."; + O << ")"; + } +} diff --git a/lib/Target/PIC16/PIC16ConstantPoolValue.h b/lib/Target/PIC16/PIC16ConstantPoolValue.h new file mode 100644 index 00000000000..04d4a17e682 --- /dev/null +++ b/lib/Target/PIC16/PIC16ConstantPoolValue.h @@ -0,0 +1,75 @@ +//===- PIC16ConstantPoolValue.h - PIC16 constantpool value ------*- C++ -*-===// +// +// 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 PIC16 specific constantpool value class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_PIC16_CONSTANTPOOLVALUE_H +#define LLVM_TARGET_PIC16_CONSTANTPOOLVALUE_H + +#include "llvm/CodeGen/MachineConstantPool.h" + +namespace llvm { + +namespace PIC16CP { + enum PIC16CPKind { + CPValue, + CPNonLazyPtr, + CPStub + }; +} + +/// PIC16ConstantPoolValue - PIC16 specific constantpool value. This is used to +/// represent PC relative displacement between the address of the load +/// instruction and the global value being loaded, i.e. (&GV-(LPIC+8)). +class PIC16ConstantPoolValue : public MachineConstantPoolValue { + GlobalValue *GV; // GlobalValue being loaded. + const char *S; // ExtSymbol being loaded. + unsigned LabelId; // Label id of the load. + PIC16CP::PIC16CPKind Kind; // non_lazy_ptr or stub? + unsigned char PCAdjust; // Extra adjustment if constantpool is pc relative. + // 8 for PIC16 + const char *Modifier; // GV modifier i.e. (&GV(modifier)-(LPIC+8)) + bool AddCurrentAddress; + +public: + PIC16ConstantPoolValue(GlobalValue *gv, unsigned id, + PIC16CP::PIC16CPKind Kind = PIC16CP::CPValue, + unsigned char PCAdj = 0, const char *Modifier = NULL, + bool AddCurrentAddress = false); + PIC16ConstantPoolValue(const char *s, unsigned id, + PIC16CP::PIC16CPKind Kind = PIC16CP::CPValue, + unsigned char PCAdj = 0, const char *Modifier = NULL, + bool AddCurrentAddress = false); + PIC16ConstantPoolValue(GlobalValue *GV, PIC16CP::PIC16CPKind Kind, + const char *Modifier); + + + GlobalValue *getGV() const { return GV; } + const char *getSymbol() const { return S; } + const char *getModifier() const { return Modifier; } + bool hasModifier() const { return Modifier != NULL; } + bool mustAddCurrentAddress() const { return AddCurrentAddress; } + unsigned getLabelId() const { return LabelId; } + bool isNonLazyPointer() const { return Kind == PIC16CP::CPNonLazyPtr; } + bool isStub() const { return Kind == PIC16CP::CPStub; } + unsigned char getPCAdjustment() const { return PCAdjust; } + + virtual int getExistingMachineCPValue(MachineConstantPool *CP, + unsigned Alignment); + + virtual void AddSelectionDAGCSEId(FoldingSetNodeID &ID); + + virtual void print(std::ostream &O) const; +}; + +} + +#endif diff --git a/lib/Target/PIC16/PIC16ISelDAGToDAG.cpp b/lib/Target/PIC16/PIC16ISelDAGToDAG.cpp new file mode 100644 index 00000000000..07ebd99a78e --- /dev/null +++ b/lib/Target/PIC16/PIC16ISelDAGToDAG.cpp @@ -0,0 +1,291 @@ +//===-- PIC16ISelDAGToDAG.cpp - A dag to dag inst selector for PIC16 ------===// +// +// 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 PIC16 target. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "pic16-isel" + +#include "PIC16.h" +#include "PIC16ISelLowering.h" +#include "PIC16RegisterInfo.h" +#include "PIC16Subtarget.h" +#include "PIC16TargetMachine.h" +#include "llvm/GlobalValue.h" +#include "llvm/Instructions.h" +#include "llvm/Intrinsics.h" +#include "llvm/Type.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/SelectionDAGISel.h" +#include "llvm/CodeGen/SelectionDAGNodes.h" +#include "llvm/Support/CFG.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" +#include "llvm/Target/TargetMachine.h" +#include +#include + +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Instruction Selector Implementation +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// PIC16DAGToDAGISel - PIC16 specific code to select PIC16 machine +// instructions for SelectionDAG operations. +//===----------------------------------------------------------------------===// +namespace { + +class VISIBILITY_HIDDEN PIC16DAGToDAGISel : public SelectionDAGISel { + + /// TM - Keep a reference to PIC16TargetMachine. + PIC16TargetMachine &TM; + + /// PIC16Lowering - This object fully describes how to lower LLVM code to an + /// PIC16-specific SelectionDAG. + PIC16TargetLowering PIC16Lowering; + + /// Subtarget - Keep a pointer to the PIC16Subtarget around so that we can + /// make the right decision when generating code for different targets. + //TODO: add initialization on constructor + //const PIC16Subtarget *Subtarget; + +public: + PIC16DAGToDAGISel(PIC16TargetMachine &tm) : + SelectionDAGISel(PIC16Lowering), + TM(tm), PIC16Lowering(*TM.getTargetLowering()) {} + + virtual void InstructionSelectBasicBlock(SelectionDAG &SD); + + // Pass Name + virtual const char *getPassName() const { + return "PIC16 DAG->DAG Pattern Instruction Selection"; + } + +private: + // Include the pieces autogenerated from the target description. + #include "PIC16GenDAGISel.inc" + + SDNode *Select(SDOperand N); + + // Select addressing mode. currently assume base + offset addr mode. + bool SelectAM(SDOperand Op, SDOperand N, SDOperand &Base, SDOperand &Offset); + bool SelectDirectAM(SDOperand Op, SDOperand N, SDOperand &Base, + SDOperand &Offset); + bool StoreInDirectAM(SDOperand Op, SDOperand N, SDOperand &fsr); + bool LoadFSR(SDOperand Op, SDOperand N, SDOperand &Base, SDOperand &Offset); + bool LoadNothing(SDOperand Op, SDOperand N, SDOperand &Base, + SDOperand &Offset); + + // getI8Imm - Return a target constant with the specified + // value, of type i8. + inline SDOperand getI8Imm(unsigned Imm) { + return CurDAG->getTargetConstant(Imm, MVT::i8); + } + + + #ifndef NDEBUG + unsigned Indent; + #endif +}; + +} + +/// InstructionSelectBasicBlock - This callback is invoked by +/// SelectionDAGISel when it has created a SelectionDAG for us to codegen. +void PIC16DAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &SD) +{ + DEBUG(BB->dump()); + // Codegen the basic block. + #ifndef NDEBUG + DOUT << "===== Instruction selection begins:\n"; + Indent = 0; + #endif + + // Select target instructions for the DAG. + SD.setRoot(SelectRoot(SD.getRoot())); + + #ifndef NDEBUG + DOUT << "===== Instruction selection ends:\n"; + #endif + + SD.RemoveDeadNodes(); + + // Emit machine code to BB. + ScheduleAndEmitDAG(SD); +} + + +bool PIC16DAGToDAGISel:: +SelectDirectAM (SDOperand Op, SDOperand N, SDOperand &Base, SDOperand &Offset) +{ + GlobalAddressSDNode *GA; + ConstantSDNode *GC; + + // if Address is FI, get the TargetFrameIndex. + if (FrameIndexSDNode *FIN = dyn_cast(N)) { + cout << "--------- its frame Index\n"; + Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); + Offset = CurDAG->getTargetConstant(0, MVT::i32); + return true; + } + + if (N.getOpcode() == ISD::GlobalAddress) { + GA = dyn_cast(N); + Offset = CurDAG->getTargetConstant((unsigned char)GA->getOffset(), MVT::i8); + Base = CurDAG->getTargetGlobalAddress(GA->getGlobal(), MVT::i16, + GA->getOffset()); + return true; + } + + if (N.getOpcode() == ISD::ADD) { + GC = dyn_cast(N.getOperand(1)); + Offset = CurDAG->getTargetConstant((unsigned char)GC->getValue(), MVT::i8); + if ((GA = dyn_cast(N.getOperand(0)))) { + Base = CurDAG->getTargetGlobalAddress(GA->getGlobal(), MVT::i16, + GC->getValue()); + return true; + } + else if (FrameIndexSDNode *FIN + = dyn_cast(N.getOperand(0))) { + Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); + return true; + } + } + + return false; +} + + +//FIXME: must also account for preinc/predec/postinc/postdec +bool PIC16DAGToDAGISel:: +StoreInDirectAM (SDOperand Op, SDOperand N, SDOperand &fsr) +{ + RegisterSDNode *Reg; + if (N.getOpcode() == ISD::LOAD) { + LoadSDNode *LD = dyn_cast(N); + if (LD) { + fsr = LD->getBasePtr(); + } + else if (isa(N.Val)) { + //FIXME an attempt to retrieve the register number + //but does not work + cout << "this is a register\n"; + Reg = dyn_cast(N.Val); + fsr = CurDAG->getRegister(Reg->getReg(),MVT::i16); + } + else { + cout << "this is not a register\n"; + // FIXME must use whatever load is using + fsr = CurDAG->getRegister(1,MVT::i16); + } + return true; + } + return false; +} + +bool PIC16DAGToDAGISel:: +LoadFSR (SDOperand Op, SDOperand N, SDOperand &Base, SDOperand &Offset) +{ + GlobalAddressSDNode *GA; + + if (N.getOpcode() == ISD::GlobalAddress) { + GA = dyn_cast(N); + Offset = CurDAG->getTargetConstant((unsigned char)GA->getOffset(), MVT::i8); + Base = CurDAG->getTargetGlobalAddress(GA->getGlobal(), MVT::i16, + GA->getOffset()); + return true; + } + else if (N.getOpcode() == PIC16ISD::Package) { + CurDAG->setGraphColor(Op.Val, "blue"); + CurDAG->viewGraph(); + } + + return false; +} + +//don't thake this seriously, it will change +bool PIC16DAGToDAGISel:: +LoadNothing (SDOperand Op, SDOperand N, SDOperand &Base, SDOperand &Offset) +{ + GlobalAddressSDNode *GA; + if (N.getOpcode() == ISD::GlobalAddress) { + GA = dyn_cast(N); + cout << "==========" << GA->getOffset() << "\n"; + Offset = CurDAG->getTargetConstant((unsigned char)GA->getOffset(), MVT::i8); + Base = CurDAG->getTargetGlobalAddress(GA->getGlobal(), MVT::i16, + GA->getOffset()); + return true; + } + + return false; +} + + +/// Select instructions not customized! Used for +/// expanded, promoted and normal instructions +SDNode* PIC16DAGToDAGISel::Select(SDOperand N) +{ + SDNode *Node = N.Val; + unsigned Opcode = Node->getOpcode(); + + // Dump information about the Node being selected + #ifndef NDEBUG + DOUT << std::string(Indent, ' ') << "Selecting: "; + DEBUG(Node->dump(CurDAG)); + DOUT << "\n"; + Indent += 2; + #endif + + // If we have a custom node, we already have selected! + if (Opcode >= ISD::BUILTIN_OP_END && Opcode < PIC16ISD::FIRST_NUMBER) { + #ifndef NDEBUG + DOUT << std::string(Indent-2, ' ') << "== "; + DEBUG(Node->dump(CurDAG)); + DOUT << "\n"; + Indent -= 2; + #endif + return NULL; + } + + /// + // Instruction Selection not handled by custom or by the + // auto-generated tablegen selection should be handled here. + /// + switch(Opcode) { + default: break; + } + + // Select the default instruction. + SDNode *ResNode = SelectCode(N); + + #ifndef NDEBUG + DOUT << std::string(Indent-2, ' ') << "=> "; + if (ResNode == NULL || ResNode == N.Val) + DEBUG(N.Val->dump(CurDAG)); + else + DEBUG(ResNode->dump(CurDAG)); + DOUT << "\n"; + Indent -= 2; + #endif + + return ResNode; +} + +/// createPIC16ISelDag - This pass converts a legalized DAG into a +/// PIC16-specific DAG, ready for instruction scheduling. +FunctionPass *llvm::createPIC16ISelDag(PIC16TargetMachine &TM) { + return new PIC16DAGToDAGISel(TM); +} + diff --git a/lib/Target/PIC16/PIC16ISelLowering.cpp b/lib/Target/PIC16/PIC16ISelLowering.cpp new file mode 100644 index 00000000000..45aaeda1824 --- /dev/null +++ b/lib/Target/PIC16/PIC16ISelLowering.cpp @@ -0,0 +1,801 @@ +//===-- PIC16ISelLowering.cpp - PIC16 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 defines the interfaces that PIC16 uses to lower LLVM code into a +// selection DAG. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "pic16-lower" + +#include "PIC16ISelLowering.h" +#include "PIC16TargetMachine.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/Intrinsics.h" +#include "llvm/CallingConv.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/SelectionDAGISel.h" +#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/Support/Debug.h" +#include +#include + +using namespace llvm; + +const char *PIC16TargetLowering:: getTargetNodeName(unsigned Opcode) const +{ + switch (Opcode) + { + case PIC16ISD::Hi : return "PIC16ISD::Hi"; + case PIC16ISD::Lo : return "PIC16ISD::Lo"; + case PIC16ISD::Package : return "PIC16ISD::Package"; + case PIC16ISD::Wrapper : return "PIC16ISD::Wrapper"; + case PIC16ISD::SetBank : return "PIC16ISD::SetBank"; + case PIC16ISD::SetPage : return "PIC16ISD::SetPage"; + case PIC16ISD::Branch : return "PIC16ISD::Branch"; + case PIC16ISD::Cmp : return "PIC16ISD::Cmp"; + case PIC16ISD::BTFSS : return "PIC16ISD::BTFSS"; + case PIC16ISD::BTFSC : return "PIC16ISD::BTFSC"; + case PIC16ISD::XORCC : return "PIC16ISD::XORCC"; + case PIC16ISD::SUBCC : return "PIC16ISD::SUBCC"; + default : return NULL; + } +} + +PIC16TargetLowering:: +PIC16TargetLowering(PIC16TargetMachine &TM): TargetLowering(TM) +{ + // PIC16 does not have i1 type, so use i8 for + // setcc operations results (slt, sgt, ...). + // setSetCCResultType(MVT::i8); + // setSetCCResultContents(ZeroOrOneSetCCResult); + + // Set up the register classes + addRegisterClass(MVT::i8, PIC16::CPURegsRegisterClass); + addRegisterClass(MVT::i16, PIC16::PTRRegsRegisterClass); + // Custom + + // Load extented operations for i1 types must be promoted + setLoadXAction(ISD::EXTLOAD, MVT::i1, Promote); + setLoadXAction(ISD::ZEXTLOAD, MVT::i1, Promote); + setLoadXAction(ISD::SEXTLOAD, MVT::i1, Promote); + + // Store operations for i1 types must be promoted + // setStoreXAction(MVT::i1, Promote); + // setStoreXAction(MVT::i8, Legal); + // setStoreXAction(MVT::i16, Custom); + // setStoreXAction(MVT::i32, Expand); + + // setOperationAction(ISD::BUILD_PAIR, MVT::i32, Expand); + // setOperationAction(ISD::BUILD_PAIR, MVT::i16, Expand); + + setOperationAction(ISD::ADD, MVT::i1, Promote); + setOperationAction(ISD::ADD, MVT::i8, Legal); + setOperationAction(ISD::ADD, MVT::i16, Custom); + setOperationAction(ISD::ADD, MVT::i32, Expand); + setOperationAction(ISD::ADD, MVT::i64, Expand); + + setOperationAction(ISD::SUB, MVT::i1, Promote); + setOperationAction(ISD::SUB, MVT::i8, Legal); + setOperationAction(ISD::SUB, MVT::i16, Custom); + setOperationAction(ISD::SUB, MVT::i32, Expand); + setOperationAction(ISD::SUB, MVT::i64, Expand); + + setOperationAction(ISD::ADDC, MVT::i1, Promote); + setOperationAction(ISD::ADDC, MVT::i8, Legal); + setOperationAction(ISD::ADDC, MVT::i16, Custom); + setOperationAction(ISD::ADDC, MVT::i32, Expand); + setOperationAction(ISD::ADDC, MVT::i64, Expand); + + setOperationAction(ISD::ADDE, MVT::i1, Promote); + setOperationAction(ISD::ADDE, MVT::i8, Legal); + setOperationAction(ISD::ADDE, MVT::i16, Custom); + setOperationAction(ISD::ADDE, MVT::i32, Expand); + setOperationAction(ISD::ADDE, MVT::i64, Expand); + + setOperationAction(ISD::SUBC, MVT::i1, Promote); + setOperationAction(ISD::SUBC, MVT::i8, Legal); + setOperationAction(ISD::SUBC, MVT::i16, Custom); + setOperationAction(ISD::SUBC, MVT::i32, Expand); + setOperationAction(ISD::SUBC, MVT::i64, Expand); + + setOperationAction(ISD::SUBE, MVT::i1, Promote); + setOperationAction(ISD::SUBE, MVT::i8, Legal); + setOperationAction(ISD::SUBE, MVT::i16, Custom); + setOperationAction(ISD::SUBE, MVT::i32, Expand); + setOperationAction(ISD::SUBE, MVT::i64, Expand); + + // PIC16 does not have these NodeTypes below. + setOperationAction(ISD::SETCC, MVT::i1, Expand); + setOperationAction(ISD::SETCC, MVT::i8, Expand); + setOperationAction(ISD::SETCC, MVT::Other, Expand); + setOperationAction(ISD::SELECT_CC, MVT::i1, Custom); + setOperationAction(ISD::SELECT_CC, MVT::i8, Custom); + + setOperationAction(ISD::BRCOND, MVT::i1, Expand); + setOperationAction(ISD::BRCOND, MVT::i8, Expand); + setOperationAction(ISD::BRCOND, MVT::Other, Expand); + setOperationAction(ISD::BR_CC, MVT::i1, Custom); + setOperationAction(ISD::BR_CC, MVT::i8, Custom); + + setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); + + + // Do we really need to Custom lower the GA ?? + // setOperationAction(ISD::GlobalAddress, MVT::i16, Custom); + setOperationAction(ISD::GlobalAddress, MVT::i8, Custom); + setOperationAction(ISD::RET, MVT::Other, Custom); + + // PIC16 not supported intrinsics. + // setOperationAction(ISD::MEMMOVE, MVT::Other, Expand); + // setOperationAction(ISD::MEMSET, MVT::Other, Expand); + // setOperationAction(ISD::MEMCPY, MVT::Other, Expand); + + setOperationAction(ISD::CTPOP, MVT::i32, Expand); + setOperationAction(ISD::CTTZ , MVT::i32, Expand); + setOperationAction(ISD::CTLZ , MVT::i32, Expand); + setOperationAction(ISD::ROTL , MVT::i32, Expand); + setOperationAction(ISD::ROTR , MVT::i32, Expand); + setOperationAction(ISD::BSWAP, MVT::i32, Expand); + + setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand); + setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand); + setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand); + + // We don't have line number support yet. + setOperationAction(ISD::LOCATION, MVT::Other, Expand); + setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand); + setOperationAction(ISD::LABEL, MVT::Other, Expand); + + // Use the default for now + setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); + setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand); + + setOperationAction(ISD::LOAD, MVT::i1, Promote); + setOperationAction(ISD::LOAD, MVT::i8, Legal); + // setOperationAction(ISD::LOAD, MVT::i16, Expand); + // setOperationAction(ISD::LOAD, MVT::i32, Expand); + + setTargetDAGCombine(ISD::LOAD); + setTargetDAGCombine(ISD::STORE); + setTargetDAGCombine(ISD::ADDE); + setTargetDAGCombine(ISD::ADDC); + setTargetDAGCombine(ISD::ADD); + setTargetDAGCombine(ISD::SUBE); + setTargetDAGCombine(ISD::SUBC); + setTargetDAGCombine(ISD::SUB); + + // We must find a way to get rid of Package nodes in the map + // setTargetDAGCombine(PIC16ISD::Package); + + // getValueTypeActions().setTypeAction((MVT::ValueType)MVT::i16, Expand); + + setStackPointerRegisterToSaveRestore(PIC16::STKPTR); + computeRegisterProperties(); +} + + +SDOperand PIC16TargetLowering:: LowerOperation(SDOperand Op, SelectionDAG &DAG) +{ + SDVTList VTList16 = DAG.getVTList(MVT::i16, MVT::i16, MVT::Other); + switch (Op.getOpcode()) + { + case ISD::STORE: + cout << "reduce store\n"; + break; + case ISD::FORMAL_ARGUMENTS: + cout<<"==== lowering formal args\n"; + return LowerFORMAL_ARGUMENTS(Op, DAG); + case ISD::GlobalAddress: + cout<<"==== lowering GA\n"; + return LowerGlobalAddress(Op, DAG); + case ISD::RET: + cout<<"==== lowering ret\n"; + return LowerRET(Op, DAG); + case ISD::FrameIndex: + cout<<"==== lowering frame index\n"; + return LowerFrameIndex(Op, DAG); + case ISD::ADDE: + cout <<"==== lowering adde\n"; + break; + case ISD::LOAD: + case ISD::ADD: + break; + case ISD::BR_CC: + cout << "==== lowering BR_CC\n"; + return LowerBR_CC(Op, DAG); + } //end swithch + return SDOperand(); +} + + +//===----------------------------------------------------------------------===// +// Lower helper functions +//===----------------------------------------------------------------------===// + + +SDOperand +PIC16TargetLowering::LowerBR_CC(SDOperand Op, SelectionDAG &DAG) +{ + MVT::ValueType VT = Op.getValueType(); + SDOperand Chain = Op.getOperand(0); + ISD::CondCode CC = cast(Op.getOperand(1))->get(); + SDOperand LHS = Op.getOperand(2); + SDOperand RHS = Op.getOperand(3); + SDOperand JumpVal = Op.getOperand(4); + SDOperand Result; + unsigned cmpOpcode; + unsigned branchOpcode; + SDOperand branchOperand; + + SDOperand StatusReg = DAG.getRegister(PIC16::STATUSREG,MVT::i8); + SDOperand CPUReg = DAG.getRegister(PIC16::WREG,MVT::i8); + switch(CC) + { + default: + assert(0 && "This condition code is not handled yet!!"); + abort(); + case ISD::SETNE: + { + cout << "setne\n"; + cmpOpcode = PIC16ISD::XORCC; + branchOpcode = PIC16ISD::BTFSS; + branchOperand = DAG.getConstant(2,MVT::i8); + break; + } + case ISD::SETEQ: + { + cout << "seteq\n"; + cmpOpcode = PIC16ISD::XORCC; + branchOpcode = PIC16ISD::BTFSC; + branchOperand = DAG.getConstant(2,MVT::i8); + break; + } + case ISD::SETGT: + { + assert(0 && "Greater Than condition code is not handled yet!!"); + abort(); + } + case ISD::SETGE: + { + cout << "setge\n"; + cmpOpcode = PIC16ISD::SUBCC; + branchOpcode = PIC16ISD::BTFSS; + branchOperand = DAG.getConstant(1, MVT::i8); + break; + } + case ISD::SETLT: + { + cout << "setlt\n"; + cmpOpcode = PIC16ISD::SUBCC; + branchOpcode = PIC16ISD::BTFSC; + branchOperand = DAG.getConstant(1,MVT::i8); + break; + } + case ISD::SETLE: + { + assert(0 && "Less Than Equal condition code is not handled yet!!"); + abort(); + } + } // End of Switch + + SDVTList VTList = DAG.getVTList(MVT::i8, MVT::Flag); + SDOperand CmpValue = DAG.getNode(cmpOpcode, VTList, LHS, RHS).getValue(1); + // SDOperand CCOper = DAG.getConstant(CC,MVT::i8); + // Result = DAG.getNode(branchOpcode,VT, Chain, JumpVal, CCOper, StatusReg, + // CmpValue); + Result = DAG.getNode(branchOpcode, VT, Chain, JumpVal, branchOperand, + StatusReg, CmpValue); + return Result; + + // return SDOperand(); +} + + +//===----------------------------------------------------------------------===// +// Misc Lower Operation implementation +//===----------------------------------------------------------------------===// +// Create a constant pool entry for global value and wrap it in a wrapper node. +SDOperand +PIC16TargetLowering::LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG) +{ + MVT::ValueType PtrVT = getPointerTy(); + GlobalAddressSDNode *GSDN = cast(Op); + GlobalValue *GV = GSDN->getGlobal(); + + //for now only do the ram. + SDOperand CPAddr = DAG.getTargetConstantPool(GV, PtrVT, 2); + SDOperand CPBank = DAG.getNode(PIC16ISD::SetBank, MVT::i8, CPAddr); + CPAddr = DAG.getNode(PIC16ISD::Wrapper, MVT::i8, CPAddr,CPBank); + + return CPAddr; +} + +SDOperand +PIC16TargetLowering::LowerRET(SDOperand Op, SelectionDAG &DAG) +{ + switch(Op.getNumOperands()) + { + default: + assert(0 && "Do not know how to return this many arguments!"); + abort(); + case 1: + return SDOperand(); // ret void is legal + } +} + +SDOperand +PIC16TargetLowering::LowerFrameIndex(SDOperand N, SelectionDAG &DAG) +{ + if (FrameIndexSDNode *FIN = dyn_cast(N)) { + return DAG.getTargetFrameIndex(FIN->getIndex(), MVT::i32); + } + + return N; +} + +SDOperand +PIC16TargetLowering::LowerLOAD(SDNode *N, + SelectionDAG &DAG, + DAGCombinerInfo &DCI) const +{ + SDOperand Outs[2]; + SDOperand TF; //TokenFactor + SDOperand OutChains[2]; + SDOperand Chain = N->getOperand(0); + SDOperand Src = N->getOperand(1); + SDOperand retVal; + SDVTList VTList; + + // If this load is directly stored, replace the load value with the stored + // value. + // TODO: Handle store large -> read small portion. + // TODO: Handle TRUNCSTORE/LOADEXT + LoadSDNode *LD = cast(N); + SDOperand Ptr = LD->getBasePtr(); + if (LD->getExtensionType() == ISD::NON_EXTLOAD) { + if (ISD::isNON_TRUNCStore(Chain.Val)) { + StoreSDNode *PrevST = cast(Chain); + if (PrevST->getBasePtr() == Ptr && + PrevST->getValue().getValueType() == N->getValueType(0)) + return DCI.CombineTo(N, Chain.getOperand(1), Chain); + } + } + + if (N->getValueType(0) != MVT::i16) + return SDOperand(); + + SDOperand toWorklist; + Outs[0] = DAG.getLoad(MVT::i8, Chain, Src, NULL, 0); + toWorklist = DAG.getNode(ISD::ADD, MVT::i16, Src, + DAG.getConstant(1, MVT::i16)); + Outs[1] = DAG.getLoad(MVT::i8, Chain, toWorklist, NULL, 0); + // Add to worklist may not be needed. + // It is meant to merge sequences of add with constant into one. + DCI.AddToWorklist(toWorklist.Val); + + // Create the tokenfactors and carry it on to the build_pair node + OutChains[0] = Outs[0].getValue(1); + OutChains[1] = Outs[1].getValue(1); + TF = DAG.getNode(ISD::TokenFactor, MVT::Other, &OutChains[0], 2); + + VTList = DAG.getVTList(MVT::i16, MVT::Flag); + retVal = DAG.getNode (PIC16ISD::Package, VTList, &Outs[0], 2); + + DCI.CombineTo (N, retVal, TF); + + return retVal; +} + +SDOperand +PIC16TargetLowering::LowerADDSUB(SDNode *N, SelectionDAG &DAG, + DAGCombinerInfo &DCI) const +{ + bool changed = false; + int i; + SDOperand LoOps[3], HiOps[3]; + SDOperand OutOps[3]; //[0]:left, [1]:right, [2]:carry + SDOperand InOp[2]; + SDOperand retVal; + SDOperand as1,as2; + SDVTList VTList; + unsigned AS,ASE,ASC; + + InOp[0] = N->getOperand(0); + InOp[1] = N->getOperand(1); + + switch (N->getOpcode()) + { + case ISD::ADD: + if (InOp[0].getOpcode() == ISD::Constant && + InOp[1].getOpcode() == ISD::Constant) { + ConstantSDNode *CST0 = dyn_cast(InOp[0]); + ConstantSDNode *CST1 = dyn_cast(InOp[1]); + return DAG.getConstant(CST0->getValue() + CST1->getValue(), MVT::i16); + } + case ISD::ADDE: + case ISD::ADDC: + AS = ISD::ADD; + ASE = ISD::ADDE; + ASC = ISD::ADDC; + break; + case ISD::SUB: + if (InOp[0].getOpcode() == ISD::Constant && + InOp[1].getOpcode() == ISD::Constant) { + ConstantSDNode *CST0 = dyn_cast(InOp[0]); + ConstantSDNode *CST1 = dyn_cast(InOp[1]); + return DAG.getConstant(CST0->getValue() - CST1->getValue(), MVT::i16); + } + case ISD::SUBE: + case ISD::SUBC: + AS = ISD::SUB; + ASE = ISD::SUBE; + ASC = ISD::SUBC; + break; + } + + assert ((N->getValueType(0) == MVT::i16) + && "expecting an MVT::i16 node for lowering"); + assert ((N->getOperand(0).getValueType() == MVT::i16) + && (N->getOperand(1).getValueType() == MVT::i16) + && "both inputs to addx/subx:i16 must be i16"); + + for (i = 0; i < 2; i++) { + if (InOp[i].getOpcode() == ISD::GlobalAddress) { + //we don't want to lower subs/adds with global address (at least not yet) + return SDOperand(); + } + else if (InOp[i].getOpcode() == ISD::Constant) { + changed = true; + ConstantSDNode *CST = dyn_cast(InOp[i]); + LoOps[i] = DAG.getConstant(CST->getValue() & 0xFF, MVT::i8); + HiOps[i] = DAG.getConstant(CST->getValue() >> 8, MVT::i8); + } + else if (InOp[i].getOpcode() == PIC16ISD::Package) { + LoOps[i] = InOp[i].getOperand(0); + HiOps[i] = InOp[i].getOperand(1); + } + else if (InOp[i].getOpcode() == ISD::LOAD) { + changed = true; + // LowerLOAD returns a Package node or it may combine and return + // anything else + SDOperand lowered = LowerLOAD(InOp[i].Val, DAG, DCI); + + // So If LowerLOAD returns something other than Package, + // then just call ADD again + if (lowered.getOpcode() != PIC16ISD::Package) + return LowerADDSUB(N, DAG, DCI); + + LoOps[i] = lowered.getOperand(0); + HiOps[i] = lowered.getOperand(1); + } + else if ((InOp[i].getOpcode() == ISD::ADD) || + (InOp[i].getOpcode() == ISD::ADDE) || + (InOp[i].getOpcode() == ISD::ADDC) || + (InOp[i].getOpcode() == ISD::SUB) || + (InOp[i].getOpcode() == ISD::SUBE) || + (InOp[i].getOpcode() == ISD::SUBC)) { + changed = true; + //must call LowerADDSUB recursively here.... + //LowerADDSUB returns a Package node + SDOperand lowered = LowerADDSUB(InOp[i].Val, DAG, DCI); + + LoOps[i] = lowered.getOperand(0); + HiOps[i] = lowered.getOperand(1); + } + else if (InOp[i].getOpcode() == ISD::SIGN_EXTEND) { + //FIXME: I am just zero extending. for now. + changed = true; + LoOps[i] = InOp[i].getOperand(0); + HiOps[i] = DAG.getConstant(0, MVT::i8); + } + else { + DAG.setGraphColor(N, "blue"); + DAG.viewGraph(); + assert (0 && "not implemented yet"); + } + } //end for + + assert (changed && "nothing changed while lowering SUBx/ADDx"); + + VTList = DAG.getVTList(MVT::i8, MVT::Flag); + if (N->getOpcode() == ASE) { + //we must take in the existing carry + //if this node is part of an existing subx/addx sequence + LoOps[2] = N->getOperand(2).getValue(1); + as1 = DAG.getNode (ASE, VTList, LoOps, 3); + } + else { + as1 = DAG.getNode (ASC, VTList, LoOps, 2); + } + HiOps[2] = as1.getValue(1); + as2 = DAG.getNode (ASE, VTList, HiOps, 3); + //we must build a pair that also provides the carry from sube/adde + OutOps[0] = as1; + OutOps[1] = as2; + OutOps[2] = as2.getValue(1); + //breaking an original i16 so lets make the Package also an i16 + if (N->getOpcode() == ASE) { + VTList = DAG.getVTList(MVT::i16, MVT::Flag); + retVal = DAG.getNode (PIC16ISD::Package, VTList, OutOps, 3); + DCI.CombineTo (N, retVal, OutOps[2]); + } + else if (N->getOpcode() == ASC) { + VTList = DAG.getVTList(MVT::i16, MVT::Flag); + retVal = DAG.getNode (PIC16ISD::Package, VTList, OutOps, 2); + DCI.CombineTo (N, retVal, OutOps[2]); + } + else if (N->getOpcode() == AS) { + VTList = DAG.getVTList(MVT::i16); + retVal = DAG.getNode (PIC16ISD::Package, VTList, OutOps, 2); + DCI.CombineTo (N, retVal); + } + + return retVal; +} + + +//===----------------------------------------------------------------------===// +// Calling Convention Implementation +// +// The lower operations present on calling convention works on this order: +// LowerCALL (virt regs --> phys regs, virt regs --> stack) +// LowerFORMAL_ARGUMENTS (phys --> virt regs, stack --> virt regs) +// LowerRET (virt regs --> phys regs) +// LowerCALL (phys regs --> virt regs) +// +//===----------------------------------------------------------------------===// + +#include "PIC16GenCallingConv.inc" + +//===----------------------------------------------------------------------===// +// CALL Calling Convention Implementation +//===----------------------------------------------------------------------===// + + +//===----------------------------------------------------------------------===// +// FORMAL_ARGUMENTS Calling Convention Implementation +//===----------------------------------------------------------------------===// +SDOperand PIC16TargetLowering:: +LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG) +{ + SmallVector ArgValues; + SDOperand Root = Op.getOperand(0); + + // Return the new list of results. + // Just copy right now. + ArgValues.push_back(Root); + + return DAG.getNode(ISD::MERGE_VALUES, Op.Val->getVTList(), &ArgValues[0], + ArgValues.size()).getValue(Op.ResNo); +} + + +//===----------------------------------------------------------------------===// +// Return Value Calling Convention Implementation +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// PIC16 Inline Assembly Support +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Target Optimization Hooks +//===----------------------------------------------------------------------===// + +SDOperand PIC16TargetLowering::PerformDAGCombine(SDNode *N, + DAGCombinerInfo &DCI) const +{ + int i; + ConstantSDNode *CST; + SelectionDAG &DAG = DCI.DAG; + + switch (N->getOpcode()) + { + default: break; + case PIC16ISD::Package : + cout <<"==== combining PIC16ISD::Package\n"; + return SDOperand(); + case ISD::ADD : + case ISD::SUB : + if ((N->getOperand(0).getOpcode() == ISD::GlobalAddress) || + (N->getOperand(0).getOpcode() == ISD::FrameIndex)) { + //do not touch pointer adds + return SDOperand (); + } + case ISD::ADDE : + case ISD::ADDC : + case ISD::SUBE : + case ISD::SUBC : + if (N->getValueType(0) == MVT::i16) { + SDOperand retVal = LowerADDSUB(N, DAG,DCI); + // LowerADDSUB has already combined the result, + // so we just return nothing to avoid assertion failure from llvm + // if N has been deleted already + return SDOperand(); + } + else if (N->getValueType(0) == MVT::i8) { + //sanity check .... + for (int i=0; i<2; i++) { + if (N->getOperand (i).getOpcode() == PIC16ISD::Package) { + assert (0 && + "don't want to have PIC16ISD::Package as intput to add:i8"); + } + } + } + break; + case ISD::STORE : + { + SDOperand Chain = N->getOperand(0); + SDOperand Src = N->getOperand(1); + SDOperand Dest = N->getOperand(2); + unsigned int DstOff = 0; + int NUM_STORES; + SDOperand Stores[6]; + + + // if source operand is expected to be extended to + // some higher type then - remove this extension + // SDNode and do the extension manually + if ((Src.getOpcode() == ISD::ANY_EXTEND) || + (Src.getOpcode() == ISD::SIGN_EXTEND) || + (Src.getOpcode() == ISD::ZERO_EXTEND)) { + Src = Src.Val->getOperand(0); + Stores[0] = DAG.getStore(Chain, Src, Dest, NULL,0); + return Stores[0]; + } + + switch(Src.getValueType()) + { + case MVT::i8: + break; + case MVT::i16: + NUM_STORES = 2; + break; + case MVT::i32: + NUM_STORES = 4; + break; + case MVT::i64: + NUM_STORES = 8; + break; + } + + if (isa(Dest) && isa(Src) && + (Src.getValueType() != MVT::i8)) { + //create direct addressing a = b + Chain = Src.getOperand(0); + for (i=0; i(Dest) && isa(Src) + && (Src.getValueType() != MVT::i8)) + { + //create direct addressing a = CONST + CST = dyn_cast(Src); + for (i = 0; i < NUM_STORES; i++) { + SDOperand CNST = DAG.getConstant(CST->getValue() >> i*8, MVT::i8); + SDOperand ADN = DAG.getNode(ISD::ADD, MVT::i16, Dest, + DAG.getConstant(DstOff, MVT::i16)); + Stores[i] = DAG.getStore(Chain, CNST, ADN, NULL, 0); + Chain = Stores[i]; + DstOff += 1; + } + + Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, &Stores[0], i); + return Chain; + } + else if (isa(Dest) && isa(Src) + && (Src.getValueType() != MVT::i8)) { + //create indirect addressing + CST = dyn_cast(Src); + Chain = Dest.getOperand(0); + SDOperand Load; + Load = DAG.getLoad(MVT::i16, Chain,Dest.getOperand(1), NULL, 0); + Chain = Load.getValue(1); + for (i=0; igetValue() >> i*8, MVT::i8); + Stores[i] = DAG.getStore(Chain, CNST, Load, NULL, 0); + Chain = Stores[i]; + DstOff += 1; + } + + Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, &Stores[0], i); + return Chain; + } + else if (isa(Dest) && isa(Src)) { + // GlobalAddressSDNode *GAD = dyn_cast(Src); + return SDOperand(); + } + else if (Src.getOpcode() == PIC16ISD::Package) { + StoreSDNode *st = dyn_cast(N); + SDOperand toWorkList, retVal; + Chain = N->getOperand(0); + + if (st->isTruncatingStore()) { + retVal = DAG.getStore(Chain, Src.getOperand(0), Dest, NULL, 0); + } + else { + toWorkList = DAG.getNode(ISD::ADD, MVT::i16, Dest, + DAG.getConstant(1, MVT::i16)); + Stores[1] = DAG.getStore(Chain, Src.getOperand(0), Dest, NULL, 0); + Stores[0] = DAG.getStore(Chain, Src.getOperand(1), toWorkList, NULL, 0); + + // We want to merge sequence of add with constant to one add and a + // constant, so add the ADD node to worklist to have llvm do that + // automatically. + DCI.AddToWorklist(toWorkList.Val); + + // We don't need the Package so add to worklist so llvm deletes it + DCI.AddToWorklist(Src.Val); + retVal = DAG.getNode(ISD::TokenFactor, MVT::Other, &Stores[0], 2); + } + + return retVal; + } + else if (Src.getOpcode() == ISD::TRUNCATE) { + } + else { + // DAG.setGraphColor(N, "blue"); + // DAG.viewGraph(); + // assert (0 && "input to store not implemented yet"); + } + } //end ISD::STORE + + break; + case ISD::LOAD : + { + SDOperand Ptr = N->getOperand(1); + if (Ptr.getOpcode() == PIC16ISD::Package) { + // DAG.setGraphColor(N, "blue"); + // DAG.viewGraph(); + // Here we must make so that: + // Ptr.getOperand(0) --> fsrl + // Ptr.getOperand(1) --> fsrh + assert (0 && "not implemented yet"); + } + //return SDOperand(); + //break; + } + }//end switch + + return SDOperand(); +} + +//===----------------------------------------------------------------------===// +// Utility functions +//===----------------------------------------------------------------------===// +const SDOperand *PIC16TargetLowering:: +findLoadi8(const SDOperand &Src, SelectionDAG &DAG) const +{ + unsigned int i; + if ((Src.getOpcode() == ISD::LOAD) && (Src.getValueType() == MVT::i8)) + return &Src; + for (i=0; i NodeMap_t; + + explicit PIC16TargetLowering(PIC16TargetMachine &TM); + + /// LowerOperation - Provide custom lowering hooks for some operations. + virtual SDOperand LowerOperation(SDOperand Op, SelectionDAG &DAG); + + SDOperand LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG); + SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG); + SDOperand LowerRET(SDOperand Op, SelectionDAG &DAG); + SDOperand LowerFrameIndex(SDOperand Op, SelectionDAG &DAG); + SDOperand LowerBR_CC(SDOperand Op, SelectionDAG &DAG); + + SDOperand RemoveHiLo(SDNode *, SelectionDAG &DAG, + DAGCombinerInfo &DCI) const; + SDOperand LowerADDSUB(SDNode *, SelectionDAG &DAG, + DAGCombinerInfo &DCI) const; + SDOperand LowerLOAD(SDNode *, SelectionDAG &DAG, + DAGCombinerInfo &DCI) const; + + /// getTargetNodeName - This method returns the name of a target specific + // DAG node. + virtual const char *getTargetNodeName(unsigned Opcode) const; + virtual SDOperand PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const; + + // utility function. + const SDOperand *findLoadi8(const SDOperand &Src, SelectionDAG &DAG) const; + }; +} // namespace llvm + +#endif // PIC16ISELLOWERING_H diff --git a/lib/Target/PIC16/PIC16InstrFormats.td b/lib/Target/PIC16/PIC16InstrFormats.td new file mode 100644 index 00000000000..d4b3ee7328e --- /dev/null +++ b/lib/Target/PIC16/PIC16InstrFormats.td @@ -0,0 +1,112 @@ +//===- PIC16RegisterInfo.td - PIC16 Register defs ------------*- tblgen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Describe PIC16 instructions format +// +// All the possible PIC16 fields are: +// +// opcode - operation code. +// f - 7-bit register file address. +// d - 1-bit direction specifier +// k - 8/11 bit literals +// b - 3 bits bit num specifier +// +//===----------------------------------------------------------------------===// + +// Generic PIC16 Format +class PIC16Inst pattern> + : Instruction +{ + field bits<14> Inst; + + let Namespace = "PIC16"; + + dag OutOperandList = outs; + dag InOperandList = ins; + + let AsmString = asmstr; + let Pattern = pattern; +} + + +//===----------------------------------------------------------------------===// +// Byte Oriented instruction class in PIC16 : <|opcode|d|f|> +//===----------------------------------------------------------------------===// + +class ByteFormat op, dag outs, dag ins, string asmstr, + list pattern> + :PIC16Inst +{ + bits<1> d; + bits<7> f; + + let Inst{13-8} = op; + + let Inst{7} = d; + let Inst{6-0} = f; +} + +//===----------------------------------------------------------------------===// +// Bit Oriented instruction class in PIC16 : <|opcode|b|f|> +//===----------------------------------------------------------------------===// + +class BitFormat op, dag outs, dag ins, string asmstr, list pattern> + : PIC16Inst +{ + bits<3> b; + bits<7> f; + + let Inst{13-10} = op; + + let Inst{9-7} = b; + let Inst{6-0} = f; +} + +//===----------------------------------------------------------------------===// +// Literal Format instruction class in PIC16 : <|opcode|k|> +//===----------------------------------------------------------------------===// + +class LiteralFormat op, dag outs, dag ins, string asmstr, + list pattern> + : PIC16Inst +{ + bits<8> k; + + + let Inst{13-8} = op; + + let Inst{7-0} = k; +} + +//===----------------------------------------------------------------------===// +// Control Format instruction class in PIC16 : <|opcode|k|> +//===----------------------------------------------------------------------===// + +class ControlFormat op, dag outs, dag ins, string asmstr, + list pattern> + :PIC16Inst +{ + bits<11> k; + + + let Inst{13-11} = op; + + let Inst{10-0} = k; +} + +//===----------------------------------------------------------------------===// +// Pseudo instruction class in PIC16 +//===----------------------------------------------------------------------===// + +class Pseudo op, dag outs, dag ins, string asmstr, list pattern>: + PIC16Inst +{ + let Inst{13-6} = op; +} diff --git a/lib/Target/PIC16/PIC16InstrInfo.cpp b/lib/Target/PIC16/PIC16InstrInfo.cpp new file mode 100644 index 00000000000..ad383823287 --- /dev/null +++ b/lib/Target/PIC16/PIC16InstrInfo.cpp @@ -0,0 +1,143 @@ +//===- PIC16InstrInfo.cpp - PIC16 Instruction Information -----------------===// +// +// 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 PIC16 implementation of the TargetInstrInfo class. +// +//===----------------------------------------------------------------------===// + +#include "PIC16.h" +#include "PIC16InstrInfo.h" +#include "llvm/Function.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "PIC16GenInstrInfo.inc" + +using namespace llvm; + +// TODO: Add the subtarget support on this constructor. +PIC16InstrInfo::PIC16InstrInfo(PIC16TargetMachine &tm) + : TargetInstrInfoImpl(PIC16Insts, array_lengthof(PIC16Insts)), + TM(tm), RI(*this) {} + +static bool isZeroImm(const MachineOperand &op) { + return op.isImmediate() && op.getImm() == 0; +} + + +/// 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 PIC16InstrInfo:: +isLoadFromStackSlot(MachineInstr *MI, int &FrameIndex) const +{ + if (MI->getOpcode() == PIC16::MOVF) { + if ((MI->getOperand(2).isFrameIndex()) && // is a stack slot + (MI->getOperand(1).isImmediate()) && // the imm is zero + (isZeroImm(MI->getOperand(1)))) { + FrameIndex = MI->getOperand(2).getIndex(); + return MI->getOperand(0).getReg(); + } + } + + return 0; +} + +/// isStoreToStackSlot - If the specified machine instruction is a direct +/// store to a stack slot, return the virtual or physical register number of +/// the source reg along with the FrameIndex of the loaded stack slot. If +/// not, return 0. This predicate must return 0 if the instruction has +/// any side effects other than storing to the stack slot. +unsigned PIC16InstrInfo:: +isStoreToStackSlot(MachineInstr *MI, int &FrameIndex) const +{ + if (MI->getOpcode() == PIC16::MOVWF) { + if ((MI->getOperand(0).isFrameIndex()) && // is a stack slot + (MI->getOperand(1).isImmediate()) && // the imm is zero + (isZeroImm(MI->getOperand(1)))) { + FrameIndex = MI->getOperand(0).getIndex(); + return MI->getOperand(2).getReg(); + } + } + return 0; +} + +void PIC16InstrInfo:: +storeRegToStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + unsigned SrcReg, bool isKill, int FI, + const TargetRegisterClass *RC) const { + const Function *Func = MBB.getParent()->getFunction(); + const std::string FuncName = Func->getName(); + + char *tmpName = new char [strlen(FuncName.c_str()) + 6]; + sprintf(tmpName, "%s_tmp_%d",FuncName.c_str(),FI); + + if (RC == PIC16::CPURegsRegisterClass) { + //src is always WREG. + BuildMI(MBB, I, this->get(PIC16::MOVWF)) + .addReg(SrcReg,false,false,true,true) + .addExternalSymbol(tmpName) // the current printer expects 3 operands, + .addExternalSymbol(tmpName); // all we need is actually one, + // so we repeat. + } + else + assert(0 && "Can't store this register to stack slot"); +} + +void PIC16InstrInfo:: +loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, + unsigned DestReg, int FI, + const TargetRegisterClass *RC) const +{ + const Function *Func = MBB.getParent()->getFunction(); + const std::string FuncName = Func->getName(); + + char *tmpName = new char [strlen(FuncName.c_str()) + 6]; + sprintf(tmpName, "%s_tmp_%d",FuncName.c_str(),FI); + + if (RC == PIC16::CPURegsRegisterClass) + BuildMI(MBB, I, this->get(PIC16::MOVF), DestReg) + .addExternalSymbol(tmpName) // the current printer expects 3 operands, + .addExternalSymbol(tmpName); // all we need is actually one,so we repeat. + else + assert(0 && "Can't load this register from stack slot"); +} + +/// InsertBranch - Insert a branch into the end of the specified +/// MachineBasicBlock. This operands to this method are the same as those +/// returned by AnalyzeBranch. This is invoked in cases where AnalyzeBranch +/// returns success and when an unconditional branch (TBB is non-null, FBB is +/// null, Cond is empty) needs to be inserted. It returns the number of +/// instructions inserted. +unsigned PIC16InstrInfo:: +InsertBranch(MachineBasicBlock &MBB, + MachineBasicBlock *TBB, MachineBasicBlock *FBB, + const std::vector &Cond) const +{ + // Shouldn't be a fall through. + assert(TBB && "InsertBranch must not be told to insert a fallthrough"); + + if (FBB == 0) { // One way branch. + if (Cond.empty()) { + // Unconditional branch? + BuildMI(&MBB, get(PIC16::GOTO)).addMBB(TBB); + } + return 1; + } + + // TODO: If the there are some conditions specified then conditional branch + // should be generated. + // For the time being no instruction is being generated therefore + // returning NULL. + return 0; +} + diff --git a/lib/Target/PIC16/PIC16InstrInfo.h b/lib/Target/PIC16/PIC16InstrInfo.h new file mode 100644 index 00000000000..f764668eac2 --- /dev/null +++ b/lib/Target/PIC16/PIC16InstrInfo.h @@ -0,0 +1,78 @@ +//===- PIC16InstrInfo.h - PIC16 Instruction Information----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the niversity of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the PIC16 implementation of the TargetInstrInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef PIC16INSTRUCTIONINFO_H +#define PIC16INSTRUCTIONINFO_H + +#include "PIC16.h" +#include "PIC16RegisterInfo.h" +#include "llvm/Target/TargetInstrInfo.h" + +namespace llvm { + + +class PIC16InstrInfo : public TargetInstrInfoImpl +{ + PIC16TargetMachine &TM; + const PIC16RegisterInfo RI; +public: + explicit PIC16InstrInfo(PIC16TargetMachine &TM); + + /// 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 TargetRegisterInfo &getRegisterInfo() const { return RI; } + + + /// isLoadFromStackSlot - If the specified machine instruction is a direct + /// load from a stack slot, return the virtual or physical register number of + /// the destination along with the FrameIndex of the loaded stack slot. If + /// not, return 0. This predicate must return 0 if the instruction has + /// any side effects other than loading from the stack slot. + virtual unsigned isLoadFromStackSlot(MachineInstr *MI, int &FrameIndex) const; + + /// 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. + virtual unsigned isStoreToStackSlot(MachineInstr *MI, int &FrameIndex) const; + + /// Used for spilling a register + void storeRegToStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned SrcReg, bool isKill, int FrameIndex, + const TargetRegisterClass *RC) const; + + + void loadRegFromStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned DestReg, int FrameIndex, + const TargetRegisterClass *RC) const; + + /// InsertBranch - Insert a branch into the end of the specified + /// MachineBasicBlock. This operands to this method are the same as those + /// returned by AnalyzeBranch. This is invoked in cases where AnalyzeBranch + /// returns success and when an unconditional branch (TBB is non-null, FBB is + /// null, Cond is empty) needs to be inserted. It returns the number of + /// instructions inserted. + virtual unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, + MachineBasicBlock *FBB, + const std::vector &Cond) const ; + +}; + +} // namespace llvm + +#endif diff --git a/lib/Target/PIC16/PIC16InstrInfo.td b/lib/Target/PIC16/PIC16InstrInfo.td new file mode 100644 index 00000000000..34c9f06dea6 --- /dev/null +++ b/lib/Target/PIC16/PIC16InstrInfo.td @@ -0,0 +1,302 @@ +//===- PIC16InstrInfo.td - PIC16 Register defs ----------------*- tblgen-*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Instruction format superclass +//===----------------------------------------------------------------------===// + +include "PIC16InstrFormats.td" + +//===----------------------------------------------------------------------===// +// PIC16 profiles and nodes +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// PIC16 addressing mode. +//===----------------------------------------------------------------------===// +// It matches address of globals as well as the stack slots +// that are created for locals and temporaries. This addressing mode +// converts the GlobalAddress and FrameIndex nodes to TargetGlobalAddress +// and TargetFrameIndex nodes. +def diraddrmode : ComplexPattern; +def dirloadmode : ComplexPattern; +def indirloadmode : ComplexPattern; + + +// Address operand. +def mem : Operand { + let PrintMethod = "printAddrModeOperand"; + let MIOperandInfo = (ops i16imm, PTRRegs); +} + +// Instruction operand types +def simm8 : Operand; + + +// These are target-independent nodes, but have target-specific formats. +def SDT_PIC16CallSeq : SDTypeProfile<0, 1, [ SDTCisVT<0, i8> ]>; +def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_PIC16CallSeq, + [SDNPHasChain, SDNPOutFlag]>; +def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_PIC16CallSeq, + [SDNPHasChain, SDNPOutFlag]>; + +def PIC16Wrapper : SDNode<"PIC16ISD::Wrapper", SDTIntUnaryOp>; + +// so_imm_XFORM - Return a so_imm value packed into the format described for +// so_imm def below. +def so_imm_XFORM : SDNodeXFormgetTargetConstant((int8_t)N->getValue(), MVT::i32); +}]>; + +def so_imm : Operand, + PatLeaf<(imm), [{}]> { + let PrintMethod = "printSOImmOperand"; +} + + + +// PIC16 Address Mode! SDNode frameindex could possibily be a match +// since load and store instructions from stack used it. +def addr : Operand; + +// Arithmetic 2 register operands +class ArithI op, string instr_asm, SDNode OpNode, + Operand Od> : + LiteralFormat< op, + (outs CPURegs:$dst), + (ins CPURegs:$b, Od:$c), + !strconcat(instr_asm, " $c"), + [(set CPURegs:$dst, (OpNode CPURegs:$b, Od:$c))]>; + +// Memory Load/Store +class LoadDirect op, string instr_asm, PatFrag OpNode>: + ByteFormat< op, + (outs CPURegs:$dst), + (ins mem:$addr), + !strconcat(instr_asm, " $addr"), + [(set CPURegs:$dst, (OpNode diraddrmode:$addr))]>; + +class LoadInDirect op, string instr_asm, PatFrag OpNode>: + ByteFormat< op, + (outs PTRRegs:$dst), + (ins mem:$addr), + !strconcat(instr_asm, " $addr, $dst"), + [(set PTRRegs:$dst, (OpNode indirloadmode:$addr))]>; + +class StoreDirect op, string instr_asm, PatFrag OpNode>: + ByteFormat< op, + (outs), + (ins CPURegs:$src, mem:$addr), + !strconcat(instr_asm, " $addr"), + [(OpNode CPURegs:$src, diraddrmode:$addr)]>; + +class StoreInDirect op, string instr_asm, PatFrag OpNode>: + ByteFormat< op, + (outs), + (ins CPURegs:$src, PTRRegs:$fsr), + !strconcat(instr_asm, " $fsr"), + [(OpNode CPURegs:$src, PTRRegs:$fsr)]>; + +// Move +class MovLit op, string instr_asm>: + LiteralFormat< op, + (outs CPURegs:$dst), + (ins i8imm:$src), + !strconcat(instr_asm, " $src"), + [(set CPURegs:$dst, imm:$src)]>; + + +// Arithmetic with memory store. +// Arithmetic instrunctions involving W and memory location. +// Since W is implicit, we only print the memory operand. +class Arith1M op, string instr_asm, SDNode OpNode>: + ByteFormat< op, + (outs), + (ins CPURegs:$b, mem:$dst), + !strconcat(instr_asm, " $dst"), + [(store (OpNode (load diraddrmode:$dst), CPURegs:$b), diraddrmode:$dst), + (store (OpNode CPURegs:$b, (load diraddrmode:$dst)), diraddrmode:$dst)]>; + +// Arithmetic with memory load. +// Arithmetic instrunctions involving W and memory location. +// Since W is implicit, we only print the memory operand. +class Arith1R op, string instr_asm, SDNode OpNode>: + ByteFormat< op, + (outs CPURegs:$dst), + (ins mem:$src1, CPURegs:$src2), + !strconcat(instr_asm, " $src1"), + [(set CPURegs:$dst, (OpNode (load diraddrmode:$src1), CPURegs:$src2))]>; + +// Arithmetic with memory load. +// Arithmetic instrunctions involving W and memory location. +// Since W is implicit, we only print the memory operand. +class Arith2R op, string instr_asm, SDNode OpNode>: + ByteFormat< op, + (outs CPURegs:$dst), + (ins mem:$src1, CPURegs:$src2), + !strconcat(instr_asm, " $src1"), + [(set CPURegs:$dst, (OpNode CPURegs:$src2, (load diraddrmode:$src1)))]>; + +//===----------------------------------------------------------------------===// +// Instruction definition +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// PIC16I Instructions +//===----------------------------------------------------------------------===// + +// Arithmetic + +// ADDiu just accept 16-bit immediates but we handle this on Pat's. +// immZExt32 is used here so it can match GlobalAddress immediates. +// def ADDLW : ArithI<0x09, "addlw", add, so_imm>; + +let isReMaterializable = 1 in { +def MOVLW : MovLit<0x24, "movlw">; +} + +// Load/Store +def LFSR1 : LoadInDirect <0x4, "lfsr", load>; + +let isReMaterializable = 1 in { +def MOVF : LoadDirect <0x23, "movf", load>; +} + +def MOVWF : StoreDirect <0x2b, "movwf", store>; + +def MOVFSRINC : StoreInDirect <0x5, "movfsrinc", store>; + +def RETURN : ControlFormat<0x03, (outs), (ins), "return", []>; + +def ADDWF : Arith1M<0x01, "addwf", add>; +def ADDFW : Arith1R<0x02, "addfw", add>; + +def ADDWFE : Arith1M<0x03, "addwfe", adde>; +def ADDFWE : Arith1R<0x04, "addfwe", adde>; + +def ADDWFC : Arith1M<0x05, "addwfc", addc>; +def ADDFWC : Arith1R<0x06, "addfwc", addc>; + +def SUBWF : Arith1M<0x07, "subwf", sub>; +def SUBFW : Arith1R<0x08, "subfw", sub>; + +def SUBWFE : Arith1M<0x09, "subwfe", sube>; +def SUBFWE : Arith1R<0x0a, "subfwe", sube>; + +def SUBWFC : Arith1M<0x0b, "subwfc", subc>; +def SUBFWC : Arith1R<0x0d, "subfwc", subc>; + +def SUBRFW : Arith2R<0x08, "subfw", sub>; + +def SUBRFWE : Arith2R<0x0a, "subfwe", sube>; + +def SUBRFWC : Arith2R<0x0d, "subfwc", subc>; + +def brtarget : Operand; + +class UncondJump< bits<4> op, string instr_asm>: + BitFormat< op, + (outs), + (ins brtarget:$target), + !strconcat(instr_asm, " $target"), + [(br bb:$target)]>; + +def GOTO : UncondJump<0x1, "goto">; + +class LogicM op, string instr_asm, SDNode OpNode> : + ByteFormat< op, + (outs), + (ins CPURegs:$b, mem:$dst), + !strconcat(instr_asm, " $dst"), + [(store (OpNode (load diraddrmode:$dst), CPURegs:$b), diraddrmode:$dst)]>; + +class LogicR op, string instr_asm, SDNode OpNode> : + ByteFormat< op, + (outs CPURegs:$dst), + (ins CPURegs:$b, mem:$c), + !strconcat(instr_asm, " $c"), + [(set CPURegs:$dst, (OpNode (load diraddrmode:$c), CPURegs:$b))]>; + +class LogicI op, string instr_asm, SDNode OpNode, Operand Od> : + LiteralFormat< op, + (outs CPURegs:$dst), + (ins CPURegs:$b, Od:$c), + !strconcat(instr_asm, " $c"), + [(set CPURegs:$dst, (OpNode CPURegs:$b, Od:$c ))]>; + +def XORWF : LogicM<0x1,"xorwf",xor>; +def XORFW : LogicR<0x1,"xorfw",xor>; +def XORLW : LogicI<0x1,"xorlw",xor, so_imm>; + +def ANDWF : LogicM<0x1,"andwf",and>; +def ANDFW : LogicR<0x1,"andfw",and>; +def ANDLW : LogicI<0x1,"andlw",and, so_imm>; + +def IORWF : LogicM<0x1,"iorwf",or>; +def IORFW : LogicR<0x1,"iorfw",or>; +def IORLW : LogicI<0x1,"iorlw",or, so_imm>; + + +/* For comparison before branch */ +def SDT_PIC16Cmp : SDTypeProfile<1, 3, [SDTCisSameAs<0,1>]>; +def SDTIntBinOpPIC16 : SDTypeProfile<1, 2, [SDTCisSameAs<0,1>, + SDTCisSameAs<1,2>, SDTCisInt<1>]>; + +def PIC16Cmp : SDNode<"PIC16ISD::Cmp",SDTIntBinOpPIC16, [SDNPOutFlag]>; +def PIC16XORCC : SDNode<"PIC16ISD::XORCC",SDTIntBinOpPIC16, [SDNPOutFlag]>; +def PIC16SUBCC : SDNode<"PIC16ISD::SUBCC",SDTIntBinOpPIC16, [SDNPOutFlag]>; + +def XORFWCC : LogicR<0x1,"xorfw",PIC16XORCC>; +def XORLWCC : LogicI<0x1,"xorlw",PIC16XORCC, so_imm>; +def SUBFWCC : Arith1R<0x1,"subfw",PIC16SUBCC>; +def SUBLWCC : ArithI<0x1,"sublw",PIC16SUBCC, so_imm>; + + +/* For branch conditions */ +def SDT_PIC16Branch : SDTypeProfile<0, 3, [SDTCisVT<0, OtherVT>, + SDTCisVT<1,i8>, SDTCisVT<2,i8>]>; + +def PIC16Branch : SDNode<"PIC16ISD::Branch",SDT_PIC16Branch, + [SDNPHasChain, SDNPInFlag]>; + +def PIC16BTFSS : SDNode<"PIC16ISD::BTFSS",SDT_PIC16Branch, + [SDNPHasChain, SDNPInFlag]>; + +def PIC16BTFSC : SDNode<"PIC16ISD::BTFSC",SDT_PIC16Branch, + [SDNPHasChain, SDNPInFlag]>; + +class InstrBitTestCC op, string instr_asm,SDNode OpNode>: + BitFormat< op, + (outs), + (ins brtarget:$target ,so_imm:$i, STATUSRegs:$s ), + !strconcat(instr_asm, " $s, $i, $target"), + [(OpNode bb:$target, so_imm:$i, STATUSRegs:$s )]>; + +def BTFSS : InstrBitTestCC<0x1,"btfss",PIC16BTFSS>; +def BTFSC : InstrBitTestCC<0x1,"btfsc",PIC16BTFSC>; + + +//===----------------------------------------------------------------------===// +// Pseudo instructions +//===----------------------------------------------------------------------===// + +let Defs = [STKPTR], Uses = [STKPTR] in { +def ADJCALLSTACKDOWN : Pseudo<255, (outs), (ins i8imm:$amt), + "!ADJCALLSTACKDOWN $amt", + [(callseq_start imm:$amt)]>; +def ADJCALLSTACKUP : Pseudo<254, (outs), (ins i8imm:$amt), + "!ADJCALLSTACKUP $amt", + [(callseq_end imm:$amt)]>; +} + + +//===----------------------------------------------------------------------===// +// Arbitrary patterns that map to one or more instructions +//===----------------------------------------------------------------------===// +def : Pat<(ret), (RETURN)>; diff --git a/lib/Target/PIC16/PIC16RegisterInfo.cpp b/lib/Target/PIC16/PIC16RegisterInfo.cpp new file mode 100644 index 00000000000..2c1b54f35d7 --- /dev/null +++ b/lib/Target/PIC16/PIC16RegisterInfo.cpp @@ -0,0 +1,223 @@ +//===- PIC16RegisterInfo.cpp - PIC16 Register Information -----------------===// +// +// 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 PIC16 implementation of the TargetRegisterInfo class. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "pic16-reg-info" + +#include "PIC16.h" +#include "PIC16RegisterInfo.h" +#include "llvm/Constants.h" +#include "llvm/Function.h" +#include "llvm/Type.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineLocation.h" +#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Target/TargetFrameInfo.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" + +using namespace llvm; + +// TODO: add subtarget support +PIC16RegisterInfo::PIC16RegisterInfo(const TargetInstrInfo &tii) + : PIC16GenRegisterInfo(PIC16::ADJCALLSTACKDOWN, PIC16::ADJCALLSTACKUP), + TII(tii) {} + +/// getRegisterNumbering - Given the enum value for some register, e.g. +/// PIC16::RA, return the number that it corresponds to (e.g. 31). +unsigned PIC16RegisterInfo:: +getRegisterNumbering(unsigned RegEnum) +{ + assert (RegEnum <= 31 && "Unknown register number!"); + return RegEnum; +} + +void PIC16RegisterInfo:: +copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, + unsigned DestReg, unsigned SrcReg, + const TargetRegisterClass *RC) const +{ + return; +} + +void PIC16RegisterInfo::reMaterialize(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + unsigned DestReg, + const MachineInstr *Orig) const +{ + MachineInstr *MI = Orig->clone(); + MI->getOperand(0).setReg(DestReg); + MBB.insert(I, MI); +} + +MachineInstr *PIC16RegisterInfo:: +foldMemoryOperand(MachineInstr* MI, unsigned OpNum, int FI) const +{ + MachineInstr *NewMI = NULL; + + return NewMI; +} + +//===----------------------------------------------------------------------===// +// +// Callee Saved Registers methods +// +//===----------------------------------------------------------------------===// + +/// PIC16 Callee Saved Registers +const unsigned* PIC16RegisterInfo:: +getCalleeSavedRegs(const MachineFunction *MF) const +{ + // PIC16 calle-save register range is $16-$26(s0-s7) + static const unsigned CalleeSavedRegs[] = { 0 }; + return CalleeSavedRegs; +} + +/// PIC16 Callee Saved Register Classes +const TargetRegisterClass* const* +PIC16RegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const +{ + static const TargetRegisterClass * const CalleeSavedRegClasses[] = { 0 }; + return CalleeSavedRegClasses; +} + +BitVector PIC16RegisterInfo:: +getReservedRegs(const MachineFunction &MF) const +{ + BitVector Reserved(getNumRegs()); + return Reserved; +} + +//===----------------------------------------------------------------------===// +// +// Stack Frame Processing methods +// +----------------------------+ +// +// FIXME: Add stack layout description here. +// +// +//===----------------------------------------------------------------------===// + +// 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 PIC16RegisterInfo:: +hasFP(const MachineFunction &MF) const { + return false; +} + +// This function eliminate ADJCALLSTACKDOWN, +// ADJCALLSTACKUP pseudo instructions +void PIC16RegisterInfo:: +eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const { + // Simply discard ADJCALLSTACKDOWN, ADJCALLSTACKUP instructions. + MBB.erase(I); +} + +// FrameIndex represent objects inside a abstract stack. +// We must replace FrameIndex with an stack/frame pointer +// direct reference. +void PIC16RegisterInfo:: +eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, + RegScavenger *RS) const +{ + MachineInstr &MI = *II; + MachineFunction &MF = *MI.getParent()->getParent(); + + unsigned i = 0; + while (!MI.getOperand(i).isFrameIndex()) { + ++i; + assert(i < MI.getNumOperands() && + "Instr doesn't have FrameIndex operand!"); + } + + int FrameIndex = MI.getOperand(i).getIndex(); + int stackSize = MF.getFrameInfo()->getStackSize(); + int spOffset = MF.getFrameInfo()->getObjectOffset(FrameIndex); + + #ifndef NDEBUG + DOUT << "\nFunction : " << MF.getFunction()->getName() << "\n"; + DOUT << "<--------->\n"; + MI.print(DOUT); + DOUT << "FrameIndex : " << FrameIndex << "\n"; + DOUT << "spOffset : " << spOffset << "\n"; + DOUT << "stackSize : " << stackSize << "\n"; + #endif + + // as explained on LowerFORMAL_ARGUMENTS, detect negative offsets + // and adjust SPOffsets considering the final stack size. + int Offset = ((spOffset < 0) ? (stackSize + (-(spOffset+4))) : (spOffset)); + //Offset += MI.getOperand(i+1).getImm(); + + #ifndef NDEBUG + DOUT << "Offset : " << Offset << "\n"; + DOUT << "<--------->\n"; + #endif + + // MI.getOperand(i+1).ChangeToImmediate(Offset); + MI.getOperand(i).ChangeToRegister(getFrameRegister(MF),false); +} + +void PIC16RegisterInfo:: +emitPrologue(MachineFunction &MF) const +{ +} + +void PIC16RegisterInfo:: +emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const +{ +} + +void PIC16RegisterInfo:: +processFunctionBeforeFrameFinalized(MachineFunction &MF) const { +} + +unsigned PIC16RegisterInfo:: +getRARegister() const { + assert(0 && "What is the return address register"); + return 0; +} + +unsigned PIC16RegisterInfo:: +getFrameRegister(MachineFunction &MF) const { + return PIC16::STKPTR; +} + +unsigned PIC16RegisterInfo:: +getEHExceptionRegister() const { + assert(0 && "What is the exception register"); + return 0; +} + +unsigned PIC16RegisterInfo:: +getEHHandlerRegister() const { + assert(0 && "What is the exception handler register"); + return 0; +} + +int PIC16RegisterInfo:: +getDwarfRegNum(unsigned RegNum, bool isEH) const { + assert(0 && "What is the dwarf register number"); + return -1; +} + + +#include "PIC16GenRegisterInfo.inc" + diff --git a/lib/Target/PIC16/PIC16RegisterInfo.h b/lib/Target/PIC16/PIC16RegisterInfo.h new file mode 100644 index 00000000000..246d5eedfa6 --- /dev/null +++ b/lib/Target/PIC16/PIC16RegisterInfo.h @@ -0,0 +1,86 @@ +//===- PIC16RegisterInfo.h - PIC16 Register Information Impl ----*- 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 PIC16 implementation of the TargetRegisterInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef PIC16REGISTERINFO_H +#define PIC16REGISTERINFO_H + +#include "PIC16GenRegisterInfo.h.inc" +#include "llvm/Target/TargetRegisterInfo.h" + +namespace llvm { + +// Forward Declarations. +class TargetInstrInfo; +class Type; + +struct PIC16RegisterInfo : public PIC16GenRegisterInfo { + const TargetInstrInfo &TII; + + explicit PIC16RegisterInfo(const TargetInstrInfo &tii); + + /// getRegisterNumbering - Given the enum value for some register, e.g. + /// PIC16::RA, return the number that it corresponds to (e.g. 31). + static unsigned getRegisterNumbering(unsigned RegEnum); + + void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, + unsigned DestReg, const MachineInstr *Orig) const; + + MachineInstr* foldMemoryOperand(MachineInstr* MI, unsigned OpNum, + int FrameIndex) const; + + MachineInstr* foldMemoryOperand(MachineInstr* MI, unsigned OpNum, + MachineInstr* LoadMI) const { + return 0; + } + + void copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, + unsigned DestReg, unsigned SrcReg, + const TargetRegisterClass *RC) const; + + + const unsigned *getCalleeSavedRegs(const MachineFunction* MF = 0) const; + + const TargetRegisterClass* const* + getCalleeSavedRegClasses(const MachineFunction* MF = 0) const; + + BitVector getReservedRegs(const MachineFunction &MF) const; + + bool hasFP(const MachineFunction &MF) const; + + void eliminateCallFramePseudoInstr(MachineFunction &MF, + MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const; + + /// Stack Frame Processing Methods. + void eliminateFrameIndex(MachineBasicBlock::iterator II, + int SPAdj, RegScavenger *RS = NULL) const; + + void processFunctionBeforeFrameFinalized(MachineFunction &MF) const; + + void emitPrologue(MachineFunction &MF) const; + void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const; + + /// Debug information queries. + unsigned getRARegister() const; + unsigned getFrameRegister(MachineFunction &MF) const; + + /// Exception handling queries. + unsigned getEHExceptionRegister() const; + unsigned getEHHandlerRegister() const; + + int getDwarfRegNum(unsigned RegNum, bool isEH) const; +}; + +} // end namespace llvm + +#endif diff --git a/lib/Target/PIC16/PIC16RegisterInfo.td b/lib/Target/PIC16/PIC16RegisterInfo.td new file mode 100644 index 00000000000..21cc3e58108 --- /dev/null +++ b/lib/Target/PIC16/PIC16RegisterInfo.td @@ -0,0 +1,84 @@ +//===- PIC16RegisterInfo.td - PIC16 Register defs ------------*- tblgen -*-===// +// +// 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 PIC16 register file +//===----------------------------------------------------------------------===// + +// We have banks of 32 registers each. +class PIC16Reg : Register { + field bits<5> Num; + let Namespace = "PIC16"; +} + +// PIC16 CPU Registers +class PIC16GPRReg num, string n> : PIC16Reg { + let Num = num; +} + +// CPU GPR Registers +def FSR0 : PIC16GPRReg< 0, "FSR0">, DwarfRegNum<[0]>; +def FSR1 : PIC16GPRReg< 1, "FSR1">, DwarfRegNum<[1]>; + +// CPU Registers Class +def PTRRegs : RegisterClass<"PIC16", [i16], 8, + [FSR0, FSR1]> +{ + let MethodProtos = [{ + iterator allocation_order_end(const MachineFunction &MF) const; + }]; + let MethodBodies = [{ + PTRRegsClass::iterator + PTRRegsClass::allocation_order_end(const MachineFunction &MF) const { + return end(); + } + }]; +} + +def WREG : PIC16GPRReg< 0, "WREG">, DwarfRegNum<[0]>; + +// CPU Registers Class +def CPURegs : RegisterClass<"PIC16", [i8], 8, + [WREG]> +{ + let MethodProtos = [{ + iterator allocation_order_end(const MachineFunction &MF) const; + }]; + let MethodBodies = [{ + CPURegsClass::iterator + CPURegsClass::allocation_order_end(const MachineFunction &MF) const { + return end(); + } + }]; +} + +def STATUSREG : PIC16GPRReg<2, "STATUS">, DwarfRegNum<[0]>; + +// STATUS Registers Class +def STATUSRegs : RegisterClass<"PIC16", [i8], 8, + [STATUSREG]>; + + +// Dummy stack pointer. +def STKPTR : PIC16GPRReg< 0, "SP">, DwarfRegNum<[0]>; + +// CPU Registers Class +def STKRegs : RegisterClass<"PIC16", [i8], 8, + [STKPTR]> +{ + let MethodProtos = [{ + iterator allocation_order_end(const MachineFunction &MF) const; + }]; + let MethodBodies = [{ + STKRegsClass::iterator + STKRegsClass::allocation_order_end(const MachineFunction &MF) const { + return end(); + } + }]; +} diff --git a/lib/Target/PIC16/PIC16Subtarget.cpp b/lib/Target/PIC16/PIC16Subtarget.cpp new file mode 100644 index 00000000000..77448a79488 --- /dev/null +++ b/lib/Target/PIC16/PIC16Subtarget.cpp @@ -0,0 +1,27 @@ +//===- PIC16Subtarget.cpp - PIC16 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 PIC16 specific subclass of TargetSubtarget. +// +//===----------------------------------------------------------------------===// + +#include "PIC16Subtarget.h" +#include "PIC16.h" +#include "PIC16GenSubtarget.inc" +using namespace llvm; + +PIC16Subtarget::PIC16Subtarget(const TargetMachine &TM, const Module &M, + const std::string &FS) + :IsPIC16Old(false) +{ + std::string CPU = "generic"; + + // Parse features string. + ParseSubtargetFeatures(FS, CPU); +} diff --git a/lib/Target/PIC16/PIC16Subtarget.h b/lib/Target/PIC16/PIC16Subtarget.h new file mode 100644 index 00000000000..e2084968cc5 --- /dev/null +++ b/lib/Target/PIC16/PIC16Subtarget.h @@ -0,0 +1,41 @@ +//=====-- PIC16Subtarget.h - Define Subtarget for the PIC16 ---*- 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 PIC16 specific subclass of TargetSubtarget. +// +//===----------------------------------------------------------------------===// + +#ifndef PIC16SUBTARGET_H +#define PIC16SUBTARGET_H + +#include "llvm/Target/TargetSubtarget.h" +#include "llvm/Target/TargetMachine.h" + +#include + +namespace llvm { +class Module; + +class PIC16Subtarget : public TargetSubtarget { + bool IsPIC16Old; + +public: + /// This constructor initializes the data members to match that + /// of the specified module. + /// + PIC16Subtarget(const TargetMachine &TM, const Module &M, + const std::string &FS); + + /// ParseSubtargetFeatures - Parses features string setting specified + /// subtarget options. Definition of function is auto generated by tblgen. + void ParseSubtargetFeatures(const std::string &FS, const std::string &CPU); +}; +} // End llvm namespace + +#endif diff --git a/lib/Target/PIC16/PIC16TargetAsmInfo.cpp b/lib/Target/PIC16/PIC16TargetAsmInfo.cpp new file mode 100644 index 00000000000..0a56a6e950c --- /dev/null +++ b/lib/Target/PIC16/PIC16TargetAsmInfo.cpp @@ -0,0 +1,26 @@ +//===-- PIC16TargetAsmInfo.cpp - PIC16 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 PIC16TargetAsmInfo properties. +// +//===----------------------------------------------------------------------===// + +#include "PIC16TargetAsmInfo.h" + +using namespace llvm; + +PIC16TargetAsmInfo:: +PIC16TargetAsmInfo(const PIC16TargetMachine &TM) +{ + Data16bitsDirective = "\t.half\t"; + Data32bitsDirective = "\t.word\t"; + CommentString = ";"; + COMMDirective = "\t"; + COMMDirectiveTakesAlignment = 0; +} diff --git a/lib/Target/PIC16/PIC16TargetAsmInfo.h b/lib/Target/PIC16/PIC16TargetAsmInfo.h new file mode 100644 index 00000000000..1401bab82d3 --- /dev/null +++ b/lib/Target/PIC16/PIC16TargetAsmInfo.h @@ -0,0 +1,30 @@ +//=====-- PIC16TargetAsmInfo.h - PIC16 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 PIC16TargetAsmInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef PIC16TARGETASMINFO_H +#define PIC16TARGETASMINFO_H + +#include "llvm/Target/TargetAsmInfo.h" + +namespace llvm { + + // Forward declaration. + class PIC16TargetMachine; + + struct PIC16TargetAsmInfo : public TargetAsmInfo { + PIC16TargetAsmInfo(const PIC16TargetMachine &TM); + }; + +} // namespace llvm + +#endif diff --git a/lib/Target/PIC16/PIC16TargetMachine.cpp b/lib/Target/PIC16/PIC16TargetMachine.cpp new file mode 100644 index 00000000000..2be0afb723a --- /dev/null +++ b/lib/Target/PIC16/PIC16TargetMachine.cpp @@ -0,0 +1,72 @@ +//===-- PIC16TargetMachine.cpp - Define TargetMachine for PIC16 -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Top-level implementation for the PIC16 target. +// +//===----------------------------------------------------------------------===// + +#include "PIC16.h" +#include "PIC16TargetMachine.h" +#include "PIC16TargetAsmInfo.h" +#include "llvm/Module.h" +#include "llvm/PassManager.h" +#include "llvm/Target/TargetMachineRegistry.h" +#include "llvm/Target/TargetAsmInfo.h" + +using namespace llvm; + +namespace { + // Register the targets + RegisterTarget X("pic16", " PIC16 14-bit"); +} + +PIC16TargetMachine:: +PIC16TargetMachine(const Module &M, const std::string &FS) : + Subtarget(*this, M, FS), DataLayout("e-p:16:8:8-i8:8:8-i16:8:8-i32:8:8"), + InstrInfo(*this), TLInfo(*this), + FrameInfo(TargetFrameInfo::StackGrowsUp, 8, 0) { } + + +const TargetAsmInfo *PIC16TargetMachine:: +createTargetAsmInfo() const +{ + return new PIC16TargetAsmInfo(*this); +} + +//===----------------------------------------------------------------------===// +// Pass Pipeline Configuration +//===----------------------------------------------------------------------===// + +bool PIC16TargetMachine:: +addInstSelector(PassManagerBase &PM, bool Fast) +{ + // Install an instruction selector. + PM.add(createPIC16ISelDag(*this)); + return false; +} + +bool PIC16TargetMachine:: +addPrologEpilogInserter(PassManagerBase &PM, bool Fast) +{ + return false; +} + +bool PIC16TargetMachine:: addPreEmitPass(PassManagerBase &PM, bool Fast) +{ + return true; +} + +bool PIC16TargetMachine:: +addAssemblyEmitter(PassManagerBase &PM, bool Fast, std::ostream &Out) +{ + // Output assembly language. + PM.add(createPIC16CodePrinterPass(Out, *this)); + return false; +} + diff --git a/lib/Target/PIC16/PIC16TargetMachine.h b/lib/Target/PIC16/PIC16TargetMachine.h new file mode 100644 index 00000000000..93ef0d1e993 --- /dev/null +++ b/lib/Target/PIC16/PIC16TargetMachine.h @@ -0,0 +1,61 @@ +//===-- PIC16TargetMachine.h - Define TargetMachine for PIC16 ---*- 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 PIC16 specific subclass of TargetMachine. +// +//===----------------------------------------------------------------------===// + + +#ifndef PIC16_TARGETMACHINE_H +#define PIC16_TARGETMACHINE_H + +#include "PIC16InstrInfo.h" +#include "PIC16ISelLowering.h" +#include "PIC16Subtarget.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetFrameInfo.h" +#include "llvm/Target/TargetMachine.h" + +namespace llvm { + +/// PIC16TargetMachine +/// +class PIC16TargetMachine : public LLVMTargetMachine { + PIC16Subtarget Subtarget; + const TargetData DataLayout; // Calculates type size & alignment + PIC16InstrInfo InstrInfo; + PIC16TargetLowering TLInfo; + TargetFrameInfo FrameInfo; + +protected: + virtual const TargetAsmInfo *createTargetAsmInfo() const; + +public: + PIC16TargetMachine(const Module &M, const std::string &FS); + + virtual const TargetFrameInfo *getFrameInfo() const + { return &FrameInfo; } + virtual const PIC16InstrInfo *getInstrInfo() const + { return &InstrInfo; } + virtual const TargetData *getTargetData() const + { return &DataLayout; } + virtual PIC16TargetLowering *getTargetLowering() const + { return const_cast(&TLInfo); } + virtual const TargetRegisterInfo *getRegisterInfo() const + { return &InstrInfo.getRegisterInfo(); } + + virtual bool addInstSelector(PassManagerBase &PM, bool Fast); + virtual bool addPrologEpilogInserter(PassManagerBase &PM, bool Fast); + virtual bool addPreEmitPass(PassManagerBase &PM, bool Fast); + virtual bool addAssemblyEmitter(PassManagerBase &PM, bool Fast, + std::ostream &Out); +}; +} // end namespace llvm + +#endif