Added a more function PIC16 backend. However to get this working a patch in
[oota-llvm.git] / lib / Target / PIC16 / PIC16ISelLowering.cpp
index ed3c64576246dbe68dea9fe7e6836b53ca61cb88..feb21ef54df87686c5dda19ce53f081b993f03d6 100644 (file)
 #include "PIC16ISelLowering.h"
 #include "PIC16TargetMachine.h"
 #include "llvm/DerivedTypes.h"
+#include "llvm/GlobalValue.h"
 #include "llvm/Function.h"
-#include "llvm/Intrinsics.h"
-#include "llvm/CallingConv.h"
-#include "llvm/CodeGen/CallingConvLower.h"
 #include "llvm/CodeGen/MachineFrameInfo.h"
 #include "llvm/CodeGen/MachineFunction.h"
-#include "llvm/CodeGen/MachineInstrBuilder.h"
-#include "llvm/CodeGen/MachineRegisterInfo.h"
-#include "llvm/CodeGen/SelectionDAGISel.h"
-#include "llvm/CodeGen/ValueTypes.h"
-#include "llvm/Support/Debug.h"
-using namespace llvm;
 
-const char *PIC16TargetLowering:: getTargetNodeName(unsigned Opcode) const 
-{
-  switch (Opcode) {
-    case PIC16ISD::Hi        : return "PIC16ISD::Hi";
-    case PIC16ISD::Lo        : return "PIC16ISD::Lo";
-    case PIC16ISD::Package   : return "PIC16ISD::Package";
-    case PIC16ISD::Wrapper   : return "PIC16ISD::Wrapper";
-    case PIC16ISD::SetBank   : return "PIC16ISD::SetBank";
-    case PIC16ISD::SetPage   : return "PIC16ISD::SetPage";
-    case PIC16ISD::Branch    : return "PIC16ISD::Branch";
-    case PIC16ISD::Cmp       : return "PIC16ISD::Cmp";
-    case PIC16ISD::BTFSS     : return "PIC16ISD::BTFSS";
-    case PIC16ISD::BTFSC     : return "PIC16ISD::BTFSC";
-    case PIC16ISD::XORCC     : return "PIC16ISD::XORCC";
-    case PIC16ISD::SUBCC     : return "PIC16ISD::SUBCC";
-    default                  : return NULL;
-  }
-}
 
-PIC16TargetLowering::
-PIC16TargetLowering(PIC16TargetMachine &TM): TargetLowering(TM) 
-{
-  // Set up the register classes.
-  addRegisterClass(MVT::i8, PIC16::CPURegsRegisterClass);
-  addRegisterClass(MVT::i16, PIC16::PTRRegsRegisterClass);
-
-  // Load extented operations for i1 types must be promoted .
-  setLoadExtAction(ISD::EXTLOAD, MVT::i1,  Promote);
-  setLoadExtAction(ISD::ZEXTLOAD, MVT::i1,  Promote);
-  setLoadExtAction(ISD::SEXTLOAD, MVT::i1,  Promote);
-
-  setOperationAction(ISD::ADD, MVT::i1, Promote);
-  setOperationAction(ISD::ADD, MVT::i8, Legal);
-  setOperationAction(ISD::ADD, MVT::i16, Custom);
-  setOperationAction(ISD::ADD, MVT::i32, Expand);
-  setOperationAction(ISD::ADD, MVT::i64, Expand);
-
-  setOperationAction(ISD::SUB, MVT::i1, Promote);
-  setOperationAction(ISD::SUB, MVT::i8, Legal);
-  setOperationAction(ISD::SUB, MVT::i16, Custom);
-  setOperationAction(ISD::SUB, MVT::i32, Expand);
-  setOperationAction(ISD::SUB, MVT::i64, Expand);
-
-  setOperationAction(ISD::ADDC, MVT::i1, Promote);
-  setOperationAction(ISD::ADDC, MVT::i8, Legal);
-  setOperationAction(ISD::ADDC, MVT::i16, Custom);
-  setOperationAction(ISD::ADDC, MVT::i32, Expand);
-  setOperationAction(ISD::ADDC, MVT::i64, Expand);
-
-  setOperationAction(ISD::ADDE, MVT::i1, Promote);
-  setOperationAction(ISD::ADDE, MVT::i8, Legal);
-  setOperationAction(ISD::ADDE, MVT::i16, Custom);
-  setOperationAction(ISD::ADDE, MVT::i32, Expand);
-  setOperationAction(ISD::ADDE, MVT::i64, Expand);
-
-  setOperationAction(ISD::SUBC, MVT::i1, Promote);
-  setOperationAction(ISD::SUBC, MVT::i8, Legal);
-  setOperationAction(ISD::SUBC, MVT::i16, Custom);
-  setOperationAction(ISD::SUBC, MVT::i32, Expand);
-  setOperationAction(ISD::SUBC, MVT::i64, Expand);
-
-  setOperationAction(ISD::SUBE, MVT::i1, Promote);
-  setOperationAction(ISD::SUBE, MVT::i8, Legal);
-  setOperationAction(ISD::SUBE, MVT::i16, Custom);
-  setOperationAction(ISD::SUBE, MVT::i32, Expand);
-  setOperationAction(ISD::SUBE, MVT::i64, Expand);
-
-  // PIC16 does not have these NodeTypes below.
-  setOperationAction(ISD::SETCC, MVT::i1, Expand);
-  setOperationAction(ISD::SETCC, MVT::i8, Expand);
-  setOperationAction(ISD::SETCC, MVT::Other, Expand);
-  setOperationAction(ISD::SELECT_CC, MVT::i1, Custom);
-  setOperationAction(ISD::SELECT_CC, MVT::i8, Custom);
-
-  setOperationAction(ISD::BRCOND, MVT::i1, Expand);
-  setOperationAction(ISD::BRCOND, MVT::i8, Expand);
-  setOperationAction(ISD::BRCOND, MVT::Other, Expand);
-
-  setOperationAction(ISD::BR_CC, MVT::i1, Custom);
-  setOperationAction(ISD::BR_CC, MVT::i8, Custom);
-
-  setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
+using namespace llvm;
+
 
+// PIC16TargetLowering Constructor.
+PIC16TargetLowering::PIC16TargetLowering(PIC16TargetMachine &TM)
+  : TargetLowering(TM) {
   
-  // FIXME: Do we really need to Custom lower the GA ??
-  setOperationAction(ISD::GlobalAddress, MVT::i8, Custom);
-  setOperationAction(ISD::RET, MVT::Other, Custom);
-
-  setOperationAction(ISD::CTPOP, MVT::i32, Expand);
-  setOperationAction(ISD::CTTZ, MVT::i32, Expand);
-  setOperationAction(ISD::CTLZ, MVT::i32, Expand);
-  setOperationAction(ISD::ROTL, MVT::i32, Expand);
-  setOperationAction(ISD::ROTR, MVT::i32, Expand);
-  setOperationAction(ISD::BSWAP, MVT::i32, Expand);
-
-  setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand);
-  setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand);
-  setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand);
-
-  // We don't have line number support yet.
-  setOperationAction(ISD::DBG_STOPPOINT, MVT::Other, Expand);
-  setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand);
-  setOperationAction(ISD::DBG_LABEL, MVT::Other, Expand);
-  setOperationAction(ISD::EH_LABEL, MVT::Other, Expand);
-
-  // Use the default for now.
-  setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);
-  setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
-
-  setOperationAction(ISD::LOAD, MVT::i1, Promote);
-  setOperationAction(ISD::LOAD, MVT::i8, Legal);
-
-  setTargetDAGCombine(ISD::LOAD);
-  setTargetDAGCombine(ISD::STORE);
-  setTargetDAGCombine(ISD::ADDE);
-  setTargetDAGCombine(ISD::ADDC);
-  setTargetDAGCombine(ISD::ADD);
-  setTargetDAGCombine(ISD::SUBE);
-  setTargetDAGCombine(ISD::SUBC);
-  setTargetDAGCombine(ISD::SUB);
-
-  setStackPointerRegisterToSaveRestore(PIC16::STKPTR);
+  Subtarget = &TM.getSubtarget<PIC16Subtarget>();
+
+  addRegisterClass(MVT::i8, PIC16::GPRRegisterClass);
+
+  setShiftAmountType(MVT::i8);
+  setShiftAmountFlavor(Extend);
+
+
+  setOperationAction(ISD::GlobalAddress, MVT::i16, Custom);
+
+  setOperationAction(ISD::LOAD,   MVT::i8,  Legal);
+  setOperationAction(ISD::LOAD,   MVT::i16, Custom);
+  setOperationAction(ISD::LOAD,   MVT::i32, Custom);
+
+  setOperationAction(ISD::STORE,  MVT::i8,  Legal);
+  setOperationAction(ISD::STORE,  MVT::i16, Custom);
+  setOperationAction(ISD::STORE,  MVT::i32, Custom);
+
+  setOperationAction(ISD::ADDE,    MVT::i8,  Custom);
+  setOperationAction(ISD::ADDC,    MVT::i8,  Custom);
+  setOperationAction(ISD::SUBE,    MVT::i8,  Custom);
+  setOperationAction(ISD::SUBC,    MVT::i8,  Custom);
+  setOperationAction(ISD::ADD,    MVT::i8,  Legal);
+  setOperationAction(ISD::ADD,    MVT::i16, Custom);
+
+  setOperationAction(ISD::SHL,    MVT::i16, Custom);
+  setOperationAction(ISD::SHL,    MVT::i32, Custom);
+
+  //setOperationAction(ISD::TRUNCATE, MVT::i16, Custom);
+  setTruncStoreAction(MVT::i16,   MVT::i8,  Custom);
+
+  // Now deduce the information based on the above mentioned 
+  // actions
   computeRegisterProperties();
 }
 
+const char *PIC16TargetLowering::getTargetNodeName(unsigned Opcode) const {
+  switch (Opcode) {
+  default:                         return NULL;
+  case PIC16ISD::Lo:               return "PIC16ISD::Lo";
+  case PIC16ISD::Hi:               return "PIC16ISD::Hi";
+  case PIC16ISD::MTLO:             return "PIC16ISD::MTLO";
+  case PIC16ISD::MTHI:             return "PIC16ISD::MTHI";
+  case PIC16ISD::Banksel:          return "PIC16ISD::Banksel";
+  case PIC16ISD::PIC16Load:        return "PIC16ISD::PIC16Load";
+  case PIC16ISD::PIC16Store:       return "PIC16ISD::PIC16Store";
+  case PIC16ISD::BCF:              return "PIC16ISD::BCF";
+  case PIC16ISD::LSLF:             return "PIC16ISD::LSLF";
+  case PIC16ISD::LRLF:             return "PIC16ISD::LRLF";
+  case PIC16ISD::RLF:              return "PIC16ISD::RLF";
+  case PIC16ISD::RRF:              return "PIC16ISD::RRF";
+  case PIC16ISD::Dummy:            return "PIC16ISD::Dummy";
+  }
+}
 
-SDValue PIC16TargetLowering:: LowerOperation(SDValue Op, SelectionDAG &DAG) 
-{
-  SDVTList VTList16 = DAG.getVTList(MVT::i16, MVT::i16, MVT::Other);
-  switch (Op.getOpcode()) {
-    case ISD::STORE: 
-      DOUT << "reduce store\n"; 
-      break;
+SDNode *PIC16TargetLowering::ReplaceNodeResults(SDNode *N, SelectionDAG &DAG) {
+  switch (N->getOpcode()) {
+    case ISD::GlobalAddress:
+      return ExpandGlobalAddress(N, DAG);
+    case ISD::STORE:
+      return ExpandStore(N, DAG);
+    case ISD::LOAD:
+      return ExpandLoad(N, DAG);
+    case ISD::ADD:
+      return ExpandAdd(N, DAG);
+    case ISD::SHL:
+      return ExpandShift(N, DAG);
+    default:
+      assert (0 && "not implemented");
+  }
+}
 
-    case ISD::FORMAL_ARGUMENTS:   
-      DOUT << "==== lowering formal args\n";
-      return LowerFORMAL_ARGUMENTS(Op, DAG);
+SDNode *PIC16TargetLowering::ExpandStore(SDNode *N, SelectionDAG &DAG) { 
+  StoreSDNode *St = cast<StoreSDNode>(N);
+  SDValue Chain = St->getChain();
+  SDValue Src = St->getValue();
+  SDValue Ptr = St->getBasePtr();
+  MVT ValueType = Src.getValueType();
+  unsigned StoreOffset = 0;
+
+  SDValue PtrLo, PtrHi;
+  LegalizeAddress(Ptr, DAG, PtrLo, PtrHi, StoreOffset);
+  if (ValueType == MVT::i8) {
+    SDValue Store = DAG.getNode (PIC16ISD::PIC16Store, MVT::Other, Chain, Src,
+                                 PtrLo, PtrHi, DAG.getConstant (0, MVT::i8));
+    return Store.getNode();
+  }
+  else if (ValueType == MVT::i16) {
+    // Get the Lo and Hi parts from MERGE_VALUE or BUILD_PAIR.
+    SDValue SrcLo, SrcHi;
+    GetExpandedParts(Src, DAG, SrcLo, SrcHi);
+    SDValue ChainLo = Chain, ChainHi = Chain;
+    if (Chain.getOpcode() == ISD::TokenFactor) {
+      ChainLo = Chain.getOperand(0);
+      ChainHi = Chain.getOperand(1);
+    }
+    SDValue Store1 = DAG.getNode(PIC16ISD::PIC16Store, MVT::Other,
+                                 ChainLo,
+                                 SrcLo, PtrLo, PtrHi,
+                                 DAG.getConstant (0 + StoreOffset, MVT::i8));
+
+    SDValue Store2 = DAG.getNode(PIC16ISD::PIC16Store, MVT::Other, ChainHi, 
+                                 SrcHi, PtrLo, PtrHi,
+                                 DAG.getConstant (1 + StoreOffset, MVT::i8));
 
-    case ISD::GlobalAddress:      
-      DOUT << "==== lowering GA\n";
-      return LowerGlobalAddress(Op, DAG);
+    return DAG.getNode(ISD::TokenFactor, MVT::Other, getChain(Store1),
+                       getChain(Store2)).getNode();
+  }
+  else if (ValueType == MVT::i32) {
+    // Get the Lo and Hi parts from MERGE_VALUE or BUILD_PAIR.
+    SDValue SrcLo, SrcHi;
+    GetExpandedParts(Src, DAG, SrcLo, SrcHi);
+
+    // Get the expanded parts of each of SrcLo and SrcHi.
+    SDValue SrcLo1, SrcLo2, SrcHi1, SrcHi2;
+    GetExpandedParts(SrcLo, DAG, SrcLo1, SrcLo2);
+    GetExpandedParts(SrcHi, DAG, SrcHi1, SrcHi2);
+
+    SDValue ChainLo = Chain, ChainHi = Chain;
+    if (Chain.getOpcode() == ISD::TokenFactor) {  
+      ChainLo = Chain.getOperand(0);
+      ChainHi = Chain.getOperand(1);
+    }
+    SDValue ChainLo1 = ChainLo, ChainLo2 = ChainLo, ChainHi1 = ChainHi,
+            ChainHi2 = ChainHi;
+    if (ChainLo.getOpcode() == ISD::TokenFactor) {
+      ChainLo1 = ChainLo.getOperand(0);
+      ChainLo2 = ChainLo.getOperand(1);
+    }
+    if (ChainHi.getOpcode() == ISD::TokenFactor) {
+      ChainHi1 = ChainHi.getOperand(0);
+      ChainHi2 = ChainHi.getOperand(1);
+    }
+    SDValue Store1 = DAG.getNode(PIC16ISD::PIC16Store, MVT::Other,
+                                 ChainLo1,
+                                 SrcLo1, PtrLo, PtrHi,
+                                 DAG.getConstant (0 + StoreOffset, MVT::i8));
 
-    case ISD::RET:                
-      DOUT << "==== lowering ret\n";
-      return LowerRET(Op, DAG);
+    SDValue Store2 = DAG.getNode(PIC16ISD::PIC16Store, MVT::Other, ChainLo2,
+                                 SrcLo2, PtrLo, PtrHi,
+                                 DAG.getConstant (1 + StoreOffset, MVT::i8));
 
-    case ISD::FrameIndex:                
-      DOUT << "==== lowering frame index\n";
-      return LowerFrameIndex(Op, DAG);
+    SDValue Store3 = DAG.getNode(PIC16ISD::PIC16Store, MVT::Other, ChainHi1,
+                                 SrcHi1, PtrLo, PtrHi,
+                                 DAG.getConstant (2 + StoreOffset, MVT::i8));
 
-    case ISD::ADDE: 
-      DOUT << "==== lowering adde\n"; 
-      break;
+    SDValue Store4 = DAG.getNode(PIC16ISD::PIC16Store, MVT::Other, ChainHi2,
+                                 SrcHi2, PtrLo, PtrHi,
+                                 DAG.getConstant (3 + StoreOffset, MVT::i8));
 
-    case ISD::LOAD:
-    case ISD::ADD: 
-      break;
+    SDValue RetLo =  DAG.getNode(ISD::TokenFactor, MVT::Other, getChain(Store1),
+                                 getChain(Store2));
+    SDValue RetHi =  DAG.getNode(ISD::TokenFactor, MVT::Other, getChain(Store3),
+                                getChain(Store4));
+    return  DAG.getNode(ISD::TokenFactor, MVT::Other, RetLo, RetHi).getNode();
 
-    case ISD::BR_CC:                
-      DOUT << "==== lowering BR_CC\n"; 
-      return LowerBR_CC(Op, DAG); 
-  } // end switch.
-  return SDValue();
+  }
+  else {
+    assert (0 && "value type not supported");
+  }
 }
 
+// ExpandGlobalAddress - 
+SDNode *PIC16TargetLowering::ExpandGlobalAddress(SDNode *N, SelectionDAG &DAG) {
+  GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(SDValue(N, 0));
+  
+  SDValue TGA = DAG.getTargetGlobalAddress(G->getGlobal(), MVT::i8,
+                                           G->getOffset());
+
+  SDValue Lo = DAG.getNode(PIC16ISD::Lo, MVT::i8, TGA);
+  SDValue Hi = DAG.getNode(PIC16ISD::Hi, MVT::i8, TGA);
 
-//===----------------------------------------------------------------------===//
-//  Lower helper functions
-//===----------------------------------------------------------------------===//
+  SDValue BP = DAG.getNode(ISD::BUILD_PAIR, MVT::i16, Lo, Hi);
+  return BP.getNode();
+}
 
-SDValue PIC16TargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) 
-{
-  MVT VT = Op.getValueType();
-  SDValue Chain = Op.getOperand(0);
-  ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get();
-  SDValue LHS = Op.getOperand(2);
-  SDValue RHS = Op.getOperand(3);
-  SDValue JumpVal = Op.getOperand(4);
-  SDValue Result;
-  unsigned  cmpOpcode;
-  unsigned  branchOpcode;
-  SDValue branchOperand;
-
-  SDValue StatusReg = DAG.getRegister(PIC16::STATUSREG, MVT::i8);
-  SDValue CPUReg = DAG.getRegister(PIC16::WREG, MVT::i8);
-  switch(CC) {
-    default:
-      assert(0 && "This condition code is not handled yet!!");
-      abort();
-
-    case ISD::SETNE:
-      DOUT << "setne\n";
-      cmpOpcode = PIC16ISD::XORCC;
-      branchOpcode = PIC16ISD::BTFSS;
-      branchOperand = DAG.getConstant(2, MVT::i8);
-      break;
-
-    case ISD::SETEQ:
-      DOUT << "seteq\n";
-      cmpOpcode = PIC16ISD::XORCC;
-      branchOpcode = PIC16ISD::BTFSC;
-      branchOperand = DAG.getConstant(2, MVT::i8);
-      break;
-
-    case ISD::SETGT:
-      assert(0 && "Greater Than condition code is not handled yet!!");
-      abort();
-      break;
-
-    case ISD::SETGE:
-      DOUT << "setge\n";
-      cmpOpcode = PIC16ISD::SUBCC;
-      branchOpcode = PIC16ISD::BTFSS;
-      branchOperand = DAG.getConstant(1, MVT::i8);
-      break;
-
-    case ISD::SETLT:
-      DOUT << "setlt\n";
-      cmpOpcode = PIC16ISD::SUBCC;
-      branchOpcode = PIC16ISD::BTFSC;
-      branchOperand = DAG.getConstant(1,MVT::i8);
-      break;
-
-    case ISD::SETLE:
-      assert(0 && "Less Than Equal condition code is not handled yet!!");
-      abort();
-      break;
-  }  // End of Switch
-
-   SDVTList VTList = DAG.getVTList(MVT::i8, MVT::Flag);
-   SDValue CmpValue = DAG.getNode(cmpOpcode, VTList, LHS, RHS).getValue(1);
-   Result = DAG.getNode(branchOpcode, VT, Chain, JumpVal, branchOperand, 
-                        StatusReg, CmpValue);
-   return Result;
+bool PIC16TargetLowering::isDirectAddress(const SDValue &Op) {
+  assert (Op.getNode() != NULL && "Can't operate on NULL SDNode!!");
+
+  if (Op.getOpcode() == ISD::BUILD_PAIR) {
+   if (Op.getOperand(0).getOpcode() == PIC16ISD::Lo) 
+     return true;
+  }
+  return false;
 }
 
+// Return true if DirectAddress is in ROM_SPACE
+bool PIC16TargetLowering::isRomAddress(const SDValue &Op) {
 
-//===----------------------------------------------------------------------===//
-//  Misc Lower Operation implementation
-//===----------------------------------------------------------------------===//
+  // RomAddress is a GlobalAddress in ROM_SPACE_
+  // If the Op is not a GlobalAddress return NULL without checking
+  // anything further.
+  if (!isDirectAddress(Op))
+    return false; 
+
+  // Its a GlobalAddress.
+  // It is BUILD_PAIR((PIC16Lo TGA), (PIC16Hi TGA)) and Op is BUILD_PAIR
+  SDValue TGA = Op.getOperand(0).getOperand(0);
+  GlobalAddressSDNode *GSDN = dyn_cast<GlobalAddressSDNode>(TGA);
+  const Type *ValueType = GSDN->getGlobal()->getType();
 
-// LowerGlobalAddress - Create a constant pool entry for global value 
-// and wrap it in a wrapper node.
-SDValue
-PIC16TargetLowering::LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) 
-{
-  MVT PtrVT = getPointerTy();
-  GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op);
-  GlobalValue *GV = GSDN->getGlobal();
-
-  // FIXME: for now only do the ram.
-  SDValue CPAddr = DAG.getTargetConstantPool(GV, PtrVT, 2);
-  SDValue CPBank = DAG.getNode(PIC16ISD::SetBank, MVT::i8, CPAddr);
-  CPAddr = DAG.getNode(PIC16ISD::Wrapper, MVT::i8, CPAddr,CPBank);
-
-  return CPAddr;
+  if (!isa<PointerType>(ValueType)) {
+    assert(0 && "TGA must be of a PointerType");
+  }
+
+  int AddrSpace = dyn_cast<PointerType>(ValueType)->getAddressSpace();
+  if (AddrSpace == PIC16ISD::ROM_SPACE)
+    return true;
+
+  // Any other address space return it false
+  return false;
 }
 
-SDValue
-PIC16TargetLowering::LowerRET(SDValue Op, SelectionDAG &DAG) 
-{
-  switch(Op.getNumOperands()) {
-    default:
-      assert(0 && "Do not know how to return this many arguments!");
-      abort();
+// To extract chain value from the SDValue Nodes
+// This function will help to maintain the chain extracting
+// code at one place. In case of any change in future it will
+// help maintain the code.
+SDValue PIC16TargetLowering::getChain(SDValue &Op) { 
+  SDValue Chain = Op.getValue(Op.getNode()->getNumValues() - 1);
 
-    case 1:
-      return SDValue(); // ret void is legal
-  }
+  // 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");
+
+  return Chain;
 }
 
-SDValue
-PIC16TargetLowering::LowerFrameIndex(SDValue N, SelectionDAG &DAG) 
-{
-  if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(N)) {
-    return DAG.getTargetFrameIndex(FIN->getIndex(), MVT::i32);
+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);
   }
 
-  return N;
+  // 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());
+
+  // 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());
 }
 
-SDValue
-PIC16TargetLowering::LowerLOAD(SDNode *N,
-                               SelectionDAG &DAG,
-                               DAGCombinerInfo &DCI) const
-{
-  SDValue Outs[2];
-  SDValue TF; //TokenFactor
-  SDValue OutChains[2];
-  SDValue Chain = N->getOperand(0);  
-  SDValue Src   = N->getOperand(1);
-  SDValue retVal;
-  SDVTList VTList;
-
-  // If this load is directly stored, replace the load value with the stored
-  // value.
-  // FIXME: Handle store large -> read small portion.
-  // FIXME: Handle TRUNCSTORE/LOADEXT
-  LoadSDNode *LD  = cast<LoadSDNode>(N);
-  SDValue Ptr   = LD->getBasePtr();
-  if (LD->getExtensionType() == ISD::NON_EXTLOAD) {
-    if (ISD::isNON_TRUNCStore(Chain.getNode())) {
-      StoreSDNode *PrevST = cast<StoreSDNode>(Chain);
-      if (PrevST->getBasePtr() == Ptr &&
-          PrevST->getValue().getValueType() == N->getValueType(0))
-        return DCI.CombineTo(N, Chain.getOperand(1), Chain);
+// This function legalizes the PIC16 Addresses. If the Pointer is  
+//  -- Direct address variable residing 
+//     --> then a Banksel for that variable will be created.
+//  -- Rom variable            
+//     --> then it will be treated as an indirect address.
+//  -- Indirect address 
+//     --> then the address will be loaded into FSR
+//  -- ADD with constant operand
+//     --> then constant operand of ADD will be returned as Offset
+//         and non-constant operand of ADD will be treated as pointer.
+// Returns the high and lo part of the address, and the offset(in case of ADD).
+
+void PIC16TargetLowering:: LegalizeAddress(SDValue Ptr, SelectionDAG &DAG, 
+                                           SDValue &Lo, SDValue &Hi,
+                                           unsigned &Offset) {
+
+  // Offset, by default, should be 0
+  Offset = 0;
+
+  // If the pointer is ADD with constant,
+  // return the constant value as the offset  
+  if (Ptr.getOpcode() == ISD::ADD) {
+    SDValue OperLeft = Ptr.getOperand(0);
+    SDValue OperRight = Ptr.getOperand(1);
+    if (OperLeft.getOpcode() == ISD::Constant) {
+      Offset = dyn_cast<ConstantSDNode>(OperLeft)->getZExtValue();
+      Ptr = OperRight;
+    } else {
+      Ptr = OperLeft;
+      Offset = dyn_cast<ConstantSDNode>(OperRight)->getZExtValue();
     }
   }
 
-  if (N->getValueType(0) != MVT::i16)
-    return SDValue();
+  if (isDirectAddress(Ptr) && !isRomAddress(Ptr)) {
+    // Direct addressing case for RAM variables. The Hi part is constant
+    // and the Lo part is the TGA itself.
+    Lo = Ptr.getOperand(0).getOperand(0);
+
+    // For direct addresses Hi is a constant. Value 1 for the constant
+    // signifies that banksel needs to generated for it. Value 0 for
+    // the constant signifies that banksel does not need to be generated 
+    // for it. Mark it as 1 now and optimize later. 
+    Hi = DAG.getConstant(1, MVT::i8);
+    return; 
+  }
 
-  SDValue toWorklist;
-  Outs[0] = DAG.getLoad(MVT::i8, Chain, Src, NULL, 0);
-  toWorklist = DAG.getNode(ISD::ADD, MVT::i16, Src,
-                           DAG.getConstant(1, MVT::i16));
-  Outs[1] = DAG.getLoad(MVT::i8, Chain, toWorklist, NULL, 0);
-  // FIXME: Add to worklist may not be needed. 
-  // It is meant to merge sequences of add with constant into one. 
-  DCI.AddToWorklist(toWorklist.getNode());   
-  
-  // Create the tokenfactors and carry it on to the build_pair node
-  OutChains[0] = Outs[0].getValue(1);
-  OutChains[1] = Outs[1].getValue(1);
-  TF = DAG.getNode(ISD::TokenFactor, MVT::Other, &OutChains[0], 2);
-  
-  VTList = DAG.getVTList(MVT::i16, MVT::Flag);
-  retVal = DAG.getNode (PIC16ISD::Package, VTList, &Outs[0], 2);
+  // Indirect addresses. Get the hi and lo parts of ptr. 
+  GetExpandedParts(Ptr, DAG, Lo, Hi);
 
-  DCI.CombineTo (N, retVal, TF);
+  // Put the hi and lo parts into FSR.
+  Lo = DAG.getNode(PIC16ISD::MTLO, MVT::i8, Lo);
+  Hi = DAG.getNode(PIC16ISD::MTHI, MVT::i8, Hi);
 
-  return retVal;
+  return;
 }
 
-SDValue
-PIC16TargetLowering::LowerADDSUB(SDNode *N, SelectionDAG &DAG,
-                                 DAGCombinerInfo &DCI) const
-{
-  bool changed = false;
-  int i;
-  SDValue LoOps[3], HiOps[3];
-  SDValue OutOps[3]; // [0]:left, [1]:right, [2]:carry
-  SDValue InOp[2];
-  SDValue retVal;
-  SDValue as1,as2;
-  SDVTList VTList;
-  unsigned AS = 0, ASE = 0, ASC=0;
-
-  InOp[0] = N->getOperand(0);
-  InOp[1] = N->getOperand(1);  
+SDNode *PIC16TargetLowering::ExpandAdd(SDNode *N, SelectionDAG &DAG) {
+  SDValue OperLeft = N->getOperand(0);
+  SDValue OperRight = N->getOperand(1);
 
-  switch (N->getOpcode()) {
-    case ISD::ADD:
-      if (InOp[0].getOpcode() == ISD::Constant &&
-          InOp[1].getOpcode() == ISD::Constant) {
-        ConstantSDNode *CST0 = dyn_cast<ConstantSDNode>(InOp[0]);
-        ConstantSDNode *CST1 = dyn_cast<ConstantSDNode>(InOp[1]);
-        return DAG.getConstant(CST0->getZExtValue() + CST1->getZExtValue(),
-                               MVT::i16);
-      }
-      break;
+  if((OperLeft.getOpcode() == ISD::Constant) || 
+     (OperRight.getOpcode() == ISD::Constant)) { 
+    return NULL;
+  }
 
-    case ISD::ADDE:
-    case ISD::ADDC:
-      AS  = ISD::ADD;
-      ASE = ISD::ADDE;
-      ASC = ISD::ADDC;
-      break;
-
-    case ISD::SUB:
-      if (InOp[0].getOpcode() == ISD::Constant &&
-          InOp[1].getOpcode() == ISD::Constant) {
-        ConstantSDNode *CST0 = dyn_cast<ConstantSDNode>(InOp[0]);
-        ConstantSDNode *CST1 = dyn_cast<ConstantSDNode>(InOp[1]);
-        return DAG.getConstant(CST0->getZExtValue() - CST1->getZExtValue(),
-                               MVT::i16);
-      }
-      break;
+  // These case are yet to be handled
+  return NULL;
+}
 
-    case ISD::SUBE:
-    case ISD::SUBC:
-      AS  = ISD::SUB;
-      ASE = ISD::SUBE;
-      ASC = ISD::SUBC;
-      break;
-  } // end switch.
-
-  assert ((N->getValueType(0) == MVT::i16) 
-           && "expecting an MVT::i16 node for lowering");
-  assert ((N->getOperand(0).getValueType() == MVT::i16) 
-           && (N->getOperand(1).getValueType() == MVT::i16) 
-            && "both inputs to addx/subx:i16 must be i16");
-
-  for (i = 0; i < 2; i++) {
-    if (InOp[i].getOpcode() == ISD::GlobalAddress) {
-      // We don't want to lower subs/adds with global address yet.
-      return SDValue();
-    }
-    else if (InOp[i].getOpcode() == ISD::Constant) {
-      changed = true;
-      ConstantSDNode *CST = dyn_cast<ConstantSDNode>(InOp[i]);
-      LoOps[i] = DAG.getConstant(CST->getZExtValue() & 0xFF, MVT::i8);
-      HiOps[i] = DAG.getConstant(CST->getZExtValue() >> 8, MVT::i8);
-    }
-    else if (InOp[i].getOpcode() == PIC16ISD::Package) {
-      LoOps[i] = InOp[i].getOperand(0);
-      HiOps[i] = InOp[i].getOperand(1);
+SDNode *PIC16TargetLowering::ExpandLoad(SDNode *N, SelectionDAG &DAG) {
+  LoadSDNode *LD = dyn_cast<LoadSDNode>(SDValue(N, 0));
+  SDValue Chain = LD->getChain();
+  SDValue Ptr = LD->getBasePtr();
+
+  SDValue Load, Offset;
+  SDVTList Tys; 
+  MVT VT, NewVT;
+  SDValue PtrLo, PtrHi;
+  unsigned LoadOffset;
+
+  // Legalize direct/indirect addresses. This will give the lo and hi parts
+  // of the address and the offset.
+  LegalizeAddress(Ptr, DAG, PtrLo, PtrHi, LoadOffset);
+
+  // Load from the pointer (direct address or FSR) 
+  VT = N->getValueType(0);
+  unsigned NumLoads = VT.getSizeInBits() / 8; 
+  std::vector<SDValue> PICLoads;
+  unsigned iter;
+  MVT MemVT = LD->getMemoryVT();
+  if(ISD::isNON_EXTLoad(N)) {
+    for (iter=0; iter<NumLoads ; ++iter) {
+      // Add the pointer offset if any
+      Offset = DAG.getConstant(iter + LoadOffset, MVT::i8);
+      Tys = DAG.getVTList(MVT::i8, MVT::Other); 
+      Load = DAG.getNode(PIC16ISD::PIC16Load, Tys, Chain, PtrLo, PtrHi,
+                         Offset); 
+      PICLoads.push_back(Load);
     }
-    else if (InOp[i].getOpcode() == ISD::LOAD) {
-      changed = true;
-      // LowerLOAD returns a Package node or it may combine and return 
-      // anything else.
-      SDValue lowered = LowerLOAD(InOp[i].getNode(), DAG, DCI);
-
-      // So If LowerLOAD returns something other than Package, 
-      // then just call ADD again.
-      if (lowered.getOpcode() != PIC16ISD::Package)
-        return LowerADDSUB(N, DAG, DCI);
-          
-      LoOps[i] = lowered.getOperand(0);
-      HiOps[i] = lowered.getOperand(1);
+  } else {
+    // If it is extended load then use PIC16Load for Memory Bytes
+    // and for all extended bytes perform action based on type of
+    // extention - i.e. SignExtendedLoad or ZeroExtendedLoad
+
+    
+    // For extended loads this is the memory value type
+    // i.e. without any extension
+    MVT MemVT = LD->getMemoryVT();
+    unsigned MemBytes = MemVT.getSizeInBits() / 8;
+    unsigned ExtdBytes = VT.getSizeInBits() / 8;
+    Offset = DAG.getConstant(LoadOffset, MVT::i8);
+
+    Tys = DAG.getVTList(MVT::i8, MVT::Other); 
+    // For MemBytes generate PIC16Load with proper offset
+    for (iter=0; iter<MemBytes; ++iter) {
+      // Add the pointer offset if any
+      Offset = DAG.getConstant(iter + LoadOffset, MVT::i8);
+      Load = DAG.getNode(PIC16ISD::PIC16Load, Tys, Chain, PtrLo, PtrHi,
+                         Offset); 
+      PICLoads.push_back(Load);
     }
-    else if ((InOp[i].getOpcode() == ISD::ADD) || 
-             (InOp[i].getOpcode() == ISD::ADDE) ||
-             (InOp[i].getOpcode() == ISD::ADDC) ||
-             (InOp[i].getOpcode() == ISD::SUB) ||
-             (InOp[i].getOpcode() == ISD::SUBE) ||
-             (InOp[i].getOpcode() == ISD::SUBC)) {
-      changed = true;
-      // Must call LowerADDSUB recursively here,
-      // LowerADDSUB returns a Package node.
-      SDValue lowered = LowerADDSUB(InOp[i].getNode(), DAG, DCI);
-
-      LoOps[i] = lowered.getOperand(0);
-      HiOps[i] = lowered.getOperand(1);
-    }
-    else if (InOp[i].getOpcode() == ISD::SIGN_EXTEND) {
-      // FIXME: I am just zero extending. for now.
-      changed = true;
-      LoOps[i] = InOp[i].getOperand(0);
-      HiOps[i] = DAG.getConstant(0, MVT::i8);
+
+    // For SignExtendedLoad
+    if (ISD::isSEXTLoad(N)) {
+      // For all ExtdBytes use the Right Shifted(Arithmetic) Value of the 
+      // highest MemByte
+      SDValue SRA = DAG.getNode(ISD::SRA, MVT::i8, Load, 
+                                DAG.getConstant(7, MVT::i8));
+      for (iter=MemBytes; iter<ExtdBytes; ++iter) { 
+        PICLoads.push_back(SRA);
+      }
+    } else if (ISD::isZEXTLoad(N)) {
+      // ZeroExtendedLoad -- For all ExtdBytes use constant 0
+      SDValue ConstZero = DAG.getConstant(0, MVT::i8);
+      for (iter=MemBytes; iter<ExtdBytes; ++iter) { 
+        PICLoads.push_back(ConstZero);
+      }
     }
+  }
+  SDValue BP;
+
+  if (VT == MVT::i8) {
+    // Operand of Load is illegal -- Load itself is legal
+    return PICLoads[0].getNode();
+  }
+  else if (VT == MVT::i16) {
+    BP = DAG.getNode(ISD::BUILD_PAIR, VT, PICLoads[0], PICLoads[1]);
+    if (MemVT == MVT::i8)
+      Chain = getChain(PICLoads[0]);
+    else
+      Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, getChain(PICLoads[0]),
+                          getChain(PICLoads[1]));
+  } else if (VT == MVT::i32) {
+    SDValue BPs[2];
+    BPs[0] = DAG.getNode(ISD::BUILD_PAIR, MVT::i16, PICLoads[0], PICLoads[1]);
+    BPs[1] = DAG.getNode(ISD::BUILD_PAIR, MVT::i16, PICLoads[2], PICLoads[3]);
+    BP = DAG.getNode(ISD::BUILD_PAIR, VT, BPs[0], BPs[1]);
+    if (MemVT == MVT::i8)
+      Chain = getChain(PICLoads[0]);
+    else if (MemVT == MVT::i16)
+      Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, getChain(PICLoads[0]),
+                          getChain(PICLoads[1]));
     else {
-      DAG.setGraphColor(N, "blue");
-      DAG.viewGraph();
-      assert (0 && "not implemented yet");
+      SDValue Chains[2];
+      Chains[0] = DAG.getNode(ISD::TokenFactor, MVT::Other,
+                              getChain(PICLoads[0]), getChain(PICLoads[1]));
+      Chains[1] = DAG.getNode(ISD::TokenFactor, MVT::Other,
+                              getChain(PICLoads[2]), getChain(PICLoads[3]));
+      Chain =  DAG.getNode(ISD::TokenFactor, MVT::Other, Chains[0], Chains[1]);
     }
-  } // end for.
+  }
+  Tys = DAG.getVTList(VT, MVT::Other); 
+  SDValue MergeV = DAG.getNode(ISD::MERGE_VALUES, Tys, BP, Chain);
+  return MergeV.getNode();
 
-  assert (changed && "nothing changed while lowering SUBx/ADDx");
+}
 
-  VTList = DAG.getVTList(MVT::i8, MVT::Flag);
-  if (N->getOpcode() == ASE) { 
-    // We must take in the existing carry
-    // if this node is part of an existing subx/addx sequence.
-    LoOps[2] = N->getOperand(2).getValue(1);
-    as1 = DAG.getNode (ASE, VTList, LoOps, 3);
-  }
-  else {
-    as1 = DAG.getNode (ASC, VTList, LoOps, 2);
-  }
-  HiOps[2] = as1.getValue(1);
-  as2 = DAG.getNode (ASE, VTList, HiOps, 3);
-  // We must build a pair that also provides the carry from sube/adde.
-  OutOps[0] = as1;
-  OutOps[1] = as2;
-  OutOps[2] = as2.getValue(1);
-  // Breaking an original i16, so lets make the Package also an i16.
-  if (N->getOpcode() == ASE) {
-    VTList = DAG.getVTList(MVT::i16, MVT::Flag);
-    retVal = DAG.getNode (PIC16ISD::Package, VTList, OutOps, 3);
-    DCI.CombineTo (N, retVal, OutOps[2]);
-  }
-  else if (N->getOpcode() == ASC) {
-    VTList = DAG.getVTList(MVT::i16, MVT::Flag);
-    retVal = DAG.getNode (PIC16ISD::Package, VTList, OutOps, 2);
-    DCI.CombineTo (N, retVal, OutOps[2]);
-  }
-  else if (N->getOpcode() == AS) {
-    VTList = DAG.getVTList(MVT::i16);
-    retVal = DAG.getNode (PIC16ISD::Package, VTList, OutOps, 2);
-    DCI.CombineTo (N, retVal);
+SDNode *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, RotNode; 
+  
+  // Currently handling Constant shift only
+  if (Amt.getOpcode() != ISD::Constant)
+    return NULL;
+
+  // Following code considers 16 bit left-shift only
+  if (N->getValueType(0) != MVT::i16)
+    return NULL;
+
+  if (N->getOpcode() == ISD::SHL) {
+    ShfNode = PIC16ISD::LSLF;
+    RotNode = PIC16ISD::RLF;
+  } else if (N->getOpcode() == ISD::SRL) {
+    ShfNode = PIC16ISD::LRLF;
+    RotNode = PIC16ISD::RRF;
   }
+  unsigned ShiftAmt = dyn_cast<ConstantSDNode>(Amt)->getZExtValue();
+  SDValue StatusReg = DAG.getRegister(PIC16::STATUS, MVT::i8);
+  // 0th Bit in StatusReg is CarryBit 
+  SDValue CarryBit= DAG.getConstant(0, MVT::i8);
 
-  return retVal;
-}
+  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);
 
-//===----------------------------------------------------------------------===//
-//                      Calling Convention Implementation
-//===----------------------------------------------------------------------===//
+    // Following are Two-Address Instructions
+    ShfCom = DAG.getNode(ShfNode, Tys, ShfCom, BCF);
+    RotCom = DAG.getNode(RotNode, Tys, RotCom, ShfCom.getValue(1));
 
-#include "PIC16GenCallingConv.inc"
+    BCFInput = RotCom.getValue(1); 
+  }
 
-//===----------------------------------------------------------------------===//
-//                  CALL Calling Convention Implementation
-//===----------------------------------------------------------------------===//
+  SDValue BP = DAG.getNode(ISD::BUILD_PAIR, N->getValueType(0), ShfCom, RotCom);
+  return BP.getNode();
+}
+
+SDValue PIC16TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {
+  switch (Op.getOpcode()) {
+    case ISD::FORMAL_ARGUMENTS:
+      return LowerFORMAL_ARGUMENTS(Op, DAG);
+    case ISD::ADDC:
+      return LowerADDC(Op, DAG);
+    case ISD::ADDE:
+      return LowerADDE(Op, DAG);
+    case ISD::SUBE:
+      return LowerSUBE(Op, DAG);
+    case ISD::SUBC:
+      return LowerSUBC(Op, DAG);
+    case ISD::LOAD:
+      return SDValue(ExpandLoad(Op.getNode(), DAG), Op.getResNo());
+    case ISD::STORE:
+      return SDValue(ExpandStore(Op.getNode(), DAG), Op.getResNo());
+    case ISD::SHL:
+      return SDValue(ExpandShift(Op.getNode(), DAG), Op.getResNo());
+  }
+  return SDValue();
+}
 
+SDValue PIC16TargetLowering::ConvertToMemOperand(SDValue Op,
+                                                 SelectionDAG &DAG) {
+
+  assert (Op.getValueType() == MVT::i8 
+          && "illegal value type to store on stack.");
+
+  MachineFunction &MF = DAG.getMachineFunction();
+  const Function *Func = MF.getFunction();
+  const std::string FuncName = Func->getName();
+
+  char *tmpName = new char [strlen(FuncName.c_str()) +  6];
+
+  // Put the value on stack.
+  // Get a stack slot index and convert to es.
+  int FI = MF.getFrameInfo()->CreateStackObject(1, 1);
+  sprintf(tmpName, "%s.tmp", FuncName.c_str());
+  SDValue ES = DAG.getTargetExternalSymbol(tmpName, MVT::i8);
+
+  // Store the value to ES.
+  SDValue Store = DAG.getNode (PIC16ISD::PIC16Store, MVT::Other,
+                               DAG.getEntryNode(),
+                               Op, ES, 
+                               DAG.getConstant (1, MVT::i8), // Banksel.
+                               DAG.getConstant (FI, MVT::i8));
+
+  // Load the value from ES.
+  SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Other);
+  SDValue Load = DAG.getNode(PIC16ISD::PIC16Load, Tys, Store,
+                             ES, DAG.getConstant (1, MVT::i8),
+                             DAG.getConstant (FI, MVT::i8));
+    
+  return Load.getValue(0);
+}
 
-//===----------------------------------------------------------------------===//
-//             FORMAL_ARGUMENTS Calling Convention Implementation
-//===----------------------------------------------------------------------===//
-SDValue PIC16TargetLowering::
-LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG)
-{
-  SmallVector<SDValue, 8> ArgValues;
-  SDValue Root = Op.getOperand(0);
+SDValue PIC16TargetLowering:: LowerADDC(SDValue Op, SelectionDAG &DAG) {
+  // We should have handled larger operands in type legalizer itself.
+  assert (Op.getValueType() == MVT::i8 && "illegal addc to lower");
 
-  // Return the new list of results.
-  // FIXME: Just copy right now.
-  ArgValues.push_back(Root);
+  // 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 DAG.getMergeValues(Op.getNode()->getVTList(), &ArgValues[0],
-                            ArgValues.size()).getValue(Op.getResNo());
+  // Put one value on stack.
+  SDValue NewVal = ConvertToMemOperand (Op.getOperand(1), DAG);
+    
+  SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Flag);
+  return DAG.getNode(ISD::ADDC, Tys, Op.getOperand(0), NewVal);
 }
 
+SDValue PIC16TargetLowering:: LowerADDE(SDValue Op, SelectionDAG &DAG) {
+  // We should have handled larger operands in type legalizer itself.
+  assert (Op.getValueType() == MVT::i8 && "illegal adde to lower");
 
-//===----------------------------------------------------------------------===//
-//               Return Value Calling Convention Implementation
-//===----------------------------------------------------------------------===//
+  // 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();
 
-//===----------------------------------------------------------------------===//
-//                           PIC16 Inline Assembly Support
-//===----------------------------------------------------------------------===//
+  // Put one value on stack.
+  SDValue NewVal = ConvertToMemOperand (Op.getOperand(1), DAG);
+    
+  SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Flag);
+  return DAG.getNode(ISD::ADDE, Tys, Op.getOperand(0), NewVal, 
+                     Op.getOperand(2));
+}
 
-//===----------------------------------------------------------------------===//
-// Target Optimization Hooks
-//===----------------------------------------------------------------------===//
+SDValue PIC16TargetLowering:: LowerSUBC(SDValue Op, SelectionDAG &DAG) {
+  // We should have handled larger operands in type legalizer itself.
+  assert (Op.getValueType() == MVT::i8 && "illegal subc to lower");
 
-SDValue PIC16TargetLowering::PerformDAGCombine(SDNode *N, 
-                                                 DAGCombinerInfo &DCI) const 
-{
-  int i;
-  ConstantSDNode *CST;
-  SelectionDAG &DAG = DCI.DAG;
+  // Nothing to do if the first operand is already a load.
+  if (Op.getOperand(0).getOpcode() == PIC16ISD::PIC16Load)
+    return SDValue();
 
-  switch (N->getOpcode()) {
-    default: 
-      break;
+  // Put first operand on stack.
+  SDValue NewVal = ConvertToMemOperand (Op.getOperand(0), DAG);
 
-    case PIC16ISD::Package:
-      DOUT << "==== combining PIC16ISD::Package\n";
-      return SDValue();
+  SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Flag);
+  return DAG.getNode(ISD::SUBC, Tys, NewVal, Op.getOperand(1));
+}
 
-    case ISD::ADD:
-    case ISD::SUB:
-      if ((N->getOperand(0).getOpcode() == ISD::GlobalAddress) ||
-          (N->getOperand(0).getOpcode() == ISD::FrameIndex)) {
-        // Do not touch pointer adds.
-        return SDValue ();
-      }
-      break;
-
-    case ISD::ADDE :
-    case ISD::ADDC :
-    case ISD::SUBE :
-    case ISD::SUBC :
-      if (N->getValueType(0) == MVT::i16) {
-        SDValue retVal = LowerADDSUB(N, DAG,DCI); 
-        // LowerADDSUB has already combined the result, 
-        // so we just return nothing to avoid assertion failure from llvm 
-        // if N has been deleted already.
-        return SDValue();
-      }
-      else if (N->getValueType(0) == MVT::i8) { 
-        // Sanity check ....
-        for (int i=0; i<2; i++) {
-          if (N->getOperand (i).getOpcode() == PIC16ISD::Package) {
-            assert (0 && 
-                    "don't want to have PIC16ISD::Package as intput to add:i8");
-          }
-        }
-      }
-      break;
-
-    // FIXME: split this large chunk of code.
-    case ISD::STORE :
-    {
-      SDValue Chain = N->getOperand(0);  
-      SDValue Src = N->getOperand(1);
-      SDValue Dest = N->getOperand(2);
-      unsigned int DstOff = 0;
-      int NUM_STORES = 0;
-      SDValue Stores[6];
-
-      // if source operand is expected to be extended to 
-      // some higher type then - remove this extension 
-      // SDNode and do the extension manually
-      if ((Src.getOpcode() == ISD::ANY_EXTEND) ||
-          (Src.getOpcode() == ISD::SIGN_EXTEND) || 
-          (Src.getOpcode() == ISD::ZERO_EXTEND)) {
-        Src = Src.getNode()->getOperand(0);
-        Stores[0] = DAG.getStore(Chain, Src, Dest, NULL,0);
-        return Stores[0];
-      }
+SDValue PIC16TargetLowering:: LowerSUBE(SDValue Op, SelectionDAG &DAG) {
+  // We should have handled larger operands in type legalizer itself.
+  assert (Op.getValueType() == MVT::i8 && "illegal sube to lower");
 
-      switch(Src.getValueType().getSimpleVT()) {
-        default:
-          assert(false && "Invalid value type!");
+  // Nothing to do if the first operand is already a load.
+  if (Op.getOperand(0).getOpcode() == PIC16ISD::PIC16Load)
+    return SDValue();
 
-        case MVT::i8:  
-          break;
+  // Put first operand on stack.
+  SDValue NewVal = ConvertToMemOperand (Op.getOperand(0), DAG);
 
-        case MVT::i16: 
-          NUM_STORES = 2;
-          break;
+  SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Flag);
+  return DAG.getNode(ISD::SUBE, Tys, NewVal, Op.getOperand(1),
+                     Op.getOperand(2));
+}
 
-        case MVT::i32: 
-          NUM_STORES = 4;
-          break;
+// LowerFORMAL_ARGUMENTS - In Lowering FORMAL ARGUMENTS - MERGE_VALUES nodes
+// is returned. MERGE_VALUES nodes number of operands and number of values are
+// equal. Therefore to construct MERGE_VALUE node, UNDEF nodes equal to the
+// number of arguments of function have been created.
 
-        case MVT::i64: 
-          NUM_STORES = 8; 
-          break;
-      }
+SDValue PIC16TargetLowering:: LowerFORMAL_ARGUMENTS(SDValue Op, 
+                                                    SelectionDAG &DAG) {
+  SmallVector<SDValue, 8> ArgValues;
+  unsigned NumArgs = Op.getNumOperands() - 3;
 
-      if (isa<GlobalAddressSDNode>(Dest) && isa<LoadSDNode>(Src) && 
-          (Src.getValueType() != MVT::i8)) {
-        //create direct addressing a = b
-        Chain = Src.getOperand(0);
-        for (i=0; i<NUM_STORES; i++) {
-          SDValue ADN = DAG.getNode(ISD::ADD, MVT::i16, Src.getOperand(1),
-                                      DAG.getConstant(DstOff, MVT::i16));
-          SDValue LDN = DAG.getLoad(MVT::i8, Chain, ADN, NULL, 0);
-          SDValue DSTADDR = DAG.getNode(ISD::ADD, MVT::i16, Dest,
-                                          DAG.getConstant(DstOff, MVT::i16));
-          Stores[i] = DAG.getStore(Chain, LDN, DSTADDR, NULL, 0);
-          Chain = Stores[i];
-          DstOff += 1;
-        } 
-        
-        Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, &Stores[0], i);
-        return Chain;
-      }
-      else if (isa<GlobalAddressSDNode>(Dest) && isa<ConstantSDNode>(Src) 
-               && (Src.getValueType() != MVT::i8)) {
-        //create direct addressing a = CONST
-        CST = dyn_cast<ConstantSDNode>(Src);
-        for (i = 0; i < NUM_STORES; i++) {
-          SDValue CNST = DAG.getConstant(CST->getZExtValue() >> i*8, MVT::i8);
-          SDValue ADN = DAG.getNode(ISD::ADD, MVT::i16, Dest,
-                                      DAG.getConstant(DstOff, MVT::i16));
-          Stores[i] = DAG.getStore(Chain, CNST, ADN, NULL, 0);
-          Chain = Stores[i];
-          DstOff += 1;
-        } 
-          
-        Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, &Stores[0], i);
-        return Chain;
-      }
-      else if (isa<LoadSDNode>(Dest) && isa<ConstantSDNode>(Src) 
-              && (Src.getValueType() != MVT::i8)) {
-        // Create indirect addressing.
-        CST = dyn_cast<ConstantSDNode>(Src);
-        Chain = Dest.getOperand(0);  
-        SDValue Load;
-        Load = DAG.getLoad(MVT::i16, Chain,Dest.getOperand(1), NULL, 0);
-        Chain = Load.getValue(1);
-        for (i=0; i<NUM_STORES; i++) {
-          SDValue CNST = DAG.getConstant(CST->getZExtValue() >> i*8, MVT::i8);
-          Stores[i] = DAG.getStore(Chain, CNST, Load, NULL, 0);
-          Chain = Stores[i];
-          DstOff += 1;
-        } 
-          
-        Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, &Stores[0], i);
-        return Chain;
-      }
-      else if (isa<LoadSDNode>(Dest) && isa<GlobalAddressSDNode>(Src)) {
-        // GlobalAddressSDNode *GAD = dyn_cast<GlobalAddressSDNode>(Src);
-        return SDValue();
-      }
-      else if (Src.getOpcode() == PIC16ISD::Package) {
-        StoreSDNode *st = dyn_cast<StoreSDNode>(N);
-        SDValue toWorkList, retVal;
-        Chain = N->getOperand(0);
-
-        if (st->isTruncatingStore()) {
-          retVal = DAG.getStore(Chain, Src.getOperand(0), Dest, NULL, 0);
-        }
-        else {
-          toWorkList = DAG.getNode(ISD::ADD, MVT::i16, Dest,
-                                   DAG.getConstant(1, MVT::i16));
-          Stores[1] = DAG.getStore(Chain, Src.getOperand(0), Dest, NULL, 0);
-          Stores[0] = DAG.getStore(Chain, Src.getOperand(1), toWorkList, NULL, 
-                                   0);
-
-          // We want to merge sequence of add with constant to one add and a 
-          // constant, so add the ADD node to worklist to have llvm do that 
-          // automatically.
-          DCI.AddToWorklist(toWorkList.getNode()); 
-
-          // We don't need the Package so add to worklist so llvm deletes it
-          DCI.AddToWorklist(Src.getNode());
-          retVal = DAG.getNode(ISD::TokenFactor, MVT::Other, &Stores[0], 2);
-        }
-
-        return retVal;
-      }
-      else if (Src.getOpcode() == ISD::TRUNCATE) {
-      }
-      else {
-      }
-    } // end ISD::STORE.
-    break;
-
-    case ISD::LOAD :
-    {
-      SDValue Ptr = N->getOperand(1);
-      if (Ptr.getOpcode() == PIC16ISD::Package) {
-        assert (0 && "not implemented yet");
-       }
-    }
-    break;
-  } // end switch.
+  // Creating UNDEF nodes to meet the requirement of MERGE_VALUES node.
+  for(unsigned i = 0 ; i<NumArgs ; i++) {
+    SDValue TempNode = DAG.getNode(ISD::UNDEF, Op.getNode()->getValueType(i));
+    ArgValues.push_back(TempNode);
+  }
 
-  return SDValue();
+  ArgValues.push_back(Op.getOperand(0));
+  return DAG.getNode(ISD::MERGE_VALUES, Op.getNode()->getVTList(), 
+                     &ArgValues[0],
+                     ArgValues.size()).getValue(Op.getResNo());
 }
 
-//===----------------------------------------------------------------------===//
-//               Utility functions
-//===----------------------------------------------------------------------===//
-const SDValue *PIC16TargetLowering::
-findLoadi8(const SDValue &Src, SelectionDAG &DAG) const
-{
-  unsigned int i;
-  if ((Src.getOpcode() == ISD::LOAD) && (Src.getValueType() == MVT::i8))
-    return &Src;
-  for (i=0; i<Src.getNumOperands(); i++) {
-    const SDValue *retVal = findLoadi8(Src.getOperand(i),DAG);
-    if (retVal) return retVal;
+// Perform DAGCombine of PIC16Load 
+SDValue PIC16TargetLowering::
+PerformPIC16LoadCombine(SDNode *N, DAGCombinerInfo &DCI) const {
+  SelectionDAG &DAG = DCI.DAG;
+  SDValue Chain = N->getOperand(0); 
+  if (N->hasNUsesOfValue(0, 0)) {
+    DAG.ReplaceAllUsesOfValueWith(SDValue(N,1), Chain);
   }
+  return SDValue();
+}
 
-  return NULL;
+
+SDValue PIC16TargetLowering::PerformDAGCombine(SDNode *N, 
+                                               DAGCombinerInfo &DCI) const {
+  switch (N->getOpcode()) {
+  case PIC16ISD::PIC16Load:
+    return PerformPIC16LoadCombine(N, DCI);
+  }
+  return SDValue();
 }