diff options
author | Sanjiv Gupta <sanjiv.gupta@microchip.com> | 2009-01-13 19:18:47 +0000 |
---|---|---|
committer | Sanjiv Gupta <sanjiv.gupta@microchip.com> | 2009-01-13 19:18:47 +0000 |
commit | 1b0469411628d8f2d6a234016481bf9aafb14362 (patch) | |
tree | 30bbccda2d01f35e7a44dee659778411baf564a5 | |
parent | a1f50e2c2cad12dd8fe7ef80e394ee7a96654021 (diff) | |
download | external_llvm-1b0469411628d8f2d6a234016481bf9aafb14362.zip external_llvm-1b0469411628d8f2d6a234016481bf9aafb14362.tar.gz external_llvm-1b0469411628d8f2d6a234016481bf9aafb14362.tar.bz2 |
Checking in conditionals, function call, arrays and libcalls implementation.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@62174 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Target/PIC16/Makefile | 6 | ||||
-rw-r--r-- | lib/Target/PIC16/PIC16.h | 27 | ||||
-rw-r--r-- | lib/Target/PIC16/PIC16AsmPrinter.cpp | 152 | ||||
-rw-r--r-- | lib/Target/PIC16/PIC16AsmPrinter.h | 8 | ||||
-rw-r--r-- | lib/Target/PIC16/PIC16ISelLowering.cpp | 942 | ||||
-rw-r--r-- | lib/Target/PIC16/PIC16ISelLowering.h | 86 | ||||
-rw-r--r-- | lib/Target/PIC16/PIC16InstrInfo.cpp | 13 | ||||
-rw-r--r-- | lib/Target/PIC16/PIC16InstrInfo.td | 155 | ||||
-rw-r--r-- | lib/Target/PIC16/PIC16RegisterInfo.cpp | 9 | ||||
-rw-r--r-- | lib/Target/PIC16/PIC16RegisterInfo.h | 4 | ||||
-rw-r--r-- | lib/Target/PIC16/PIC16TargetAsmInfo.cpp | 12 | ||||
-rw-r--r-- | lib/Target/PIC16/PIC16TargetAsmInfo.h | 10 |
12 files changed, 1149 insertions, 275 deletions
diff --git a/lib/Target/PIC16/Makefile b/lib/Target/PIC16/Makefile index 3975849..c429324 100644 --- a/lib/Target/PIC16/Makefile +++ b/lib/Target/PIC16/Makefile @@ -1,10 +1,10 @@ ##===- lib/Target/PIC16/Makefile ---------------------------*- Makefile -*-===## -# +# # The LLVM Compiler Infrastructure # -# This file is distributed under the University of Illinois Open Source +# This file is distributed under the University of Illinois Open Source # License. See LICENSE.TXT for details. -# +# ##===----------------------------------------------------------------------===## LEVEL = ../../.. LIBRARYNAME = LLVMPIC16 diff --git a/lib/Target/PIC16/PIC16.h b/lib/Target/PIC16/PIC16.h index 6850bd6..f9f51ab 100644 --- a/lib/Target/PIC16/PIC16.h +++ b/lib/Target/PIC16/PIC16.h @@ -15,12 +15,39 @@ #ifndef LLVM_TARGET_PIC16_H #define LLVM_TARGET_PIC16_H +#include <iosfwd> +#include <cassert> + namespace llvm { class PIC16TargetMachine; class FunctionPass; class MachineCodeEmitter; class raw_ostream; +namespace PIC16CC { + enum CondCodes { + EQ, + NE, + LT, + LE, + GT, + GE + }; +} + + inline static const char *PIC16CondCodeToString(PIC16CC::CondCodes CC) { + switch (CC) { + default: assert(0 && "Unknown condition code"); + case PIC16CC::NE: return "ne"; + case PIC16CC::EQ: return "eq"; + case PIC16CC::LT: return "lt"; + case PIC16CC::LE: return "le"; + case PIC16CC::GT: return "gt"; + case PIC16CC::GE: return "ge"; + } + } + + FunctionPass *createPIC16ISelDag(PIC16TargetMachine &TM); FunctionPass *createPIC16CodePrinterPass(raw_ostream &OS, PIC16TargetMachine &TM); diff --git a/lib/Target/PIC16/PIC16AsmPrinter.cpp b/lib/Target/PIC16/PIC16AsmPrinter.cpp index d468efd..dc91128 100644 --- a/lib/Target/PIC16/PIC16AsmPrinter.cpp +++ b/lib/Target/PIC16/PIC16AsmPrinter.cpp @@ -24,6 +24,33 @@ using namespace llvm; #include "PIC16GenAsmWriter.inc" +bool PIC16AsmPrinter::inSameBank (char *s1, char *s2){ + + assert (s1 && s2 && "Null pointer assignment"); + + if ((*s1 == '.') && (*s2 == '.')) { //skip if they both start with '.' + s1++; + s2++; + } + while (*s1 && *s2) { + if (*s1 != *s2) + goto _NotInSameBank; + + if ((*s1 == '.') && (*s2 == '.')) //both symbols in same function + goto _InSameBank; //in the same bank + + s1++; + s2++; + } + + if (*s1 && *s1) { + _InSameBank: + return true; + } + + _NotInSameBank: + return false; +} bool PIC16AsmPrinter::printMachineInstruction(const MachineInstr *MI) { std::string NewBankselLabel; @@ -45,8 +72,8 @@ bool PIC16AsmPrinter::printMachineInstruction(const MachineInstr *MI) { // generate banksel. const MachineOperand &BS = MI->getOperand(Operands-1); if (((int)BS.getImm() == 1) && - (strcmp (CurrentBankselLabelInBasicBlock.c_str(), - NewBankselLabel.c_str()))) { + (!inSameBank ((char *)CurrentBankselLabelInBasicBlock.c_str(), + (char *)NewBankselLabel.c_str()))) { CurrentBankselLabelInBasicBlock = NewBankselLabel; O << "\tbanksel "; printOperand(MI, Operands-2); @@ -73,9 +100,11 @@ bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF) { // Emit the function variables. emitFunctionData(MF); std::string codeSection; - codeSection = "code." + CurrentFnName + ".#"; + codeSection = "code." + CurrentFnName + ".# " + "CODE"; + const Section *fCodeSection = TAI->getNamedSection(codeSection.c_str(), + SectionFlags::Code); O << "\n"; - SwitchToTextSection (codeSection.c_str(),F); + SwitchToSection (fCodeSection); // Print out code for the function. for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); @@ -130,11 +159,21 @@ void PIC16AsmPrinter::printOperand(const MachineInstr *MI, int opNum) { O << MO.getSymbolName(); break; + case MachineOperand::MO_MachineBasicBlock: + printBasicBlockLabel(MO.getMBB()); + return; + default: assert(0 && " Operand type not supported."); } } +void PIC16AsmPrinter::printCCOperand(const MachineInstr *MI, int opNum) { + int CC = (int)MI->getOperand(opNum).getImm(); + O << PIC16CondCodeToString((PIC16CC::CondCodes)CC); +} + + bool PIC16AsmPrinter::doInitialization (Module &M) { bool Result = AsmPrinter::doInitialization(M); // FIXME:: This is temporary solution to generate the include file. @@ -166,6 +205,10 @@ void PIC16AsmPrinter::EmitExternsAndGlobals (Module &M) { O << "\tglobal " << Name << ".args\n"; } } + + // Emit header file to include declaration of library functions + O << "\t#include C16IntrinsicCalls.INC\n"; + // Emit declarations for external globals. for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); I != E; I++) { @@ -177,8 +220,7 @@ void PIC16AsmPrinter::EmitExternsAndGlobals (Module &M) { } } void PIC16AsmPrinter::EmitInitData (Module &M) { - std::string iDataSection = "idata.#"; - SwitchToDataSection(iDataSection.c_str()); + SwitchToSection(TAI->getDataSection()); for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) { if (!I->hasInitializer()) // External global require no code. @@ -244,8 +286,7 @@ void PIC16AsmPrinter::EmitConstantValueOnly(const Constant* CV) { void PIC16AsmPrinter::EmitRomData (Module &M) { - std::string romDataSection = "romdata.#"; - SwitchToRomDataSection(romDataSection.c_str()); + SwitchToSection(TAI->getReadOnlySection()); IsRomData = true; for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) { @@ -274,11 +315,9 @@ void PIC16AsmPrinter::EmitRomData (Module &M) IsRomData = false; } - void PIC16AsmPrinter::EmitUnInitData (Module &M) { - std::string uDataSection = "udata.#"; - SwitchToUDataSection(uDataSection.c_str()); + SwitchToSection(TAI->getBSSSection_()); const TargetData *TD = TM.getTargetData(); for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); @@ -300,6 +339,7 @@ void PIC16AsmPrinter::EmitUnInitData (Module &M) const Type *Ty = C->getType(); unsigned Size = TD->getTypePaddedSize(Ty); + O << name << " " <<"RES"<< " " << Size ; O << "\n"; } @@ -317,29 +357,24 @@ void PIC16AsmPrinter::emitFunctionData(MachineFunction &MF) { std::string FuncName = Mang->getValueName(F); const Module *M = F->getParent(); const TargetData *TD = TM.getTargetData(); - + unsigned FrameSize = 0; // Emit the data section name. O << "\n"; - std::string fDataSection = "fdata." + CurrentFnName + ".#"; - SwitchToUDataSection(fDataSection.c_str(), F); + std::string SectionName = "fdata." + CurrentFnName + ".# " + "UDATA"; + + const Section *fDataSection = TAI->getNamedSection(SectionName.c_str(), + SectionFlags::Writeable); + SwitchToSection(fDataSection); //Emit function return value. O << CurrentFnName << ".retval:\n"; const Type *RetType = F->getReturnType(); - if (RetType->getTypeID() != Type::VoidTyID) { - unsigned RetSize = TD->getTypePaddedSize(RetType); - if (RetSize > 0) - O << CurrentFnName << ".retval" << " RES " << RetSize; - } + unsigned RetSize = 0; + if (RetType->getTypeID() != Type::VoidTyID) + RetSize = TD->getTypePaddedSize(RetType); + // Emit function arguments. O << CurrentFnName << ".args:\n"; - for (Function::const_arg_iterator AI = F->arg_begin(), AE = F->arg_end(); - AI != AE; ++AI) { - std::string ArgName = Mang->getValueName(AI); - const Type *ArgTy = AI->getType(); - unsigned ArgSize = TD->getTypePaddedSize(ArgTy); - O << CurrentFnName << ".args." << ArgName << " RES " << ArgSize; - } // Emit the function variables. // In PIC16 all the function arguments and local variables are global. @@ -358,22 +393,28 @@ void PIC16AsmPrinter::emitFunctionData(MachineFunction &MF) { Constant *C = I->getInitializer(); const Type *Ty = C->getType(); unsigned Size = TD->getTypePaddedSize(Ty); + FrameSize += Size; // Emit memory reserve directive. O << VarName << " RES " << Size << "\n"; } - emitFunctionTempData(MF); + emitFunctionTempData(MF, FrameSize); + if (RetSize > FrameSize) + O << CurrentFnName << ".dummy" << "RES" << (RetSize - FrameSize); } -void PIC16AsmPrinter::emitFunctionTempData(MachineFunction &MF) { +void PIC16AsmPrinter::emitFunctionTempData(MachineFunction &MF, + unsigned &FrameSize) { // Emit temporary variables. MachineFrameInfo *FrameInfo = MF.getFrameInfo(); if (FrameInfo->hasStackObjects()) { int indexBegin = FrameInfo->getObjectIndexBegin(); int indexEnd = FrameInfo->getObjectIndexEnd(); - if (indexBegin < indexEnd) + if (indexBegin < indexEnd) { + FrameSize += indexEnd - indexBegin; O << CurrentFnName << ".tmp RES"<< " " <<indexEnd - indexBegin <<"\n"; + } /* while (indexBegin < indexEnd) { O << CurrentFnName << "_tmp_" << indexBegin << " " << "RES"<< " " @@ -383,56 +424,3 @@ void PIC16AsmPrinter::emitFunctionTempData(MachineFunction &MF) { */ } } - -/// 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 - 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))-> - getUDataSectionStartSuffix() << '\n'; - - IsInTextSection = false; -} - -/// 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 - 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/PIC16AsmPrinter.h b/lib/Target/PIC16/PIC16AsmPrinter.h index b0a2baf..876e4be 100644 --- a/lib/Target/PIC16/PIC16AsmPrinter.h +++ b/lib/Target/PIC16/PIC16AsmPrinter.h @@ -36,10 +36,7 @@ namespace llvm { bool runOnMachineFunction(MachineFunction &F); void printOperand(const MachineInstr *MI, int opNum); - void SwitchToUDataSection(const char *NewSection, - const GlobalValue *GV = NULL); - void SwitchToRomDataSection(const char *NewSection, - const GlobalValue *GV = NULL); + void printCCOperand(const MachineInstr *MI, int opNum); bool printInstruction(const MachineInstr *MI); // definition autogenerated. bool printMachineInstruction(const MachineInstr *MI); void EmitExternsAndGlobals (Module &M); @@ -48,11 +45,12 @@ namespace llvm { void EmitRomData (Module &M); virtual void EmitConstantValueOnly(const Constant *CV); void emitFunctionData(MachineFunction &MF); - void emitFunctionTempData(MachineFunction &MF); + void emitFunctionTempData(MachineFunction &MF, unsigned &FrameSize); protected: bool doInitialization(Module &M); bool doFinalization(Module &M); + bool inSameBank(char *s1, char *s2); private: std::string CurrentBankselLabelInBasicBlock; diff --git a/lib/Target/PIC16/PIC16ISelLowering.cpp b/lib/Target/PIC16/PIC16ISelLowering.cpp index 880fcc9..1f1f9e4 100644 --- a/lib/Target/PIC16/PIC16ISelLowering.cpp +++ b/lib/Target/PIC16/PIC16ISelLowering.cpp @@ -1,4 +1,3 @@ -//===-- PIC16ISelLowering.cpp - PIC16 DAG Lowering Implementation ---------===// // // The LLVM Compiler Infrastructure // @@ -19,8 +18,11 @@ #include "llvm/DerivedTypes.h" #include "llvm/GlobalValue.h" #include "llvm/Function.h" +#include "llvm/CallingConv.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" #include <cstdio> @@ -38,6 +40,20 @@ PIC16TargetLowering::PIC16TargetLowering(PIC16TargetMachine &TM) setShiftAmountType(MVT::i8); setShiftAmountFlavor(Extend); + // SRA library call names + setPIC16LibCallName(PIC16ISD::SRA_I8, "__intrinsics.sra.i8"); + setPIC16LibCallName(PIC16ISD::SRA_I16, "__intrinsics.sra.i16"); + setPIC16LibCallName(PIC16ISD::SRA_I32, "__intrinsics.sra.i32"); + + // SLL library call names + setPIC16LibCallName(PIC16ISD::SLL_I8, "__intrinsics.sll.i8"); + setPIC16LibCallName(PIC16ISD::SLL_I16, "__intrinsics.sll.i16"); + setPIC16LibCallName(PIC16ISD::SLL_I32, "__intrinsics.sll.i32"); + + // SRL library call names + setPIC16LibCallName(PIC16ISD::SRL_I8, "__intrinsics.srl.i8"); + setPIC16LibCallName(PIC16ISD::SRL_I16, "__intrinsics.srl.i16"); + setPIC16LibCallName(PIC16ISD::SRL_I32, "__intrinsics.srl.i32"); setOperationAction(ISD::GlobalAddress, MVT::i16, Custom); @@ -60,8 +76,29 @@ PIC16TargetLowering::PIC16TargetLowering(PIC16TargetMachine &TM) setOperationAction(ISD::AND, MVT::i8, Custom); setOperationAction(ISD::XOR, MVT::i8, Custom); + setOperationAction(ISD::FrameIndex, MVT::i16, Custom); + setOperationAction(ISD::CALL, MVT::i16, Custom); + setOperationAction(ISD::RET, MVT::Other, Custom); + + setOperationAction(ISD::SRA, MVT::i8, Custom); + setOperationAction(ISD::SRA, MVT::i16, Custom); + setOperationAction(ISD::SRA, MVT::i32, Custom); + + setOperationAction(ISD::SHL, MVT::i8, Custom); setOperationAction(ISD::SHL, MVT::i16, Custom); setOperationAction(ISD::SHL, MVT::i32, Custom); + setOperationAction(ISD::SRL, MVT::i8, Custom); + setOperationAction(ISD::SRL, MVT::i16, Custom); + setOperationAction(ISD::SRL, MVT::i32, Custom); + + // PIC16 does not have a SETCC, expand it to SELECT_CC. + setOperationAction(ISD::SETCC, MVT::i8, Expand); + setOperationAction(ISD::SELECT, MVT::i8, Expand); + setOperationAction(ISD::BRCOND, MVT::Other, Expand); + setOperationAction(ISD::BRIND, MVT::Other, Expand); + + setOperationAction(ISD::SELECT_CC, MVT::i8, Custom); + setOperationAction(ISD::BR_CC, MVT::i8, Custom); //setOperationAction(ISD::TRUNCATE, MVT::i16, Custom); setTruncStoreAction(MVT::i16, MVT::i8, Custom); @@ -71,6 +108,100 @@ PIC16TargetLowering::PIC16TargetLowering(PIC16TargetMachine &TM) computeRegisterProperties(); } +static void PopulateResults(SDValue N, SmallVectorImpl<SDValue>&Results) { + if (N.getOpcode() == ISD::MERGE_VALUES) { + int NumResults = N.getNumOperands(); + for( int i = 0; i < NumResults; i++) + Results.push_back(N.getOperand(i)); + } + else + Results.push_back(N); +} + +MVT PIC16TargetLowering::getSetCCResultType(MVT ValType) const { + return MVT::i8; +} + + +void +PIC16TargetLowering::setPIC16LibCallName(PIC16ISD::PIC16LibCall Call, + const char *Name) { + PIC16LibCallNames[Call] = Name; +} + +const char * +PIC16TargetLowering::getPIC16LibCallName(PIC16ISD::PIC16LibCall Call) { + return PIC16LibCallNames[Call]; +} + +SDValue +PIC16TargetLowering::MakePIC16LibCall(PIC16ISD::PIC16LibCall Call, + MVT RetVT, const SDValue *Ops, + unsigned NumOps, bool isSigned, + SelectionDAG &DAG) { + + TargetLowering::ArgListTy Args; + Args.reserve(NumOps); + + TargetLowering::ArgListEntry Entry; + for (unsigned i = 0; i != NumOps; ++i) { + Entry.Node = Ops[i]; + Entry.Ty = Entry.Node.getValueType().getTypeForMVT(); + Entry.isSExt = isSigned; + Entry.isZExt = !isSigned; + Args.push_back(Entry); + } + SDValue Callee = DAG.getExternalSymbol(getPIC16LibCallName(Call), MVT::i8); + + const Type *RetTy = RetVT.getTypeForMVT(); + std::pair<SDValue,SDValue> CallInfo = + LowerCallTo(DAG.getEntryNode(), RetTy, isSigned, !isSigned, false, + false, CallingConv::C, false, Callee, Args, DAG); + + return CallInfo.first; +} + +SDValue +PIC16TargetLowering::getCurrentFrame(SelectionDAG &DAG) { + MachineFunction &MF = DAG.getMachineFunction(); + const Function *Func = MF.getFunction(); + const std::string FuncName = Func->getName(); + + // this is causing memory waste + // because for every call new memory will be allocated + char *tmpName = new char [strlen(FuncName.c_str()) + 6]; + sprintf(tmpName, "%s.tmp", FuncName.c_str()); + + // if the external symbol of the same name already exists then + // it will not create the new one. + return DAG.getTargetExternalSymbol(tmpName, MVT::i8); +} + +void +PIC16TargetLowering::getCurrentFrameIndex(SelectionDAG &DAG, SDValue &ES, + unsigned SlotSize, int &FromFI) { + MachineFunction &MF = DAG.getMachineFunction(); + const Function *Func = MF.getFunction(); + const std::string FuncName = Func->getName(); + + // this is causing memory waste + // because for every call new memory will be allocated + char *tmpName = new char [strlen(FuncName.c_str()) + 6]; + sprintf(tmpName, "%s.tmp", FuncName.c_str()); + + // if the external symbol of the same name already exists then + // it will not create the new one. + ES = DAG.getTargetExternalSymbol(tmpName, MVT::i8); + + // Alignment is always 1 + //FromFI = MF.getFrameInfo()->CreateStackObject(SlotSize, 1); + FromFI = MF.getFrameInfo()->CreateStackObject(1, 1); + int FI; + for(unsigned i=1;i<SlotSize; ++i) { + FI = MF.getFrameInfo()->CreateStackObject(1, 1); + } +} + const char *PIC16TargetLowering::getTargetNodeName(unsigned Opcode) const { switch (Opcode) { default: return NULL; @@ -80,12 +211,18 @@ const char *PIC16TargetLowering::getTargetNodeName(unsigned Opcode) const { case PIC16ISD::MTHI: return "PIC16ISD::MTHI"; case PIC16ISD::Banksel: return "PIC16ISD::Banksel"; case PIC16ISD::PIC16Load: return "PIC16ISD::PIC16Load"; + case PIC16ISD::PIC16LdWF: return "PIC16ISD::PIC16LdWF"; case PIC16ISD::PIC16Store: return "PIC16ISD::PIC16Store"; + case PIC16ISD::PIC16StWF: return "PIC16ISD::PIC16StWF"; 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::CALL: return "PIC16ISD::CALL"; + case PIC16ISD::SUBCC: return "PIC16ISD::SUBCC"; + case PIC16ISD::SELECT_ICC: return "PIC16ISD::SELECT_ICC"; + case PIC16ISD::BRCOND: return "PIC16ISD::BRCOND"; case PIC16ISD::Dummy: return "PIC16ISD::Dummy"; } } @@ -93,32 +230,68 @@ const char *PIC16TargetLowering::getTargetNodeName(unsigned Opcode) const { void PIC16TargetLowering::ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue>&Results, SelectionDAG &DAG) { + switch (N->getOpcode()) { case ISD::GlobalAddress: Results.push_back(ExpandGlobalAddress(N, DAG)); return; + case ISD::ExternalSymbol: + Results.push_back(ExpandExternalSymbol(N, DAG)); + return; case ISD::STORE: Results.push_back(ExpandStore(N, DAG)); return; case ISD::LOAD: - Results.push_back(ExpandLoad(N, DAG)); + PopulateResults(ExpandLoad(N, DAG), Results); return; case ISD::ADD: -// return ExpandAdd(N, DAG); + // Results.push_back(ExpandAdd(N, DAG)); return; - case ISD::SHL: { + case ISD::SHL: + case ISD::SRL: + case ISD::SRA: + { SDValue Res = ExpandShift(N, DAG); if (Res.getNode()) Results.push_back(Res); return; } + case ISD::FrameIndex: + Results.push_back(ExpandFrameIndex(N, DAG)); + return; default: assert (0 && "not implemented"); return; } } -SDValue PIC16TargetLowering::ExpandStore(SDNode *N, SelectionDAG &DAG) { +SDValue PIC16TargetLowering::ExpandFrameIndex(SDNode *N, SelectionDAG &DAG) { + + // Currently handling FrameIndex of size MVT::i16 only + // One example of this scenario is when return value is written on + // FrameIndex#0 + + if (N->getValueType(0) != MVT::i16) + return SDValue(); + + // Expand the FrameIndex into ExternalSymbol and a Constant node + // The constant will represent the frame index number + // Get the current function frame + MachineFunction &MF = DAG.getMachineFunction(); + const Function *Func = MF.getFunction(); + const std::string Name = Func->getName(); + + FrameIndexSDNode *FR = dyn_cast<FrameIndexSDNode>(SDValue(N,0)); + int Index = FR->getIndex(); + + SDValue FI[2]; + FI[0] = DAG.getTargetFrameIndex(Index, MVT::i8); + FI[1] = DAG.getTargetFrameIndex(Index + 1, MVT::i8); + return DAG.getNode(ISD::BUILD_PAIR, N->getValueType(0), FI[0], FI[1]); +} + + +SDValue PIC16TargetLowering::ExpandStore(SDNode *N, SelectionDAG &DAG) { StoreSDNode *St = cast<StoreSDNode>(N); SDValue Chain = St->getChain(); SDValue Src = St->getValue(); @@ -131,7 +304,8 @@ SDValue PIC16TargetLowering::ExpandStore(SDNode *N, SelectionDAG &DAG) { if (ValueType == MVT::i8) { return DAG.getNode (PIC16ISD::PIC16Store, MVT::Other, Chain, Src, - PtrLo, PtrHi, DAG.getConstant (0, MVT::i8)); + PtrLo, PtrHi, + DAG.getConstant (0 + StoreOffset, MVT::i8)); } else if (ValueType == MVT::i16) { // Get the Lo and Hi parts from MERGE_VALUE or BUILD_PAIR. @@ -200,7 +374,8 @@ SDValue PIC16TargetLowering::ExpandStore(SDNode *N, SelectionDAG &DAG) { getChain(Store2)); SDValue RetHi = DAG.getNode(ISD::TokenFactor, MVT::Other, getChain(Store3), getChain(Store4)); - return DAG.getNode(ISD::TokenFactor, MVT::Other, RetLo, RetHi); + return DAG.getNode(ISD::TokenFactor, MVT::Other, RetLo, RetHi); + } else { assert (0 && "value type not supported"); @@ -208,6 +383,18 @@ SDValue PIC16TargetLowering::ExpandStore(SDNode *N, SelectionDAG &DAG) { } } +SDValue PIC16TargetLowering::ExpandExternalSymbol(SDNode *N, SelectionDAG &DAG) +{ + ExternalSymbolSDNode *ES = dyn_cast<ExternalSymbolSDNode>(SDValue(N, 0)); + + SDValue TES = DAG.getTargetExternalSymbol(ES->getSymbol(), MVT::i8); + + SDValue Lo = DAG.getNode(PIC16ISD::Lo, MVT::i8, TES); + SDValue Hi = DAG.getNode(PIC16ISD::Hi, MVT::i8, TES); + + return DAG.getNode(ISD::BUILD_PAIR, MVT::i16, Lo, Hi); +} + // ExpandGlobalAddress - SDValue PIC16TargetLowering::ExpandGlobalAddress(SDNode *N, SelectionDAG &DAG) { GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(SDValue(N, 0)); @@ -218,8 +405,7 @@ SDValue PIC16TargetLowering::ExpandGlobalAddress(SDNode *N, SelectionDAG &DAG) { SDValue Lo = DAG.getNode(PIC16ISD::Lo, MVT::i8, TGA); SDValue Hi = DAG.getNode(PIC16ISD::Hi, MVT::i8, TGA); - SDValue BP = DAG.getNode(ISD::BUILD_PAIR, MVT::i16, Lo, Hi); - return BP; + return DAG.getNode(ISD::BUILD_PAIR, MVT::i16, Lo, Hi); } bool PIC16TargetLowering::isDirectAddress(const SDValue &Op) { @@ -259,6 +445,15 @@ bool PIC16TargetLowering::isRomAddress(const SDValue &Op) { return false; } +// Extract the out flag +SDValue PIC16TargetLowering::getOutFlag(SDValue &Op) { + SDValue Flag = Op.getValue(Op.getNode()->getNumValues() - 1); + + assert (Flag.getValueType() == MVT::Flag && "Node does not have an out Flag"); + + return Flag; +} + // 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 @@ -266,6 +461,11 @@ bool PIC16TargetLowering::isRomAddress(const SDValue &Op) { SDValue PIC16TargetLowering::getChain(SDValue &Op) { SDValue Chain = Op.getValue(Op.getNode()->getNumValues() - 1); + // If the last value returned in Flag then the chain is + // second last value returned. + if (Chain.getValueType() == MVT::Flag) + Chain = Op.getValue(Op.getNode()->getNumValues() - 2); + // 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"); @@ -274,35 +474,40 @@ SDValue PIC16TargetLowering::getChain(SDValue &Op) { } void PIC16TargetLowering::GetExpandedParts(SDValue Op, SelectionDAG &DAG, + SDValue &Lo, SDValue &Hi) { SDNode *N = Op.getNode(); - unsigned NumValues = N->getNumValues(); - std::vector<MVT> VTs; MVT NewVT; std::vector<SDValue> Opers; - - // 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. - - for (unsigned i=0;i < NumValues; ++i) { - NewVT = getTypeToTransformTo(N->getValueType(i)); - VTs.push_back(NewVT); - } + NewVT = getTypeToTransformTo(N->getValueType(0)); // 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()); - + Lo = DAG.getNode(ISD::EXTRACT_ELEMENT,NewVT,&Opers[0],Opers.size()); // 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()); + Hi = DAG.getNode(ISD::EXTRACT_ELEMENT,NewVT,&Opers[0],Opers.size()); +} + +// Legalize FrameIndex into ExternalSymbol and offset. +void +PIC16TargetLowering::LegalizeFrameIndex(SDValue Op, SelectionDAG &DAG, + SDValue &ES, int &Offset) { + + MachineFunction &MF = DAG.getMachineFunction(); + const Function *Func = MF.getFunction(); + const std::string Name = Func->getName(); + + char *tmpName = new char [strlen(Name.c_str()) + 8]; + sprintf(tmpName, "%s.args", Name.c_str()); + ES = DAG.getTargetExternalSymbol(tmpName, MVT::i8); + FrameIndexSDNode *FR = dyn_cast<FrameIndexSDNode>(Op); + Offset = FR->getIndex(); + + return; } // This function legalizes the PIC16 Addresses. If the Pointer is @@ -332,12 +537,35 @@ void PIC16TargetLowering:: LegalizeAddress(SDValue Ptr, SelectionDAG &DAG, if (OperLeft.getOpcode() == ISD::Constant) { Offset = dyn_cast<ConstantSDNode>(OperLeft)->getZExtValue(); Ptr = OperRight; - } else { - Ptr = OperLeft; + } else if (OperRight.getOpcode() == ISD::Constant) { Offset = dyn_cast<ConstantSDNode>(OperRight)->getZExtValue(); + Ptr = OperLeft; } } + // If the pointer is Type i8 and an external symbol + // then treat it as direct address. + // One example for such case is storing and loading + // from function frame during a call + if (Ptr.getValueType() == MVT::i8) { + switch (Ptr.getOpcode()) { + case ISD::TargetExternalSymbol: + Lo = Ptr; + Hi = DAG.getConstant(1, MVT::i8); + return; + } + } + + if (Ptr.getOpcode() == ISD::BUILD_PAIR && + Ptr.getOperand(0).getOpcode() == ISD::TargetFrameIndex) { + + int FrameOffset; + LegalizeFrameIndex(Ptr.getOperand(0), DAG, Lo, FrameOffset); + Hi = DAG.getConstant(1, MVT::i8); + Offset += FrameOffset; + return; + } + if (isDirectAddress(Ptr) && !isRomAddress(Ptr)) { // Direct addressing case for RAM variables. The Hi part is constant // and the Lo part is the TGA itself. @@ -361,17 +589,17 @@ void PIC16TargetLowering:: LegalizeAddress(SDValue Ptr, SelectionDAG &DAG, 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; +//SDValue 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 SDValue(); + //} + + // These case are yet to be handled + //return SDValue(); //} SDValue PIC16TargetLowering::ExpandLoad(SDNode *N, SelectionDAG &DAG) { @@ -484,70 +712,124 @@ SDValue PIC16TargetLowering::ExpandShift(SDNode *N, SelectionDAG &DAG) { SDValue Value = N->getOperand(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 = PIC16ISD::Dummy, RotNode = PIC16ISD::Dummy; - - // Currently handling Constant shift only - if (Amt.getOpcode() != ISD::Constant) - return SDValue(); - - // Following code considers 16 bit left-shift only - if (N->getValueType(0) != MVT::i16) - return SDValue(); - if (N->getOpcode() == ISD::SHL) { - ShfNode = PIC16ISD::LSLF; - RotNode = PIC16ISD::RLF; - } else if (N->getOpcode() == ISD::SRL) { - ShfNode = PIC16ISD::LRLF; - RotNode = PIC16ISD::RRF; + PIC16ISD::PIC16LibCall CallCode; + + // Shift amount should be MVT::i8 only. If it is more than that then + // extract MVT::i8 from that + if (Amt.getValueType() == MVT::i8) { + // Do Nothing - This is ok + } else if (Amt.getValueType() == MVT::i16) { + SDValue Lo, Hi; + GetExpandedParts(Amt, DAG, Lo, Hi); + Amt = Lo; // Take the Lo part as amount + + } else if (Amt.getValueType() == MVT::i32) { + SDValue Lo, Hi; + // Get MVT::i16 Components + GetExpandedParts(Amt, DAG, Lo, Hi); + // Get MVT::i8 Components + GetExpandedParts(Lo, DAG, Lo, Hi); + Amt = Lo; + + } else { + assert ( 0 && "Invalid Shift amount"); } - unsigned ShiftAmt = dyn_cast<ConstantSDNode>(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;i<ShiftAmt;i++) { - BCF = DAG.getNode(PIC16ISD::BCF, MVT::Flag, StatusReg, CarryBit, BCFInput); - - // Following are Two-Address Instructions - ShfCom = DAG.getNode(ShfNode, Tys, ShfCom, BCF); - RotCom = DAG.getNode(RotNode, Tys, RotCom, ShfCom.getValue(1)); - - BCFInput = RotCom.getValue(1); + // Shift library call will always have two operands + if (N->getValueType(0) == MVT::i8) { + switch (N->getOpcode()) { + case ISD::SRA: + CallCode = PIC16ISD::SRA_I8; + break; + case ISD::SHL: + CallCode = PIC16ISD::SLL_I8; + break; + case ISD::SRL: + CallCode = PIC16ISD::SRL_I8; + break; + default: + assert ( 0 && "This shift is not implemented yet."); + return SDValue(); + } + } else if (N->getValueType(0) == MVT::i16) { + switch (N->getOpcode()) { + case ISD::SRA: + CallCode = PIC16ISD::SRA_I16; + break; + case ISD::SHL: + CallCode = PIC16ISD::SLL_I16; + break; + case ISD::SRL: + CallCode = PIC16ISD::SRL_I16; + break; + default: + assert ( 0 && "This shift is not implemented yet."); + return SDValue(); + } + } else if (N->getValueType(0) == MVT::i32) { + switch (N->getOpcode()) { + case ISD::SRA: + CallCode = PIC16ISD::SRA_I32; + break; + case ISD::SHL: + CallCode = PIC16ISD::SLL_I32; + break; + case ISD::SRL: + CallCode = PIC16ISD::SRL_I32; + break; + default: + assert ( 0 && "This shift is not implemented yet."); + return SDValue(); + } + } else { + //assert ( 0 && "Shift for this value type not yet implemented."); + return SDValue(); } - return DAG.getNode(ISD::BUILD_PAIR, N->getValueType(0), ShfCom, RotCom); + SmallVector<SDValue, 2> Ops(2); + Ops[0] = Value; + Ops[1] = Amt; + SDValue Call = MakePIC16LibCall(CallCode, N->getValueType(0), &Ops[0], 2, true, DAG); + return Call; } SDValue PIC16TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) { switch (Op.getOpcode()) { case ISD::FORMAL_ARGUMENTS: return LowerFORMAL_ARGUMENTS(Op, DAG); + case ISD::ADD: case ISD::ADDC: - return LowerADDC(Op, DAG); case ISD::ADDE: - return LowerADDE(Op, DAG); - case ISD::SUBE: - return LowerSUBE(Op, DAG); + return LowerADD(Op, DAG); + case ISD::SUB: case ISD::SUBC: - return LowerSUBC(Op, DAG); + case ISD::SUBE: + return LowerSUB(Op, DAG); case ISD::LOAD: return ExpandLoad(Op.getNode(), DAG); case ISD::STORE: return ExpandStore(Op.getNode(), DAG); case ISD::SHL: + case ISD::SRA: + case ISD::SRL: return ExpandShift(Op.getNode(), DAG); case ISD::OR: case ISD::AND: case ISD::XOR: return LowerBinOp(Op, DAG); + case ISD::CALL: + // This is called only from LegalizeDAG. No call is made to + // legalize CALL node from LegalizeType. + return LowerCALL(Op, DAG); + case ISD::RET: + return LowerRET(Op, DAG); + case ISD::BR_CC: + return LowerBR_CC(Op, DAG); + case ISD::SELECT_CC: + return LowerSELECT_CC(Op, DAG); } return SDValue(); } @@ -585,84 +867,304 @@ SDValue PIC16TargetLowering::ConvertToMemOperand(SDValue Op, return Load.getValue(0); } + +SDValue +PIC16TargetLowering::LowerCallArguments(SDValue Op, SDValue Chain, + SDValue FrameAddress, + SDValue InFlag, + SelectionDAG &DAG) { + CallSDNode *TheCall = dyn_cast<CallSDNode>(Op); + unsigned NumOps = TheCall->getNumArgs(); + std::string Name; + SDValue Arg, StoreAt; + MVT ArgVT; + unsigned Size=0; + unsigned ArgCount=0; + + + // FIXME: This portion of code currently assumes only + // primitive types being passed as arguments. + + // Legalize the address before use + SDValue PtrLo, PtrHi; + unsigned AddressOffset; + int StoreOffset = 0; + LegalizeAddress(FrameAddress, DAG, PtrLo, PtrHi, AddressOffset); + SDValue StoreRet; + + std::vector<SDValue> Ops; + SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Flag); + for (unsigned i=ArgCount, Offset = 0; i<NumOps; i++) { + // Get the argument + Arg = TheCall->getArg(i); + + StoreOffset = (Offset + AddressOffset); + + // Store the argument on frame + + Ops.clear(); + Ops.push_back(Chain); + Ops.push_back(Arg.getValue(0)); + Ops.push_back(PtrLo); + Ops.push_back(PtrHi); + Ops.push_back(DAG.getConstant(StoreOffset, MVT::i8)); + Ops.push_back(InFlag); + + StoreRet = DAG.getNode (PIC16ISD::PIC16StWF, Tys, &Ops[0], Ops.size()); + + Chain = getChain(StoreRet); + InFlag = getOutFlag(StoreRet); + + // Update the frame offset to be used for next argument + ArgVT = Arg.getValueType(); + Size = ArgVT.getSizeInBits(); + Size = Size/8; // Calculate size in bytes + Offset += Size; // Increase the frame offset + } + return Chain; +} -SDValue PIC16TargetLowering:: LowerBinOp(SDValue Op, SelectionDAG &DAG) { - // We should have handled larger operands in type legalizer itself. - assert (Op.getValueType() == MVT::i8 && "illegal Op to lower"); +SDValue +PIC16TargetLowering::LowerCallReturn(SDValue Op, SDValue Chain, + SDValue FrameAddress, + SDValue InFlag, + SelectionDAG &DAG) { + CallSDNode *TheCall = dyn_cast<CallSDNode>(Op); + // Currently handling primitive types only. They will come in + // i8 parts + unsigned RetVals = TheCall->getNumRetVals(); + + std::vector<SDValue> ResultVals; - // Return the original Op if the one of the operands is already a load. - if (Op.getOperand(0).getOpcode() == PIC16ISD::PIC16Load - || Op.getOperand(1).getOpcode() == PIC16ISD::PIC16Load) - return Op; + // Return immediately if the return type is void + if (RetVals == 0) + return Chain; - // Put one value on stack. - SDValue NewVal = ConvertToMemOperand (Op.getOperand(1), DAG); + // Call has something to return + + // Legalize the address before use + SDValue LdLo, LdHi; + unsigned LdOffset; + LegalizeAddress(FrameAddress, DAG, LdLo, LdHi, LdOffset); - return DAG.getNode(Op.getOpcode(), MVT::i8, Op.getOperand(0), NewVal); -} + SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Other, MVT::Flag); + SDValue LoadRet; + + for(unsigned i=0, Offset=0;i<RetVals;i++) { -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"); + LoadRet = DAG.getNode(PIC16ISD::PIC16LdWF, Tys, Chain, LdLo, LdHi, + DAG.getConstant(LdOffset + Offset, MVT::i8), + InFlag); - // 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(); + InFlag = getOutFlag(LoadRet); - // 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); + Chain = getChain(LoadRet); + Offset++; + ResultVals.push_back(LoadRet); + } + + // To return use MERGE_VALUES + ResultVals.push_back(Chain); + SDValue Res = DAG.getMergeValues(&ResultVals[0], ResultVals.size()); + return Res; } -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"); +SDValue PIC16TargetLowering::LowerRET(SDValue Op, SelectionDAG &DAG) { + //int NumOps = Op.getNode()->getNumOperands(); - // 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(); + // For default cases LLVM returns the value on the function frame + // So let LLVM do this for all the cases other than character + return Op; +} + +SDValue PIC16TargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) { + CallSDNode *TheCall = dyn_cast<CallSDNode>(Op); + SDValue Chain = TheCall->getChain(); + SDValue Callee = TheCall->getCallee(); + unsigned i =0; + if (Callee.getValueType() == MVT::i16 && + Callee.getOpcode() == ISD::BUILD_PAIR) { + // It has come from TypeLegalizer for lowering + + Callee = Callee.getOperand(0).getOperand(0); + + std::vector<SDValue> Ops; + Ops.push_back(Chain); + Ops.push_back(Callee); + + // Add the call arguments and their flags + unsigned NumArgs = TheCall->getNumArgs(); + for(i=0;i<NumArgs;i++) { + Ops.push_back(TheCall->getArg(i)); + Ops.push_back(TheCall->getArgFlagsVal(i)); + } + + std::vector<MVT> NodeTys; + unsigned NumRets = TheCall->getNumRetVals(); + for(i=0;i<NumRets;i++) + NodeTys.push_back(TheCall->getRetValType(i)); - // Put one value on stack. - SDValue NewVal = ConvertToMemOperand (Op.getOperand(1), DAG); + // Return a Chain as well + NodeTys.push_back(MVT::Other); + + SDVTList VTs = DAG.getVTList(&NodeTys[0], NodeTys.size()); + SDValue NewCall = + DAG.getCall(TheCall->getCallingConv(), TheCall->isVarArg(), + TheCall->isTailCall(), TheCall->isInreg(), VTs, + &Ops[0], Ops.size()); + + return NewCall; + } - SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Flag); - return DAG.getNode(ISD::ADDE, Tys, Op.getOperand(0), NewVal, - Op.getOperand(2)); + SDValue ZeroOperand = DAG.getConstant(0, MVT::i8); + + // Start the call sequence. + // Carring the Constant 0 along the CALLSEQSTART + // because there is nothing else to carry. + SDValue SeqStart = DAG.getCALLSEQ_START(Chain, ZeroOperand); + Chain = getChain(SeqStart); + + // For any direct call - callee will be GlobalAddressNode or + // ExternalSymbol + + // Considering the GlobalAddressNode case here. + if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) { + GlobalValue *GV = G->getGlobal(); + Callee = DAG.getTargetGlobalAddress(GV, MVT::i8); + } + + // Considering the ExternalSymbol case here + if (ExternalSymbolSDNode *ES = dyn_cast<ExternalSymbolSDNode>(Callee)) { + Callee = DAG.getTargetExternalSymbol(ES->getSymbol(), MVT::i8); + } + + SDValue OperFlag = getOutFlag(Chain); // To manage the data dependency + + std::string Name; + + // Considering GlobalAddress here + if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) + Name = G->getGlobal()->getName(); + + // Considering ExternalSymbol here + if (ExternalSymbolSDNode *ES = dyn_cast<ExternalSymbolSDNode>(Callee)) + Name = ES->getSymbol(); + + char *argFrame = new char [strlen(Name.c_str()) + 8]; + sprintf(argFrame, "%s.args", Name.c_str()); + SDValue ArgLabel = DAG.getTargetExternalSymbol(argFrame, MVT::i8); + + char *retName = new char [strlen(Name.c_str()) + 8]; + sprintf(retName, "%s.retval", Name.c_str()); + SDValue RetLabel = DAG.getTargetExternalSymbol(retName, MVT::i8); + + // Pass the argument to function before making the call. + SDValue CallArgs = LowerCallArguments(Op, Chain, ArgLabel, OperFlag, DAG); + Chain = getChain(CallArgs); + OperFlag = getOutFlag(CallArgs); + + SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Flag); + SDValue PICCall = DAG.getNode(PIC16ISD::CALL, Tys, Chain, Callee, + OperFlag); + Chain = getChain(PICCall); + OperFlag = getOutFlag(PICCall); + + + // Carrying the Constant 0 along the CALLSEQSTART + // because there is nothing else to carry. + SDValue SeqEnd = DAG.getCALLSEQ_END(Chain, ZeroOperand, ZeroOperand, + OperFlag); + Chain = getChain(SeqEnd); + OperFlag = getOutFlag(SeqEnd); + + // Lower the return value reading after the call. + return LowerCallReturn(Op, Chain, RetLabel, OperFlag, DAG); } -SDValue PIC16TargetLowering:: LowerSUBC(SDValue Op, SelectionDAG &DAG) { +bool PIC16TargetLowering::isDirectLoad(const SDValue Op) { + if (Op.getOpcode() == PIC16ISD::PIC16Load) + if (Op.getOperand(1).getOpcode() == ISD::TargetGlobalAddress + || Op.getOperand(1).getOpcode() == ISD::TargetExternalSymbol) + return true; + return false; +} + +bool PIC16TargetLowering::NeedToConvertToMemOp(SDValue Op, unsigned &MemOp) { + // Return false if one of the operands is already a direct + // load and that operand has only one use. + if (Op.getOperand(0).getOpcode() == ISD::Constant || + Op.getOperand(1).getOpcode() == ISD::Constant) + return false; + if (isDirectLoad(Op.getOperand(0))) { + if (Op.getOperand(0).hasOneUse()) + return false; + else + MemOp = 0; + } + if (isDirectLoad(Op.getOperand(1))) { + if (Op.getOperand(1).hasOneUse()) + return false; + else + MemOp = 1; + } + return true; +} + +SDValue PIC16TargetLowering:: LowerBinOp(SDValue Op, SelectionDAG &DAG) { // We should have handled larger operands in type legalizer itself. - assert (Op.getValueType() == MVT::i8 && "illegal subc to lower"); + assert (Op.getValueType() == MVT::i8 && "illegal Op to lower"); + unsigned MemOp = 1; + if (NeedToConvertToMemOp(Op, MemOp)) { + // Put one value on stack. + SDValue NewVal = ConvertToMemOperand (Op.getOperand(MemOp), DAG); - // Nothing to do if the first operand is already a load. - if (Op.getOperand(0).getOpcode() == PIC16ISD::PIC16Load) - return SDValue(); + return DAG.getNode(Op.getOpcode(), MVT::i8, Op.getOperand(MemOp ^ 1), + NewVal); + } + else { + return Op; + } +} - // Put first operand on stack. - SDValue NewVal = ConvertToMemOperand (Op.getOperand(0), DAG); +SDValue PIC16TargetLowering:: LowerADD(SDValue Op, SelectionDAG &DAG) { + // We should have handled larger operands in type legalizer itself. + assert (Op.getValueType() == MVT::i8 && "illegal add to lower"); + unsigned MemOp = 1; + if (NeedToConvertToMemOp(Op, MemOp)) { + // Put one value on stack. + SDValue NewVal = ConvertToMemOperand (Op.getOperand(MemOp), DAG); + + SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Flag); - SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Flag); - return DAG.getNode(ISD::SUBC, Tys, NewVal, Op.getOperand(1)); + if (Op.getOpcode() == ISD::ADDE) + return DAG.getNode(Op.getOpcode(), Tys, Op.getOperand(MemOp ^ 1), NewVal, + Op.getOperand(2)); + else + return DAG.getNode(Op.getOpcode(), Tys, Op.getOperand(MemOp ^ 1), NewVal); + } + else { + return SDValue(); + } } -SDValue PIC16TargetLowering:: LowerSUBE(SDValue Op, SelectionDAG &DAG) { +SDValue PIC16TargetLowering::LowerSUB(SDValue Op, SelectionDAG &DAG) { // We should have handled larger operands in type legalizer itself. - assert (Op.getValueType() == MVT::i8 && "illegal sube to lower"); + assert (Op.getValueType() == MVT::i8 && "illegal sub to lower"); - // Nothing to do if the first operand is already a load. - if (Op.getOperand(0).getOpcode() == PIC16ISD::PIC16Load) + // Nothing to do if the first operand is already a direct load and it has + // only one use. + if (isDirectLoad(Op.getOperand(0)) && Op.getOperand(0).hasOneUse()) 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)); + if (Op.getOpcode() == ISD::SUBE) + return DAG.getNode(Op.getOpcode(), Tys, NewVal, Op.getOperand(1), + Op.getOperand(2)); + else + return DAG.getNode(Op.getOpcode(), Tys, NewVal, Op.getOperand(1)); } // LowerFORMAL_ARGUMENTS - In Lowering FORMAL ARGUMENTS - MERGE_VALUES nodes @@ -707,3 +1209,189 @@ SDValue PIC16TargetLowering::PerformDAGCombine(SDNode *N, } return SDValue(); } + +static PIC16CC::CondCodes IntCCToPIC16CC(ISD::CondCode CC) { + switch (CC) { + default: assert(0 && "Unknown condition code!"); + case ISD::SETNE: return PIC16CC::NE; + case ISD::SETEQ: return PIC16CC::EQ; + case ISD::SETGT: return PIC16CC::GT; + case ISD::SETGE: return PIC16CC::GE; + case ISD::SETLT: return PIC16CC::LT; + case ISD::SETLE: return PIC16CC::LE; + case ISD::SETULT: return PIC16CC::LT; + case ISD::SETULE: return PIC16CC::LE; + case ISD::SETUGE: return PIC16CC::GE; + case ISD::SETUGT: return PIC16CC::GT; + } +} + +// Look at LHS/RHS/CC and see if they are a lowered setcc instruction. If so +// set LHS/RHS and SPCC to the LHS/RHS of the setcc and SPCC to the condition. +static void LookThroughSetCC(SDValue &LHS, SDValue &RHS, + ISD::CondCode CC, unsigned &SPCC) { + if (isa<ConstantSDNode>(RHS) && + cast<ConstantSDNode>(RHS)->getZExtValue() == 0 && + CC == ISD::SETNE && + (LHS.getOpcode() == PIC16ISD::SELECT_ICC && + LHS.getOperand(3).getOpcode() == PIC16ISD::SUBCC) && + isa<ConstantSDNode>(LHS.getOperand(0)) && + isa<ConstantSDNode>(LHS.getOperand(1)) && + cast<ConstantSDNode>(LHS.getOperand(0))->getZExtValue() == 1 && + cast<ConstantSDNode>(LHS.getOperand(1))->getZExtValue() == 0) { + SDValue CMPCC = LHS.getOperand(3); + SPCC = cast<ConstantSDNode>(LHS.getOperand(2))->getZExtValue(); + LHS = CMPCC.getOperand(0); + RHS = CMPCC.getOperand(1); + } +} + +// Returns appropriate CMP insn and corresponding condition code in PIC16CC +SDValue PIC16TargetLowering::getPIC16Cmp(SDValue LHS, SDValue RHS, + unsigned CC, SDValue &PIC16CC, + SelectionDAG &DAG) { + PIC16CC::CondCodes CondCode = (PIC16CC::CondCodes) CC; + + // PIC16 sub is literal - W. So Swap the operands and condition if needed. + // i.e. a < 12 can be rewritten as 12 > a. + if (RHS.getOpcode() == ISD::Constant) { + + SDValue Tmp = LHS; + LHS = RHS; + RHS = Tmp; + + switch (CondCode) { + default: break; + case PIC16CC::LT: + CondCode = PIC16CC::GT; + break; + case PIC16CC::GT: + CondCode = PIC16CC::LT; + break; + case PIC16CC::GE: + CondCode = PIC16CC::LE; + break; + case PIC16CC::LE: + CondCode = PIC16CC::GE; + break; + } + } + + PIC16CC = DAG.getConstant(CondCode, MVT::i8); + SDVTList VTs = DAG.getVTList (MVT::i8, MVT::Flag); + + // We can use a subtract operation to set the condition codes. But + // we need to put one operand in memory if required. + // Nothing to do if the first operand is already a direct load and it has + // only one use. + if (! (isDirectLoad(LHS) && LHS.hasOneUse())) + // Put first operand on stack. + LHS = ConvertToMemOperand (LHS, DAG); + + SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Flag); + return DAG.getNode(PIC16ISD::SUBCC, VTs, LHS, RHS); +} + + +SDValue PIC16TargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) { + SDValue LHS = Op.getOperand(0); + SDValue RHS = Op.getOperand(1); + ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get(); + SDValue TrueVal = Op.getOperand(2); + SDValue FalseVal = Op.getOperand(3); + unsigned ORIGCC = ~0; + + // If this is a select_cc of a "setcc", and if the setcc got lowered into + // an CMP[IF]CC/SELECT_[IF]CC pair, find the original compared values. + // i.e. + // A setcc: lhs, rhs, cc is expanded by llvm to + // select_cc: result of setcc, 0, 1, 0, setne + // We can think of it as: + // select_cc: lhs, rhs, 1, 0, cc + LookThroughSetCC(LHS, RHS, CC, ORIGCC); + if (ORIGCC == ~0U) ORIGCC = IntCCToPIC16CC (CC); + + SDValue PIC16CC; + SDValue Cmp = getPIC16Cmp(LHS, RHS, ORIGCC, PIC16CC, DAG); + + return DAG.getNode (PIC16ISD::SELECT_ICC, TrueVal.getValueType(), TrueVal, + FalseVal, PIC16CC, Cmp.getValue(1)); +} + +MachineBasicBlock * +PIC16TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, + MachineBasicBlock *BB) { + const TargetInstrInfo &TII = *getTargetMachine().getInstrInfo(); + unsigned CC = (PIC16CC::CondCodes)MI->getOperand(3).getImm(); + + // To "insert" a SELECT_CC instruction, we actually have to insert the diamond + // control-flow pattern. The incoming instruction knows the destination vreg + // to set, the condition code register to branch on, the true/false values to + // select between, and a branch opcode to use. + const BasicBlock *LLVM_BB = BB->getBasicBlock(); + MachineFunction::iterator It = BB; + ++It; + + // thisMBB: + // ... + // TrueVal = ... + // [f]bCC copy1MBB + // fallthrough --> copy0MBB + MachineBasicBlock *thisMBB = BB; + MachineFunction *F = BB->getParent(); + MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB); + BuildMI(BB, TII.get(PIC16::pic16brcond)).addMBB(sinkMBB).addImm(CC); + F->insert(It, copy0MBB); + F->insert(It, sinkMBB); + + // Update machine-CFG edges by transferring all successors of the current + // block to the new block which will contain the Phi node for the select. + sinkMBB->transferSuccessors(BB); + // Next, add the true and fallthrough blocks as its successors. + BB->addSuccessor(copy0MBB); + BB->addSuccessor(sinkMBB); + + // copy0MBB: + // %FalseValue = ... + // # fallthrough to sinkMBB + BB = copy0MBB; + + // Update machine-CFG edges + BB->addSuccessor(sinkMBB); + + // sinkMBB: + // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ] + // ... + BB = sinkMBB; + BuildMI(BB, TII.get(PIC16::PHI), MI->getOperand(0).getReg()) + .addReg(MI->getOperand(2).getReg()).addMBB(copy0MBB) + .addReg(MI->getOperand(1).getReg()).addMBB(thisMBB); + + F->DeleteMachineInstr(MI); // The pseudo instruction is gone now. + return BB; +} + + +SDValue PIC16TargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) { + SDValue Chain = Op.getOperand(0); + ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get(); + SDValue LHS = Op.getOperand(2); // LHS of the condition. + SDValue RHS = Op.getOperand(3); // RHS of the condition. + SDValue Dest = Op.getOperand(4); // BB to jump to + unsigned ORIGCC = ~0; + + // If this is a br_cc of a "setcc", and if the setcc got lowered into + // an CMP[IF]CC/SELECT_[IF]CC pair, find the original compared values. + LookThroughSetCC(LHS, RHS, CC, ORIGCC); + if (ORIGCC == ~0U) ORIGCC = IntCCToPIC16CC (CC); + + // Get the Compare insn and condition code. + SDValue PIC16CC; + SDValue Cmp = getPIC16Cmp(LHS, RHS, ORIGCC, PIC16CC, DAG); + + return DAG.getNode(PIC16ISD::BRCOND, MVT::Other, Chain, Dest, PIC16CC, + Cmp.getValue(1)); +} + + diff --git a/lib/Target/PIC16/PIC16ISelLowering.h b/lib/Target/PIC16/PIC16ISelLowering.h index de8bd2b..503b72c 100644 --- a/lib/Target/PIC16/PIC16ISelLowering.h +++ b/lib/Target/PIC16/PIC16ISelLowering.h @@ -29,7 +29,9 @@ namespace llvm { Lo, // Low 8-bits of GlobalAddress. Hi, // High 8-bits of GlobalAddress. PIC16Load, + PIC16LdWF, PIC16Store, + PIC16StWF, Banksel, MTLO, MTHI, @@ -38,6 +40,10 @@ namespace llvm { LRLF, // PIC16 Logical shift right RLF, // Rotate left through carry RRF, // Rotate right through carry + CALL, // PIC16 Call instruction + SUBCC, // Compare for equality or inequality. + SELECT_ICC, // Psuedo to be caught in schedular and expanded to brcond. + BRCOND, // Conditional branch. Dummy }; @@ -46,8 +52,21 @@ namespace llvm { RAM_SPACE = 0, // RAM address space ROM_SPACE = 1 // ROM address space number is 1 }; + enum PIC16LibCall { + SRA_I8, + SLL_I8, + SRL_I8, + SRA_I16, + SLL_I16, + SRL_I16, + SRA_I32, + SLL_I32, + SRL_I32, + PIC16UnknownCall + }; } + //===--------------------------------------------------------------------===// // TargetLowering Implementation //===--------------------------------------------------------------------===// @@ -58,25 +77,37 @@ namespace llvm { /// getTargetNodeName - This method returns the name of a target specific /// DAG node. virtual const char *getTargetNodeName(unsigned Opcode) const; + /// getSetCCResultType - Return the ISD::SETCC ValueType + virtual MVT getSetCCResultType(MVT ValType) 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); + SDValue LowerADD(SDValue Op, SelectionDAG &DAG); + SDValue LowerSUB(SDValue Op, SelectionDAG &DAG); SDValue LowerBinOp(SDValue Op, SelectionDAG &DAG); - - /// ReplaceNodeResults - Replace the results of node with an illegal result - /// type with new values built out of custom code. - /// - virtual void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue>&Results, + SDValue LowerCALL(SDValue Op, SelectionDAG &DAG); + SDValue LowerRET(SDValue Op, SelectionDAG &DAG); + SDValue LowerCallReturn(SDValue Op, SDValue Chain, SDValue FrameAddress, + SDValue InFlag, SelectionDAG &DAG); + SDValue LowerCallArguments(SDValue Op, SDValue Chain, SDValue FrameAddress, + SDValue InFlag, SelectionDAG &DAG); + SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG); + SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG); + SDValue getPIC16Cmp(SDValue LHS, SDValue RHS, unsigned OrigCC, SDValue &CC, + SelectionDAG &DAG); + virtual MachineBasicBlock *EmitInstrWithCustomInserter(MachineInstr *MI, + MachineBasicBlock *MBB); + + + virtual void ReplaceNodeResults(SDNode *N, + SmallVectorImpl<SDValue> &Results, SelectionDAG &DAG); - SDValue ExpandStore(SDNode *N, SelectionDAG &DAG); SDValue ExpandLoad(SDNode *N, SelectionDAG &DAG); -// SDNode *ExpandAdd(SDNode *N, SelectionDAG &DAG); + //SDValue ExpandAdd(SDNode *N, SelectionDAG &DAG); SDValue ExpandGlobalAddress(SDNode *N, SelectionDAG &DAG); + SDValue ExpandExternalSymbol(SDNode *N, SelectionDAG &DAG); SDValue ExpandShift(SDNode *N, SelectionDAG &DAG); + SDValue ExpandFrameIndex(SDNode *N, SelectionDAG &DAG); SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const; SDValue PerformPIC16LoadCombine(SDNode *N, DAGCombinerInfo &DCI) const; @@ -95,6 +126,8 @@ namespace llvm { // code at one place. In case of any change in future it will // help maintain the code SDValue getChain(SDValue &Op); + + SDValue getOutFlag(SDValue &Op); // Extract the Lo and Hi component of Op. @@ -108,13 +141,44 @@ namespace llvm { void LegalizeAddress(SDValue Ptr, SelectionDAG &DAG, SDValue &Chain, SDValue &NewPtr, unsigned &Offset); + // FrameIndex should be broken down into ExternalSymbol and FrameOffset. + void LegalizeFrameIndex(SDValue Op, SelectionDAG &DAG, SDValue &ES, + int &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); + // This function checks if we need to put an operand of an operation on + // stack and generate a load or not. + bool NeedToConvertToMemOp(SDValue Op, unsigned &MemOp); + /// 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; + + + // Extending the LIB Call framework of LLVM + // To hold the names of PIC16LibCalls + const char *PIC16LibCallNames[PIC16ISD::PIC16UnknownCall]; + + // To set and retrieve the lib call names + void setPIC16LibCallName(PIC16ISD::PIC16LibCall Call, const char *Name); + const char *getPIC16LibCallName(PIC16ISD::PIC16LibCall Call); + + // Make PIC16 LibCall + SDValue MakePIC16LibCall(PIC16ISD::PIC16LibCall Call, MVT RetVT, + const SDValue *Ops, unsigned NumOps, bool isSigned, + SelectionDAG &DAG); + + // Check if operation has a direct load operand. + inline bool isDirectLoad(const SDValue Op); + + // Create the symbol and index for function frame + void getCurrentFrameIndex(SelectionDAG &DAG, SDValue &ES, + unsigned SlotSize, int &FI); + + SDValue getCurrentFrame(SelectionDAG &DAG); }; } // namespace llvm diff --git a/lib/Target/PIC16/PIC16InstrInfo.cpp b/lib/Target/PIC16/PIC16InstrInfo.cpp index bce7d26..5fe5dac 100644 --- a/lib/Target/PIC16/PIC16InstrInfo.cpp +++ b/lib/Target/PIC16/PIC16InstrInfo.cpp @@ -125,20 +125,29 @@ bool PIC16InstrInfo::copyRegToReg (MachineBasicBlock &MBB, const TargetRegisterClass *SrcRC) const { if (DestRC == PIC16::FSR16RegisterClass) { BuildMI(MBB, I, get(PIC16::copy_fsr), DestReg).addReg(SrcReg); + return true; + } + + if (DestRC == PIC16::GPRRegisterClass) { + BuildMI(MBB, I, get(PIC16::copy_w), DestReg).addReg(SrcReg); + return true; } - return true; + // Not yet supported. + return false; } bool PIC16InstrInfo::isMoveInstr(const MachineInstr &MI, unsigned &SrcReg, unsigned &DestReg) const { - if (MI.getOpcode() == PIC16::copy_fsr) { + if (MI.getOpcode() == PIC16::copy_fsr + || MI.getOpcode() == PIC16::copy_w) { DestReg = MI.getOperand(0).getReg(); SrcReg = MI.getOperand(1).getReg(); return true; } + return false; } diff --git a/lib/Target/PIC16/PIC16InstrInfo.td b/lib/Target/PIC16/PIC16InstrInfo.td index 60d92ec..077b508 100644 --- a/lib/Target/PIC16/PIC16InstrInfo.td +++ b/lib/Target/PIC16/PIC16InstrInfo.td @@ -38,9 +38,22 @@ def SDTI16BinOp : SDTypeProfile<1, 2, [SDTCisI16<0>, SDTCisI16<1>, // 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>]>; +// PIC16ISD::CALL type prorile +def SDT_PIC16call : SDTypeProfile<0, -1, [SDTCisInt<0>]>; + +// PIC16ISD::BRCOND +def SDT_PIC16Brcond: SDTypeProfile<0, 2, + [SDTCisVT<0, OtherVT>, SDTCisI8<1>]>; + +// PIC16ISD::BRCOND +def SDT_PIC16Selecticc: SDTypeProfile<1, 3, + [SDTCisI8<0>, SDTCisI8<1>, SDTCisI8<2>, + SDTCisI8<3>]>; + //===----------------------------------------------------------------------===// // PIC16 addressing modes matching via DAG. //===----------------------------------------------------------------------===// @@ -52,7 +65,7 @@ def diraddr : ComplexPattern<i8, 1, "SelectDirectAddr", [], []>; def PIC16callseq_start : SDNode<"ISD::CALLSEQ_START", SDTI8VoidOp, [SDNPHasChain, SDNPOutFlag]>; def PIC16callseq_end : SDNode<"ISD::CALLSEQ_END", SDTI8VoidOp, - [SDNPHasChain, SDNPOutFlag]>; + [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>; // Low 8-bits of GlobalAddress. def PIC16Lo : SDNode<"PIC16ISD::Lo", SDTI8UnaryOp>; @@ -71,18 +84,37 @@ def Banksel : SDNode<"PIC16ISD::Banksel", SDTI8UnaryOp>; // Node to match a direct store operation. def PIC16Store : SDNode<"PIC16ISD::PIC16Store", SDT_PIC16Store, [SDNPHasChain]>; +def PIC16StWF : SDNode<"PIC16ISD::PIC16StWF", SDT_PIC16Store, + [SDNPHasChain, SDNPInFlag, SDNPOutFlag]>; // Node to match a direct load operation. def PIC16Load : SDNode<"PIC16ISD::PIC16Load", SDT_PIC16Load, [SDNPHasChain]>; +def PIC16LdWF : SDNode<"PIC16ISD::PIC16LdWF", SDT_PIC16Load, + [SDNPHasChain, SDNPInFlag, SDNPOutFlag]>; + +// Node to match PIC16 call +def PIC16call : SDNode<"PIC16ISD::CALL", SDT_PIC16call, + [SDNPHasChain , SDNPOptInFlag, SDNPOutFlag]>; + +// Node to match a comparison instruction. +def PIC16Subcc : SDNode<"PIC16ISD::SUBCC", SDTI8BinOp, [SDNPOutFlag]>; + +// Node to match a conditional branch. +def PIC16Brcond : SDNode<"PIC16ISD::BRCOND", SDT_PIC16Brcond, + [SDNPHasChain, SDNPInFlag]>; + +def PIC16Selecticc : SDNode<"PIC16ISD::SELECT_ICC", SDT_PIC16Selecticc, + [SDNPInFlag]>; -// Nodes to match bitwise operatios. -def OR : SDNode<"ISD::OR", SDTI8BinOp>; -def XOR : SDNode<"ISD::XOR", SDTI8BinOp>; -def AND : SDNode<"ISD::AND", SDTI8BinOp>; //===----------------------------------------------------------------------===// // PIC16 Operand Definitions. //===----------------------------------------------------------------------===// def i8mem : Operand<i8>; +def brtarget: Operand<OtherVT>; + +// Operand for printing out a condition code. +let PrintMethod = "printCCOperand" in + def CCOp : Operand<i8>; include "PIC16InstrFormats.td" @@ -90,7 +122,7 @@ include "PIC16InstrFormats.td" // PIC16 Common Classes. //===----------------------------------------------------------------------===// -// W = W Op F : Load the value from F and do Op to W +// W = W Op F : Load the value from F and do Op to W. class BinOpFW<bits<6> OpCode, string OpcStr, SDNode OpNode>: ByteFormat<OpCode, (outs GPR:$dst), (ins GPR:$src, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi), @@ -98,7 +130,8 @@ class BinOpFW<bits<6> OpCode, string OpcStr, SDNode OpNode>: [(set GPR:$dst, (OpNode GPR:$src, (PIC16Load diraddr:$ptrlo, (i8 imm:$ptrhi), (i8 imm:$offset))))]>; -// F = F Op W : Load the value from F, do op with W and store in F + +// F = F Op W : Load the value from F, do op with W and store in F. class BinOpWF<bits<6> OpCode, string OpcStr, SDNode OpNode>: ByteFormat<OpCode, (outs), (ins GPR:$src, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi), @@ -110,6 +143,13 @@ class BinOpWF<bits<6> OpCode, string OpcStr, SDNode OpNode>: (i8 imm:$ptrhi), (i8 imm:$offset) )]>; +// W = W Op L : Do Op of L with W and place result in W. +class BinOpLW<bits<6> opcode, string OpcStr, SDNode OpNode> : + LiteralFormat<opcode, (outs GPR:$dst), + (ins GPR:$src, i8imm:$literal), + !strconcat(OpcStr, " $literal"), + [(set GPR:$dst, (OpNode GPR:$src, (i8 imm:$literal)))]>; + //===----------------------------------------------------------------------===// // PIC16 Instructions. //===----------------------------------------------------------------------===// @@ -163,6 +203,9 @@ def set_fsrhi: def copy_fsr: Pseudo<(outs FSR16:$dst), (ins FSR16:$src), "copy_fsr $dst, $src", []>; +def copy_w: + Pseudo<(outs GPR:$dst), (ins GPR:$src), "copy_w $dst, $src", []>; + //-------------------------- // Store to memory //------------------------- @@ -181,6 +224,14 @@ def movwf_1 : [(PIC16Store GPR:$val, texternalsym:$ptrlo, (i8 imm:$ptrhi), (i8 imm:$offset))]>; +// Store with InFlag and OutFlag +def movwf_2 : + ByteFormat<0, (outs), + (ins GPR:$val, i8mem:$ptrlo, i8imm:$ptrhi, i8imm:$offset), + "movwf ${ptrlo} + ${offset}", + [(PIC16StWF GPR:$val, texternalsym:$ptrlo, (i8 imm:$ptrhi), + (i8 imm:$offset))]>; + // Indirect store. Matched via a DAG replacement pattern. def store_indirect : ByteFormat<0, (outs), @@ -208,6 +259,16 @@ def movf_1 : (PIC16Load texternalsym:$ptrlo, (i8 imm:$ptrhi), (i8 imm:$offset)))]>; +// Load with InFlag and OutFlag +def movf_2 : + ByteFormat<0, (outs GPR:$dst), + (ins i8mem:$ptrlo, i8imm:$ptrhi, i8imm:$offset), + "movf ${ptrlo} + ${offset}, W", + [(set GPR:$dst, + (PIC16LdWF texternalsym:$ptrlo, (i8 imm:$ptrhi), + (i8 imm:$offset)))]>; + + // Indirect load. Matched via a DAG replacement pattern. def load_indirect : ByteFormat<0, (outs GPR:$dst), @@ -218,23 +279,25 @@ def load_indirect : //------------------------- // Bitwise operations patterns //-------------------------- -def OrFW : BinOpFW<0, "iorwf", OR>; -def XOrFW : BinOpFW<0, "xorwf", XOR>; -def AndFW : BinOpFW<0, "andwf", AND>; +let isTwoAddress = 1 in { +def OrFW : BinOpFW<0, "iorwf", or>; +def XOrFW : BinOpFW<0, "xorwf", xor>; +def AndFW : BinOpFW<0, "andwf", and>; +} -def OrWF : BinOpWF<0, "iorwf", OR>; -def XOrWF : BinOpWF<0, "xorwf", XOR>; -def AndWF : BinOpWF<0, "andwf", AND>; +def OrWF : BinOpWF<0, "iorwf", or>; +def XOrWF : BinOpWF<0, "xorwf", xor>; +def AndWF : BinOpWF<0, "andwf", and>; //------------------------- // Various add/sub patterns. //------------------------- -// let isTwoAddress = 1 in { +let isTwoAddress = 1 in { def addfw_1: BinOpFW<0, "addwf", add>; def addfw_2: BinOpFW<0, "addwf", addc>; def addfwc: BinOpFW<0, "addwfc", adde>; // With Carry. -// } +} def addwf_1: BinOpWF<0, "addwf", add>; def addwf_2: BinOpWF<0, "addwf", addc>; @@ -248,11 +311,12 @@ class SUBFW<bits<6> OpCode, string OpcStr, SDNode OpNode>: [(set GPR:$dst, (OpNode (PIC16Load diraddr:$ptrlo, (i8 imm:$ptrhi), (i8 imm:$offset)), GPR:$src))]>; -//let isTwoAddress = 1 in { +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. -//} +def subfw_cc: SUBFW<0, "subwf", PIC16Subcc>; +} // [F] -= W ; class SUBWF<bits<6> OpCode, string OpcStr, SDNode OpNode>: @@ -267,33 +331,62 @@ class SUBWF<bits<6> OpCode, string OpcStr, SDNode OpNode>: def subwf_1: SUBWF<0, "subwf", sub>; def subwf_2: SUBWF<0, "subwf", subc>; def subwfb: SUBWF<0, "subwfb", sube>; // With Borrow. +def subwf_cc: SUBWF<0, "subwf", PIC16Subcc>; // addlw -// W += C ; add literal to W. (Without carry). May Produce a carry. -class ADDLW<bits<6> opcode, string OpcStr, SDNode OpNode> : - LiteralFormat<opcode, (outs GPR:$dst), - (ins GPR:$src, i8imm:$literal), - !strconcat(OpcStr, " $literal"), - [(set GPR:$dst, (OpNode GPR:$src, (i8 imm:$literal)))]>; +let isTwoAddress = 1 in { +def addlw_1 : BinOpLW<0, "addlw", add>; +def addlw_2 : BinOpLW<0, "addlw", addc>; +def addlwc : BinOpLW<0, "addlwc", adde>; // With Carry. (Assembler macro). +} -// 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). -//} +// bitwise operations involving a literal and w. +let isTwoAddress = 1 in { +def andlw : BinOpLW<0, "andlw", and>; +def xorlw : BinOpLW<0, "xorlw", xor>; +def orlw : BinOpLW<0, "iorlw", or>; +} // sublw // W = C - W ; sub W from literal. (Without borrow). class SUBLW<bits<6> opcode, SDNode OpNode> : LiteralFormat<opcode, (outs GPR:$dst), (ins GPR:$src, i8imm:$literal), - "addlw $literal", + "sublw $literal", [(set GPR:$dst, (OpNode (i8 imm:$literal), GPR:$src))]>; -//let isTwoAddress = 1 in { +let isTwoAddress = 1 in { def sublw_1 : SUBLW<0, sub>; def sublw_2 : SUBLW<0, subc>; -//} +def sublw_cc : SUBLW<0, PIC16Subcc>; +} + +// Call instruction. +let isCall = 1 in { + def CALL: LiteralFormat<0x1, (outs), (ins i8imm:$func), + "call ${func}", + [(PIC16call diraddr:$func)]>; +} + +def pic16brcond: ControlFormat<0x0, (outs), (ins brtarget:$dst, CCOp:$cc), + "b$cc $dst", + [(PIC16Brcond bb:$dst, imm:$cc)]>; + +// Unconditional branch. +def br_uncond: ControlFormat<0x0, (outs), (ins brtarget:$dst), + "goto $dst", + [(br bb:$dst)]>; + +// SELECT_CC_* - Used to implement the SELECT_CC DAG operation. Expanded by the +// scheduler into a branch sequence. +let usesCustomDAGSchedInserter = 1 in { // Expanded by the scheduler. + def SELECT_CC_Int_ICC + : Pseudo<(outs GPR:$dst), (ins GPR:$T, GPR:$F, i8imm:$Cond), + "; SELECT_CC_Int_ICC PSEUDO!", + [(set GPR:$dst, (PIC16Selecticc GPR:$T, GPR:$F, + imm:$Cond))]>; +} + // Banksel. let isReMaterializable = 1 in { diff --git a/lib/Target/PIC16/PIC16RegisterInfo.cpp b/lib/Target/PIC16/PIC16RegisterInfo.cpp index 838e848..eb758d8 100644 --- a/lib/Target/PIC16/PIC16RegisterInfo.cpp +++ b/lib/Target/PIC16/PIC16RegisterInfo.cpp @@ -79,4 +79,13 @@ unsigned PIC16RegisterInfo::getRARegister() const { return 0; } +// This function eliminates ADJCALLSTACKDOWN, +// ADJCALLSTACKUP pseudo instructions +void PIC16RegisterInfo:: +eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const { + // Simply discard ADJCALLSTACKDOWN, + // ADJCALLSTACKUP instructions. + MBB.erase(I); +} diff --git a/lib/Target/PIC16/PIC16RegisterInfo.h b/lib/Target/PIC16/PIC16RegisterInfo.h index aaabb41..83689d0 100644 --- a/lib/Target/PIC16/PIC16RegisterInfo.h +++ b/lib/Target/PIC16/PIC16RegisterInfo.h @@ -51,6 +51,10 @@ class PIC16RegisterInfo : public PIC16GenRegisterInfo { virtual void eliminateFrameIndex(MachineBasicBlock::iterator MI, int SPAdj, RegScavenger *RS=NULL) const; + void eliminateCallFramePseudoInstr(MachineFunction &MF, + MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const; + virtual void emitPrologue(MachineFunction &MF) const; virtual void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const; virtual int getDwarfRegNum(unsigned RegNum, bool isEH) const; diff --git a/lib/Target/PIC16/PIC16TargetAsmInfo.cpp b/lib/Target/PIC16/PIC16TargetAsmInfo.cpp index 4dcd41a..8e2392e 100644 --- a/lib/Target/PIC16/PIC16TargetAsmInfo.cpp +++ b/lib/Target/PIC16/PIC16TargetAsmInfo.cpp @@ -13,6 +13,7 @@ #include "PIC16TargetAsmInfo.h" #include "PIC16TargetMachine.h" +#include "llvm/GlobalValue.h" using namespace llvm; @@ -23,9 +24,12 @@ PIC16TargetAsmInfo(const PIC16TargetMachine &TM) Data8bitsDirective = " db "; Data16bitsDirective = " db "; Data32bitsDirective = " db "; - DataSectionStartSuffix = " IDATA "; - UDataSectionStartSuffix = " UDATA "; - TextSectionStartSuffix = " CODE "; - RomDataSectionStartSuffix = " ROMDATA "; ZeroDirective = NULL; + AsciiDirective = " dt "; + AscizDirective = NULL; + BSSSection_ = getNamedSection("udata.# UDATA", + SectionFlags::Writeable | SectionFlags::BSS); + ReadOnlySection = getNamedSection("romdata.# ROMDATA", SectionFlags::None); + DataSection = getNamedSection("idata.# IDATA", SectionFlags::Writeable); + SwitchToSectionDirective = ""; } diff --git a/lib/Target/PIC16/PIC16TargetAsmInfo.h b/lib/Target/PIC16/PIC16TargetAsmInfo.h index 680c8e7..88de79f 100644 --- a/lib/Target/PIC16/PIC16TargetAsmInfo.h +++ b/lib/Target/PIC16/PIC16TargetAsmInfo.h @@ -23,17 +23,7 @@ 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 |