[llvm-commits] [llvm] r62174 - in /llvm/trunk/lib/Target/PIC16: Makefile PIC16.h PIC16AsmPrinter.cpp PIC16AsmPrinter.h PIC16ISelLowering.cpp PIC16ISelLowering.h PIC16InstrInfo.cpp PIC16InstrInfo.td PIC16RegisterInfo.cpp PIC16RegisterInfo.h PIC16TargetAsmInfo.cpp PIC16TargetAsmInfo.h

Sanjiv Gupta sanjiv.gupta at microchip.com
Tue Jan 13 11:18:48 PST 2009


Author: sgupta
Date: Tue Jan 13 13:18:47 2009
New Revision: 62174

URL: http://llvm.org/viewvc/llvm-project?rev=62174&view=rev
Log:
Checking in conditionals, function call, arrays and libcalls implementation.

Modified:
    llvm/trunk/lib/Target/PIC16/Makefile
    llvm/trunk/lib/Target/PIC16/PIC16.h
    llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.cpp
    llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.h
    llvm/trunk/lib/Target/PIC16/PIC16ISelLowering.cpp
    llvm/trunk/lib/Target/PIC16/PIC16ISelLowering.h
    llvm/trunk/lib/Target/PIC16/PIC16InstrInfo.cpp
    llvm/trunk/lib/Target/PIC16/PIC16InstrInfo.td
    llvm/trunk/lib/Target/PIC16/PIC16RegisterInfo.cpp
    llvm/trunk/lib/Target/PIC16/PIC16RegisterInfo.h
    llvm/trunk/lib/Target/PIC16/PIC16TargetAsmInfo.cpp
    llvm/trunk/lib/Target/PIC16/PIC16TargetAsmInfo.h

Modified: llvm/trunk/lib/Target/PIC16/Makefile
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PIC16/Makefile?rev=62174&r1=62173&r2=62174&view=diff

==============================================================================
--- llvm/trunk/lib/Target/PIC16/Makefile (original)
+++ llvm/trunk/lib/Target/PIC16/Makefile Tue Jan 13 13:18:47 2009
@@ -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

Modified: llvm/trunk/lib/Target/PIC16/PIC16.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PIC16/PIC16.h?rev=62174&r1=62173&r2=62174&view=diff

==============================================================================
--- llvm/trunk/lib/Target/PIC16/PIC16.h (original)
+++ llvm/trunk/lib/Target/PIC16/PIC16.h Tue Jan 13 13:18:47 2009
@@ -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);

Modified: llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.cpp?rev=62174&r1=62173&r2=62174&view=diff

==============================================================================
--- llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.cpp (original)
+++ llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.cpp Tue Jan 13 13:18:47 2009
@@ -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 @@
       // 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 @@
   // 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 @@
       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 @@
       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::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::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 @@
   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 @@
 
       const Type *Ty = C->getType();
       unsigned Size = TD->getTypePaddedSize(Ty);
+
       O << name << " " <<"RES"<< " " << Size ;
       O << "\n";
     }
@@ -317,29 +357,24 @@
   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 @@
     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 @@
     */
   }
 }
-
-/// 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;
-}
-

Modified: llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.h?rev=62174&r1=62173&r2=62174&view=diff

==============================================================================
--- llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.h (original)
+++ llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.h Tue Jan 13 13:18:47 2009
@@ -36,10 +36,7 @@
 
     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 @@
     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;

Modified: llvm/trunk/lib/Target/PIC16/PIC16ISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PIC16/PIC16ISelLowering.cpp?rev=62174&r1=62173&r2=62174&view=diff

==============================================================================
--- llvm/trunk/lib/Target/PIC16/PIC16ISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/PIC16/PIC16ISelLowering.cpp Tue Jan 13 13:18:47 2009
@@ -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 @@
   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 @@
   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 @@
   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 @@
   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 @@
 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 @@
  
   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 @@
                                  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::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 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 @@
   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 @@
 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 @@
 }
 
 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 @@
     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 @@
   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 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();
+  PIC16ISD::PIC16LibCall CallCode;
 
-  if (N->getOpcode() == ISD::SHL) {
-    ShfNode = PIC16ISD::LSLF;
-    RotNode = PIC16ISD::RLF;
-  } else if (N->getOpcode() == ISD::SRL) {
-    ShfNode = PIC16ISD::LRLF;
-    RotNode = PIC16ISD::RRF;
+  // 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 @@
     
   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;
 
-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");
-
-  // 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;
 
-  // Put one value on stack.
-  SDValue NewVal = ConvertToMemOperand (Op.getOperand(1), DAG);
+  // FIXME: This portion of code currently assumes only
+  // primitive types being passed as arguments.
 
-  return DAG.getNode(Op.getOpcode(), MVT::i8, Op.getOperand(0), NewVal);
+  // 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:: LowerADDC(SDValue Op, SelectionDAG &DAG) {
-  // We should have handled larger operands in type legalizer itself.
-  assert (Op.getValueType() == MVT::i8 && "illegal addc 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;
 
-  // 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();
+  // 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);
-    
-  SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Flag);
-  return DAG.getNode(ISD::ADDC, Tys, Op.getOperand(0), NewVal);
-}
+  // Call has something to return
+  
+  // Legalize the address before use
+  SDValue LdLo, LdHi;
+  unsigned LdOffset;
+  LegalizeAddress(FrameAddress, DAG, LdLo, LdHi, LdOffset);
 
-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");
+  SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Other, MVT::Flag);
+  SDValue LoadRet;
+ 
+  for(unsigned i=0, Offset=0;i<RetVals;i++) {
 
-  // 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();
+    LoadRet = DAG.getNode(PIC16ISD::PIC16LdWF, Tys, Chain, LdLo, LdHi,
+                          DAG.getConstant(LdOffset + Offset, MVT::i8),
+                          InFlag);
+
+    InFlag = getOutFlag(LoadRet);
+
+    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::LowerRET(SDValue Op, SelectionDAG &DAG) {
+ //int NumOps = Op.getNode()->getNumOperands();
+
+ // 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));
+      }
 
-  // Put one value on stack.
-  SDValue NewVal = ConvertToMemOperand (Op.getOperand(1), DAG);
+      std::vector<MVT> NodeTys;
+      unsigned NumRets = TheCall->getNumRetVals();
+      for(i=0;i<NumRets;i++)
+        NodeTys.push_back(TheCall->getRetValType(i));
+
+      // 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);
+}
+
+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;
 }
 
-SDValue PIC16TargetLowering:: LowerSUBC(SDValue Op, SelectionDAG &DAG) {
+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 @@
   }
   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));
+}
+
+  

Modified: llvm/trunk/lib/Target/PIC16/PIC16ISelLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PIC16/PIC16ISelLowering.h?rev=62174&r1=62173&r2=62174&view=diff

==============================================================================
--- llvm/trunk/lib/Target/PIC16/PIC16ISelLowering.h (original)
+++ llvm/trunk/lib/Target/PIC16/PIC16ISelLowering.h Tue Jan 13 13:18:47 2009
@@ -29,7 +29,9 @@
       Lo,            // Low 8-bits of GlobalAddress.
       Hi,            // High 8-bits of GlobalAddress.
       PIC16Load,
+      PIC16LdWF,
       PIC16Store,
+      PIC16StWF,
       Banksel,
       MTLO,
       MTHI,
@@ -38,6 +40,10 @@
       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 @@
       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 @@
     /// 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);
+    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);
 
-    /// 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,
-                                    SelectionDAG &DAG);
 
+    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 @@
     // 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 @@
     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
 

Modified: llvm/trunk/lib/Target/PIC16/PIC16InstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PIC16/PIC16InstrInfo.cpp?rev=62174&r1=62173&r2=62174&view=diff

==============================================================================
--- llvm/trunk/lib/Target/PIC16/PIC16InstrInfo.cpp (original)
+++ llvm/trunk/lib/Target/PIC16/PIC16InstrInfo.cpp Tue Jan 13 13:18:47 2009
@@ -125,20 +125,29 @@
                                    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;
 }
 

Modified: llvm/trunk/lib/Target/PIC16/PIC16InstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PIC16/PIC16InstrInfo.td?rev=62174&r1=62173&r2=62174&view=diff

==============================================================================
--- llvm/trunk/lib/Target/PIC16/PIC16InstrInfo.td (original)
+++ llvm/trunk/lib/Target/PIC16/PIC16InstrInfo.td Tue Jan 13 13:18:47 2009
@@ -38,9 +38,22 @@
 // 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 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 @@
 
 // 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 @@
 // 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 @@
              [(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 @@
                                              (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 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 @@
              [(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 @@
                (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 @@
 //-------------------------
 // Bitwise operations patterns
 //--------------------------
-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>;
+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>;
 
 //-------------------------
 // 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 @@
              [(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 @@
 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 {

Modified: llvm/trunk/lib/Target/PIC16/PIC16RegisterInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PIC16/PIC16RegisterInfo.cpp?rev=62174&r1=62173&r2=62174&view=diff

==============================================================================
--- llvm/trunk/lib/Target/PIC16/PIC16RegisterInfo.cpp (original)
+++ llvm/trunk/lib/Target/PIC16/PIC16RegisterInfo.cpp Tue Jan 13 13:18:47 2009
@@ -79,4 +79,13 @@
   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);
+}
 

Modified: llvm/trunk/lib/Target/PIC16/PIC16RegisterInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PIC16/PIC16RegisterInfo.h?rev=62174&r1=62173&r2=62174&view=diff

==============================================================================
--- llvm/trunk/lib/Target/PIC16/PIC16RegisterInfo.h (original)
+++ llvm/trunk/lib/Target/PIC16/PIC16RegisterInfo.h Tue Jan 13 13:18:47 2009
@@ -51,6 +51,10 @@
   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;

Modified: llvm/trunk/lib/Target/PIC16/PIC16TargetAsmInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PIC16/PIC16TargetAsmInfo.cpp?rev=62174&r1=62173&r2=62174&view=diff

==============================================================================
--- llvm/trunk/lib/Target/PIC16/PIC16TargetAsmInfo.cpp (original)
+++ llvm/trunk/lib/Target/PIC16/PIC16TargetAsmInfo.cpp Tue Jan 13 13:18:47 2009
@@ -13,6 +13,7 @@
 
 #include "PIC16TargetAsmInfo.h"
 #include "PIC16TargetMachine.h"
+#include "llvm/GlobalValue.h"
 
 using namespace llvm;
 
@@ -23,9 +24,12 @@
   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 = "";
 }

Modified: llvm/trunk/lib/Target/PIC16/PIC16TargetAsmInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PIC16/PIC16TargetAsmInfo.h?rev=62174&r1=62173&r2=62174&view=diff

==============================================================================
--- llvm/trunk/lib/Target/PIC16/PIC16TargetAsmInfo.h (original)
+++ llvm/trunk/lib/Target/PIC16/PIC16TargetAsmInfo.h Tue Jan 13 13:18:47 2009
@@ -23,17 +23,7 @@
 
   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





More information about the llvm-commits mailing list