diff --git a/lib/Target/MSP430/MSP430ISelLowering.cpp b/lib/Target/MSP430/MSP430ISelLowering.cpp index 99996bbb848..625df96d198 100644 --- a/lib/Target/MSP430/MSP430ISelLowering.cpp +++ b/lib/Target/MSP430/MSP430ISelLowering.cpp @@ -43,12 +43,15 @@ MSP430TargetLowering::MSP430TargetLowering(MSP430TargetMachine &tm) : // Compute derived properties from the register classes computeRegisterProperties(); + + setOperationAction(ISD::RET, MVT::Other, Custom); } SDValue MSP430TargetLowering:: LowerOperation(SDValue Op, SelectionDAG &DAG) { switch (Op.getOpcode()) { case ISD::FORMAL_ARGUMENTS: return LowerFORMAL_ARGUMENTS(Op, DAG); + case ISD::RET: return LowerRET(Op, DAG); default: assert(0 && "unimplemented operand"); return SDValue(); @@ -154,3 +157,58 @@ SDValue MSP430TargetLowering:: LowerCCCArguments(SDValue Op, return DAG.getNode(ISD::MERGE_VALUES, dl, Op.getNode()->getVTList(), &ArgValues[0], ArgValues.size()).getValue(Op.getResNo()); } + +SDValue MSP430TargetLowering::LowerRET(SDValue Op, SelectionDAG &DAG) { + // CCValAssign - represent the assignment of the return value to a location + SmallVector RVLocs; + unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv(); + bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg(); + DebugLoc dl = Op.getDebugLoc(); + + // CCState - Info about the registers and stack slot. + CCState CCInfo(CC, isVarArg, getTargetMachine(), RVLocs); + + // Analize return values of ISD::RET + CCInfo.AnalyzeReturn(Op.getNode(), RetCC_MSP430); + + // If this is the first return lowered for this function, add the regs to the + // liveout set for the function. + if (DAG.getMachineFunction().getRegInfo().liveout_empty()) { + for (unsigned i = 0; i != RVLocs.size(); ++i) + if (RVLocs[i].isRegLoc()) + DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg()); + } + + // The chain is always operand #0 + SDValue Chain = Op.getOperand(0); + SDValue Flag; + + // Copy the result values into the output registers. + for (unsigned i = 0; i != RVLocs.size(); ++i) { + CCValAssign &VA = RVLocs[i]; + assert(VA.isRegLoc() && "Can only return in registers!"); + + // ISD::RET => ret chain, (regnum1,val1), ... + // So i*2+1 index only the regnums + Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), + Op.getOperand(i*2+1), Flag); + + // guarantee that all emitted copies are + // stuck together, avoiding something bad + Flag = Chain.getValue(1); + } + + if (Flag.getNode()) + return DAG.getNode(MSP430ISD::RET_FLAG, dl, MVT::Other, Chain, Flag); + + // Return Void + return DAG.getNode(MSP430ISD::RET_FLAG, dl, MVT::Other, Chain); +} + +const char *MSP430TargetLowering::getTargetNodeName(unsigned Opcode) const { + switch (Opcode) { + default: return NULL; + case MSP430ISD::RET_FLAG: return "MSP430ISD::RET_FLAG"; + } +} + diff --git a/lib/Target/MSP430/MSP430ISelLowering.h b/lib/Target/MSP430/MSP430ISelLowering.h index 0d17ddc5741..4ee7a9c8cc4 100644 --- a/lib/Target/MSP430/MSP430ISelLowering.h +++ b/lib/Target/MSP430/MSP430ISelLowering.h @@ -20,6 +20,14 @@ #include "llvm/Target/TargetLowering.h" namespace llvm { + namespace MSP430ISD { + enum { + FIRST_NUMBER = ISD::BUILTIN_OP_END, + + /// Return with a flag operand. Operand 0 is the chain operand. + RET_FLAG + }; + } class MSP430Subtarget; class MSP430TargetMachine; @@ -30,7 +38,13 @@ namespace llvm { /// LowerOperation - Provide custom lowering hooks for some operations. virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG); + + /// getTargetNodeName - This method returns the name of a target specific + /// DAG node. + virtual const char *getTargetNodeName(unsigned Opcode) const; + SDValue LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG); + SDValue LowerRET(SDValue Op, SelectionDAG &DAG); SDValue LowerCCCArguments(SDValue Op, SelectionDAG &DAG); private: diff --git a/lib/Target/MSP430/MSP430InstrInfo.td b/lib/Target/MSP430/MSP430InstrInfo.td index 74fcebc9154..cd70fd3c136 100644 --- a/lib/Target/MSP430/MSP430InstrInfo.td +++ b/lib/Target/MSP430/MSP430InstrInfo.td @@ -26,9 +26,20 @@ class SDTCisI16 : SDTCisVT; //===----------------------------------------------------------------------===// // MSP430 Specific Node Definitions. //===----------------------------------------------------------------------===// +def retflag : SDNode<"MSP430ISD::RET_FLAG", SDTNone, + [SDNPHasChain, SDNPOptInFlag]>; //===----------------------------------------------------------------------===// // Pseudo Instructions //===----------------------------------------------------------------------===// def NOP : Pseudo<(outs), (ins), "nop", []>; + +//===----------------------------------------------------------------------===// +// Real Instructions +//===----------------------------------------------------------------------===// + +// FIXME: Provide proper encoding! +let isReturn = 1, isTerminator = 1 in { + def RETI: Pseudo<(outs), (ins), "reti", [(retflag)]>; +}