diff options
-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 3975849b3d..c429324cc2 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 6850bd664b..f9f51ab9cc 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 d468efd7b3..dc91128d5a 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 b0a2baf1fc..876e4be743 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 880fcc9496..1f1f9e477c 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) |