From b1b5ffd827c77f0668d803b8c06b2f9296744f99 Mon Sep 17 00:00:00 2001 From: Sanjiv Gupta Date: Wed, 19 Nov 2008 11:00:54 +0000 Subject: [PATCH] Added a more function PIC16 backend. However to get this working a patch in ExpandIntegerOperand (LegalizeIntegerTypes.cpp) is needed which is yet to be reworked and submitted. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@59617 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/PIC16/PIC16.h | 5 +- lib/Target/PIC16/PIC16.td | 26 +- lib/Target/PIC16/PIC16AsmPrinter.cpp | 776 +++++------ lib/Target/PIC16/PIC16CallingConv.td | 16 - lib/Target/PIC16/PIC16ConstantPoolValue.cpp | 89 -- lib/Target/PIC16/PIC16ConstantPoolValue.h | 77 -- lib/Target/PIC16/PIC16ISelDAGToDAG.cpp | 288 +---- lib/Target/PIC16/PIC16ISelDAGToDAG.h | 60 + lib/Target/PIC16/PIC16ISelLowering.cpp | 1277 +++++++++---------- lib/Target/PIC16/PIC16ISelLowering.h | 119 +- lib/Target/PIC16/PIC16InstrFormats.td | 61 +- lib/Target/PIC16/PIC16InstrInfo.cpp | 173 ++- lib/Target/PIC16/PIC16InstrInfo.h | 55 +- lib/Target/PIC16/PIC16InstrInfo.td | 559 ++++---- lib/Target/PIC16/PIC16RegisterInfo.cpp | 196 +-- lib/Target/PIC16/PIC16RegisterInfo.h | 76 +- lib/Target/PIC16/PIC16RegisterInfo.td | 74 +- lib/Target/PIC16/PIC16Subtarget.cpp | 8 +- lib/Target/PIC16/PIC16Subtarget.h | 13 +- lib/Target/PIC16/PIC16TargetAsmInfo.cpp | 14 +- lib/Target/PIC16/PIC16TargetAsmInfo.h | 11 + lib/Target/PIC16/PIC16TargetMachine.cpp | 49 +- lib/Target/PIC16/PIC16TargetMachine.h | 48 +- 23 files changed, 1671 insertions(+), 2399 deletions(-) delete mode 100644 lib/Target/PIC16/PIC16CallingConv.td delete mode 100644 lib/Target/PIC16/PIC16ConstantPoolValue.cpp delete mode 100644 lib/Target/PIC16/PIC16ConstantPoolValue.h create mode 100644 lib/Target/PIC16/PIC16ISelDAGToDAG.h diff --git a/lib/Target/PIC16/PIC16.h b/lib/Target/PIC16/PIC16.h index 6921bfd71a8..f35acd57315 100644 --- a/lib/Target/PIC16/PIC16.h +++ b/lib/Target/PIC16/PIC16.h @@ -12,14 +12,13 @@ // //===----------------------------------------------------------------------===// -#ifndef TARGET_PIC16_H -#define TARGET_PIC16_H +#ifndef LLVM_TARGET_PIC16_H +#define LLVM_TARGET_PIC16_H #include namespace llvm { class PIC16TargetMachine; - class FunctionPassManager; class FunctionPass; class MachineCodeEmitter; class raw_ostream; diff --git a/lib/Target/PIC16/PIC16.td b/lib/Target/PIC16/PIC16.td index 8355de10670..d37075b1cb1 100644 --- a/lib/Target/PIC16/PIC16.td +++ b/lib/Target/PIC16/PIC16.td @@ -15,30 +15,24 @@ 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">; +//===----------------------------------------------------------------------===// +// Subtarget Features. +//===----------------------------------------------------------------------===// +def FeatureCooper : SubtargetFeature<"cooper", "IsCooper", "true", + "PIC16 Cooper ISA Support">; //===----------------------------------------------------------------------===// -// PIC16 processors supported. +// PIC16 supported processors. //===----------------------------------------------------------------------===// def : Processor<"generic", NoItineraries, []>; +def : Processor<"cooper", NoItineraries, [FeatureCooper]>; + + +def PIC16InstrInfo : InstrInfo {} def PIC16 : Target { let InstructionSet = PIC16InstrInfo; diff --git a/lib/Target/PIC16/PIC16AsmPrinter.cpp b/lib/Target/PIC16/PIC16AsmPrinter.cpp index d765d7522ef..21f1902a9ec 100644 --- a/lib/Target/PIC16/PIC16AsmPrinter.cpp +++ b/lib/Target/PIC16/PIC16AsmPrinter.cpp @@ -12,99 +12,91 @@ // //===----------------------------------------------------------------------===// -#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/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 "PIC16AsmPrinter.h" +#include "PIC16TargetAsmInfo.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetAsmInfo.h" -#include "llvm/Target/TargetData.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetOptions.h" -#include +#include "llvm/Support/Mangler.h" +#include "llvm/Function.h" +#include "llvm/Module.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/DerivedTypes.h" using namespace llvm; -STATISTIC(EmittedInsts, "Number of machine instrs printed"); - -namespace { - struct VISIBILITY_HIDDEN PIC16AsmPrinter : public AsmPrinter { - PIC16AsmPrinter(raw_ostream &O, TargetMachine &TM, const TargetAsmInfo *T) - : AsmPrinter(O, TM, T) { - } - - - /// We name each basic block in a Function with a unique number, so - /// that we can consistently refer to them later. This is cleared - /// at the beginning of each call to runOnMachineFunction(). - /// - typedef std::map ValueMapTy; - ValueMapTy NumberForBB; - - /// Keeps the set of GlobalValues that require non-lazy-pointers for - /// indirect access. - std::set GVNonLazyPtrs; - - /// Keeps the set of external function GlobalAddresses that the asm - /// printer should generate stubs for. - std::set FnStubs; - - /// True if asm printer is printing a series of CONSTPOOL_ENTRY. - bool InCPMode; - - virtual const char *getPassName() const { - return "PIC16 Assembly Printer"; - } - - void printOperand(const MachineInstr *MI, int opNum, - const char *Modifier = 0); - - void printSOImmOperand(const MachineInstr *MI, int opNum); - - void printAddrModeOperand(const MachineInstr *MI, int OpNo); - - void printRegisterList(const MachineInstr *MI, int opNum); - void printCPInstOperand(const MachineInstr *MI, int opNum, - const char *Modifier); - - - bool printInstruction(const MachineInstr *MI); // autogenerated. - void emitFunctionStart(MachineFunction &F); - bool runOnMachineFunction(MachineFunction &F); - bool doInitialization(Module &M); - bool doFinalization(Module &M); - - virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV); - - void getAnalysisUsage(AnalysisUsage &AU) const; - - public: - void SwitchToTextSection(const char *NewSection, - const GlobalValue *GV = NULL); - void SwitchToDataSection(const char *NewSection, - const GlobalValue *GV = NULL); - void SwitchToDataOvrSection(const char *NewSection, - const GlobalValue *GV = NULL); - }; -} // end of anonymous namespace - #include "PIC16GenAsmWriter.inc" +bool PIC16AsmPrinter::printMachineInstruction(const MachineInstr *MI) { + std::string NewBankselLabel; + unsigned Operands = MI->getNumOperands(); + if (Operands > 1) { + // Global address or external symbol should be second operand from last + // if we want to print banksel for it. + const MachineOperand &Op = MI->getOperand(Operands-2); + unsigned OpType = Op.getType(); + if (OpType == MachineOperand::MO_GlobalAddress || + OpType == MachineOperand::MO_ExternalSymbol) { + if (OpType == MachineOperand::MO_GlobalAddress ) + NewBankselLabel = Mang->getValueName(Op.getGlobal()); + else + NewBankselLabel = Op.getSymbolName(); + + // Operand after global address or external symbol should be banksel. + // Value 1 for this operand means we need to generate banksel else do not + // generate banksel. + const MachineOperand &BS = MI->getOperand(Operands-1); + if (((int)BS.getImm() == 1) && + (strcmp (CurrentBankselLabelInBasicBlock.c_str(), + NewBankselLabel.c_str()))) { + CurrentBankselLabelInBasicBlock = NewBankselLabel; + O << "\tbanksel "; + printOperand(MI, Operands-2); + O << "\n"; + } + } + } + printInstruction(MI); + return true; +} + +/// runOnMachineFunction - This uses the printInstruction() +/// method to print assembly for each instruction. +/// +bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF) { + // This calls the base class function required to be called at beginning + // of runOnMachineFunction. + SetupMachineFunction(MF); + + // Get the mangled name. + const Function *F = MF.getFunction(); + CurrentFnName = Mang->getValueName(F); + + // Emit the function variables. + emitFunctionData(MF); + std::string codeSection; + codeSection = "code." + CurrentFnName + ".#"; + O << "\n"; + SwitchToTextSection (codeSection.c_str(),F); + + // 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'; + } + else + O << "_" << CurrentFnName << ":\n"; + CurrentBankselLabelInBasicBlock = ""; + for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); + II != E; ++II) { + // Print the assembly for the instruction. + printMachineInstruction(II); + } + } + return false; // we didn't modify anything. +} + /// 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 @@ -115,413 +107,295 @@ FunctionPass *llvm::createPIC16CodePrinterPass(raw_ostream &o, return new PIC16AsmPrinter(o, tm, tm.getTargetAsmInfo()); } -void PIC16AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const -{ - // FIXME: 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); -} - -/// emitFunctionStart - 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) -{ - SetupMachineFunction(MF); - O << "\n"; - - // What's my mangled name? - CurrentFnName = Mang->getValueName(MF.getFunction()); - - // Emit the function start directives - emitFunctionStart(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; - } - } - - // We didn't modify anything. - return false; -} - -void PIC16AsmPrinter:: -printOperand(const MachineInstr *MI, int opNum, const char *Modifier) -{ +void PIC16AsmPrinter::printOperand(const MachineInstr *MI, int opNum) { 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; + O << TM.getRegisterInfo()->get(MO.getReg()).AsmName; else assert(0 && "not implemented"); - break; + return; - case MachineOperand::MO_Immediate: - if (!Modifier || strcmp(Modifier, "no_hash") != 0) - O << "#"; + case MachineOperand::MO_Immediate: O << (int)MO.getImm(); - break; - - case MachineOperand::MO_MachineBasicBlock: - printBasicBlockLabel(MO.getMBB()); return; - case MachineOperand::MO_GlobalAddress: - O << Mang->getValueName(MO.getGlobal())<<'+'<getValueName(MO.getGlobal()); break; - case MachineOperand::MO_ExternalSymbol: + 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 << ""; abort (); - break; - } // end switch. -} - -static void -printSOImm(raw_ostream &O, int64_t V, const TargetAsmInfo *TAI) -{ - assert(V < (1 << 12) && "Not a valid so_imm value!"); - - O << (unsigned) V; -} - -/// printSOImmOperand - SOImm is 4-bit rotated 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.isImm() && "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.isFI()) { - printOperand(MI, Op+1); - return; - } - - if (!MO1.isReg()) { - // FIXME: This is for CP entries, but isn't right. - printOperand(MI, Op); - return; - } - - // If this is Stack Slot - if (MO1.isReg()) { - if (strcmp(TM.getRegisterInfo()->get(MO1.getReg()).Name, "SP") == 0) { - O << CurrentFnName <<"_"<< MO2.getImm(); - return; - } - O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name; - O << "+"; - O << MO2.getImm(); - O << "]"; - return; - } - - O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name; - O << "]"; -} - - -void PIC16AsmPrinter::printRegisterList(const MachineInstr *MI, int opNum) -{ - O << "{"; - for (unsigned i = opNum, e = MI->getNumOperands(); i != e; ++i) { - printOperand(MI, i); - if (i != e-1) O << ", "; - } - O << "}"; -} - -void PIC16AsmPrinter:: -printCPInstOperand(const MachineInstr *MI, int OpNo, const char *Modifier) -{ - assert(Modifier && "This operand only works with a modifier!"); - - // There are two aspects to a CONSTANTPOOL_ENTRY operand, the label and the - // data itself. - if (!strcmp(Modifier, "label")) { - unsigned ID = MI->getOperand(OpNo).getImm(); - O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() - << '_' << ID << ":\n"; - } else { - assert(!strcmp(Modifier, "cpentry") && "Unknown modifier for CPE"); - unsigned CPI = MI->getOperand(OpNo).getIndex(); - - const MachineConstantPoolEntry &MCPE = // Chasing pointers is fun? - MI->getParent()->getParent()->getConstantPool()->getConstants()[CPI]; - - if (MCPE.isMachineConstantPoolEntry()) - EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal); - else { - EmitGlobalConstant(MCPE.Val.ConstVal); - // remember to emit the weak reference - if (const GlobalValue *GV = dyn_cast(MCPE.Val.ConstVal)) - if (GV->hasExternalWeakLinkage()) - ExtWeakSymbols.insert(GV); - } + assert(0 && " Operand type not supported."); } } - -bool PIC16AsmPrinter::doInitialization(Module &M) -{ +bool PIC16AsmPrinter::doInitialization (Module &M) { bool Result = AsmPrinter::doInitialization(M); + // FIXME:: This is temporary solution to generate the include file. + // The processor should be passed to llc as in input and the header file + // should be generated accordingly. + O << "\t#include P16F1937.INC\n"; + + EmitInitData (M); + EmitUnInitData(M); + EmitRomData(M); return Result; } -bool PIC16AsmPrinter::doFinalization(Module &M) +void PIC16AsmPrinter::EmitInitData (Module &M) { + std::string iDataSection = "idata.#"; + SwitchToDataSection(iDataSection.c_str()); + 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; + + Constant *C = I->getInitializer(); + const PointerType *PtrTy = I->getType(); + int AddrSpace = PtrTy->getAddressSpace(); + + if ((!C->isNullValue()) && (AddrSpace == PIC16ISD::RAM_SPACE)) { + + if (EmitSpecialLLVMGlobal(I)) + continue; + + // Any variables reaching here with "." in its name is a local scope + // variable and should not be printed in global data section. + std::string name = Mang->getValueName(I); + if (name.find(".") != std::string::npos) + continue; + + O << name; + EmitGlobalConstant(C); + } + } +} + +void PIC16AsmPrinter::EmitConstantValueOnly(const Constant* CV) { + if (const ConstantInt *CI = dyn_cast(CV)) { + unsigned BitWidth = CI->getBitWidth(); + int Val = CI->getZExtValue(); + if (BitWidth == 8) { + // Expecting db directive here. In case of romdata we need to pad the + // word with zeros. + if (IsRomData) + O << 0 <<", "; + O << Val; + } + else if (BitWidth == 16) { + unsigned Element1, Element2; + Element1 = 0x00ff & Val; + Element2 = 0x00ff & (Val >> 8); + if (IsRomData) + O << 0 <<", "<> 8); + Element3 = 0x00ff & (Val >> 16); + Element4 = 0x00ff & (Val >> 24); + if (IsRomData) + O << 0 <<", "<< Element1 <<", "<< 0 <<", "<< Element2 <<", "<< 0 + <<", "<< Element3 <<", "<< 0 <<", "<< Element4; + else + O << Element1 <<", "<< Element2 <<", "<< Element3 <<", "<< Element4; + } + return; + } + AsmPrinter::EmitConstantValueOnly(CV); +} + +void PIC16AsmPrinter::EmitRomData (Module &M) +{ + std::string romDataSection = "romdata.#"; + SwitchToRomDataSection(romDataSection.c_str()); + IsRomData = true; + 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; + + Constant *C = I->getInitializer(); + const PointerType *PtrTy = I->getType(); + int AddrSpace = PtrTy->getAddressSpace(); + if ((!C->isNullValue()) && (AddrSpace == PIC16ISD::ROM_SPACE)) { + + if (EmitSpecialLLVMGlobal(I)) + continue; + + // Any variables reaching here with "." in its name is a local scope + // variable and should not be printed in global data section. + std::string name = Mang->getValueName(I); + if (name.find(".") != std::string::npos) + continue; + + O << name; + EmitGlobalConstant(C); + O << "\n"; + } + } + IsRomData = false; +} + + +void PIC16AsmPrinter::EmitUnInitData (Module &M) +{ + std::string uDataSection = "udata.#"; + SwitchToUDataSection(uDataSection.c_str()); 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 + if (!I->hasInitializer()) // External global require no code. continue; - if (EmitSpecialLLVMGlobal(I)) { - continue; + Constant *C = I->getInitializer(); + if (C->isNullValue()) { + + if (EmitSpecialLLVMGlobal(I)) + continue; + + // Any variables reaching here with "." in its name is a local scope + // variable and should not be printed in global data section. + std::string name = Mang->getValueName(I); + if (name.find(".") != std::string::npos) + continue; + + const Type *Ty = C->getType(); + unsigned Size = TD->getABITypeSize(Ty); + O << name << " " <<"RES"<< " " << Size ; + O << "\n"; } + } +} - std::string name = Mang->getValueName(I); +bool PIC16AsmPrinter::doFinalization(Module &M) { + O << "\t" << "END\n"; + bool Result = AsmPrinter::doFinalization(M); + return Result; +} + +void PIC16AsmPrinter::emitFunctionData(MachineFunction &MF) { + const Function *F = MF.getFunction(); + std::string FuncName = Mang->getValueName(F); + const Module *M = F->getParent(); + const TargetData *TD = TM.getTargetData(); + + // Emit the data section name. + O << "\n"; + std::string fDataSection = "fdata." + CurrentFnName + ".#"; + SwitchToUDataSection(fDataSection.c_str(), F); + // Emit the label for data section of current function. + O << "_frame_" << CurrentFnName << ":" ; + O << "\n"; + + // Emit the function variables. + + if (F->hasExternalLinkage()) { + O << "\t" << "GLOBAL _frame_" << CurrentFnName << "\n"; + O << "\t" << "GLOBAL _" << CurrentFnName << "\n"; + } + // In PIC16 all the function arguments and local variables are global. + // Therefore to get the variable belonging to this function entire + // global list will be traversed and variables belonging to this function + // will be emitted in the current data section. + for (Module::const_global_iterator I = M->global_begin(), E = M->global_end(); + I != E; ++I) { + std::string VarName = Mang->getValueName(I); + + // The variables of a function are of form FuncName.* . If this variable + // does not belong to this function then continue. + if (!(VarName.find(FuncName + ".") == 0 ? true : false)) + continue; + Constant *C = I->getInitializer(); const Type *Ty = C->getType(); unsigned Size = TD->getABITypeSize(Ty); - unsigned Align = TD->getPreferredAlignmentLog(I); + // Emit memory reserve directive. + O << VarName << " RES " << Size << "\n"; + } + emitFunctionTempData(MF); +} - const char *VisibilityDirective = NULL; - if (I->hasHiddenVisibility()) - VisibilityDirective = TAI->getHiddenDirective(); - else if (I->hasProtectedVisibility()) - VisibilityDirective = TAI->getProtectedDirective(); +void PIC16AsmPrinter::emitFunctionTempData(MachineFunction &MF) { + // Emit temporary variables. + MachineFrameInfo *FrameInfo = MF.getFrameInfo(); + if (FrameInfo->hasStackObjects()) { + int indexBegin = FrameInfo->getObjectIndexBegin(); + int indexEnd = FrameInfo->getObjectIndexEnd(); - 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() || I->hasCommonLinkage())) { - if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it. - SwitchToDataSection(M.getModuleIdentifier().c_str(), 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; - } + if (indexBegin < indexEnd) + O << CurrentFnName << ".tmp RES"<< " " + <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: - break; - - default: - assert(0 && "Unknown linkage type!"); - break; - } // end switch. - - EmitAlignment(Align, I); - O << name << ":\t\t\t\t" << TAI->getCommentString() << " " << I->getName() - << "\n"; - - // If the initializer is a extern weak symbol, remember to emit the weak - // reference! - if (const GlobalValue *GV = dyn_cast(C)) - if (GV->hasExternalWeakLinkage()) - ExtWeakSymbols.insert(GV); - - EmitGlobalConstant(C); - O << '\n'; - } // end for. - - O << "\n "<< "END"; - return AsmPrinter::doFinalization(M); + */ + } } -void PIC16AsmPrinter:: -SwitchToTextSection(const char *NewSection, const GlobalValue *GV) -{ - O << "\n"; - if (NewSection && *NewSection) { - std::string codeSection = "code_"; - codeSection += NewSection; - codeSection += " "; - codeSection += "CODE"; - AsmPrinter::SwitchToTextSection(codeSection.c_str(), GV); - } - else - AsmPrinter::SwitchToTextSection(NewSection, GV); -} - -void PIC16AsmPrinter:: -SwitchToDataSection(const char *NewSection, const GlobalValue *GV) -{ - // Need to append index for page. - O << "\n"; - if (NewSection && *NewSection) { - std::string dataSection = "udata_"; - dataSection += NewSection; - if (dataSection.substr(dataSection.length() - 2).compare(".o") == 0) { - dataSection = dataSection.substr(0, dataSection.length() - 2); - } - dataSection += " "; - dataSection += "UDATA"; - AsmPrinter::SwitchToDataSection(dataSection.c_str(), GV); - } +/// The function is same as AsmPrinter::SwitchtoDataSection except the call +/// to getUDataSectionStartSuffix. +void PIC16AsmPrinter::SwitchToUDataSection(const char *NewSection, + const GlobalValue *GV) { + std::string NS; + if (GV && GV->hasSection()) + NS = TAI->getSwitchToSectionDirective() + GV->getSection(); else - AsmPrinter::SwitchToDataSection(NewSection, GV); + NS = NewSection; + + // If we're already in this section, we're done. + if (CurrentSection == NS) return; + + // Close the current section, if applicable. + if (TAI->getSectionEndDirectiveSuffix() && !CurrentSection.empty()) + O << CurrentSection << TAI->getSectionEndDirectiveSuffix() << '\n'; + + CurrentSection = NS; + + if (!CurrentSection.empty()){} + O << CurrentSection << (static_cast(TAI))-> + getUDataSectionStartSuffix() << '\n'; + + IsInTextSection = false; } -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); - } +/// The function is same as AsmPrinter::SwitchtoDataSection except the call +/// to getRomDataSectionStartSuffix. +void PIC16AsmPrinter::SwitchToRomDataSection(const char *NewSection, + const GlobalValue *GV) { + std::string NS; + if (GV && GV->hasSection()) + NS = TAI->getSwitchToSectionDirective() + GV->getSection(); else - AsmPrinter::SwitchToDataSection(NewSection, GV); + NS = NewSection; + + // If we're already in this section, we're done. + if (CurrentSection == NS) return; + + // Close the current section, if applicable. + if (TAI->getSectionEndDirectiveSuffix() && !CurrentSection.empty()) + O << CurrentSection << TAI->getSectionEndDirectiveSuffix() << '\n'; + + CurrentSection = NS; + + if (!CurrentSection.empty()) {} + O << CurrentSection << (static_cast< const PIC16TargetAsmInfo *>(TAI))-> + getRomDataSectionStartSuffix() << '\n'; + + IsInTextSection = false; } + diff --git a/lib/Target/PIC16/PIC16CallingConv.td b/lib/Target/PIC16/PIC16CallingConv.td deleted file mode 100644 index fb6c9a33ff3..00000000000 --- a/lib/Target/PIC16/PIC16CallingConv.td +++ /dev/null @@ -1,16 +0,0 @@ -//===- PIC16CallingConv.td - Calling Conventions PIC16 -----*- 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 deleted file mode 100644 index 152c7377ab7..00000000000 --- a/lib/Target/PIC16/PIC16ConstantPoolValue.cpp +++ /dev/null @@ -1,89 +0,0 @@ -//===- 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" -#include "llvm/Support/raw_ostream.h" -using namespace llvm; - -PIC16ConstantPoolValue::PIC16ConstantPoolValue(GlobalValue *gv, unsigned id, - PIC16CP::PIC16CPKind k, - unsigned char PCAdj, - const char *Modif, bool AddCA) - : MachineConstantPoolValue((const Type*)gv->getType()), - GV(gv), S(NULL), LabelId(id), Kind(k), PCAdjust(PCAdj), - Modifier(Modif), AddCurrentAddress(AddCA) {} - -PIC16ConstantPoolValue::PIC16ConstantPoolValue(const char *s, unsigned id, - PIC16CP::PIC16CPKind k, - unsigned char PCAdj, - const char *Modif, bool AddCA) - : MachineConstantPoolValue((const Type*)Type::Int32Ty), - GV(NULL), S(s), LabelId(id), Kind(k), PCAdjust(PCAdj), - Modifier(Modif), AddCurrentAddress(AddCA) {} - -PIC16ConstantPoolValue::PIC16ConstantPoolValue(GlobalValue *gv, - PIC16CP::PIC16CPKind k, - const char *Modif) - : MachineConstantPoolValue((const Type*)Type::Int32Ty), - GV(gv), S(NULL), LabelId(0), Kind(k), PCAdjust(0), - Modifier(Modif) {} - -int PIC16ConstantPoolValue::getExistingMachineCPValue(MachineConstantPool *CP, - unsigned Alignment) { - unsigned AlignMask = (1 << Alignment)-1; - const std::vector Constants = CP->getConstants(); - for (unsigned i = 0, e = Constants.size(); i != e; ++i) { - if (Constants[i].isMachineConstantPoolEntry() && - (Constants[i].Offset & AlignMask) == 0) { - PIC16ConstantPoolValue *CPV = - (PIC16ConstantPoolValue *)Constants[i].Val.MachineCPVal; - if (CPV->GV == GV && - CPV->S == S && - CPV->LabelId == LabelId && - CPV->Kind == Kind && - CPV->PCAdjust == PCAdjust) - return i; - } - } - - return -1; -} - -void -PIC16ConstantPoolValue::AddSelectionDAGCSEId(FoldingSetNodeID &ID) { - ID.AddPointer(GV); - ID.AddPointer(S); - ID.AddInteger(LabelId); - ID.AddInteger((unsigned)Kind); - ID.AddInteger(PCAdjust); -} - -void PIC16ConstantPoolValue::print(raw_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 deleted file mode 100644 index 657fb15171b..00000000000 --- a/lib/Target/PIC16/PIC16ConstantPoolValue.h +++ /dev/null @@ -1,77 +0,0 @@ -//===- 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 { - -class GlobalValue; - -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(raw_ostream &O) const; -}; - -} - -#endif diff --git a/lib/Target/PIC16/PIC16ISelDAGToDAG.cpp b/lib/Target/PIC16/PIC16ISelDAGToDAG.cpp index d98be99f86c..6c2b8ec9747 100644 --- a/lib/Target/PIC16/PIC16ISelDAGToDAG.cpp +++ b/lib/Target/PIC16/PIC16ISelDAGToDAG.cpp @@ -13,263 +13,47 @@ #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/Support/CFG.h" -#include "llvm/Support/Compiler.h" +#include "PIC16ISelDAGToDAG.h" #include "llvm/Support/Debug.h" -#include "llvm/Target/TargetMachine.h" + 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; - -public: - explicit PIC16DAGToDAGISel(PIC16TargetMachine &tm) : - SelectionDAGISel(*tm.getTargetLowering()), - TM(tm) {} - - virtual void InstructionSelect(); - - // 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(SDValue N); - - // Select addressing mode. currently assume base + offset addr mode. - bool SelectAM(SDValue Op, SDValue N, SDValue &Base, SDValue &Offset); - bool SelectDirectAM(SDValue Op, SDValue N, SDValue &Base, - SDValue &Offset); - bool StoreInDirectAM(SDValue Op, SDValue N, SDValue &fsr); - bool LoadFSR(SDValue Op, SDValue N, SDValue &Base, SDValue &Offset); - bool LoadNothing(SDValue Op, SDValue N, SDValue &Base, - SDValue &Offset); - - // getI8Imm - Return a target constant with the specified - // value, of type i8. - inline SDValue getI8Imm(unsigned Imm) { - return CurDAG->getTargetConstant(Imm, MVT::i8); - } - - -#ifndef NDEBUG - unsigned Indent; -#endif -}; - -} - -/// InstructionSelect - This callback is invoked by -/// SelectionDAGISel when it has created a SelectionDAG for us to codegen. -void PIC16DAGToDAGISel::InstructionSelect() -{ - DEBUG(BB->dump()); - // Codegen the basic block. - - DOUT << "===== Instruction selection begins:\n"; -#ifndef NDEBUG - Indent = 0; -#endif - - // Select target instructions for the DAG. - SelectRoot(*CurDAG); - - DOUT << "===== Instruction selection ends:\n"; - - CurDAG->RemoveDeadNodes(); -} - - -bool PIC16DAGToDAGISel:: -SelectDirectAM (SDValue Op, SDValue N, SDValue &Base, SDValue &Offset) -{ - GlobalAddressSDNode *GA; - ConstantSDNode *GC; - - // if Address is FI, get the TargetFrameIndex. - if (FrameIndexSDNode *FIN = dyn_cast(N)) { - DOUT << "--------- its frame Index\n"; - Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); - Offset = CurDAG->getTargetConstant(0, MVT::i32); - return true; - } - - if (N.getOpcode() == ISD::GlobalAddress) { - GA = dyn_cast(N); - Offset = CurDAG->getTargetConstant((unsigned char)GA->getOffset(), MVT::i8); - Base = CurDAG->getTargetGlobalAddress(GA->getGlobal(), MVT::i16, - GA->getOffset()); - return true; - } - - if (N.getOpcode() == ISD::ADD) { - GC = dyn_cast(N.getOperand(1)); - Offset = CurDAG->getTargetConstant((unsigned char)GC->getZExtValue(), - MVT::i8); - if ((GA = dyn_cast(N.getOperand(0)))) { - Base = CurDAG->getTargetGlobalAddress(GA->getGlobal(), MVT::i16, - GC->getZExtValue()); - return true; - } - else if (FrameIndexSDNode *FIN - = dyn_cast(N.getOperand(0))) { - Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); - return true; - } - } - - return false; -} - - -// FIXME: must also account for preinc/predec/postinc/postdec. -bool PIC16DAGToDAGISel:: -StoreInDirectAM (SDValue Op, SDValue N, SDValue &fsr) -{ - RegisterSDNode *Reg; - if (N.getOpcode() == ISD::LOAD) { - LoadSDNode *LD = dyn_cast(N); - if (LD) { - fsr = LD->getBasePtr(); - } - else if (isa(N.getNode())) { - //FIXME an attempt to retrieve the register number - //but does not work - DOUT << "this is a register\n"; - Reg = dyn_cast(N.getNode()); - fsr = CurDAG->getRegister(Reg->getReg(),MVT::i16); - } - else { - DOUT << "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 (SDValue Op, SDValue N, SDValue &Base, SDValue &Offset) -{ - GlobalAddressSDNode *GA; - - if (N.getOpcode() == ISD::GlobalAddress) { - GA = dyn_cast(N); - Offset = CurDAG->getTargetConstant((unsigned char)GA->getOffset(), MVT::i8); - Base = CurDAG->getTargetGlobalAddress(GA->getGlobal(), MVT::i16, - GA->getOffset()); - return true; - } - else if (N.getOpcode() == PIC16ISD::Package) { - CurDAG->setGraphColor(Op.getNode(), "blue"); - CurDAG->viewGraph(); - } - - return false; -} - -// LoadNothing - Don't thake this seriously, it will change. -bool PIC16DAGToDAGISel:: -LoadNothing (SDValue Op, SDValue N, SDValue &Base, SDValue &Offset) -{ - GlobalAddressSDNode *GA; - if (N.getOpcode() == ISD::GlobalAddress) { - GA = dyn_cast(N); - DOUT << "==========" << 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 - Select instructions not customized! Used for -/// expanded, promoted and normal instructions. -SDNode* PIC16DAGToDAGISel::Select(SDValue N) -{ - SDNode *Node = N.getNode(); - 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 (Node->isMachineOpcode()) { -#ifndef NDEBUG - DOUT << std::string(Indent-2, ' ') << "== "; - DEBUG(Node->dump(CurDAG)); - DOUT << "\n"; - Indent -= 2; -#endif - return NULL; - } - - /// - // FIXME: 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.getNode()) - DEBUG(N.getNode()->dump(CurDAG)); - else - DEBUG(ResNode->dump(CurDAG)); - DOUT << "\n"; - Indent -= 2; -#endif - - return ResNode; -} - -/// createPIC16ISelDag - This pass converts a legalized DAG into a +/// 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); } + +/// InstructionSelect - This callback is invoked by +/// SelectionDAGISel when it has created a SelectionDAG for us to codegen. +void PIC16DAGToDAGISel::InstructionSelect() { + DEBUG(BB->dump()); + SelectRoot(*CurDAG); + CurDAG->RemoveDeadNodes(); +} + +/// Select - Select instructions not customized! Used for +/// expanded, promoted and normal instructions. +SDNode* PIC16DAGToDAGISel::Select(SDValue N) { + + // Select the default instruction. + SDNode *ResNode = SelectCode(N); + + return ResNode; +} + + +// SelectDirectAddr - Match a direct address for DAG. +// A direct address could be a globaladdress or externalsymbol. +bool PIC16DAGToDAGISel::SelectDirectAddr(SDValue Op, SDValue N, + SDValue &Address) { + // Return true if TGA or ES. + if (N.getOpcode() == ISD::TargetGlobalAddress + || N.getOpcode() == ISD::TargetExternalSymbol) { + Address = N; + return true; + } + + return false; +} diff --git a/lib/Target/PIC16/PIC16ISelDAGToDAG.h b/lib/Target/PIC16/PIC16ISelDAGToDAG.h new file mode 100644 index 00000000000..177313372bd --- /dev/null +++ b/lib/Target/PIC16/PIC16ISelDAGToDAG.h @@ -0,0 +1,60 @@ +//===-- 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 "PIC16TargetMachine.h" +#include "llvm/CodeGen/SelectionDAGISel.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Intrinsics.h" +using namespace llvm; + +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; + +public: + explicit PIC16DAGToDAGISel(PIC16TargetMachine &tm) : + SelectionDAGISel(PIC16Lowering), + TM(tm), PIC16Lowering(*TM.getTargetLowering()) {} + + // Pass Name + virtual const char *getPassName() const { + return "PIC16 DAG->DAG Pattern Instruction Selection"; + } + + virtual void InstructionSelect(); + +private: + // Include the pieces autogenerated from the target description. +#include "PIC16GenDAGISel.inc" + + SDNode *Select(SDValue N); + + // Match direct address complex pattern. + bool SelectDirectAddr(SDValue Op, SDValue N, SDValue &Address); + +}; + +} + diff --git a/lib/Target/PIC16/PIC16ISelLowering.cpp b/lib/Target/PIC16/PIC16ISelLowering.cpp index ed3c6457624..feb21ef54df 100644 --- a/lib/Target/PIC16/PIC16ISelLowering.cpp +++ b/lib/Target/PIC16/PIC16ISelLowering.cpp @@ -17,751 +17,662 @@ #include "PIC16ISelLowering.h" #include "PIC16TargetMachine.h" #include "llvm/DerivedTypes.h" +#include "llvm/GlobalValue.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" + + 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) -{ - // Set up the register classes. - addRegisterClass(MVT::i8, PIC16::CPURegsRegisterClass); - addRegisterClass(MVT::i16, PIC16::PTRRegsRegisterClass); - - // Load extented operations for i1 types must be promoted . - setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote); - setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote); - setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote); - - 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); +// PIC16TargetLowering Constructor. +PIC16TargetLowering::PIC16TargetLowering(PIC16TargetMachine &TM) + : TargetLowering(TM) { - // FIXME: Do we really need to Custom lower the GA ?? - setOperationAction(ISD::GlobalAddress, MVT::i8, Custom); - setOperationAction(ISD::RET, MVT::Other, Custom); + Subtarget = &TM.getSubtarget(); - 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); + addRegisterClass(MVT::i8, PIC16::GPRRegisterClass); - setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand); - setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand); - setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand); + setShiftAmountType(MVT::i8); + setShiftAmountFlavor(Extend); - // We don't have line number support yet. - setOperationAction(ISD::DBG_STOPPOINT, MVT::Other, Expand); - setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand); - setOperationAction(ISD::DBG_LABEL, MVT::Other, Expand); - setOperationAction(ISD::EH_LABEL, MVT::Other, Expand); - // Use the default for now. - setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); - setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand); + setOperationAction(ISD::GlobalAddress, MVT::i16, Custom); - setOperationAction(ISD::LOAD, MVT::i1, Promote); - setOperationAction(ISD::LOAD, MVT::i8, Legal); + setOperationAction(ISD::LOAD, MVT::i8, Legal); + setOperationAction(ISD::LOAD, MVT::i16, Custom); + setOperationAction(ISD::LOAD, MVT::i32, Custom); - setTargetDAGCombine(ISD::LOAD); - setTargetDAGCombine(ISD::STORE); - setTargetDAGCombine(ISD::ADDE); - setTargetDAGCombine(ISD::ADDC); - setTargetDAGCombine(ISD::ADD); - setTargetDAGCombine(ISD::SUBE); - setTargetDAGCombine(ISD::SUBC); - setTargetDAGCombine(ISD::SUB); + setOperationAction(ISD::STORE, MVT::i8, Legal); + setOperationAction(ISD::STORE, MVT::i16, Custom); + setOperationAction(ISD::STORE, MVT::i32, Custom); - setStackPointerRegisterToSaveRestore(PIC16::STKPTR); + setOperationAction(ISD::ADDE, MVT::i8, Custom); + setOperationAction(ISD::ADDC, MVT::i8, Custom); + setOperationAction(ISD::SUBE, MVT::i8, Custom); + setOperationAction(ISD::SUBC, MVT::i8, Custom); + setOperationAction(ISD::ADD, MVT::i8, Legal); + setOperationAction(ISD::ADD, MVT::i16, Custom); + + setOperationAction(ISD::SHL, MVT::i16, Custom); + setOperationAction(ISD::SHL, MVT::i32, Custom); + + //setOperationAction(ISD::TRUNCATE, MVT::i16, Custom); + setTruncStoreAction(MVT::i16, MVT::i8, Custom); + + // Now deduce the information based on the above mentioned + // actions computeRegisterProperties(); } - -SDValue PIC16TargetLowering:: LowerOperation(SDValue Op, SelectionDAG &DAG) -{ - SDVTList VTList16 = DAG.getVTList(MVT::i16, MVT::i16, MVT::Other); - switch (Op.getOpcode()) { - case ISD::STORE: - DOUT << "reduce store\n"; - break; - - case ISD::FORMAL_ARGUMENTS: - DOUT << "==== lowering formal args\n"; - return LowerFORMAL_ARGUMENTS(Op, DAG); - - case ISD::GlobalAddress: - DOUT << "==== lowering GA\n"; - return LowerGlobalAddress(Op, DAG); - - case ISD::RET: - DOUT << "==== lowering ret\n"; - return LowerRET(Op, DAG); - - case ISD::FrameIndex: - DOUT << "==== lowering frame index\n"; - return LowerFrameIndex(Op, DAG); - - case ISD::ADDE: - DOUT << "==== lowering adde\n"; - break; - - case ISD::LOAD: - case ISD::ADD: - break; - - case ISD::BR_CC: - DOUT << "==== lowering BR_CC\n"; - return LowerBR_CC(Op, DAG); - } // end switch. - return SDValue(); -} - - -//===----------------------------------------------------------------------===// -// Lower helper functions -//===----------------------------------------------------------------------===// - -SDValue PIC16TargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) -{ - MVT VT = Op.getValueType(); - SDValue Chain = Op.getOperand(0); - ISD::CondCode CC = cast(Op.getOperand(1))->get(); - SDValue LHS = Op.getOperand(2); - SDValue RHS = Op.getOperand(3); - SDValue JumpVal = Op.getOperand(4); - SDValue Result; - unsigned cmpOpcode; - unsigned branchOpcode; - SDValue branchOperand; - - SDValue StatusReg = DAG.getRegister(PIC16::STATUSREG, MVT::i8); - SDValue CPUReg = DAG.getRegister(PIC16::WREG, MVT::i8); - switch(CC) { - default: - assert(0 && "This condition code is not handled yet!!"); - abort(); - - case ISD::SETNE: - DOUT << "setne\n"; - cmpOpcode = PIC16ISD::XORCC; - branchOpcode = PIC16ISD::BTFSS; - branchOperand = DAG.getConstant(2, MVT::i8); - break; - - case ISD::SETEQ: - DOUT << "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(); - break; - - case ISD::SETGE: - DOUT << "setge\n"; - cmpOpcode = PIC16ISD::SUBCC; - branchOpcode = PIC16ISD::BTFSS; - branchOperand = DAG.getConstant(1, MVT::i8); - break; - - case ISD::SETLT: - DOUT << "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(); - break; - } // End of Switch - - SDVTList VTList = DAG.getVTList(MVT::i8, MVT::Flag); - SDValue CmpValue = DAG.getNode(cmpOpcode, VTList, LHS, RHS).getValue(1); - Result = DAG.getNode(branchOpcode, VT, Chain, JumpVal, branchOperand, - StatusReg, CmpValue); - return Result; -} - - -//===----------------------------------------------------------------------===// -// Misc Lower Operation implementation -//===----------------------------------------------------------------------===// - -// LowerGlobalAddress - Create a constant pool entry for global value -// and wrap it in a wrapper node. -SDValue -PIC16TargetLowering::LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) -{ - MVT PtrVT = getPointerTy(); - GlobalAddressSDNode *GSDN = cast(Op); - GlobalValue *GV = GSDN->getGlobal(); - - // FIXME: for now only do the ram. - SDValue CPAddr = DAG.getTargetConstantPool(GV, PtrVT, 2); - SDValue CPBank = DAG.getNode(PIC16ISD::SetBank, MVT::i8, CPAddr); - CPAddr = DAG.getNode(PIC16ISD::Wrapper, MVT::i8, CPAddr,CPBank); - - return CPAddr; -} - -SDValue -PIC16TargetLowering::LowerRET(SDValue Op, SelectionDAG &DAG) -{ - switch(Op.getNumOperands()) { - default: - assert(0 && "Do not know how to return this many arguments!"); - abort(); - - case 1: - return SDValue(); // ret void is legal +const char *PIC16TargetLowering::getTargetNodeName(unsigned Opcode) const { + switch (Opcode) { + default: return NULL; + case PIC16ISD::Lo: return "PIC16ISD::Lo"; + case PIC16ISD::Hi: return "PIC16ISD::Hi"; + case PIC16ISD::MTLO: return "PIC16ISD::MTLO"; + case PIC16ISD::MTHI: return "PIC16ISD::MTHI"; + case PIC16ISD::Banksel: return "PIC16ISD::Banksel"; + case PIC16ISD::PIC16Load: return "PIC16ISD::PIC16Load"; + case PIC16ISD::PIC16Store: return "PIC16ISD::PIC16Store"; + case PIC16ISD::BCF: return "PIC16ISD::BCF"; + case PIC16ISD::LSLF: return "PIC16ISD::LSLF"; + case PIC16ISD::LRLF: return "PIC16ISD::LRLF"; + case PIC16ISD::RLF: return "PIC16ISD::RLF"; + case PIC16ISD::RRF: return "PIC16ISD::RRF"; + case PIC16ISD::Dummy: return "PIC16ISD::Dummy"; } } -SDValue -PIC16TargetLowering::LowerFrameIndex(SDValue N, SelectionDAG &DAG) -{ - if (FrameIndexSDNode *FIN = dyn_cast(N)) { - return DAG.getTargetFrameIndex(FIN->getIndex(), MVT::i32); - } - - return N; -} - -SDValue -PIC16TargetLowering::LowerLOAD(SDNode *N, - SelectionDAG &DAG, - DAGCombinerInfo &DCI) const -{ - SDValue Outs[2]; - SDValue TF; //TokenFactor - SDValue OutChains[2]; - SDValue Chain = N->getOperand(0); - SDValue Src = N->getOperand(1); - SDValue retVal; - SDVTList VTList; - - // If this load is directly stored, replace the load value with the stored - // value. - // FIXME: Handle store large -> read small portion. - // FIXME: Handle TRUNCSTORE/LOADEXT - LoadSDNode *LD = cast(N); - SDValue Ptr = LD->getBasePtr(); - if (LD->getExtensionType() == ISD::NON_EXTLOAD) { - if (ISD::isNON_TRUNCStore(Chain.getNode())) { - StoreSDNode *PrevST = cast(Chain); - if (PrevST->getBasePtr() == Ptr && - PrevST->getValue().getValueType() == N->getValueType(0)) - return DCI.CombineTo(N, Chain.getOperand(1), Chain); - } - } - - if (N->getValueType(0) != MVT::i16) - return SDValue(); - - SDValue 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); - // FIXME: Add to worklist may not be needed. - // It is meant to merge sequences of add with constant into one. - DCI.AddToWorklist(toWorklist.getNode()); - - // 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; -} - -SDValue -PIC16TargetLowering::LowerADDSUB(SDNode *N, SelectionDAG &DAG, - DAGCombinerInfo &DCI) const -{ - bool changed = false; - int i; - SDValue LoOps[3], HiOps[3]; - SDValue OutOps[3]; // [0]:left, [1]:right, [2]:carry - SDValue InOp[2]; - SDValue retVal; - SDValue as1,as2; - SDVTList VTList; - unsigned AS = 0, ASE = 0, ASC=0; - - InOp[0] = N->getOperand(0); - InOp[1] = N->getOperand(1); - +SDNode *PIC16TargetLowering::ReplaceNodeResults(SDNode *N, SelectionDAG &DAG) { switch (N->getOpcode()) { + case ISD::GlobalAddress: + return ExpandGlobalAddress(N, DAG); + case ISD::STORE: + return ExpandStore(N, DAG); + case ISD::LOAD: + return ExpandLoad(N, DAG); case ISD::ADD: - if (InOp[0].getOpcode() == ISD::Constant && - InOp[1].getOpcode() == ISD::Constant) { - ConstantSDNode *CST0 = dyn_cast(InOp[0]); - ConstantSDNode *CST1 = dyn_cast(InOp[1]); - return DAG.getConstant(CST0->getZExtValue() + CST1->getZExtValue(), - MVT::i16); - } - break; + return ExpandAdd(N, DAG); + case ISD::SHL: + return ExpandShift(N, DAG); + default: + assert (0 && "not implemented"); + } +} - case ISD::ADDE: - case ISD::ADDC: - AS = ISD::ADD; - ASE = ISD::ADDE; - ASC = ISD::ADDC; - break; +SDNode *PIC16TargetLowering::ExpandStore(SDNode *N, SelectionDAG &DAG) { + StoreSDNode *St = cast(N); + SDValue Chain = St->getChain(); + SDValue Src = St->getValue(); + SDValue Ptr = St->getBasePtr(); + MVT ValueType = Src.getValueType(); + unsigned StoreOffset = 0; - case ISD::SUB: - if (InOp[0].getOpcode() == ISD::Constant && - InOp[1].getOpcode() == ISD::Constant) { - ConstantSDNode *CST0 = dyn_cast(InOp[0]); - ConstantSDNode *CST1 = dyn_cast(InOp[1]); - return DAG.getConstant(CST0->getZExtValue() - CST1->getZExtValue(), - MVT::i16); - } - break; - - case ISD::SUBE: - case ISD::SUBC: - AS = ISD::SUB; - ASE = ISD::SUBE; - ASC = ISD::SUBC; - break; - } // end switch. - - 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 yet. - return SDValue(); + SDValue PtrLo, PtrHi; + LegalizeAddress(Ptr, DAG, PtrLo, PtrHi, StoreOffset); + + if (ValueType == MVT::i8) { + SDValue Store = DAG.getNode (PIC16ISD::PIC16Store, MVT::Other, Chain, Src, + PtrLo, PtrHi, DAG.getConstant (0, MVT::i8)); + return Store.getNode(); + } + else if (ValueType == MVT::i16) { + // Get the Lo and Hi parts from MERGE_VALUE or BUILD_PAIR. + SDValue SrcLo, SrcHi; + GetExpandedParts(Src, DAG, SrcLo, SrcHi); + SDValue ChainLo = Chain, ChainHi = Chain; + if (Chain.getOpcode() == ISD::TokenFactor) { + ChainLo = Chain.getOperand(0); + ChainHi = Chain.getOperand(1); } - else if (InOp[i].getOpcode() == ISD::Constant) { - changed = true; - ConstantSDNode *CST = dyn_cast(InOp[i]); - LoOps[i] = DAG.getConstant(CST->getZExtValue() & 0xFF, MVT::i8); - HiOps[i] = DAG.getConstant(CST->getZExtValue() >> 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. - SDValue lowered = LowerLOAD(InOp[i].getNode(), DAG, DCI); + SDValue Store1 = DAG.getNode(PIC16ISD::PIC16Store, MVT::Other, + ChainLo, + SrcLo, PtrLo, PtrHi, + DAG.getConstant (0 + StoreOffset, MVT::i8)); - // 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. - SDValue lowered = LowerADDSUB(InOp[i].getNode(), DAG, DCI); + SDValue Store2 = DAG.getNode(PIC16ISD::PIC16Store, MVT::Other, ChainHi, + SrcHi, PtrLo, PtrHi, + DAG.getConstant (1 + StoreOffset, MVT::i8)); - 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. + return DAG.getNode(ISD::TokenFactor, MVT::Other, getChain(Store1), + getChain(Store2)).getNode(); + } + else if (ValueType == MVT::i32) { + // Get the Lo and Hi parts from MERGE_VALUE or BUILD_PAIR. + SDValue SrcLo, SrcHi; + GetExpandedParts(Src, DAG, SrcLo, SrcHi); - assert (changed && "nothing changed while lowering SUBx/ADDx"); + // Get the expanded parts of each of SrcLo and SrcHi. + SDValue SrcLo1, SrcLo2, SrcHi1, SrcHi2; + GetExpandedParts(SrcLo, DAG, SrcLo1, SrcLo2); + GetExpandedParts(SrcHi, DAG, SrcHi1, SrcHi2); + + SDValue ChainLo = Chain, ChainHi = Chain; + if (Chain.getOpcode() == ISD::TokenFactor) { + ChainLo = Chain.getOperand(0); + ChainHi = Chain.getOperand(1); + } + SDValue ChainLo1 = ChainLo, ChainLo2 = ChainLo, ChainHi1 = ChainHi, + ChainHi2 = ChainHi; + if (ChainLo.getOpcode() == ISD::TokenFactor) { + ChainLo1 = ChainLo.getOperand(0); + ChainLo2 = ChainLo.getOperand(1); + } + if (ChainHi.getOpcode() == ISD::TokenFactor) { + ChainHi1 = ChainHi.getOperand(0); + ChainHi2 = ChainHi.getOperand(1); + } + SDValue Store1 = DAG.getNode(PIC16ISD::PIC16Store, MVT::Other, + ChainLo1, + SrcLo1, PtrLo, PtrHi, + DAG.getConstant (0 + StoreOffset, MVT::i8)); + + SDValue Store2 = DAG.getNode(PIC16ISD::PIC16Store, MVT::Other, ChainLo2, + SrcLo2, PtrLo, PtrHi, + DAG.getConstant (1 + StoreOffset, MVT::i8)); + + SDValue Store3 = DAG.getNode(PIC16ISD::PIC16Store, MVT::Other, ChainHi1, + SrcHi1, PtrLo, PtrHi, + DAG.getConstant (2 + StoreOffset, MVT::i8)); + + SDValue Store4 = DAG.getNode(PIC16ISD::PIC16Store, MVT::Other, ChainHi2, + SrcHi2, PtrLo, PtrHi, + DAG.getConstant (3 + StoreOffset, MVT::i8)); + + SDValue RetLo = DAG.getNode(ISD::TokenFactor, MVT::Other, getChain(Store1), + getChain(Store2)); + SDValue RetHi = DAG.getNode(ISD::TokenFactor, MVT::Other, getChain(Store3), + getChain(Store4)); + return DAG.getNode(ISD::TokenFactor, MVT::Other, RetLo, RetHi).getNode(); - 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); + assert (0 && "value type not supported"); } - 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; } +// ExpandGlobalAddress - +SDNode *PIC16TargetLowering::ExpandGlobalAddress(SDNode *N, SelectionDAG &DAG) { + GlobalAddressSDNode *G = dyn_cast(SDValue(N, 0)); + + SDValue TGA = DAG.getTargetGlobalAddress(G->getGlobal(), MVT::i8, + G->getOffset()); -//===----------------------------------------------------------------------===// -// Calling Convention Implementation -//===----------------------------------------------------------------------===// + SDValue Lo = DAG.getNode(PIC16ISD::Lo, MVT::i8, TGA); + SDValue Hi = DAG.getNode(PIC16ISD::Hi, MVT::i8, TGA); -#include "PIC16GenCallingConv.inc" - -//===----------------------------------------------------------------------===// -// CALL Calling Convention Implementation -//===----------------------------------------------------------------------===// - - -//===----------------------------------------------------------------------===// -// FORMAL_ARGUMENTS Calling Convention Implementation -//===----------------------------------------------------------------------===// -SDValue PIC16TargetLowering:: -LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG) -{ - SmallVector ArgValues; - SDValue Root = Op.getOperand(0); - - // Return the new list of results. - // FIXME: Just copy right now. - ArgValues.push_back(Root); - - return DAG.getMergeValues(Op.getNode()->getVTList(), &ArgValues[0], - ArgValues.size()).getValue(Op.getResNo()); + SDValue BP = DAG.getNode(ISD::BUILD_PAIR, MVT::i16, Lo, Hi); + return BP.getNode(); } +bool PIC16TargetLowering::isDirectAddress(const SDValue &Op) { + assert (Op.getNode() != NULL && "Can't operate on NULL SDNode!!"); -//===----------------------------------------------------------------------===// -// Return Value Calling Convention Implementation -//===----------------------------------------------------------------------===// + if (Op.getOpcode() == ISD::BUILD_PAIR) { + if (Op.getOperand(0).getOpcode() == PIC16ISD::Lo) + return true; + } + return false; +} -//===----------------------------------------------------------------------===// -// PIC16 Inline Assembly Support -//===----------------------------------------------------------------------===// +// Return true if DirectAddress is in ROM_SPACE +bool PIC16TargetLowering::isRomAddress(const SDValue &Op) { -//===----------------------------------------------------------------------===// -// Target Optimization Hooks -//===----------------------------------------------------------------------===// + // RomAddress is a GlobalAddress in ROM_SPACE_ + // If the Op is not a GlobalAddress return NULL without checking + // anything further. + if (!isDirectAddress(Op)) + return false; -SDValue PIC16TargetLowering::PerformDAGCombine(SDNode *N, - DAGCombinerInfo &DCI) const -{ - int i; - ConstantSDNode *CST; - SelectionDAG &DAG = DCI.DAG; + // Its a GlobalAddress. + // It is BUILD_PAIR((PIC16Lo TGA), (PIC16Hi TGA)) and Op is BUILD_PAIR + SDValue TGA = Op.getOperand(0).getOperand(0); + GlobalAddressSDNode *GSDN = dyn_cast(TGA); + const Type *ValueType = GSDN->getGlobal()->getType(); - switch (N->getOpcode()) { - default: - break; + if (!isa(ValueType)) { + assert(0 && "TGA must be of a PointerType"); + } - case PIC16ISD::Package: - DOUT << "==== combining PIC16ISD::Package\n"; - return SDValue(); + int AddrSpace = dyn_cast(ValueType)->getAddressSpace(); + if (AddrSpace == PIC16ISD::ROM_SPACE) + return true; - 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 SDValue (); - } - break; + // Any other address space return it false + return false; +} - case ISD::ADDE : - case ISD::ADDC : - case ISD::SUBE : - case ISD::SUBC : - if (N->getValueType(0) == MVT::i16) { - SDValue 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 SDValue(); - } - 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; +// To extract chain value from the SDValue Nodes +// This function will help to maintain the chain extracting +// code at one place. In case of any change in future it will +// help maintain the code. +SDValue PIC16TargetLowering::getChain(SDValue &Op) { + SDValue Chain = Op.getValue(Op.getNode()->getNumValues() - 1); - // FIXME: split this large chunk of code. - case ISD::STORE : - { - SDValue Chain = N->getOperand(0); - SDValue Src = N->getOperand(1); - SDValue Dest = N->getOperand(2); - unsigned int DstOff = 0; - int NUM_STORES = 0; - SDValue Stores[6]; + // All nodes may not produce a chain. Therefore following assert + // verifies that the node is returning a chain only. + assert (Chain.getValueType() == MVT::Other && "Node does not have a chain"); - // 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.getNode()->getOperand(0); - Stores[0] = DAG.getStore(Chain, Src, Dest, NULL,0); - return Stores[0]; - } + return Chain; +} - switch(Src.getValueType().getSimpleVT()) { - default: - assert(false && "Invalid value type!"); +void PIC16TargetLowering::GetExpandedParts(SDValue Op, SelectionDAG &DAG, + SDValue &Lo, SDValue &Hi) { + SDNode *N = Op.getNode(); + unsigned NumValues = N->getNumValues(); + std::vector VTs; + MVT NewVT; + std::vector Opers; - case MVT::i8: - break; + // EXTRACT_ELEMENT should have same number and type of values that the + // node replacing the EXTRACT_ELEMENT should have. (i.e. extracted element) + // Some nodes such as LOAD and PIC16Load have more than one values. In such + // cases EXTRACT_ELEMENT should have more than one values. Therefore creating + // vector of Values for EXTRACT_ELEMENT. This list will have same number of + // values as the extracted element will have. - case MVT::i16: - NUM_STORES = 2; - break; + for (unsigned i=0;i < NumValues; ++i) { + NewVT = getTypeToTransformTo(N->getValueType(i)); + VTs.push_back(NewVT); + } - case MVT::i32: - NUM_STORES = 4; - break; + // extract the lo component + Opers.push_back(Op); + Opers.push_back(DAG.getConstant(0,MVT::i8)); + Lo = DAG.getNode(ISD::EXTRACT_ELEMENT,VTs,&Opers[0],Opers.size()); - case MVT::i64: - NUM_STORES = 8; - break; - } + // extract the hi component + Opers.clear(); + Opers.push_back(Op); + Opers.push_back(DAG.getConstant(1,MVT::i8)); + Hi = DAG.getNode(ISD::EXTRACT_ELEMENT,VTs,&Opers[0],Opers.size()); +} - if (isa(Dest) && isa(Src) && - (Src.getValueType() != MVT::i8)) { - //create direct addressing a = b - Chain = Src.getOperand(0); - for (i=0; i(Dest) && isa(Src) - && (Src.getValueType() != MVT::i8)) { - //create direct addressing a = CONST - CST = dyn_cast(Src); - for (i = 0; i < NUM_STORES; i++) { - SDValue CNST = DAG.getConstant(CST->getZExtValue() >> i*8, MVT::i8); - SDValue ADN = DAG.getNode(ISD::ADD, MVT::i16, Dest, - DAG.getConstant(DstOff, MVT::i16)); - Stores[i] = DAG.getStore(Chain, CNST, ADN, NULL, 0); - Chain = Stores[i]; - DstOff += 1; - } - - Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, &Stores[0], i); - return Chain; - } - else if (isa(Dest) && isa(Src) - && (Src.getValueType() != MVT::i8)) { - // Create indirect addressing. - CST = dyn_cast(Src); - Chain = Dest.getOperand(0); - SDValue Load; - Load = DAG.getLoad(MVT::i16, Chain,Dest.getOperand(1), NULL, 0); - Chain = Load.getValue(1); - for (i=0; igetZExtValue() >> i*8, MVT::i8); - Stores[i] = DAG.getStore(Chain, CNST, Load, NULL, 0); - Chain = Stores[i]; - DstOff += 1; - } - - Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, &Stores[0], i); - return Chain; - } - else if (isa(Dest) && isa(Src)) { - // GlobalAddressSDNode *GAD = dyn_cast(Src); - return SDValue(); - } - else if (Src.getOpcode() == PIC16ISD::Package) { - StoreSDNode *st = dyn_cast(N); - SDValue toWorkList, retVal; - Chain = N->getOperand(0); +// This function legalizes the PIC16 Addresses. If the Pointer is +// -- Direct address variable residing +// --> then a Banksel for that variable will be created. +// -- Rom variable +// --> then it will be treated as an indirect address. +// -- Indirect address +// --> then the address will be loaded into FSR +// -- ADD with constant operand +// --> then constant operand of ADD will be returned as Offset +// and non-constant operand of ADD will be treated as pointer. +// Returns the high and lo part of the address, and the offset(in case of ADD). - 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); +void PIC16TargetLowering:: LegalizeAddress(SDValue Ptr, SelectionDAG &DAG, + SDValue &Lo, SDValue &Hi, + unsigned &Offset) { - // 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.getNode()); + // Offset, by default, should be 0 + Offset = 0; - // We don't need the Package so add to worklist so llvm deletes it - DCI.AddToWorklist(Src.getNode()); - retVal = DAG.getNode(ISD::TokenFactor, MVT::Other, &Stores[0], 2); - } - - return retVal; - } - else if (Src.getOpcode() == ISD::TRUNCATE) { - } - else { - } - } // end ISD::STORE. - break; - - case ISD::LOAD : - { - SDValue Ptr = N->getOperand(1); - if (Ptr.getOpcode() == PIC16ISD::Package) { - assert (0 && "not implemented yet"); - } + // If the pointer is ADD with constant, + // return the constant value as the offset + if (Ptr.getOpcode() == ISD::ADD) { + SDValue OperLeft = Ptr.getOperand(0); + SDValue OperRight = Ptr.getOperand(1); + if (OperLeft.getOpcode() == ISD::Constant) { + Offset = dyn_cast(OperLeft)->getZExtValue(); + Ptr = OperRight; + } else { + Ptr = OperLeft; + Offset = dyn_cast(OperRight)->getZExtValue(); } - break; - } // end switch. + } + if (isDirectAddress(Ptr) && !isRomAddress(Ptr)) { + // Direct addressing case for RAM variables. The Hi part is constant + // and the Lo part is the TGA itself. + Lo = Ptr.getOperand(0).getOperand(0); + + // For direct addresses Hi is a constant. Value 1 for the constant + // signifies that banksel needs to generated for it. Value 0 for + // the constant signifies that banksel does not need to be generated + // for it. Mark it as 1 now and optimize later. + Hi = DAG.getConstant(1, MVT::i8); + return; + } + + // Indirect addresses. Get the hi and lo parts of ptr. + GetExpandedParts(Ptr, DAG, Lo, Hi); + + // Put the hi and lo parts into FSR. + Lo = DAG.getNode(PIC16ISD::MTLO, MVT::i8, Lo); + Hi = DAG.getNode(PIC16ISD::MTHI, MVT::i8, Hi); + + return; +} + +SDNode *PIC16TargetLowering::ExpandAdd(SDNode *N, SelectionDAG &DAG) { + SDValue OperLeft = N->getOperand(0); + SDValue OperRight = N->getOperand(1); + + if((OperLeft.getOpcode() == ISD::Constant) || + (OperRight.getOpcode() == ISD::Constant)) { + return NULL; + } + + // These case are yet to be handled + return NULL; +} + +SDNode *PIC16TargetLowering::ExpandLoad(SDNode *N, SelectionDAG &DAG) { + LoadSDNode *LD = dyn_cast(SDValue(N, 0)); + SDValue Chain = LD->getChain(); + SDValue Ptr = LD->getBasePtr(); + + SDValue Load, Offset; + SDVTList Tys; + MVT VT, NewVT; + SDValue PtrLo, PtrHi; + unsigned LoadOffset; + + // Legalize direct/indirect addresses. This will give the lo and hi parts + // of the address and the offset. + LegalizeAddress(Ptr, DAG, PtrLo, PtrHi, LoadOffset); + + // Load from the pointer (direct address or FSR) + VT = N->getValueType(0); + unsigned NumLoads = VT.getSizeInBits() / 8; + std::vector PICLoads; + unsigned iter; + MVT MemVT = LD->getMemoryVT(); + if(ISD::isNON_EXTLoad(N)) { + for (iter=0; itergetMemoryVT(); + unsigned MemBytes = MemVT.getSizeInBits() / 8; + unsigned ExtdBytes = VT.getSizeInBits() / 8; + Offset = DAG.getConstant(LoadOffset, MVT::i8); + + Tys = DAG.getVTList(MVT::i8, MVT::Other); + // For MemBytes generate PIC16Load with proper offset + for (iter=0; itergetOperand(0); + SDValue Amt = N->getOperand(1); + SDValue BCF, BCFInput; + SDVTList Tys; + SDValue ShfCom; // Shift Component - Lo component should be shifted + SDValue RotCom; // Rotate Component- Hi component should be rotated + PIC16ISD::NodeType ShfNode, RotNode; + + // Currently handling Constant shift only + if (Amt.getOpcode() != ISD::Constant) + return NULL; + + // Following code considers 16 bit left-shift only + if (N->getValueType(0) != MVT::i16) + return NULL; + + if (N->getOpcode() == ISD::SHL) { + ShfNode = PIC16ISD::LSLF; + RotNode = PIC16ISD::RLF; + } else if (N->getOpcode() == ISD::SRL) { + ShfNode = PIC16ISD::LRLF; + RotNode = PIC16ISD::RRF; + } + unsigned ShiftAmt = dyn_cast(Amt)->getZExtValue(); + SDValue StatusReg = DAG.getRegister(PIC16::STATUS, MVT::i8); + // 0th Bit in StatusReg is CarryBit + SDValue CarryBit= DAG.getConstant(0, MVT::i8); + + GetExpandedParts(Value, DAG, ShfCom, RotCom); + BCFInput = DAG.getNode(PIC16ISD::Dummy, MVT::Flag); + Tys = DAG.getVTList(MVT::i8, MVT::Flag); + + for (unsigned i=0;igetValueType(0), ShfCom, RotCom); + return BP.getNode(); +} + +SDValue PIC16TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) { + switch (Op.getOpcode()) { + case ISD::FORMAL_ARGUMENTS: + return LowerFORMAL_ARGUMENTS(Op, DAG); + case ISD::ADDC: + return LowerADDC(Op, DAG); + case ISD::ADDE: + return LowerADDE(Op, DAG); + case ISD::SUBE: + return LowerSUBE(Op, DAG); + case ISD::SUBC: + return LowerSUBC(Op, DAG); + case ISD::LOAD: + return SDValue(ExpandLoad(Op.getNode(), DAG), Op.getResNo()); + case ISD::STORE: + return SDValue(ExpandStore(Op.getNode(), DAG), Op.getResNo()); + case ISD::SHL: + return SDValue(ExpandShift(Op.getNode(), DAG), Op.getResNo()); + } return SDValue(); } -//===----------------------------------------------------------------------===// -// Utility functions -//===----------------------------------------------------------------------===// -const SDValue *PIC16TargetLowering:: -findLoadi8(const SDValue &Src, SelectionDAG &DAG) const -{ - unsigned int i; - if ((Src.getOpcode() == ISD::LOAD) && (Src.getValueType() == MVT::i8)) - return &Src; - for (i=0; igetName(); + + char *tmpName = new char [strlen(FuncName.c_str()) + 6]; + + // Put the value on stack. + // Get a stack slot index and convert to es. + int FI = MF.getFrameInfo()->CreateStackObject(1, 1); + sprintf(tmpName, "%s.tmp", FuncName.c_str()); + SDValue ES = DAG.getTargetExternalSymbol(tmpName, MVT::i8); + + // Store the value to ES. + SDValue Store = DAG.getNode (PIC16ISD::PIC16Store, MVT::Other, + DAG.getEntryNode(), + Op, ES, + DAG.getConstant (1, MVT::i8), // Banksel. + DAG.getConstant (FI, MVT::i8)); + + // Load the value from ES. + SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Other); + SDValue Load = DAG.getNode(PIC16ISD::PIC16Load, Tys, Store, + ES, DAG.getConstant (1, MVT::i8), + DAG.getConstant (FI, MVT::i8)); + + return Load.getValue(0); +} + +SDValue PIC16TargetLowering:: LowerADDC(SDValue Op, SelectionDAG &DAG) { + // We should have handled larger operands in type legalizer itself. + assert (Op.getValueType() == MVT::i8 && "illegal addc to lower"); + + // Nothing to do if the one of the operands is already a load. + if (Op.getOperand(0).getOpcode() == PIC16ISD::PIC16Load + || Op.getOperand(1).getOpcode() == PIC16ISD::PIC16Load) + return SDValue(); + + // Put one value on stack. + SDValue NewVal = ConvertToMemOperand (Op.getOperand(1), DAG); + + SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Flag); + return DAG.getNode(ISD::ADDC, Tys, Op.getOperand(0), NewVal); +} + +SDValue PIC16TargetLowering:: LowerADDE(SDValue Op, SelectionDAG &DAG) { + // We should have handled larger operands in type legalizer itself. + assert (Op.getValueType() == MVT::i8 && "illegal adde to lower"); + + // Nothing to do if the one of the operands is already a load. + if (Op.getOperand(0).getOpcode() == PIC16ISD::PIC16Load + || Op.getOperand(1).getOpcode() == PIC16ISD::PIC16Load) + return SDValue(); + + // Put one value on stack. + SDValue NewVal = ConvertToMemOperand (Op.getOperand(1), DAG); + + SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Flag); + return DAG.getNode(ISD::ADDE, Tys, Op.getOperand(0), NewVal, + Op.getOperand(2)); +} + +SDValue PIC16TargetLowering:: LowerSUBC(SDValue Op, SelectionDAG &DAG) { + // We should have handled larger operands in type legalizer itself. + assert (Op.getValueType() == MVT::i8 && "illegal subc to lower"); + + // Nothing to do if the first operand is already a load. + if (Op.getOperand(0).getOpcode() == PIC16ISD::PIC16Load) + return SDValue(); + + // Put first operand on stack. + SDValue NewVal = ConvertToMemOperand (Op.getOperand(0), DAG); + + SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Flag); + return DAG.getNode(ISD::SUBC, Tys, NewVal, Op.getOperand(1)); +} + +SDValue PIC16TargetLowering:: LowerSUBE(SDValue Op, SelectionDAG &DAG) { + // We should have handled larger operands in type legalizer itself. + assert (Op.getValueType() == MVT::i8 && "illegal sube to lower"); + + // Nothing to do if the first operand is already a load. + if (Op.getOperand(0).getOpcode() == PIC16ISD::PIC16Load) + return SDValue(); + + // Put first operand on stack. + SDValue NewVal = ConvertToMemOperand (Op.getOperand(0), DAG); + + SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Flag); + return DAG.getNode(ISD::SUBE, Tys, NewVal, Op.getOperand(1), + Op.getOperand(2)); +} + +// LowerFORMAL_ARGUMENTS - In Lowering FORMAL ARGUMENTS - MERGE_VALUES nodes +// is returned. MERGE_VALUES nodes number of operands and number of values are +// equal. Therefore to construct MERGE_VALUE node, UNDEF nodes equal to the +// number of arguments of function have been created. + +SDValue PIC16TargetLowering:: LowerFORMAL_ARGUMENTS(SDValue Op, + SelectionDAG &DAG) { + SmallVector ArgValues; + unsigned NumArgs = Op.getNumOperands() - 3; + + // Creating UNDEF nodes to meet the requirement of MERGE_VALUES node. + for(unsigned i = 0 ; igetValueType(i)); + ArgValues.push_back(TempNode); } - return NULL; + ArgValues.push_back(Op.getOperand(0)); + return DAG.getNode(ISD::MERGE_VALUES, Op.getNode()->getVTList(), + &ArgValues[0], + ArgValues.size()).getValue(Op.getResNo()); +} + +// Perform DAGCombine of PIC16Load +SDValue PIC16TargetLowering:: +PerformPIC16LoadCombine(SDNode *N, DAGCombinerInfo &DCI) const { + SelectionDAG &DAG = DCI.DAG; + SDValue Chain = N->getOperand(0); + if (N->hasNUsesOfValue(0, 0)) { + DAG.ReplaceAllUsesOfValueWith(SDValue(N,1), Chain); + } + return SDValue(); +} + + +SDValue PIC16TargetLowering::PerformDAGCombine(SDNode *N, + DAGCombinerInfo &DCI) const { + switch (N->getOpcode()) { + case PIC16ISD::PIC16Load: + return PerformPIC16LoadCombine(N, DCI); + } + return SDValue(); } diff --git a/lib/Target/PIC16/PIC16ISelLowering.h b/lib/Target/PIC16/PIC16ISelLowering.h index e14a0c2cb3c..dfe5b5f7e45 100644 --- a/lib/Target/PIC16/PIC16ISelLowering.h +++ b/lib/Target/PIC16/PIC16ISelLowering.h @@ -26,66 +26,89 @@ namespace llvm { // Start the numbering from where ISD NodeType finishes. FIRST_NUMBER = ISD::BUILTIN_OP_END, - // used for encapsulating the expanded nodes into one node. - Package, + Lo, // Low 8-bits of GlobalAddress. + Hi, // High 8-bits of GlobalAddress. + PIC16Load, + PIC16Store, + Banksel, + MTLO, + MTHI, + BCF, + LSLF, // PIC16 Logical shift left + LRLF, // PIC16 Logical shift right + RLF, // Rotate left through carry + RRF, // Rotate right through carry + Dummy + }; - // 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 + // Keep track of different address spaces. + enum AddressSpace { + RAM_SPACE = 0, // RAM address space + ROM_SPACE = 1 // ROM address space number is 1 }; } //===--------------------------------------------------------------------===// // TargetLowering Implementation //===--------------------------------------------------------------------===// - class PIC16TargetLowering : public TargetLowering - { + class PIC16TargetLowering : public TargetLowering { public: - typedef std::map NodeMap_t; - explicit PIC16TargetLowering(PIC16TargetMachine &TM); - /// LowerOperation - Provide custom lowering hooks for some operations. - virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG); - - SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG); - SDValue LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG); - SDValue LowerRET(SDValue Op, SelectionDAG &DAG); - SDValue LowerFrameIndex(SDValue Op, SelectionDAG &DAG); - SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG); - - SDValue RemoveHiLo(SDNode *, SelectionDAG &DAG, - DAGCombinerInfo &DCI) const; - SDValue LowerADDSUB(SDNode *, SelectionDAG &DAG, - DAGCombinerInfo &DCI) const; - SDValue LowerLOAD(SDNode *, SelectionDAG &DAG, - DAGCombinerInfo &DCI) const; - - /// getTargetNodeName - This method returns the name of a target specific - // DAG node. + /// getTargetNodeName - This method returns the name of a target specific + /// DAG node. virtual const char *getTargetNodeName(unsigned Opcode) const; - virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const; + SDValue LowerOperation(SDValue Op, SelectionDAG &DAG); + SDValue LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG); + SDValue LowerADDE(SDValue Op, SelectionDAG &DAG); + SDValue LowerADDC(SDValue Op, SelectionDAG &DAG); + SDValue LowerSUBE(SDValue Op, SelectionDAG &DAG); + SDValue LowerSUBC(SDValue Op, SelectionDAG &DAG); - // utility function. - const SDValue *findLoadi8(const SDValue &Src, SelectionDAG &DAG) const; + SDNode *ReplaceNodeResults(SDNode *N, SelectionDAG &DAG); + SDNode *ExpandStore(SDNode *N, SelectionDAG &DAG); + SDNode *ExpandLoad(SDNode *N, SelectionDAG &DAG); + SDNode *ExpandAdd(SDNode *N, SelectionDAG &DAG); + SDNode *ExpandGlobalAddress(SDNode *N, SelectionDAG &DAG); + SDNode *ExpandShift(SDNode *N, SelectionDAG &DAG); + + SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const; + SDValue PerformPIC16LoadCombine(SDNode *N, DAGCombinerInfo &DCI) const; + + private: + // If the Node is a BUILD_PAIR representing representing an Address + // then this function will return true + bool isDirectAddress(const SDValue &Op); + + // If the Node is a DirectAddress in ROM_SPACE then this + // function will return true + bool isRomAddress(const SDValue &Op); + + // To extract chain value from the SDValue Nodes + // This function will help to maintain the chain extracting + // code at one place. In case of any change in future it will + // help maintain the code + SDValue getChain(SDValue &Op); + + + // Extract the Lo and Hi component of Op. + void GetExpandedParts(SDValue Op, SelectionDAG &DAG, SDValue &Lo, + SDValue &Hi); + + + // Load pointer can be a direct or indirect address. In PIC16 direct + // addresses need Banksel and Indirect addresses need to be loaded to + // FSR first. Handle address specific cases here. + void LegalizeAddress(SDValue Ptr, SelectionDAG &DAG, SDValue &Chain, + SDValue &NewPtr, unsigned &Offset); + + // We can not have both operands of a binary operation in W. + // This function is used to put one operand on stack and generate a load. + SDValue ConvertToMemOperand(SDValue Op, SelectionDAG &DAG); + + /// Subtarget - Keep a pointer to the PIC16Subtarget around so that we can + /// make the right decision when generating code for different targets. + const PIC16Subtarget *Subtarget; }; } // namespace llvm diff --git a/lib/Target/PIC16/PIC16InstrFormats.td b/lib/Target/PIC16/PIC16InstrFormats.td index e8ecf6a3d32..e213ea847fc 100644 --- a/lib/Target/PIC16/PIC16InstrFormats.td +++ b/lib/Target/PIC16/PIC16InstrFormats.td @@ -1,4 +1,4 @@ -//===- PIC16RegisterInfo.td - PIC16 Register defs ------------*- tblgen -*-===// +//===- PIC16InstrFormats.td - PIC16 Instruction Formats-------*- tblgen -*-===// // // The LLVM Compiler Infrastructure // @@ -21,16 +21,17 @@ //===----------------------------------------------------------------------===// // Generic PIC16 Format +// PIC16 Instructions are 14-bit wide. + +// FIXME: Add Cooper Specific Formats if any. + class PIC16Inst pattern> - : Instruction -{ + : Instruction { field bits<14> Inst; let Namespace = "PIC16"; - dag OutOperandList = outs; dag InOperandList = ins; - let AsmString = asmstr; let Pattern = pattern; } @@ -38,16 +39,18 @@ class PIC16Inst pattern> //===----------------------------------------------------------------------===// // Byte Oriented instruction class in PIC16 : <|opcode|d|f|> +// opcode = 6 bits. +// d = direction = 1 bit. +// f = file register address = 7 bits. //===----------------------------------------------------------------------===// -class ByteFormat op, dag outs, dag ins, string asmstr, - list pattern> - :PIC16Inst -{ +class ByteFormat opcode, dag outs, dag ins, string asmstr, + list pattern> + :PIC16Inst { bits<1> d; bits<7> f; - let Inst{13-8} = op; + let Inst{13-8} = opcode; let Inst{7} = d; let Inst{6-0} = f; @@ -55,15 +58,18 @@ class ByteFormat op, dag outs, dag ins, string asmstr, //===----------------------------------------------------------------------===// // Bit Oriented instruction class in PIC16 : <|opcode|b|f|> +// opcode = 4 bits. +// b = bit specifier = 3 bits. +// f = file register address = 7 bits. //===----------------------------------------------------------------------===// -class BitFormat op, dag outs, dag ins, string asmstr, list pattern> - : PIC16Inst -{ +class BitFormat opcode, dag outs, dag ins, string asmstr, + list pattern> + : PIC16Inst { bits<3> b; bits<7> f; - let Inst{13-10} = op; + let Inst{13-10} = opcode; let Inst{9-7} = b; let Inst{6-0} = f; @@ -71,32 +77,32 @@ class BitFormat op, dag outs, dag ins, string asmstr, list pattern> //===----------------------------------------------------------------------===// // Literal Format instruction class in PIC16 : <|opcode|k|> +// opcode = 6 bits +// k = literal = 8 bits //===----------------------------------------------------------------------===// -class LiteralFormat op, dag outs, dag ins, string asmstr, +class LiteralFormat opcode, dag outs, dag ins, string asmstr, list pattern> - : PIC16Inst -{ + : PIC16Inst { bits<8> k; - - let Inst{13-8} = op; + let Inst{13-8} = opcode; let Inst{7-0} = k; } //===----------------------------------------------------------------------===// // Control Format instruction class in PIC16 : <|opcode|k|> +// opcode = 3 bits. +// k = jump address = 11 bits. //===----------------------------------------------------------------------===// -class ControlFormat op, dag outs, dag ins, string asmstr, +class ControlFormat opcode, dag outs, dag ins, string asmstr, list pattern> - :PIC16Inst -{ + : PIC16Inst { bits<11> k; - - let Inst{13-11} = op; + let Inst{13-11} = opcode; let Inst{10-0} = k; } @@ -105,8 +111,7 @@ class ControlFormat op, dag outs, dag ins, string asmstr, // Pseudo instruction class in PIC16 //===----------------------------------------------------------------------===// -class Pseudo op, dag outs, dag ins, string asmstr, list pattern>: - PIC16Inst -{ - let Inst{13-6} = op; +class Pseudo pattern> + : PIC16Inst { + let Inst{13-6} = 0; } diff --git a/lib/Target/PIC16/PIC16InstrInfo.cpp b/lib/Target/PIC16/PIC16InstrInfo.cpp index 7cb2379d1ba..d70ebc649bb 100644 --- a/lib/Target/PIC16/PIC16InstrInfo.cpp +++ b/lib/Target/PIC16/PIC16InstrInfo.cpp @@ -13,132 +13,131 @@ #include "PIC16.h" #include "PIC16InstrInfo.h" +#include "PIC16TargetMachine.h" +#include "PIC16GenInstrInfo.inc" #include "llvm/Function.h" #include "llvm/ADT/STLExtras.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBuilder.h" -#include "PIC16GenInstrInfo.inc" -#include +#include "llvm/CodeGen/MachineRegisterInfo.h" + using namespace llvm; // FIXME: Add the subtarget support on this constructor. PIC16InstrInfo::PIC16InstrInfo(PIC16TargetMachine &tm) : TargetInstrInfoImpl(PIC16Insts, array_lengthof(PIC16Insts)), - TM(tm), RI(*this) {} + TM(tm), + RegInfo(*this, *TM.getSubtargetImpl()) {} -static bool isZeroImm(const MachineOperand &op) { - return op.isImm() && 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(const MachineInstr *MI, int &FrameIndex) const -{ - if (MI->getOpcode() == PIC16::MOVF) { - if ((MI->getOperand(2).isFI()) && // is a stack slot - (MI->getOperand(1).isImm()) && // 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 +/// 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(const MachineInstr *MI, int &FrameIndex) const -{ - if (MI->getOpcode() == PIC16::MOVWF) { - if ((MI->getOperand(0).isFI()) && // is a stack slot - (MI->getOperand(1).isImm()) && // the imm is zero - (isZeroImm(MI->getOperand(1)))) { - FrameIndex = MI->getOperand(0).getIndex(); - return MI->getOperand(2).getReg(); - } +unsigned PIC16InstrInfo::isStoreToStackSlot(MachineInstr *MI, + int &FrameIndex) const { + if (MI->getOpcode() == PIC16::movwf + && MI->getOperand(0).isReg() + && MI->getOperand(1).isSymbol()) { + FrameIndex = MI->getOperand(1).getIndex(); + return MI->getOperand(0).getReg(); } return 0; } -void PIC16InstrInfo:: -storeRegToStackSlot(MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, - unsigned SrcReg, bool isKill, int FI, - const TargetRegisterClass *RC) const { +/// isLoadFromStackSlot - If the specified machine instruction is a direct +/// load from a stack slot, return the virtual or physical register number of +/// the dest reg along with the FrameIndex of the 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::isLoadFromStackSlot(MachineInstr *MI, + int &FrameIndex) const { + if (MI->getOpcode() == PIC16::movf + && MI->getOperand(0).isReg() + && MI->getOperand(1).isSymbol()) { + FrameIndex = MI->getOperand(1).getIndex(); + return MI->getOperand(0).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); + sprintf(tmpName, "%s.tmp", FuncName.c_str()); - 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. + // On the order of operands here: think "movwf SrcReg, tmp_slot, offset". + if (RC == PIC16::GPRRegisterClass) { + //MachineFunction &MF = *MBB.getParent(); + //MachineRegisterInfo &RI = MF.getRegInfo(); + BuildMI(MBB, I, get(PIC16::movwf)) + .addReg(SrcReg, false, false, isKill) + .addImm(FI) + .addExternalSymbol(tmpName) + .addImm(1); // Emit banksel for it. } + else if (RC == PIC16::FSR16RegisterClass) + assert(0 && "Don't know yet how to store a FSR16 to stack slot"); 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 -{ +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); + sprintf(tmpName, "%s.tmp", FuncName.c_str()); - 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. + // On the order of operands here: think "movf FrameIndex, W". + if (RC == PIC16::GPRRegisterClass) { + //MachineFunction &MF = *MBB.getParent(); + //MachineRegisterInfo &RI = MF.getRegInfo(); + BuildMI(MBB, I, get(PIC16::movf), DestReg) + .addImm(FI) + .addExternalSymbol(tmpName) + .addImm(1); // Emit banksel for it. + } + else if (RC == PIC16::FSR16RegisterClass) + assert(0 && "Don't know yet how to load an FSR16 from stack slot"); 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 SmallVectorImpl &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; +bool PIC16InstrInfo::copyRegToReg (MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + unsigned DestReg, unsigned SrcReg, + const TargetRegisterClass *DestRC, + const TargetRegisterClass *SrcRC) const { + if (DestRC == PIC16::FSR16RegisterClass) { + BuildMI(MBB, I, get(PIC16::copy_fsr), DestReg).addReg(SrcReg); } - // FIXME: 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; + return true; +} + +bool PIC16InstrInfo::isMoveInstr(const MachineInstr &MI, + unsigned &SrcReg, + unsigned &DestReg) const { + + if (MI.getOpcode() == PIC16::copy_fsr) { + DestReg = MI.getOperand(0).getReg(); + SrcReg = MI.getOperand(1).getReg(); + return true; + } + return false; } diff --git a/lib/Target/PIC16/PIC16InstrInfo.h b/lib/Target/PIC16/PIC16InstrInfo.h index 250142daf6c..bd3e48858fe 100644 --- a/lib/Target/PIC16/PIC16InstrInfo.h +++ b/lib/Target/PIC16/PIC16InstrInfo.h @@ -24,54 +24,43 @@ namespace llvm { class PIC16InstrInfo : public TargetInstrInfoImpl { PIC16TargetMachine &TM; - const PIC16RegisterInfo RI; + const PIC16RegisterInfo RegInfo; 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 PIC16RegisterInfo &getRegisterInfo() const { return RI; } + virtual const PIC16RegisterInfo &getRegisterInfo() const { return RegInfo; } - /// 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(const MachineInstr *MI, - int &FrameIndex) const; - + 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(const 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; + virtual unsigned isStoreToStackSlot(MachineInstr *MI, int &FrameIndex) 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 SmallVectorImpl &Cond) const ; + virtual void storeRegToStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + unsigned SrcReg, bool isKill, int FrameIndex, + const TargetRegisterClass *RC) const; + + virtual void loadRegFromStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + unsigned DestReg, int FrameIndex, + const TargetRegisterClass *RC) const; + virtual bool copyRegToReg(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + unsigned DestReg, unsigned SrcReg, + const TargetRegisterClass *DestRC, + const TargetRegisterClass *SrcRC) const; + virtual bool isMoveInstr(const MachineInstr &MI, + unsigned &SrcReg, + unsigned &DestReg) const; }; diff --git a/lib/Target/PIC16/PIC16InstrInfo.td b/lib/Target/PIC16/PIC16InstrInfo.td index a0e7f7cb966..0335e92bbf9 100644 --- a/lib/Target/PIC16/PIC16InstrInfo.td +++ b/lib/Target/PIC16/PIC16InstrInfo.td @@ -1,4 +1,4 @@ -//===- PIC16InstrInfo.td - PIC16 Register defs ----------------*- tblgen-*-===// +//===- PIC16InstrInfo.td - PIC16 Instruction defs -------------*- tblgen-*-===// // // The LLVM Compiler Infrastructure // @@ -6,297 +6,302 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// Instruction format superclass +// +// This file describes the ARM instructions in TableGen format. +// //===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// +// PIC16 Specific Type Constraints. +//===----------------------------------------------------------------------===// +class SDTCisI8 : SDTCisVT; +class SDTCisI16 : SDTCisVT; + +//===----------------------------------------------------------------------===// +// PIC16 Specific Type Profiles. +//===----------------------------------------------------------------------===// + +// Generic type profiles for i8/i16 unary/binary operations. +// Taking one i8 or i16 and producing void. +def SDTI8VoidOp : SDTypeProfile<0, 1, [SDTCisI8<0>]>; +def SDTI16VoidOp : SDTypeProfile<0, 1, [SDTCisI16<0>]>; + +// Taking one value and producing an output of same type. +def SDTI8UnaryOp : SDTypeProfile<1, 1, [SDTCisI8<0>, SDTCisI8<1>]>; +def SDTI16UnaryOp : SDTypeProfile<1, 1, [SDTCisI16<0>, SDTCisI16<1>]>; + +// Taking two values and producing an output of same type. +def SDTI8BinOp : SDTypeProfile<1, 2, [SDTCisI8<0>, SDTCisI8<1>, SDTCisI8<2>]>; +def SDTI16BinOp : SDTypeProfile<1, 2, [SDTCisI16<0>, SDTCisI16<1>, + SDTCisI16<2>]>; + +// Node specific type profiles. +def SDT_PIC16Load : SDTypeProfile<1, 3, [SDTCisI8<0>, SDTCisI8<1>, + SDTCisI8<2>, SDTCisI8<3>]>; +def SDT_PIC16Store : SDTypeProfile<0, 4, [SDTCisI8<0>, SDTCisI8<1>, + SDTCisI8<2>, SDTCisI8<3>]>; + +//===----------------------------------------------------------------------===// +// PIC16 addressing modes matching via DAG. +//===----------------------------------------------------------------------===// +def diraddr : ComplexPattern; + +//===----------------------------------------------------------------------===// +// PIC16 Specific Node Definitions. +//===----------------------------------------------------------------------===// +def PIC16callseq_start : SDNode<"ISD::CALLSEQ_START", SDTI8VoidOp, + [SDNPHasChain, SDNPOutFlag]>; +def PIC16callseq_end : SDNode<"ISD::CALLSEQ_END", SDTI8VoidOp, + [SDNPHasChain, SDNPOutFlag]>; + +// Low 8-bits of GlobalAddress. +def PIC16Lo : SDNode<"PIC16ISD::Lo", SDTI8UnaryOp>; + +// High 8-bits of GlobalAddress. +def PIC16Hi : SDNode<"PIC16ISD::Hi", SDTI8UnaryOp>; + +// The MTHI and MTLO nodes are used only to match them in the incoming +// DAG for replacement by corresponding set_fsrhi, set_fsrlo insntructions. +// These nodes are not used for defining any instructions. +def MTLO : SDNode<"PIC16ISD::MTLO", SDTI8UnaryOp>; +def MTHI : SDNode<"PIC16ISD::MTHI", SDTI8UnaryOp>; + +// Node to generate Bank Select for a GlobalAddress. +def Banksel : SDNode<"PIC16ISD::Banksel", SDTI8UnaryOp>; + +// Node to match a direct store operation. +def PIC16Store : SDNode<"PIC16ISD::PIC16Store", SDT_PIC16Store, [SDNPHasChain]>; + +// Node to match a direct load operation. +def PIC16Load : SDNode<"PIC16ISD::PIC16Load", SDT_PIC16Load, [SDNPHasChain]>; + +//===----------------------------------------------------------------------===// +// PIC16 Operand Definitions. +//===----------------------------------------------------------------------===// +def i8mem : Operand; + + + +//===----------------------------------------------------------------------===// +// PIC16 Instructions. +//===----------------------------------------------------------------------===// include "PIC16InstrFormats.td" -//===----------------------------------------------------------------------===// -// PIC16 profiles and nodes -//===----------------------------------------------------------------------===// +// Pseudo-instructions. +def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i8imm:$amt), + "!ADJCALLSTACKDOWN $amt", + [(PIC16callseq_start imm:$amt)]>; -//===----------------------------------------------------------------------===// -// PIC16 addressing mode. -//===----------------------------------------------------------------------===// -// It matches address of globals as well as the stack slots -// that are created for locals and temporaries. This addressing mode -// converts the GlobalAddress and FrameIndex nodes to TargetGlobalAddress -// and TargetFrameIndex nodes. -def diraddrmode : ComplexPattern; -def dirloadmode : ComplexPattern; -def indirloadmode : ComplexPattern; - - -// Address operand. -def mem : Operand { - let PrintMethod = "printAddrModeOperand"; - let MIOperandInfo = (ops i16imm, PTRRegs); -} - -// Instruction operand types -def simm8 : Operand; - - -// These are target-independent nodes, but have target-specific formats. -def SDT_PIC16CallSeq : SDTypeProfile<0, 1, [ SDTCisVT<0, i8> ]>; -def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_PIC16CallSeq, - [SDNPHasChain, SDNPOutFlag]>; -def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_PIC16CallSeq, - [SDNPHasChain, SDNPOutFlag]>; - -def PIC16Wrapper : SDNode<"PIC16ISD::Wrapper", SDTIntUnaryOp>; - -// so_imm_XFORM - Return a so_imm value packed into the format described for -// so_imm def below. -def so_imm_XFORM : SDNodeXFormgetTargetConstant((int8_t)N->getZExtValue(), MVT::i32); -}]>; - -def so_imm : Operand, - PatLeaf<(imm), [{}]> { - let PrintMethod = "printSOImmOperand"; -} - - - -// PIC16 Address Mode! SDNode frameindex could possibily be a match -// since load and store instructions from stack used it. -def addr : Operand; - -// Arithmetic 2 register operands -class ArithI op, string instr_asm, SDNode OpNode, - Operand Od> : - LiteralFormat< op, - (outs CPURegs:$dst), - (ins CPURegs:$b, Od:$c), - !strconcat(instr_asm, " $c"), - [(set CPURegs:$dst, (OpNode CPURegs:$b, Od:$c))]>; - -// Memory Load/Store. -class LoadDirect op, string instr_asm, PatFrag OpNode>: - ByteFormat< op, - (outs CPURegs:$dst), - (ins mem:$addr), - !strconcat(instr_asm, " $addr"), - [(set CPURegs:$dst, (OpNode diraddrmode:$addr))]>; - -class LoadInDirect op, string instr_asm, PatFrag OpNode>: - ByteFormat< op, - (outs PTRRegs:$dst), - (ins mem:$addr), - !strconcat(instr_asm, " $addr, $dst"), - [(set PTRRegs:$dst, (OpNode indirloadmode:$addr))]>; - -class StoreDirect op, string instr_asm, PatFrag OpNode>: - ByteFormat< op, - (outs), - (ins CPURegs:$src, mem:$addr), - !strconcat(instr_asm, " $addr"), - [(OpNode CPURegs:$src, diraddrmode:$addr)]>; - -class StoreInDirect op, string instr_asm, PatFrag OpNode>: - ByteFormat< op, - (outs), - (ins CPURegs:$src, PTRRegs:$fsr), - !strconcat(instr_asm, " $fsr"), - [(OpNode CPURegs:$src, PTRRegs:$fsr)]>; - -// Move. -class MovLit op, string instr_asm>: - LiteralFormat< op, - (outs CPURegs:$dst), - (ins i8imm:$src), - !strconcat(instr_asm, " $src"), - [(set CPURegs:$dst, imm:$src)]>; - - -// Arithmetic with memory store. -// Arithmetic instrunctions involving W and memory location. -// Since W is implicit, we only print the memory operand. -class Arith1M op, string instr_asm, SDNode OpNode>: - ByteFormat< op, - (outs), - (ins CPURegs:$b, mem:$dst), - !strconcat(instr_asm, " $dst"), - [(store (OpNode (load diraddrmode:$dst), CPURegs:$b), diraddrmode:$dst), - (store (OpNode CPURegs:$b, (load diraddrmode:$dst)), diraddrmode:$dst)]>; - -// Arithmetic with memory load. -// Arithmetic instrunctions involving W and memory location. -// Since W is implicit, we only print the memory operand. -class Arith1R op, string instr_asm, SDNode OpNode>: - ByteFormat< op, - (outs CPURegs:$dst), - (ins mem:$src1, CPURegs:$src2), - !strconcat(instr_asm, " $src1"), - [(set CPURegs:$dst, (OpNode (load diraddrmode:$src1), CPURegs:$src2))]>; - -// Arithmetic with memory load. -// Arithmetic instrunctions involving W and memory location. -// Since W is implicit, we only print the memory operand. -class Arith2R op, string instr_asm, SDNode OpNode>: - ByteFormat< op, - (outs CPURegs:$dst), - (ins mem:$src1, CPURegs:$src2), - !strconcat(instr_asm, " $src1"), - [(set CPURegs:$dst, (OpNode CPURegs:$src2, (load diraddrmode:$src1)))]>; - -//===----------------------------------------------------------------------===// -// Instruction definition -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// PIC16I Instructions -//===----------------------------------------------------------------------===// - -// Arithmetic - -// ADDiu just accept 16-bit immediates but we handle this on Pat's. -// immZExt32 is used here so it can match GlobalAddress immediates. -// def ADDLW : ArithI<0x09, "addlw", add, so_imm>; +def ADJCALLSTACKUP : Pseudo<(outs), (ins i8imm:$amt), + "!ADJCALLSTACKUP $amt", + [(PIC16callseq_end imm:$amt)]>; +//----------------------------------- +// Vaious movlw insn patterns. +//----------------------------------- let isReMaterializable = 1 in { -def MOVLW : MovLit<0x24, "movlw">; +// Move 8-bit literal to W. +def movlw : BitFormat<12, (outs GPR:$dst), (ins i8imm:$src), + "movlw $src", + [(set GPR:$dst, (i8 imm:$src))]>; + +// Move a Lo(TGA) to W. +def movlw_lo : BitFormat<12, (outs GPR:$dst), (ins i8imm:$src), + "movlw LOW(${src})", + [(set GPR:$dst, (PIC16Lo tglobaladdr:$src))]>; + +// Move a Hi(TGA) to W. +def movlw_hi : BitFormat<12, (outs GPR:$dst), (ins i8imm:$src), + "movlw HIGH(${src})", + [(set GPR:$dst, (PIC16Hi tglobaladdr:$src))]>; } -// Load/Store -def LFSR1 : LoadInDirect <0x4, "lfsr", load>; +//------------------- +// FSR setting insns. +//------------------- +// These insns are matched via a DAG replacement pattern. +def set_fsrlo: + ByteFormat<0, (outs FSR16:$fsr), + (ins GPR:$val), + "movwf ${fsr}L", + []>; +let isTwoAddress = 1 in +def set_fsrhi: + ByteFormat<0, (outs FSR16:$dst), + (ins FSR16:$src, GPR:$val), + "movwf ${dst}H", + []>; + +def copy_fsr: + Pseudo<(outs FSR16:$dst), (ins FSR16:$src), "copy_fsr $dst, $src", []>; + +//-------------------------- +// Store to memory +//------------------------- +// Direct store. +def movwf : + ByteFormat<0, (outs), + (ins GPR:$val, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi), + "movwf ${ptrlo} + ${offset}", + [(PIC16Store GPR:$val, tglobaladdr:$ptrlo, (i8 imm:$ptrhi), + (i8 imm:$offset))]>; + +def movwf_1 : + ByteFormat<0, (outs), + (ins GPR:$val, i8mem:$ptrlo, i8imm:$ptrhi, i8imm:$offset), + "movwf ${ptrlo} + ${offset}", + [(PIC16Store GPR:$val, texternalsym:$ptrlo, (i8 imm:$ptrhi), + (i8 imm:$offset))]>; + +// Indirect store. Matched via a DAG replacement pattern. +def store_indirect : + ByteFormat<0, (outs), + (ins GPR:$val, FSR16:$fsr, i8imm:$offset), + "movwi $offset[$fsr]", + []>; + +//---------------------------- +// Load from memory +//---------------------------- +// Direct load. +def movf : + ByteFormat<0, (outs GPR:$dst), + (ins i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi), + "movf ${ptrlo} + ${offset}, W", + [(set GPR:$dst, + (PIC16Load tglobaladdr:$ptrlo, (i8 imm:$ptrhi), + (i8 imm:$offset)))]>; + +def movf_1 : + ByteFormat<0, (outs GPR:$dst), + (ins i8mem:$ptrlo, i8imm:$ptrhi, i8imm:$offset), + "movf ${ptrlo} + ${offset}, W", + [(set GPR:$dst, + (PIC16Load texternalsym:$ptrlo, (i8 imm:$ptrhi), + (i8 imm:$offset)))]>; + +// Indirect load. Matched via a DAG replacement pattern. +def load_indirect : + ByteFormat<0, (outs GPR:$dst), + (ins FSR16:$fsr, i8imm:$offset), + "moviw $offset[$fsr]", + []>; + +//------------------------- +// Various add/sub patterns. +//------------------------- +// W += [F] ; load from F and add the value to W. +class ADDFW OpCode, string OpcStr, SDNode OpNode>: + ByteFormat; +// let isTwoAddress = 1 in { +def addfw_1: ADDFW<0, "addwf", add>; +def addfw_2: ADDFW<0, "addwf", addc>; +def addfwc: ADDFW<0, "addwfc", adde>; // With Carry. +// } + +// [F] += W ; add the value of W to [F]. +class ADDWF OpCode, string OpcStr, SDNode OpNode>: + ByteFormat; +def addwf_1: ADDWF<0, "addwf", add>; +def addwf_2: ADDWF<0, "addwf", addc>; +def addwfc: ADDWF<0, "addwfc", adde>; // With Carry. + +// W -= [F] ; load from F and sub the value from W. +class SUBFW OpCode, string OpcStr, SDNode OpNode>: + ByteFormat; +//let isTwoAddress = 1 in { +def subfw_1: SUBFW<0, "subwf", sub>; +def subfw_2: SUBFW<0, "subwf", subc>; +def subfwb: SUBFW<0, "subwfb", sube>; // With Borrow. +//} + +// [F] -= W ; +class SUBWF OpCode, string OpcStr, SDNode OpNode>: + ByteFormat; + +def subwf_1: SUBWF<0, "subwf", sub>; +def subwf_2: SUBWF<0, "subwf", subc>; +def subwfb: SUBWF<0, "subwfb", sube>; // With Borrow. + +// addlw +// W += C ; add literal to W. (Without carry). May Produce a carry. +class ADDLW opcode, string OpcStr, SDNode OpNode> : + LiteralFormat; + +// let isTwoAddress = 1 in { +def addlw_1 : ADDLW<0, "addlw", add>; +def addlw_2 : ADDLW<0, "addlw", addc>; +def addlwc : ADDLW<0, "addlwc", adde>; // With Carry. (Assembler macro). +//} + +// sublw +// W = C - W ; sub W from literal. (Without borrow). +class SUBLW opcode, SDNode OpNode> : + LiteralFormat; + +//let isTwoAddress = 1 in { +def sublw_1 : SUBLW<0, sub>; +def sublw_2 : SUBLW<0, subc>; +//} + +// Banksel. let isReMaterializable = 1 in { -def MOVF : LoadDirect <0x23, "movf", load>; +def banksel : + Pseudo<(outs BSR:$dst), + (ins i8mem:$ptr), + "banksel $ptr", + [(set BSR:$dst, (Banksel tglobaladdr:$ptr))]>; } -def MOVWF : StoreDirect <0x2b, "movwf", store>; - -def MOVFSRINC : StoreInDirect <0x5, "movfsrinc", store>; - -def RETURN : ControlFormat<0x03, (outs), (ins), "return", []>; - -def ADDWF : Arith1M<0x01, "addwf", add>; -def ADDFW : Arith1R<0x02, "addfw", add>; - -def ADDWFE : Arith1M<0x03, "addwfe", adde>; -def ADDFWE : Arith1R<0x04, "addfwe", adde>; - -def ADDWFC : Arith1M<0x05, "addwfc", addc>; -def ADDFWC : Arith1R<0x06, "addfwc", addc>; - -def SUBWF : Arith1M<0x07, "subwf", sub>; -def SUBFW : Arith1R<0x08, "subfw", sub>; - -def SUBWFE : Arith1M<0x09, "subwfe", sube>; -def SUBFWE : Arith1R<0x0a, "subfwe", sube>; - -def SUBWFC : Arith1M<0x0b, "subwfc", subc>; -def SUBFWC : Arith1R<0x0d, "subfwc", subc>; - -def SUBRFW : Arith2R<0x08, "subfw", sub>; - -def SUBRFWE : Arith2R<0x0a, "subfwe", sube>; - -def SUBRFWC : Arith2R<0x0d, "subfwc", subc>; - -def brtarget : Operand; - -class UncondJump< bits<4> op, string instr_asm>: - BitFormat< op, - (outs), - (ins brtarget:$target), - !strconcat(instr_asm, " $target"), - [(br bb:$target)]>; - -def GOTO : UncondJump<0x1, "goto">; - -class LogicM op, string instr_asm, SDNode OpNode> : - ByteFormat< op, - (outs), - (ins CPURegs:$b, mem:$dst), - !strconcat(instr_asm, " $dst"), - [(store (OpNode (load diraddrmode:$dst), CPURegs:$b), diraddrmode:$dst)]>; - -class LogicR op, string instr_asm, SDNode OpNode> : - ByteFormat< op, - (outs CPURegs:$dst), - (ins CPURegs:$b, mem:$c), - !strconcat(instr_asm, " $c"), - [(set CPURegs:$dst, (OpNode (load diraddrmode:$c), CPURegs:$b))]>; - -class LogicI op, string instr_asm, SDNode OpNode, Operand Od> : - LiteralFormat< op, - (outs CPURegs:$dst), - (ins CPURegs:$b, Od:$c), - !strconcat(instr_asm, " $c"), - [(set CPURegs:$dst, (OpNode CPURegs:$b, Od:$c ))]>; - -def XORWF : LogicM<0x1,"xorwf",xor>; -def XORFW : LogicR<0x1,"xorfw",xor>; -def XORLW : LogicI<0x1,"xorlw",xor, so_imm>; - -def ANDWF : LogicM<0x1,"andwf",and>; -def ANDFW : LogicR<0x1,"andfw",and>; -def ANDLW : LogicI<0x1,"andlw",and, so_imm>; - -def IORWF : LogicM<0x1,"iorwf",or>; -def IORFW : LogicR<0x1,"iorfw",or>; -def IORLW : LogicI<0x1,"iorlw",or, so_imm>; - - -/* For comparison before branch */ -def SDT_PIC16Cmp : SDTypeProfile<1, 3, [SDTCisSameAs<0,1>]>; -def SDTIntBinOpPIC16 : SDTypeProfile<1, 2, [SDTCisSameAs<0,1>, - SDTCisSameAs<1,2>, SDTCisInt<1>]>; - -def PIC16Cmp : SDNode<"PIC16ISD::Cmp",SDTIntBinOpPIC16, [SDNPOutFlag]>; -def PIC16XORCC : SDNode<"PIC16ISD::XORCC",SDTIntBinOpPIC16, [SDNPOutFlag]>; -def PIC16SUBCC : SDNode<"PIC16ISD::SUBCC",SDTIntBinOpPIC16, [SDNPOutFlag]>; - -def XORFWCC : LogicR<0x1,"xorfw",PIC16XORCC>; -def XORLWCC : LogicI<0x1,"xorlw",PIC16XORCC, so_imm>; -def SUBFWCC : Arith1R<0x1,"subfw",PIC16SUBCC>; -def SUBLWCC : ArithI<0x1,"sublw",PIC16SUBCC, so_imm>; - - -/* For branch conditions */ -def SDT_PIC16Branch : SDTypeProfile<0, 3, [SDTCisVT<0, OtherVT>, - SDTCisVT<1,i8>, SDTCisVT<2,i8>]>; - -def PIC16Branch : SDNode<"PIC16ISD::Branch",SDT_PIC16Branch, - [SDNPHasChain, SDNPInFlag]>; - -def PIC16BTFSS : SDNode<"PIC16ISD::BTFSS",SDT_PIC16Branch, - [SDNPHasChain, SDNPInFlag]>; - -def PIC16BTFSC : SDNode<"PIC16ISD::BTFSC",SDT_PIC16Branch, - [SDNPHasChain, SDNPInFlag]>; - -class InstrBitTestCC op, string instr_asm,SDNode OpNode>: - BitFormat< op, - (outs), - (ins brtarget:$target ,so_imm:$i, STATUSRegs:$s ), - !strconcat(instr_asm, " $s, $i, $target"), - [(OpNode bb:$target, so_imm:$i, STATUSRegs:$s )]>; - -def BTFSS : InstrBitTestCC<0x1,"btfss",PIC16BTFSS>; -def BTFSC : InstrBitTestCC<0x1,"btfsc",PIC16BTFSC>; - - +// Return insn. +def Return : + ControlFormat<0, (outs), (ins), "return", [(ret)]>; + //===----------------------------------------------------------------------===// -// Pseudo instructions +// PIC16 Replacment Patterns. //===----------------------------------------------------------------------===// -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)]>; -} +// Identify an indirect store and select insns for it. +def : Pat<(PIC16Store GPR:$val, (MTLO GPR:$loaddr), (MTHI GPR:$hiaddr), + imm:$offset), + (store_indirect GPR:$val, + (set_fsrhi (set_fsrlo GPR:$loaddr), GPR:$hiaddr), + imm:$offset)>; +// Identify an indirect load and select insns for it. +def : Pat<(PIC16Load (MTLO GPR:$loaddr), (MTHI GPR:$hiaddr), + imm:$offset), + (load_indirect (set_fsrhi (set_fsrlo GPR:$loaddr), GPR:$hiaddr), + imm:$offset)>; -//===----------------------------------------------------------------------===// -// 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 index d05f62c607d..838e84883d1 100644 --- a/lib/Target/PIC16/PIC16RegisterInfo.cpp +++ b/lib/Target/PIC16/PIC16RegisterInfo.cpp @@ -15,206 +15,68 @@ #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; -// FIXME: add subtarget support. -PIC16RegisterInfo::PIC16RegisterInfo(const TargetInstrInfo &tii) +PIC16RegisterInfo::PIC16RegisterInfo(const TargetInstrInfo &tii, + const PIC16Subtarget &st) : PIC16GenRegisterInfo(PIC16::ADJCALLSTACKDOWN, PIC16::ADJCALLSTACKUP), - TII(tii) {} + TII(tii), + ST(st) {} -/// 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 = MBB.getParent()->CloneMachineInstr(Orig); - 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 -// -//===----------------------------------------------------------------------===// +#include "PIC16GenRegisterInfo.inc" /// PIC16 Callee Saved Registers const unsigned* PIC16RegisterInfo:: -getCalleeSavedRegs(const MachineFunction *MF) const -{ - // PIC16 calle-save register range is $16-$26(s0-s7) +getCalleeSavedRegs(const MachineFunction *MF) const { static const unsigned CalleeSavedRegs[] = { 0 }; return CalleeSavedRegs; } -/// PIC16 Callee Saved Register Classes -const TargetRegisterClass* const* -PIC16RegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const -{ +// PIC16 Callee Saved Reg 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 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 { +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); -} +eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, + RegScavenger *RS) const +{ /* NOT YET IMPLEMENTED */ } -// 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).isFI()) { - ++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); - - DOUT << "\nFunction : " << MF.getFunction()->getName() << "\n"; - DOUT << "<--------->\n"; -#ifndef NDEBUG - MI.print(DOUT); -#endif - DOUT << "FrameIndex : " << FrameIndex << "\n"; - DOUT << "spOffset : " << spOffset << "\n"; - DOUT << "stackSize : " << stackSize << "\n"; - - // As explained on LowerFORMAL_ARGUMENTS, detect negative offsets - // and adjust SPOffsets considering the final stack size. - int Offset = ((spOffset < 0) ? (stackSize + (-(spOffset+4))) : (spOffset)); - - DOUT << "Offset : " << Offset << "\n"; - DOUT << "<--------->\n"; - - // MI.getOperand(i+1).ChangeToImmediate(Offset); - MI.getOperand(i).ChangeToRegister(getFrameRegister(MF), false); -} +void PIC16RegisterInfo::emitPrologue(MachineFunction &MF) const +{ /* NOT YET IMPLEMENTED */ } 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; -} +emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const +{ /* NOT YET IMPLEMENTED */ } int PIC16RegisterInfo:: getDwarfRegNum(unsigned RegNum, bool isEH) const { - assert(0 && "What is the dwarf register number"); + assert(0 && "Not keeping track of debug information yet!!"); return -1; } +unsigned PIC16RegisterInfo::getFrameRegister(MachineFunction &MF) const { + assert(0 && "PIC16 Does not have any frame register"); + return 0; +} + +unsigned PIC16RegisterInfo::getRARegister() const { + assert(0 && "PIC16 Does not have any return address register"); + return 0; +} -#include "PIC16GenRegisterInfo.inc" diff --git a/lib/Target/PIC16/PIC16RegisterInfo.h b/lib/Target/PIC16/PIC16RegisterInfo.h index 8a85adc9b9d..aaabb411993 100644 --- a/lib/Target/PIC16/PIC16RegisterInfo.h +++ b/lib/Target/PIC16/PIC16RegisterInfo.h @@ -20,65 +20,43 @@ namespace llvm { // Forward Declarations. -class TargetInstrInfo; -class Type; + class PIC16Subtarget; + class TargetInstrInfo; -struct PIC16RegisterInfo : public PIC16GenRegisterInfo { - const TargetInstrInfo &TII; +class PIC16RegisterInfo : public PIC16GenRegisterInfo { + private: + const TargetInstrInfo &TII; + const PIC16Subtarget &ST; - explicit PIC16RegisterInfo(const TargetInstrInfo &tii); + public: + PIC16RegisterInfo(const TargetInstrInfo &tii, + const PIC16Subtarget &st); - /// 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; + //------------------------------------------------------ + // Pure virtual functions from TargetRegisterInfo + //------------------------------------------------------ - MachineInstr* foldMemoryOperand(MachineInstr* MI, unsigned OpNum, - int FrameIndex) const; + // PIC16 callee saved registers + virtual const unsigned* + getCalleeSavedRegs(const MachineFunction *MF = 0) const; - MachineInstr* foldMemoryOperand(MachineInstr* MI, unsigned OpNum, - MachineInstr* LoadMI) const { - return 0; - } + // PIC16 callee saved register classes + virtual const TargetRegisterClass* const * + getCalleeSavedRegClasses(const MachineFunction *MF) const; - void copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, - unsigned DestReg, unsigned SrcReg, - const TargetRegisterClass *RC) const; - + virtual BitVector getReservedRegs(const MachineFunction &MF) const; + virtual bool hasFP(const MachineFunction &MF) const; - const unsigned *getCalleeSavedRegs(const MachineFunction* MF = 0) const; + virtual void eliminateFrameIndex(MachineBasicBlock::iterator MI, + int SPAdj, RegScavenger *RS=NULL) const; - const TargetRegisterClass* const* - getCalleeSavedRegClasses(const MachineFunction* MF = 0) const; + virtual void emitPrologue(MachineFunction &MF) const; + virtual void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const; + virtual int getDwarfRegNum(unsigned RegNum, bool isEH) const; + virtual unsigned getFrameRegister(MachineFunction &MF) const; + virtual unsigned getRARegister() 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 diff --git a/lib/Target/PIC16/PIC16RegisterInfo.td b/lib/Target/PIC16/PIC16RegisterInfo.td index 21cc3e58108..938974f4d48 100644 --- a/lib/Target/PIC16/PIC16RegisterInfo.td +++ b/lib/Target/PIC16/PIC16RegisterInfo.td @@ -11,74 +11,22 @@ // Declarations that describe the PIC16 register file //===----------------------------------------------------------------------===// -// We have banks of 32 registers each. class PIC16Reg : Register { - field bits<5> Num; let Namespace = "PIC16"; } -// PIC16 CPU Registers -class PIC16GPRReg num, string n> : PIC16Reg { - let Num = num; -} +// PIC16 Registers. +def W : PIC16Reg<"W">; +def FSR0 : PIC16Reg<"FSR0">; +def FSR1 : PIC16Reg<"FSR1">; +def BS : PIC16Reg<"BS">; -// CPU GPR Registers -def FSR0 : PIC16GPRReg< 0, "FSR0">, DwarfRegNum<[0]>; -def FSR1 : PIC16GPRReg< 1, "FSR1">, DwarfRegNum<[1]>; +def STATUS : PIC16Reg<"STATUS">; -// 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(); - } - }]; -} +// PIC16 Register classes. +def GPR : RegisterClass<"PIC16", [i8], 8, [W]>; +def FSR16 : RegisterClass<"PIC16", [i16], 8, [FSR0, FSR1]>; +def BSR : RegisterClass<"PIC16", [i8], 8, [BS]>; -def WREG : PIC16GPRReg< 0, "WREG">, DwarfRegNum<[0]>; +def STATUSR: RegisterClass<"PIC16", [i8], 8, [STATUS]>; -// 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 index b7ebf94bc16..db8a5d84a4b 100644 --- a/lib/Target/PIC16/PIC16Subtarget.cpp +++ b/lib/Target/PIC16/PIC16Subtarget.cpp @@ -11,14 +11,14 @@ // //===----------------------------------------------------------------------===// -#include "PIC16.h" #include "PIC16Subtarget.h" #include "PIC16GenSubtarget.inc" + using namespace llvm; -PIC16Subtarget::PIC16Subtarget(const TargetMachine &TM, const Module &M, - const std::string &FS) - :IsPIC16Old(false) +PIC16Subtarget::PIC16Subtarget(const Module &M, const std::string &FS, + bool Cooper) + :IsCooper(Cooper) { std::string CPU = "generic"; diff --git a/lib/Target/PIC16/PIC16Subtarget.h b/lib/Target/PIC16/PIC16Subtarget.h index d7cb2392b07..c6eb7119d95 100644 --- a/lib/Target/PIC16/PIC16Subtarget.h +++ b/lib/Target/PIC16/PIC16Subtarget.h @@ -14,7 +14,6 @@ #ifndef PIC16SUBTARGET_H #define PIC16SUBTARGET_H -#include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetSubtarget.h" #include @@ -23,19 +22,23 @@ namespace llvm { class Module; class PIC16Subtarget : public TargetSubtarget { - bool IsPIC16Old; + + // IsCooper - Target ISA is Cooper. + bool IsCooper; 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); + PIC16Subtarget(const Module &M, const std::string &FS, bool Cooper); + /// isCooper - Returns true if the target ISA is Cooper. + bool isCooper() const { return IsCooper; } + /// 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 +#endif // PIC16SUBTARGET_H diff --git a/lib/Target/PIC16/PIC16TargetAsmInfo.cpp b/lib/Target/PIC16/PIC16TargetAsmInfo.cpp index 91dcbe3e058..4dcd41a99f4 100644 --- a/lib/Target/PIC16/PIC16TargetAsmInfo.cpp +++ b/lib/Target/PIC16/PIC16TargetAsmInfo.cpp @@ -17,11 +17,15 @@ using namespace llvm; PIC16TargetAsmInfo:: -PIC16TargetAsmInfo(const PIC16TargetMachine &TM) +PIC16TargetAsmInfo(const PIC16TargetMachine &TM) : TargetAsmInfo(TM) { - Data16bitsDirective = "\t.half\t"; - Data32bitsDirective = "\t.word\t"; CommentString = ";"; - COMMDirective = "\t"; - COMMDirectiveTakesAlignment = 0; + Data8bitsDirective = " db "; + Data16bitsDirective = " db "; + Data32bitsDirective = " db "; + DataSectionStartSuffix = " IDATA "; + UDataSectionStartSuffix = " UDATA "; + TextSectionStartSuffix = " CODE "; + RomDataSectionStartSuffix = " ROMDATA "; + ZeroDirective = NULL; } diff --git a/lib/Target/PIC16/PIC16TargetAsmInfo.h b/lib/Target/PIC16/PIC16TargetAsmInfo.h index 1401bab82d3..680c8e7e9ce 100644 --- a/lib/Target/PIC16/PIC16TargetAsmInfo.h +++ b/lib/Target/PIC16/PIC16TargetAsmInfo.h @@ -23,6 +23,17 @@ namespace llvm { struct PIC16TargetAsmInfo : public TargetAsmInfo { PIC16TargetAsmInfo(const PIC16TargetMachine &TM); + const char *UDataSectionStartSuffix; + const char *RomDataSectionStartSuffix; + public : + const char *getUDataSectionStartSuffix() const { + return UDataSectionStartSuffix; + } + const char *getRomDataSectionStartSuffix() const { + return RomDataSectionStartSuffix; + } + + }; } // namespace llvm diff --git a/lib/Target/PIC16/PIC16TargetMachine.cpp b/lib/Target/PIC16/PIC16TargetMachine.cpp index f2ddad14bf2..f3a96f777f4 100644 --- a/lib/Target/PIC16/PIC16TargetMachine.cpp +++ b/lib/Target/PIC16/PIC16TargetMachine.cpp @@ -16,6 +16,7 @@ #include "PIC16TargetMachine.h" #include "llvm/Module.h" #include "llvm/PassManager.h" +#include "llvm/CodeGen/Passes.h" #include "llvm/Target/TargetAsmInfo.h" #include "llvm/Target/TargetMachineRegistry.h" @@ -29,50 +30,42 @@ using namespace llvm; extern "C" int PIC16TargetMachineModule; int PIC16TargetMachineModule = 0; -namespace { - // Register the targets - RegisterTarget X("pic16", "PIC16 14-bit [experimental]"); -} -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"), +// Register the targets +static RegisterTarget +X("pic16", "PIC16 14-bit (experimental)."); +static RegisterTarget +Y("cooper", "PIC16 Cooper (experimental)."); + +// PIC16TargetMachine - Traditional PIC16 Machine. +PIC16TargetMachine::PIC16TargetMachine(const Module &M, const std::string &FS, + bool Cooper) +: Subtarget(M, FS, Cooper), + DataLayout("e-p:16:8:8-i8:8:8-i16:8:8-i32:8:8"), InstrInfo(*this), TLInfo(*this), FrameInfo(TargetFrameInfo::StackGrowsUp, 8, 0) { } +// CooperTargetMachine - Uses the same PIC16TargetMachine, but makes IsCooper +// as true. +CooperTargetMachine::CooperTargetMachine(const Module &M, const std::string &FS) + : PIC16TargetMachine(M, FS, true) {} -const TargetAsmInfo *PIC16TargetMachine::createTargetAsmInfo() const -{ + +const TargetAsmInfo *PIC16TargetMachine::createTargetAsmInfo() const { return new PIC16TargetAsmInfo(*this); } -//===----------------------------------------------------------------------===// -// Pass Pipeline Configuration -//===----------------------------------------------------------------------===// - -bool PIC16TargetMachine::addInstSelector(PassManagerBase &PM, bool Fast) -{ +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, raw_ostream &Out) -{ +addAssemblyEmitter(PassManagerBase &PM, bool Fast, raw_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 index bf0642f4f3a..85e14c1915d 100644 --- a/lib/Target/PIC16/PIC16TargetMachine.h +++ b/lib/Target/PIC16/PIC16TargetMachine.h @@ -17,6 +17,7 @@ #include "PIC16InstrInfo.h" #include "PIC16ISelLowering.h" +#include "PIC16RegisterInfo.h" #include "PIC16Subtarget.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetFrameInfo.h" @@ -31,31 +32,42 @@ class PIC16TargetMachine : public LLVMTargetMachine { const TargetData DataLayout; // Calculates type size & alignment PIC16InstrInfo InstrInfo; PIC16TargetLowering TLInfo; + + // PIC16 does not have any call stack frame, therefore not having + // any PIC16 specific FrameInfo class. TargetFrameInfo FrameInfo; protected: virtual const TargetAsmInfo *createTargetAsmInfo() const; - -public: - PIC16TargetMachine(const Module &M, const std::string &FS); - virtual const TargetFrameInfo *getFrameInfo() const - { return &FrameInfo; } - virtual const PIC16InstrInfo *getInstrInfo() const - { return &InstrInfo; } - virtual const TargetData *getTargetData() const - { return &DataLayout; } - virtual PIC16TargetLowering *getTargetLowering() const - { return const_cast(&TLInfo); } - virtual const PIC16RegisterInfo *getRegisterInfo() const - { return &InstrInfo.getRegisterInfo(); } - +public: + PIC16TargetMachine(const Module &M, const std::string &FS, + bool Cooper = false); + + virtual const TargetFrameInfo *getFrameInfo() const { return &FrameInfo; } + virtual const PIC16InstrInfo *getInstrInfo() const { return &InstrInfo; } + virtual const TargetData *getTargetData() const { return &DataLayout;} + virtual const PIC16Subtarget *getSubtargetImpl() const { return &Subtarget; } + + virtual const PIC16RegisterInfo *getRegisterInfo() const { + return &(InstrInfo.getRegisterInfo()); + } + + virtual PIC16TargetLowering *getTargetLowering() const { + return const_cast(&TLInfo); + } + 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, + virtual bool addAssemblyEmitter(PassManagerBase &PM, bool Fast, raw_ostream &Out); -}; +}; // PIC16TargetMachine. + +/// CooperTargetMachine +class CooperTargetMachine : public PIC16TargetMachine { +public: + CooperTargetMachine(const Module &M, const std::string &FS); +}; // CooperTargetMachine. + } // end namespace llvm #endif