diff options
author | Sanjiv Gupta <sanjiv.gupta@microchip.com> | 2008-05-13 09:02:57 +0000 |
---|---|---|
committer | Sanjiv Gupta <sanjiv.gupta@microchip.com> | 2008-05-13 09:02:57 +0000 |
commit | 09bb420cf4975a6a51f7b1d03f029d76d4e9689a (patch) | |
tree | cfd4a927ef4bb5bbfabb6694b6214b3bd890ceb2 /lib/Target/PIC16 | |
parent | 411fc17b569bac71b8d0578174d027663202c203 (diff) | |
download | external_llvm-09bb420cf4975a6a51f7b1d03f029d76d4e9689a.zip external_llvm-09bb420cf4975a6a51f7b1d03f029d76d4e9689a.tar.gz external_llvm-09bb420cf4975a6a51f7b1d03f029d76d4e9689a.tar.bz2 |
Adding files for Microchip's PIC16 target.
A brief description about PIC16:
===============================
PIC16 is an 8-bit microcontroller with only one 8-bit register which is the
accumulator. All arithmetic/load/store operations are 8-bit only.
The architecture has two address spaces: program and data. The program memory
is divided into 2K pages and the data memory is divided into banks of 128 byte, with only 80 usable bytes, resulting in an non-contiguous data memory.
It supports direct data memory access (by specifying the address as part of the instruction) and indirect data and program memory access (in an unorthodox fashion which utilize a 16 bit pointer register).
Two classes of registers exist: (8-bit class which is only one
accumulator) (16-bit class, which contains one or more 16 bit
pointer(s))
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@51027 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/PIC16')
23 files changed, 3323 insertions, 0 deletions
diff --git a/lib/Target/PIC16/Makefile b/lib/Target/PIC16/Makefile new file mode 100644 index 0000000..c429324 --- /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 0000000..5c2a4cc --- /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 <iosfwd> + +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 0000000..0ab4a34 --- /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 0000000..151fafc --- /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 <cctype> + +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<const Value *, unsigned> ValueMapTy; + ValueMapTy NumberForBB; + + /// Keeps the set of GlobalValues that require non-lazy-pointers for + /// indirect access. + std::set<std::string> GVNonLazyPtrs; + + /// Keeps the set of external function GlobalAddresses that the asm + /// printer should generate stubs for. + std::set<std::string> 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 (indexBegin<indexEnd) { + if (indexBegin ==0) + SwitchToDataOvrSection(F->getParent()->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<MachineModuleInfo>()); + 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())<<'+'<<MO.getOffset(); + break; + } + case MachineOperand::MO_ExternalSymbol: + { + O << MO.getSymbolName(); + break; + } + case MachineOperand::MO_ConstantPoolIndex: + { + O << TAI->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 << "<unknown operand type>"; 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<GlobalValue>(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<ConstantArray>(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<GlobalValue>(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 0000000..bcd5f7c --- /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 0000000..6e324f9 --- /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<MachineConstantPoolEntry> 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 0000000..04d4a17 --- /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 0000000..07ebd99 --- /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 <queue> +#include <set> + +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<FrameIndexSDNode>(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<GlobalAddressSDNode>(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<ConstantSDNode>(N.getOperand(1)); + Offset = CurDAG->getTargetConstant((unsigned char)GC->getValue(), MVT::i8); + if ((GA = dyn_cast<GlobalAddressSDNode>(N.getOperand(0)))) { + Base = CurDAG->getTargetGlobalAddress(GA->getGlobal(), MVT::i16, + GC->getValue()); + return true; + } + else if (FrameIndexSDNode *FIN + = dyn_cast<FrameIndexSDNode>(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<LoadSDNode>(N); + if (LD) { + fsr = LD->getBasePtr(); + } + else if (isa<RegisterSDNode>(N.Val)) { + //FIXME an attempt to retrieve the register number + //but does not work + cout << "this is a register\n"; + Reg = dyn_cast<RegisterSDNode>(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<GlobalAddressSDNode>(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<GlobalAddressSDNode>(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 0000000..45aaeda --- /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 <queue> +#include <set> + +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<CondCodeSDNode>(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<GlobalAddressSDNode>(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<FrameIndexSDNode>(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<LoadSDNode>(N); + SDOperand Ptr = LD->getBasePtr(); + if (LD->getExtensionType() == ISD::NON_EXTLOAD) { + if (ISD::isNON_TRUNCStore(Chain.Val)) { + StoreSDNode *PrevST = cast<StoreSDNode>(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<ConstantSDNode>(InOp[0]); + ConstantSDNode *CST1 = dyn_cast<ConstantSDNode>(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<ConstantSDNode>(InOp[0]); + ConstantSDNode *CST1 = dyn_cast<ConstantSDNode>(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<ConstantSDNode>(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<SDOperand, 8> 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<GlobalAddressSDNode>(Dest) && isa<LoadSDNode>(Src) && + (Src.getValueType() != MVT::i8)) { + //create direct addressing a = b + Chain = Src.getOperand(0); + for (i=0; i<NUM_STORES; i++) { + SDOperand ADN = DAG.getNode(ISD::ADD, MVT::i16, Src.getOperand(1), + DAG.getConstant(DstOff, MVT::i16)); + SDOperand LDN = DAG.getLoad(MVT::i8, Chain, ADN, NULL, 0); + SDOperand DSTADDR = DAG.getNode(ISD::ADD, MVT::i16, Dest, + DAG.getConstant(DstOff, MVT::i16)); + Stores[i] = DAG.getStore(Chain, LDN, DSTADDR, NULL, 0); + Chain = Stores[i]; + DstOff += 1; + } + + Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, &Stores[0], i); + return Chain; + } + else if (isa<GlobalAddressSDNode>(Dest) && isa<ConstantSDNode>(Src) + && (Src.getValueType() != MVT::i8)) + { + //create direct addressing a = CONST + CST = dyn_cast<ConstantSDNode>(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<LoadSDNode>(Dest) && isa<ConstantSDNode>(Src) + && (Src.getValueType() != MVT::i8)) { + //create indirect addressing + CST = dyn_cast<ConstantSDNode>(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; i<NUM_STORES; i++) { + SDOperand CNST = DAG.getConstant(CST->getValue() >> 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<LoadSDNode>(Dest) && isa<GlobalAddressSDNode>(Src)) { + // GlobalAddressSDNode *GAD = dyn_cast<GlobalAddressSDNode>(Src); + return SDOperand(); + } + else if (Src.getOpcode() == PIC16ISD::Package) { + StoreSDNode *st = dyn_cast<StoreSDNode>(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<Src.getNumOperands(); i++) { + const SDOperand *retVal = findLoadi8(Src.getOperand(i),DAG); + if (retVal) return retVal; + } + + return NULL; +} diff --git a/lib/Target/PIC16/PIC16ISelLowering.h b/lib/Target/PIC16/PIC16ISelLowering.h new file mode 100644 index 0000000..a94ec4a --- /dev/null +++ b/lib/Target/PIC16/PIC16ISelLowering.h @@ -0,0 +1,92 @@ +//===-- PIC16ISelLowering.h - PIC16 DAG Lowering Interface ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the interfaces that PIC16 uses to lower LLVM code into a +// selection DAG. +// +//===----------------------------------------------------------------------===// + +#ifndef PIC16ISELLOWERING_H +#define PIC16ISELLOWERING_H + +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/Target/TargetLowering.h" +#include "PIC16.h" +#include "PIC16Subtarget.h" + +namespace llvm { + namespace PIC16ISD { + enum NodeType { + // Start the numbering from where ISD NodeType finishes. + FIRST_NUMBER = ISD::BUILTIN_OP_END+PIC16::INSTRUCTION_LIST_END, + + // used for encapsulating the expanded nodes into one node. + Package, + + // Get the Higher 16 bits from a 32-bit immediate + Hi, + + // Get the Lower 16 bits from a 32-bit immediate + Lo, + + Cmp, // PIC16 Generic Comparison instruction. + Branch, // PIC16 Generic Branch Instruction. + BTFSS, // PIC16 BitTest Instruction (Skip if set). + BTFSC, // PIC16 BitTest Instruction (Skip if clear). + + // PIC16 comparison to be converted to either XOR or SUB + // Following instructions cater to those convertions. + XORCC, + SUBCC, + + // Get the Global Address wrapped into a wrapper that also captures + // the bank or page. + Wrapper, + SetBank, + SetPage + }; + } + + //===--------------------------------------------------------------------===// + // TargetLowering Implementation + //===--------------------------------------------------------------------===// + class PIC16TargetLowering : public TargetLowering + { + public: + typedef std::map<SDNode *, SDNode *> 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 0000000..d4b3ee7 --- /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<dag outs, dag ins, string asmstr, list<dag> 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<bits<6> op, dag outs, dag ins, string asmstr, + list<dag> pattern> + :PIC16Inst<outs, ins, asmstr, pattern> +{ + 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<bits<4> op, dag outs, dag ins, string asmstr, list<dag> pattern> + : PIC16Inst<outs, ins, asmstr, pattern> +{ + 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<bits<6> op, dag outs, dag ins, string asmstr, + list<dag> pattern> + : PIC16Inst<outs, ins, asmstr, pattern> +{ + bits<8> k; + + + let Inst{13-8} = op; + + let Inst{7-0} = k; +} + +//===----------------------------------------------------------------------===// +// Control Format instruction class in PIC16 : <|opcode|k|> +//===----------------------------------------------------------------------===// + +class ControlFormat<bits<3> op, dag outs, dag ins, string asmstr, + list<dag> pattern> + :PIC16Inst<outs, ins, asmstr, pattern> +{ + bits<11> k; + + + let Inst{13-11} = op; + + let Inst{10-0} = k; +} + +//===----------------------------------------------------------------------===// +// Pseudo instruction class in PIC16 +//===----------------------------------------------------------------------===// + +class Pseudo<bits<8> op, dag outs, dag ins, string asmstr, list<dag> pattern>: + PIC16Inst<outs, ins, asmstr, pattern> +{ + let Inst{13-6} = op; +} diff --git a/lib/Target/PIC16/PIC16InstrInfo.cpp b/lib/Target/PIC16/PIC16InstrInfo.cpp new file mode 100644 index 0000000..ad38382 --- /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<MachineOperand> &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 0000000..f764668 --- /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<MachineOperand> &Cond) const ; + +}; + +} // namespace llvm + +#endif diff --git a/lib/Target/PIC16/PIC16InstrInfo.td b/lib/Target/PIC16/PIC16InstrInfo.td new file mode 100644 index 0000000..34c9f06 --- /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<i16, 2, "SelectDirectAM", [frameindex], []>; +def dirloadmode : ComplexPattern<i16, 2, "LoadNothing", [frameindex], []>; +def indirloadmode : ComplexPattern<i16, 2, "LoadFSR", [frameindex], []>; + + +// Address operand. +def mem : Operand<i16> { + let PrintMethod = "printAddrModeOperand"; + let MIOperandInfo = (ops i16imm, PTRRegs); +} + +// Instruction operand types +def simm8 : Operand<i8>; + + +// 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 : SDNodeXForm<imm, [{ + return CurDAG->getTargetConstant((int8_t)N->getValue(), MVT::i32); +}]>; + +def so_imm : Operand<i8>, + 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<i16>; + +// Arithmetic 2 register operands +class ArithI<bits<6> 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<bits<6> 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<bits<6> 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<bits<6> 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<bits<6> 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<bits<6> 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<bits<6> 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<bits<6> 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<bits<6> 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<OtherVT>; + +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<bits<6> 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<bits<6> 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<bits<6> 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<bits<4> 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 0000000..2c1b54f --- /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 0000000..246d5ee --- /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 0000000..21cc3e5 --- /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<string n> : Register<n> { + field bits<5> Num; + let Namespace = "PIC16"; +} + +// PIC16 CPU Registers +class PIC16GPRReg<bits<5> num, string n> : PIC16Reg<n> { + 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 0000000..77448a7 --- /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 0000000..e208496 --- /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 <string> + +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 0000000..0a56a6e --- /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 0000000..1401bab --- /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 0000000..2be0afb --- /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<PIC16TargetMachine> 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 0000000..93ef0d1 --- /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<PIC16TargetLowering*>(&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 |