From 7836fc129ab5f212ee2cd5b3c232d93751f3e853 Mon Sep 17 00:00:00 2001 From: Sanjiv Gupta Date: Wed, 8 Apr 2009 05:38:48 +0000 Subject: [PATCH] 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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@68597 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/PIC16/PIC16AsmPrinter.cpp | 6 +- lib/Target/PIC16/PIC16ISelLowering.cpp | 330 +++++++++++++++++++------ lib/Target/PIC16/PIC16ISelLowering.h | 42 +++- lib/Target/PIC16/PIC16InstrInfo.td | 46 +++- lib/Target/PIC16/PIC16RegisterInfo.td | 11 +- 5 files changed, 346 insertions(+), 89 deletions(-) diff --git a/lib/Target/PIC16/PIC16AsmPrinter.cpp b/lib/Target/PIC16/PIC16AsmPrinter.cpp index c0b1f6e8607..109504ec68a 100644 --- a/lib/Target/PIC16/PIC16AsmPrinter.cpp +++ b/lib/Target/PIC16/PIC16AsmPrinter.cpp @@ -113,6 +113,10 @@ bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF) { 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 @@ bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF) { printBasicBlockLabel(I, true); O << '\n'; } - else - O << CurrentFnName << ":\n"; CurBank = ""; for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); II != E; ++II) { diff --git a/lib/Target/PIC16/PIC16ISelLowering.cpp b/lib/Target/PIC16/PIC16ISelLowering.cpp index 473e9d745d4..1f7b0614589 100644 --- a/lib/Target/PIC16/PIC16ISelLowering.cpp +++ b/lib/Target/PIC16/PIC16ISelLowering.cpp @@ -255,6 +255,8 @@ const char *PIC16TargetLowering::getTargetNodeName(unsigned Opcode) const { 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 @@ const char *PIC16TargetLowering::getTargetNodeName(unsigned Opcode) const { 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 @@ SDValue PIC16TargetLowering::ConvertToMemOperand(SDValue Op, 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(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 Ops; + SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Flag); + SDValue Arg, StoreRet; + for (unsigned i=0; igetArg(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(Op); unsigned NumOps = TheCall->getNumArgs(); DebugLoc dl = TheCall->getDebugLoc(); @@ -887,6 +922,9 @@ PIC16TargetLowering::LowerCallArguments(SDValue Op, SDValue Chain, 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 @@ PIC16TargetLowering::LowerCallArguments(SDValue Op, SDValue Chain, 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(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 ResultVals; + SDValue LoadRet; + + SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Other, MVT::Flag); + for(unsigned i=0;i(Op); DebugLoc dl = TheCall->getDebugLoc(); // Currently handling primitive types only. They will come in @@ -1014,46 +1081,147 @@ SDValue PIC16TargetLowering::LowerRET(SDValue Op, SelectionDAG &DAG) { 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(Op); SDValue Chain = TheCall->getChain(); SDValue Callee = TheCall->getCallee(); DebugLoc dl = TheCall->getDebugLoc(); unsigned i =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 Ops; + Ops.push_back(Chain); + Ops.push_back(Callee); + + // Add the call arguments and their flags + unsigned NumArgs = TheCall->getNumArgs(); + for(i=0;igetArg(i)); + Ops.push_back(TheCall->getArgFlagsVal(i)); + } + std::vector NodeTys; + unsigned NumRets = TheCall->getNumRetVals(); + for(i=0;igetRetValType(i)); + + // 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); +} + + +SDValue PIC16TargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) { + CallSDNode *TheCall = dyn_cast(Op); + SDValue Chain = TheCall->getChain(); + SDValue Callee = TheCall->getCallee(); + DebugLoc dl = TheCall->getDebugLoc(); if (Callee.getValueType() == MVT::i16 && Callee.getOpcode() == ISD::BUILD_PAIR) { - // It has come from TypeLegalizer for lowering - - Callee = Callee.getOperand(0).getOperand(0); - - std::vector Ops; - Ops.push_back(Chain); - Ops.push_back(Callee); - - // Add the call arguments and their flags - unsigned NumArgs = TheCall->getNumArgs(); - for(i=0;igetArg(i)); - Ops.push_back(TheCall->getArgFlagsVal(i)); - } - - std::vector NodeTys; - unsigned NumRets = TheCall->getNumRetVals(); - for(i=0;igetRetValType(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 NewCall; + // 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 @@ SDValue PIC16TargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) { // 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 + SDValue ArgLabel, RetLabel; + if (IsDirectCall) { + // Considering the GlobalAddressNode case here. + if (GlobalAddressSDNode *G = dyn_cast(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(Callee); + Callee = DAG.getTargetExternalSymbol(ES->getSymbol(), MVT::i8); + Name = ES->getSymbol(); + } - // Considering the GlobalAddressNode case here. - if (GlobalAddressSDNode *G = dyn_cast(Callee)) { - GlobalValue *GV = G->getGlobal(); - Callee = DAG.getTargetGlobalAddress(GV, MVT::i8); - } + // 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); - // Considering the ExternalSymbol case here - if (ExternalSymbolSDNode *ES = dyn_cast(Callee)) { - Callee = DAG.getTargetExternalSymbol(ES->getSymbol(), 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); - SDValue OperFlag = getOutFlag(Chain); // To manage the data dependency + CodeAddr_Lo = DAG.getNode(ISD::ADD, dl, MVT::i8, CodeAddr_Lo, + DAG.getConstant(2, MVT::i8)); - std::string Name; - - // Considering GlobalAddress here - if (GlobalAddressSDNode *G = dyn_cast(Callee)) - Name = G->getGlobal()->getName(); - - // Considering ExternalSymbol here - if (ExternalSymbolSDNode *ES = dyn_cast(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); + // 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 @@ SDValue PIC16TargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) { 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) { diff --git a/lib/Target/PIC16/PIC16ISelLowering.h b/lib/Target/PIC16/PIC16ISelLowering.h index 498610a9753..74e4507741f 100644 --- a/lib/Target/PIC16/PIC16ISelLowering.h +++ b/lib/Target/PIC16/PIC16ISelLowering.h @@ -38,14 +38,17 @@ namespace llvm { 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 @@ namespace llvm { 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 @@ namespace llvm { 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); diff --git a/lib/Target/PIC16/PIC16InstrInfo.td b/lib/Target/PIC16/PIC16InstrInfo.td index 85dc828295d..69b0097d9cc 100644 --- a/lib/Target/PIC16/PIC16InstrInfo.td +++ b/lib/Target/PIC16/PIC16InstrInfo.td @@ -42,8 +42,12 @@ def SDT_PIC16Load : SDTypeProfile<1, 3, [SDTCisI8<0>, SDTCisI8<1>, 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 @@ def PIC16Hi : SDNode<"PIC16ISD::Hi", SDTI8UnaryOp>; // 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 PIC16Load : SDNode<"PIC16ISD::PIC16Load", SDT_PIC16Load, [SDNPHasChain]>; 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 @@ def set_fsrhi: "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 @@ def sublw_cc : SUBLW<0, PIC16Subcc>; // 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 @@ def banksel : // Return insn. def Return : ControlFormat<0, (outs), (ins), "return", [(ret)]>; - + //===----------------------------------------------------------------------===// // PIC16 Replacment Patterns. //===----------------------------------------------------------------------===// @@ -441,9 +468,20 @@ def : Pat<(PIC16Store GPR:$val, (MTLO GPR:$loaddr), (MTHI GPR:$hiaddr), (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)>; + diff --git a/lib/Target/PIC16/PIC16RegisterInfo.td b/lib/Target/PIC16/PIC16RegisterInfo.td index 938974f4d48..2959d912ec3 100644 --- a/lib/Target/PIC16/PIC16RegisterInfo.td +++ b/lib/Target/PIC16/PIC16RegisterInfo.td @@ -20,13 +20,14 @@ def W : PIC16Reg<"W">; 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]>;