[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