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

Sanjiv Gupta sanjiv.gupta at microchip.com
Tue Apr 7 22:38:48 PDT 2009


Author: sgupta
Date: Wed Apr  8 00:38:48 2009
New Revision: 68597

URL: http://llvm.org/viewvc/llvm-project?rev=68597&view=rev
Log:
Handle indirect function calls.
Every function has the address of its frame in the beginning of code section.
The frame address is retrieved and used to pass arguments.


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

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

==============================================================================
--- llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.cpp (original)
+++ llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.cpp Wed Apr  8 00:38:48 2009
@@ -113,6 +113,10 @@
                                                SectionFlags::Code);
   O <<  "\n";
   SwitchToSection (fCodeSection);
+  O << CurrentFnName << ":\n";
+  O << "    retlw  low(" << CurrentFnName << ".frame)\n";
+  O << "    retlw  high(" << CurrentFnName << ".frame)\n"; 
+
 
   // Print out code for the function.
   for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
@@ -122,8 +126,6 @@
       printBasicBlockLabel(I, true);
       O << '\n';
     }
-    else
-      O << CurrentFnName << ":\n";
     CurBank = "";
     for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
          II != E; ++II) {

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

==============================================================================
--- llvm/trunk/lib/Target/PIC16/PIC16ISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/PIC16/PIC16ISelLowering.cpp Wed Apr  8 00:38:48 2009
@@ -255,6 +255,8 @@
   case PIC16ISD::Hi:               return "PIC16ISD::Hi";
   case PIC16ISD::MTLO:             return "PIC16ISD::MTLO";
   case PIC16ISD::MTHI:             return "PIC16ISD::MTHI";
+  case PIC16ISD::MTPCLATH:         return "PIC16ISD::MTPCLATH";
+  case PIC16ISD::PIC16Connect:     return "PIC16ISD::PIC16Connect";
   case PIC16ISD::Banksel:          return "PIC16ISD::Banksel";
   case PIC16ISD::PIC16Load:        return "PIC16ISD::PIC16Load";
   case PIC16ISD::PIC16LdArg:       return "PIC16ISD::PIC16LdArg";
@@ -267,6 +269,7 @@
   case PIC16ISD::RLF:              return "PIC16ISD::RLF";
   case PIC16ISD::RRF:              return "PIC16ISD::RRF";
   case PIC16ISD::CALL:             return "PIC16ISD::CALL";
+  case PIC16ISD::CALLW:            return "PIC16ISD::CALLW";
   case PIC16ISD::SUBCC:            return "PIC16ISD::SUBCC";
   case PIC16ISD::SELECT_ICC:       return "PIC16ISD::SELECT_ICC";
   case PIC16ISD::BRCOND:           return "PIC16ISD::BRCOND";
@@ -872,12 +875,44 @@
     
   return Load.getValue(0);
 }
+
+SDValue PIC16TargetLowering::
+LowerIndirectCallArguments(SDValue Op, SDValue Chain, SDValue InFlag,
+                           SDValue DataAddr_Lo, SDValue DataAddr_Hi,
+                           SelectionDAG &DAG) {
+  CallSDNode *TheCall = dyn_cast<CallSDNode>(Op);
+  unsigned NumOps = TheCall->getNumArgs();
+  DebugLoc dl = TheCall->getDebugLoc();
+
+  // If call has no arguments then do nothing and return.
+  if (NumOps == 0)
+    return Chain;
+
+  std::vector<SDValue> Ops;
+  SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Flag);
+  SDValue Arg, StoreRet;
+  for (unsigned i=0; i<NumOps; i++) {
+    // Get the arguments
+    Arg = TheCall->getArg(i);
+    Ops.clear();
+    Ops.push_back(Chain);
+    Ops.push_back(Arg);
+    Ops.push_back(DataAddr_Lo);
+    Ops.push_back(DataAddr_Hi);
+    Ops.push_back(DAG.getConstant(i, MVT::i8));
+    Ops.push_back(InFlag);
+
+    StoreRet = DAG.getNode (PIC16ISD::PIC16StWF, dl, Tys, &Ops[0], Ops.size());
+
+    Chain = getChain(StoreRet);
+    InFlag = getOutFlag(StoreRet);
+  }
+  return Chain;
+}
           
-SDValue
-PIC16TargetLowering::LowerCallArguments(SDValue Op, SDValue Chain,
-                                        SDValue FrameAddress, 
-                                        SDValue InFlag,
-                                        SelectionDAG &DAG) {
+SDValue PIC16TargetLowering::
+LowerDirectCallArguments(SDValue Op, SDValue Chain, SDValue FrameAddress, 
+                         SDValue InFlag, SelectionDAG &DAG) {
   CallSDNode *TheCall = dyn_cast<CallSDNode>(Op);
   unsigned NumOps = TheCall->getNumArgs();
   DebugLoc dl = TheCall->getDebugLoc();
@@ -887,6 +922,9 @@
   unsigned Size=0;
   unsigned ArgCount=0;
 
+  // If call has no arguments then do nothing and return.
+  if (NumOps == 0)
+    return Chain; 
 
   // FIXME: This portion of code currently assumes only
   // primitive types being passed as arguments.
@@ -930,11 +968,40 @@
   return Chain;
 }
 
-SDValue
-PIC16TargetLowering::LowerCallReturn(SDValue Op, SDValue Chain,
-                                     SDValue FrameAddress,
-                                     SDValue InFlag,
-                                     SelectionDAG &DAG) {
+SDValue PIC16TargetLowering::
+LowerIndirectCallReturn (SDValue Op, SDValue Chain, SDValue InFlag,
+                         SDValue DataAddr_Lo, SDValue DataAddr_Hi,
+                         SelectionDAG &DAG) {
+  CallSDNode *TheCall = dyn_cast<CallSDNode>(Op);
+  DebugLoc dl = TheCall->getDebugLoc();
+  unsigned RetVals = TheCall->getNumRetVals();
+
+  // If call does not have anything to return
+  // then do nothing and go back.
+  if (RetVals == 0)
+    return Chain;
+
+  // Call has something to return
+  std::vector<SDValue> ResultVals;
+  SDValue LoadRet;
+
+  SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Other, MVT::Flag);
+  for(unsigned i=0;i<RetVals;i++) {
+    LoadRet = DAG.getNode(PIC16ISD::PIC16LdWF, dl, Tys, Chain, DataAddr_Lo,
+                          DataAddr_Hi, DAG.getConstant(i, MVT::i8),
+                          InFlag);
+    InFlag = getOutFlag(LoadRet);
+    Chain = getChain(LoadRet);
+    ResultVals.push_back(LoadRet);
+  }
+  ResultVals.push_back(Chain);
+  SDValue Res = DAG.getMergeValues(&ResultVals[0], ResultVals.size(), dl);
+  return Res;
+}
+
+SDValue PIC16TargetLowering::
+LowerDirectCallReturn(SDValue Op, SDValue Chain, SDValue FrameAddress,
+                      SDValue InFlag, SelectionDAG &DAG) {
   CallSDNode *TheCall = dyn_cast<CallSDNode>(Op);
   DebugLoc dl = TheCall->getDebugLoc();
   // Currently handling primitive types only. They will come in
@@ -1014,46 +1081,147 @@
   return DAG.getNode(ISD::RET, dl, MVT::Other, Chain);
 }
 
-SDValue PIC16TargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) {
+// CALL node may have some operands non-legal to PIC16. Generate new CALL
+// node with all the operands legal.
+// Currently only Callee operand of the CALL node is non-legal. This function
+// legalizes the Callee operand and uses all other operands as are to generate
+// new CALL node.
+
+SDValue PIC16TargetLowering::LegalizeCALL(SDValue Op, SelectionDAG &DAG) {
     CallSDNode *TheCall = dyn_cast<CallSDNode>(Op);
     SDValue Chain = TheCall->getChain();
     SDValue Callee = TheCall->getCallee();
     DebugLoc dl = TheCall->getDebugLoc();
     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);
+    assert(Callee.getValueType() == MVT::i16 &&
+           "Don't know how to legalize this call node!!!");
+    assert(Callee.getOpcode() == ISD::BUILD_PAIR &&
+           "Don't know how to legalize this call node!!!");
+
+    if (isDirectAddress(Callee)) {
+       // Come here for direct calls
+       Callee = Callee.getOperand(0).getOperand(0);
+    } else {
+      // Come here for indirect calls
+      SDValue Lo, Hi;
+      // Indirect addresses. Get the hi and lo parts of ptr.
+      GetExpandedParts(Callee, DAG, Lo, Hi);
+      // Connect Lo and Hi parts of the callee with the PIC16Connect
+      Callee = DAG.getNode(PIC16ISD::PIC16Connect, dl, MVT::i8, Lo, Hi);
+    }
+    std::vector<SDValue> Ops;
+    Ops.push_back(Chain);
+    Ops.push_back(Callee);
 
-      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));
-      }
+    // Add the call arguments and their flags
+    unsigned NumArgs = TheCall->getNumArgs();
+    for(i=0;i<NumArgs;i++) {
+       Ops.push_back(TheCall->getArg(i));
+       Ops.push_back(TheCall->getArgFlagsVal(i));
+    }
+    std::vector<MVT> NodeTys;
+    unsigned NumRets = TheCall->getNumRetVals();
+    for(i=0;i<NumRets;i++)
+       NodeTys.push_back(TheCall->getRetValType(i));
 
-      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(), dl,
-                          TheCall->isVarArg(), TheCall->isTailCall(), 
-                          TheCall->isInreg(), VTs, &Ops[0], Ops.size());
+   // Return a Chain as well
+   NodeTys.push_back(MVT::Other);
+   
+   SDVTList VTs = DAG.getVTList(&NodeTys[0], NodeTys.size());
+   // Generate new call with all the operands legal
+   return DAG.getCall(TheCall->getCallingConv(), dl,
+                      TheCall->isVarArg(), TheCall->isTailCall(),
+                      TheCall->isInreg(), VTs, &Ops[0], Ops.size());
+}
+
+void PIC16TargetLowering::
+GetDataAddress(DebugLoc dl, SDValue Callee, SDValue &Chain, 
+               SDValue &DataAddr_Lo, SDValue &DataAddr_Hi,
+               SelectionDAG &DAG) {
+   assert (Callee.getOpcode() == PIC16ISD::PIC16Connect
+           && "Don't know what to do of such callee!!");
+   SDValue ZeroOperand = DAG.getConstant(0, MVT::i8);
+   SDValue SeqStart  = DAG.getCALLSEQ_START(Chain, ZeroOperand);
+   Chain = getChain(SeqStart);
+   SDValue OperFlag = getOutFlag(SeqStart); // To manage the data dependency
+
+   // Get the Lo and Hi part of code address
+   SDValue Lo = Callee.getOperand(0);
+   SDValue Hi = Callee.getOperand(1);
+
+   SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Other, MVT::Flag);
+   Hi = DAG.getNode(PIC16ISD::MTPCLATH, dl, MVT::i8, Hi);
+   // Use the Lo part as is and make CALLW
+   Callee = DAG.getNode(PIC16ISD::PIC16Connect, dl, MVT::i8, Lo, Hi);
+   SDValue Call = DAG.getNode(PIC16ISD::CALLW, dl, Tys, Chain, Callee,
+                              OperFlag);
+   Chain = getChain(Call);
+   OperFlag = getOutFlag(Call);
+   SDValue SeqEnd = DAG.getCALLSEQ_END(Chain, ZeroOperand, ZeroOperand,
+                                       OperFlag);
+   Chain = getChain(SeqEnd);
+   OperFlag = getOutFlag(SeqEnd);
+
+   // Low part of Data Address 
+   DataAddr_Lo = DAG.getNode(PIC16ISD::MTLO, dl, MVT::i8, Call, OperFlag);
+
+   // Make the second call.
+   SeqStart  = DAG.getCALLSEQ_START(Chain, ZeroOperand);
+   Chain = getChain(SeqStart);
+   OperFlag = getOutFlag(SeqStart); // To manage the data dependency
+
+   // Add 1 to Lo part for the second code word.
+   Lo = DAG.getNode(ISD::ADD, dl, MVT::i8, Lo, DAG.getConstant(1, MVT::i8));
+   // Use new Lo to make another CALLW
+   Callee = DAG.getNode(PIC16ISD::PIC16Connect, dl, MVT::i8, Lo, Hi);
+   Call = DAG.getNode(PIC16ISD::CALLW, dl, Tys, Chain, Callee, OperFlag);
+   Chain = getChain(Call);
+   OperFlag = getOutFlag(Call);
+   SeqEnd = DAG.getCALLSEQ_END(Chain, ZeroOperand, ZeroOperand,
+                                        OperFlag);
+   Chain = getChain(SeqEnd);
+   OperFlag = getOutFlag(SeqEnd);
+   // Hi part of Data Address
+   DataAddr_Hi = DAG.getNode(PIC16ISD::MTHI, dl, MVT::i8, Call, OperFlag);
+}
 
-      return NewCall;
+
+SDValue PIC16TargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) {
+    CallSDNode *TheCall = dyn_cast<CallSDNode>(Op);
+    SDValue Chain = TheCall->getChain();
+    SDValue Callee = TheCall->getCallee();
+    DebugLoc dl = TheCall->getDebugLoc();
+    if (Callee.getValueType() == MVT::i16 &&
+      Callee.getOpcode() == ISD::BUILD_PAIR) {
+          // Control should come here only from TypeLegalizer for lowering
+          
+          // Legalize the non-legal arguments of call and return the
+          // new call with legal arguments.
+          return LegalizeCALL(Op, DAG);
     }
+    // Control should come here from Legalize DAG.
+    // Here all the operands of CALL node should be legal.
     
+    // If this is an indirect call then to pass the arguments
+    // and read the return value back, we need the data address
+    // of the function being called. 
+    // To get the data address two more calls need to be made.
+
+    // The flag to track if this is a direct or indirect call.
+    bool IsDirectCall = true;    
+    unsigned RetVals = TheCall->getNumRetVals();
+    unsigned NumArgs = TheCall->getNumArgs();
+
+    SDValue DataAddr_Lo, DataAddr_Hi; 
+    if (Callee.getOpcode() == PIC16ISD::PIC16Connect) { 
+       IsDirectCall = false;    // This is indirect call
+       // Read DataAddress only if we have to pass arguments or 
+       // read return value. 
+       if ((RetVals > 0) || (NumArgs > 0)) 
+         GetDataAddress(dl, Callee, Chain, DataAddr_Lo, DataAddr_Hi, DAG);
+    }
+
     SDValue ZeroOperand = DAG.getConstant(0, MVT::i8);
 
     // Start the call sequence.
@@ -1061,45 +1229,59 @@
     // because there is nothing else to carry.
     SDValue SeqStart  = DAG.getCALLSEQ_START(Chain, ZeroOperand);
     Chain = getChain(SeqStart);
+    SDValue OperFlag = getOutFlag(SeqStart); // To manage the data dependency
+    std::string Name;
 
     // 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);
+    SDValue ArgLabel, RetLabel;
+    if (IsDirectCall) { 
+       // Considering the GlobalAddressNode case here.
+       if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
+          GlobalValue *GV = G->getGlobal();
+          Callee = DAG.getTargetGlobalAddress(GV, MVT::i8);
+          Name = G->getGlobal()->getName();
+       } else {// Considering the ExternalSymbol case here
+          ExternalSymbolSDNode *ES = dyn_cast<ExternalSymbolSDNode>(Callee);
+          Callee = DAG.getTargetExternalSymbol(ES->getSymbol(), MVT::i8); 
+          Name = ES->getSymbol();
+       }
+
+       // Label for argument passing
+       char *argFrame = new char [strlen(Name.c_str()) +  8];
+       sprintf(argFrame, "%s.args", Name.c_str());
+       ArgLabel = DAG.getTargetExternalSymbol(argFrame, MVT::i8);
+
+       // Label for reading return value
+       char *retName = new char [strlen(Name.c_str()) +  8];
+       sprintf(retName, "%s.retval", Name.c_str());
+       RetLabel = DAG.getTargetExternalSymbol(retName, MVT::i8);
+    } else {
+       // if indirect call
+       SDValue CodeAddr_Lo = Callee.getOperand(0);
+       SDValue CodeAddr_Hi = Callee.getOperand(1);
+
+       CodeAddr_Lo = DAG.getNode(ISD::ADD, dl, MVT::i8, CodeAddr_Lo,
+                                 DAG.getConstant(2, MVT::i8));
+
+       // move Hi part in PCLATH
+       CodeAddr_Hi = DAG.getNode(PIC16ISD::MTPCLATH, dl, MVT::i8, CodeAddr_Hi);
+       Callee = DAG.getNode(PIC16ISD::PIC16Connect, dl, MVT::i8, CodeAddr_Lo,
+                            CodeAddr_Hi);
+    } 
 
     // Pass the argument to function before making the call.
-    SDValue CallArgs = LowerCallArguments(Op, Chain, ArgLabel, OperFlag, DAG);
-    Chain = getChain(CallArgs);
-    OperFlag = getOutFlag(CallArgs);
+    SDValue CallArgs;
+    if (IsDirectCall) {
+      CallArgs = LowerDirectCallArguments(Op, Chain, ArgLabel, OperFlag, DAG);
+      Chain = getChain(CallArgs);
+      OperFlag = getOutFlag(CallArgs);
+    } else {
+      CallArgs = LowerIndirectCallArguments(Op, Chain, OperFlag, DataAddr_Lo, 
+                                            DataAddr_Hi, DAG);
+      Chain = getChain(CallArgs);
+      OperFlag = getOutFlag(CallArgs);
+    }
 
     SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Flag);
     SDValue PICCall = DAG.getNode(PIC16ISD::CALL, dl, Tys, Chain, Callee,
@@ -1116,7 +1298,11 @@
     OperFlag = getOutFlag(SeqEnd);
 
     // Lower the return value reading after the call.
-    return LowerCallReturn(Op, Chain, RetLabel, OperFlag, DAG);
+    if (IsDirectCall)
+      return LowerDirectCallReturn(Op, Chain, RetLabel, OperFlag, DAG);
+    else
+      return LowerIndirectCallReturn(Op, Chain, OperFlag, DataAddr_Lo,
+                                     DataAddr_Hi, DAG);
 }
 
 bool PIC16TargetLowering::isDirectLoad(const SDValue Op) {

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

==============================================================================
--- llvm/trunk/lib/Target/PIC16/PIC16ISelLowering.h (original)
+++ llvm/trunk/lib/Target/PIC16/PIC16ISelLowering.h Wed Apr  8 00:38:48 2009
@@ -38,14 +38,17 @@
       PIC16Store,
       PIC16StWF,
       Banksel,
-      MTLO,
-      MTHI,
+      MTLO,          // Move to low part of FSR
+      MTHI,          // Move to high part of FSR
+      MTPCLATH,      // Move to PCLATCH
+      PIC16Connect,  // General connector for PIC16 nodes
       BCF,
       LSLF,          // PIC16 Logical shift left
       LRLF,          // PIC16 Logical shift right
       RLF,           // Rotate left through carry
       RRF,           // Rotate right through carry
       CALL,          // PIC16 Call instruction 
+      CALLW,         // PIC16 CALLW instruction 
       SUBCC,	     // Compare for equality or inequality.
       SELECT_ICC,    // Psuedo to be caught in schedular and expanded to brcond.
       BRCOND,        // Conditional branch.
@@ -87,10 +90,25 @@
     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);
+    // Call returns
+    SDValue 
+    LowerDirectCallReturn(SDValue Op, SDValue Chain, SDValue FrameAddress, 
+                          SDValue InFlag, SelectionDAG &DAG);
+    SDValue 
+    LowerIndirectCallReturn(SDValue Op, SDValue Chain, SDValue InFlag,
+                            SDValue DataAddr_Lo, SDValue DataAddr_Hi,
+                            SelectionDAG &DAG);
+
+    // Call arguments
+    SDValue 
+    LowerDirectCallArguments(SDValue Op, SDValue Chain, SDValue FrameAddress, 
+                             SDValue InFlag, SelectionDAG &DAG);
+
+    SDValue 
+    LowerIndirectCallArguments(SDValue Op, SDValue Chain, SDValue InFlag, 
+                               SDValue DataAddr_Lo, SDValue DataAddr_Hi, 
+                               SelectionDAG &DAG);
+
     SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG);
     SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG);
     SDValue LowerStopPoint(SDValue Op, SelectionDAG &DAG);
@@ -152,6 +170,18 @@
     void LegalizeFrameIndex(SDValue Op, SelectionDAG &DAG, SDValue &ES, 
                             int &Offset);
 
+    // CALL node should have all legal operands only. Legalize all non-legal
+    // operands of CALL node and then return the new call will all operands
+    // legal.
+    SDValue LegalizeCALL(SDValue Op, SelectionDAG &DAG);
+
+    // For indirect calls data address of the callee frame need to be
+    // extracted. This function fills the arguments DataAddr_Lo and 
+    // DataAddr_Hi with the address of the callee frame.
+    void GetDataAddress(DebugLoc dl, SDValue Callee, SDValue &Chain,
+                        SDValue &DataAddr_Lo, SDValue &DataAddr_Hi,
+                        SelectionDAG &DAG); 
+
     // 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, DebugLoc dl); 

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

==============================================================================
--- llvm/trunk/lib/Target/PIC16/PIC16InstrInfo.td (original)
+++ llvm/trunk/lib/Target/PIC16/PIC16InstrInfo.td Wed Apr  8 00:38:48 2009
@@ -42,8 +42,12 @@
 def SDT_PIC16Store : SDTypeProfile<0, 4, [SDTCisI8<0>, SDTCisI8<1>, 
                                           SDTCisI8<2>, SDTCisI8<3>]>;
 
+def SDT_PIC16Connect : SDTypeProfile<1, 2, [SDTCisI8<0>, SDTCisI8<1>,
+                                            SDTCisI8<2>]>;
+
 // PIC16ISD::CALL type prorile
 def SDT_PIC16call : SDTypeProfile<0, -1, [SDTCisInt<0>]>;
+def SDT_PIC16callw : SDTypeProfile<1, -1, [SDTCisInt<0>]>;
 
 // PIC16ISD::BRCOND
 def SDT_PIC16Brcond: SDTypeProfile<0, 2, 
@@ -79,8 +83,9 @@
 // The MTHI and MTLO nodes are used only to match them in the incoming 
 // DAG for replacement by corresponding set_fsrhi, set_fsrlo insntructions.
 // These nodes are not used for defining any instructions.
-def MTLO : SDNode<"PIC16ISD::MTLO", SDTI8UnaryOp>;
-def MTHI : SDNode<"PIC16ISD::MTHI", SDTI8UnaryOp>;
+def MTLO     : SDNode<"PIC16ISD::MTLO", SDTI8UnaryOp>;
+def MTHI     : SDNode<"PIC16ISD::MTHI", SDTI8UnaryOp>;
+def MTPCLATH : SDNode<"PIC16ISD::MTPCLATH", SDTI8UnaryOp>;
 
 // Node to generate Bank Select for a GlobalAddress.
 def Banksel : SDNode<"PIC16ISD::Banksel", SDTI8UnaryOp>;
@@ -95,10 +100,13 @@
 def PIC16LdArg  : SDNode<"PIC16ISD::PIC16LdArg", SDT_PIC16Load, [SDNPHasChain]>;
 def PIC16LdWF  : SDNode<"PIC16ISD::PIC16LdWF", SDT_PIC16Load, 
                        [SDNPHasChain, SDNPInFlag, SDNPOutFlag]>;
+def PIC16Connect: SDNode<"PIC16ISD::PIC16Connect", SDT_PIC16Connect, []>;
 
 // Node to match PIC16 call
 def PIC16call : SDNode<"PIC16ISD::CALL", SDT_PIC16call,
                               [SDNPHasChain , SDNPOptInFlag, SDNPOutFlag]>;
+def PIC16callw : SDNode<"PIC16ISD::CALLW", SDT_PIC16callw,
+                              [SDNPHasChain , SDNPOptInFlag, SDNPOutFlag]>;
 
 // Node to match a comparison instruction.
 def PIC16Subcc : SDNode<"PIC16ISD::SUBCC", SDTI8BinOp, [SDNPOutFlag]>;
@@ -213,6 +221,12 @@
              "movwf ${dst}H",
              []>;
 
+def set_pclath:
+  ByteFormat<0, (outs PCLATHR:$dst), 
+             (ins GPR:$val),
+             "movwf ${dst}",
+             [(set PCLATHR:$dst , (MTPCLATH GPR:$val))]>;
+
 //----------------------------
 // copyRegToReg 
 // copyRegToReg insns. These are dummy. They should always be deleted
@@ -392,10 +406,23 @@
 // Call instruction.
 let isCall = 1 in {
     def CALL: LiteralFormat<0x1, (outs), (ins i8imm:$func),
-            "call ${func}",
+            "call ${func} + 2",
             [(PIC16call diraddr:$func)]>;
 }
 
+let isCall = 1 in {
+    def CALL_1: LiteralFormat<0x1, (outs), (ins GPR:$func, PCLATHR:$pc),
+            "callw",
+            [(PIC16call (PIC16Connect GPR:$func, PCLATHR:$pc))]>;
+}
+
+let isCall = 1  in {
+    def CALLW: LiteralFormat<0x1, (outs GPR:$dest), 
+                                  (ins GPR:$func, PCLATHR:$pc),
+            "callw",
+            [(set GPR:$dest, (PIC16callw (PIC16Connect GPR:$func, PCLATHR:$pc)))]>;
+}
+
 let Uses = [STATUS] in
 def pic16brcond: ControlFormat<0x0, (outs), (ins brtarget:$dst, CCOp:$cc),
                           "b$cc $dst",
@@ -429,7 +456,7 @@
 // Return insn.
 def Return : 
   ControlFormat<0, (outs), (ins), "return", [(ret)]>;
-                      
+
 //===----------------------------------------------------------------------===//
 // PIC16 Replacment Patterns.
 //===----------------------------------------------------------------------===//
@@ -441,9 +468,20 @@
            (set_fsrhi (set_fsrlo GPR:$loaddr), GPR:$hiaddr),
            imm:$offset)>;
 
+def : Pat<(PIC16StWF GPR:$val, (MTLO GPR:$loaddr), (MTHI GPR:$hiaddr), 
+           imm:$offset),
+          (store_indirect GPR:$val, 
+           (set_fsrhi (set_fsrlo GPR:$loaddr), GPR:$hiaddr),
+           imm:$offset)>;
+
 // Identify an indirect load and select insns for it.
 def : Pat<(PIC16Load (MTLO GPR:$loaddr), (MTHI GPR:$hiaddr), 
            imm:$offset),
           (load_indirect  (set_fsrhi (set_fsrlo GPR:$loaddr), GPR:$hiaddr),
            imm:$offset)>;
 
+def : Pat<(PIC16LdWF (MTLO GPR:$loaddr), (MTHI GPR:$hiaddr), 
+           imm:$offset),
+          (load_indirect  (set_fsrhi (set_fsrlo GPR:$loaddr), GPR:$hiaddr),
+           imm:$offset)>;
+

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

==============================================================================
--- llvm/trunk/lib/Target/PIC16/PIC16RegisterInfo.td (original)
+++ llvm/trunk/lib/Target/PIC16/PIC16RegisterInfo.td Wed Apr  8 00:38:48 2009
@@ -20,13 +20,14 @@
 def FSR0   : PIC16Reg<"FSR0">;
 def FSR1   : PIC16Reg<"FSR1">;
 def BS     : PIC16Reg<"BS">;
+def PCLATH : PIC16Reg<"PCLATH">;
 
 def STATUS : PIC16Reg<"STATUS">;
 
 // PIC16 Register classes.
-def GPR    : RegisterClass<"PIC16", [i8], 8, [W]>;
-def FSR16  : RegisterClass<"PIC16", [i16], 8, [FSR0, FSR1]>;
-def BSR  : RegisterClass<"PIC16", [i8], 8, [BS]>;
-
-def STATUSR: RegisterClass<"PIC16", [i8], 8, [STATUS]>;
+def GPR     : RegisterClass<"PIC16", [i8],  8, [W]>;
+def FSR16   : RegisterClass<"PIC16", [i16], 8, [FSR0, FSR1]>;
+def BSR     : RegisterClass<"PIC16", [i8],  8, [BS]>;
+def PCLATHR : RegisterClass<"PIC16", [i8],  8, [PCLATH]>;
+def STATUSR : RegisterClass<"PIC16", [i8],  8, [STATUS]>;
 





More information about the llvm-commits mailing list