diff options
Diffstat (limited to 'contrib/llvm/lib/Target/PIC16/PIC16ISelLowering.cpp')
-rw-r--r-- | contrib/llvm/lib/Target/PIC16/PIC16ISelLowering.cpp | 2000 |
1 files changed, 0 insertions, 2000 deletions
diff --git a/contrib/llvm/lib/Target/PIC16/PIC16ISelLowering.cpp b/contrib/llvm/lib/Target/PIC16/PIC16ISelLowering.cpp deleted file mode 100644 index 527b31d..0000000 --- a/contrib/llvm/lib/Target/PIC16/PIC16ISelLowering.cpp +++ /dev/null @@ -1,2000 +0,0 @@ -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the interfaces that PIC16 uses to lower LLVM code into a -// selection DAG. -// -//===----------------------------------------------------------------------===// - -#define DEBUG_TYPE "pic16-lower" -#include "PIC16ABINames.h" -#include "PIC16ISelLowering.h" -#include "PIC16TargetObjectFile.h" -#include "PIC16TargetMachine.h" -#include "PIC16MachineFunctionInfo.h" -#include "llvm/DerivedTypes.h" -#include "llvm/GlobalValue.h" -#include "llvm/Function.h" -#include "llvm/CallingConv.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/Support/ErrorHandling.h" - - -using namespace llvm; - -static const char *getIntrinsicName(unsigned opcode) { - std::string Basename; - switch(opcode) { - default: llvm_unreachable("do not know intrinsic name"); - // Arithmetic Right shift for integer types. - case PIC16ISD::SRA_I8: Basename = "sra.i8"; break; - case RTLIB::SRA_I16: Basename = "sra.i16"; break; - case RTLIB::SRA_I32: Basename = "sra.i32"; break; - - // Left shift for integer types. - case PIC16ISD::SLL_I8: Basename = "sll.i8"; break; - case RTLIB::SHL_I16: Basename = "sll.i16"; break; - case RTLIB::SHL_I32: Basename = "sll.i32"; break; - - // Logical Right Shift for integer types. - case PIC16ISD::SRL_I8: Basename = "srl.i8"; break; - case RTLIB::SRL_I16: Basename = "srl.i16"; break; - case RTLIB::SRL_I32: Basename = "srl.i32"; break; - - // Multiply for integer types. - case PIC16ISD::MUL_I8: Basename = "mul.i8"; break; - case RTLIB::MUL_I16: Basename = "mul.i16"; break; - case RTLIB::MUL_I32: Basename = "mul.i32"; break; - - // Signed division for integers. - case RTLIB::SDIV_I16: Basename = "sdiv.i16"; break; - case RTLIB::SDIV_I32: Basename = "sdiv.i32"; break; - - // Unsigned division for integers. - case RTLIB::UDIV_I16: Basename = "udiv.i16"; break; - case RTLIB::UDIV_I32: Basename = "udiv.i32"; break; - - // Signed Modulas for integers. - case RTLIB::SREM_I16: Basename = "srem.i16"; break; - case RTLIB::SREM_I32: Basename = "srem.i32"; break; - - // Unsigned Modulas for integers. - case RTLIB::UREM_I16: Basename = "urem.i16"; break; - case RTLIB::UREM_I32: Basename = "urem.i32"; break; - - ////////////////////// - // LIBCALLS FOR FLOATS - ////////////////////// - - // Float to signed integrals - case RTLIB::FPTOSINT_F32_I8: Basename = "f32_to_si32"; break; - case RTLIB::FPTOSINT_F32_I16: Basename = "f32_to_si32"; break; - case RTLIB::FPTOSINT_F32_I32: Basename = "f32_to_si32"; break; - - // Signed integrals to float. char and int are first sign extended to i32 - // before being converted to float, so an I8_F32 or I16_F32 isn't required. - case RTLIB::SINTTOFP_I32_F32: Basename = "si32_to_f32"; break; - - // Float to Unsigned conversions. - // Signed conversion can be used for unsigned conversion as well. - // In signed and unsigned versions only the interpretation of the - // MSB is different. Bit representation remains the same. - case RTLIB::FPTOUINT_F32_I8: Basename = "f32_to_si32"; break; - case RTLIB::FPTOUINT_F32_I16: Basename = "f32_to_si32"; break; - case RTLIB::FPTOUINT_F32_I32: Basename = "f32_to_si32"; break; - - // Unsigned to Float conversions. char and int are first zero extended - // before being converted to float. - case RTLIB::UINTTOFP_I32_F32: Basename = "ui32_to_f32"; break; - - // Floating point add, sub, mul, div. - case RTLIB::ADD_F32: Basename = "add.f32"; break; - case RTLIB::SUB_F32: Basename = "sub.f32"; break; - case RTLIB::MUL_F32: Basename = "mul.f32"; break; - case RTLIB::DIV_F32: Basename = "div.f32"; break; - - // Floating point comparison - case RTLIB::O_F32: Basename = "unordered.f32"; break; - case RTLIB::UO_F32: Basename = "unordered.f32"; break; - case RTLIB::OLE_F32: Basename = "le.f32"; break; - case RTLIB::OGE_F32: Basename = "ge.f32"; break; - case RTLIB::OLT_F32: Basename = "lt.f32"; break; - case RTLIB::OGT_F32: Basename = "gt.f32"; break; - case RTLIB::OEQ_F32: Basename = "eq.f32"; break; - case RTLIB::UNE_F32: Basename = "neq.f32"; break; - } - - std::string prefix = PAN::getTagName(PAN::PREFIX_SYMBOL); - std::string tagname = PAN::getTagName(PAN::LIBCALL); - std::string Fullname = prefix + tagname + Basename; - - // The name has to live through program life. - return ESNames::createESName(Fullname); -} - -// getStdLibCallName - Get the name for the standard library function. -static const char *getStdLibCallName(unsigned opcode) { - std::string BaseName; - switch(opcode) { - case RTLIB::COS_F32: BaseName = "cos"; - break; - case RTLIB::SIN_F32: BaseName = "sin"; - break; - case RTLIB::MEMCPY: BaseName = "memcpy"; - break; - case RTLIB::MEMSET: BaseName = "memset"; - break; - case RTLIB::MEMMOVE: BaseName = "memmove"; - break; - default: llvm_unreachable("do not know std lib call name"); - } - std::string prefix = PAN::getTagName(PAN::PREFIX_SYMBOL); - std::string LibCallName = prefix + BaseName; - - // The name has to live through program life. - return ESNames::createESName(LibCallName); -} - -// PIC16TargetLowering Constructor. -PIC16TargetLowering::PIC16TargetLowering(PIC16TargetMachine &TM) - : TargetLowering(TM, new PIC16TargetObjectFile()) { - - Subtarget = &TM.getSubtarget<PIC16Subtarget>(); - - addRegisterClass(MVT::i8, PIC16::GPRRegisterClass); - - setShiftAmountType(MVT::i8); - - // Std lib call names - setLibcallName(RTLIB::COS_F32, getStdLibCallName(RTLIB::COS_F32)); - setLibcallName(RTLIB::SIN_F32, getStdLibCallName(RTLIB::SIN_F32)); - setLibcallName(RTLIB::MEMCPY, getStdLibCallName(RTLIB::MEMCPY)); - setLibcallName(RTLIB::MEMSET, getStdLibCallName(RTLIB::MEMSET)); - setLibcallName(RTLIB::MEMMOVE, getStdLibCallName(RTLIB::MEMMOVE)); - - // SRA library call names - setPIC16LibcallName(PIC16ISD::SRA_I8, getIntrinsicName(PIC16ISD::SRA_I8)); - setLibcallName(RTLIB::SRA_I16, getIntrinsicName(RTLIB::SRA_I16)); - setLibcallName(RTLIB::SRA_I32, getIntrinsicName(RTLIB::SRA_I32)); - - // SHL library call names - setPIC16LibcallName(PIC16ISD::SLL_I8, getIntrinsicName(PIC16ISD::SLL_I8)); - setLibcallName(RTLIB::SHL_I16, getIntrinsicName(RTLIB::SHL_I16)); - setLibcallName(RTLIB::SHL_I32, getIntrinsicName(RTLIB::SHL_I32)); - - // SRL library call names - setPIC16LibcallName(PIC16ISD::SRL_I8, getIntrinsicName(PIC16ISD::SRL_I8)); - setLibcallName(RTLIB::SRL_I16, getIntrinsicName(RTLIB::SRL_I16)); - setLibcallName(RTLIB::SRL_I32, getIntrinsicName(RTLIB::SRL_I32)); - - // MUL Library call names - setPIC16LibcallName(PIC16ISD::MUL_I8, getIntrinsicName(PIC16ISD::MUL_I8)); - setLibcallName(RTLIB::MUL_I16, getIntrinsicName(RTLIB::MUL_I16)); - setLibcallName(RTLIB::MUL_I32, getIntrinsicName(RTLIB::MUL_I32)); - - // Signed division lib call names - setLibcallName(RTLIB::SDIV_I16, getIntrinsicName(RTLIB::SDIV_I16)); - setLibcallName(RTLIB::SDIV_I32, getIntrinsicName(RTLIB::SDIV_I32)); - - // Unsigned division lib call names - setLibcallName(RTLIB::UDIV_I16, getIntrinsicName(RTLIB::UDIV_I16)); - setLibcallName(RTLIB::UDIV_I32, getIntrinsicName(RTLIB::UDIV_I32)); - - // Signed remainder lib call names - setLibcallName(RTLIB::SREM_I16, getIntrinsicName(RTLIB::SREM_I16)); - setLibcallName(RTLIB::SREM_I32, getIntrinsicName(RTLIB::SREM_I32)); - - // Unsigned remainder lib call names - setLibcallName(RTLIB::UREM_I16, getIntrinsicName(RTLIB::UREM_I16)); - setLibcallName(RTLIB::UREM_I32, getIntrinsicName(RTLIB::UREM_I32)); - - // Floating point to signed int conversions. - setLibcallName(RTLIB::FPTOSINT_F32_I8, - getIntrinsicName(RTLIB::FPTOSINT_F32_I8)); - setLibcallName(RTLIB::FPTOSINT_F32_I16, - getIntrinsicName(RTLIB::FPTOSINT_F32_I16)); - setLibcallName(RTLIB::FPTOSINT_F32_I32, - getIntrinsicName(RTLIB::FPTOSINT_F32_I32)); - - // Signed int to floats. - setLibcallName(RTLIB::SINTTOFP_I32_F32, - getIntrinsicName(RTLIB::SINTTOFP_I32_F32)); - - // Floating points to unsigned ints. - setLibcallName(RTLIB::FPTOUINT_F32_I8, - getIntrinsicName(RTLIB::FPTOUINT_F32_I8)); - setLibcallName(RTLIB::FPTOUINT_F32_I16, - getIntrinsicName(RTLIB::FPTOUINT_F32_I16)); - setLibcallName(RTLIB::FPTOUINT_F32_I32, - getIntrinsicName(RTLIB::FPTOUINT_F32_I32)); - - // Unsigned int to floats. - setLibcallName(RTLIB::UINTTOFP_I32_F32, - getIntrinsicName(RTLIB::UINTTOFP_I32_F32)); - - // Floating point add, sub, mul ,div. - setLibcallName(RTLIB::ADD_F32, getIntrinsicName(RTLIB::ADD_F32)); - setLibcallName(RTLIB::SUB_F32, getIntrinsicName(RTLIB::SUB_F32)); - setLibcallName(RTLIB::MUL_F32, getIntrinsicName(RTLIB::MUL_F32)); - setLibcallName(RTLIB::DIV_F32, getIntrinsicName(RTLIB::DIV_F32)); - - // Floationg point comparison - setLibcallName(RTLIB::O_F32, getIntrinsicName(RTLIB::O_F32)); - setLibcallName(RTLIB::UO_F32, getIntrinsicName(RTLIB::UO_F32)); - setLibcallName(RTLIB::OLE_F32, getIntrinsicName(RTLIB::OLE_F32)); - setLibcallName(RTLIB::OGE_F32, getIntrinsicName(RTLIB::OGE_F32)); - setLibcallName(RTLIB::OLT_F32, getIntrinsicName(RTLIB::OLT_F32)); - setLibcallName(RTLIB::OGT_F32, getIntrinsicName(RTLIB::OGT_F32)); - setLibcallName(RTLIB::OEQ_F32, getIntrinsicName(RTLIB::OEQ_F32)); - setLibcallName(RTLIB::UNE_F32, getIntrinsicName(RTLIB::UNE_F32)); - - // Return value comparisons of floating point calls. - setCmpLibcallCC(RTLIB::OEQ_F32, ISD::SETNE); - setCmpLibcallCC(RTLIB::UNE_F32, ISD::SETNE); - setCmpLibcallCC(RTLIB::OLT_F32, ISD::SETNE); - setCmpLibcallCC(RTLIB::OLE_F32, ISD::SETNE); - setCmpLibcallCC(RTLIB::OGE_F32, ISD::SETNE); - setCmpLibcallCC(RTLIB::OGT_F32, ISD::SETNE); - setCmpLibcallCC(RTLIB::UO_F32, ISD::SETNE); - setCmpLibcallCC(RTLIB::O_F32, ISD::SETEQ); - - setOperationAction(ISD::GlobalAddress, MVT::i16, Custom); - setOperationAction(ISD::ExternalSymbol, 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::STORE, MVT::i64, 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::SUB, MVT::i8, Custom); - setOperationAction(ISD::ADD, MVT::i8, Custom); - setOperationAction(ISD::ADD, MVT::i16, Custom); - - setOperationAction(ISD::OR, MVT::i8, Custom); - setOperationAction(ISD::AND, MVT::i8, Custom); - setOperationAction(ISD::XOR, MVT::i8, Custom); - - setOperationAction(ISD::FrameIndex, MVT::i16, Custom); - - setOperationAction(ISD::MUL, MVT::i8, Custom); - - setOperationAction(ISD::SMUL_LOHI, MVT::i8, Expand); - setOperationAction(ISD::UMUL_LOHI, MVT::i8, Expand); - setOperationAction(ISD::MULHU, MVT::i8, Expand); - setOperationAction(ISD::MULHS, MVT::i8, Expand); - - setOperationAction(ISD::SRA, MVT::i8, Custom); - setOperationAction(ISD::SHL, MVT::i8, Custom); - setOperationAction(ISD::SRL, MVT::i8, Custom); - - setOperationAction(ISD::ROTL, MVT::i8, Expand); - setOperationAction(ISD::ROTR, MVT::i8, Expand); - - setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); - - // PIC16 does not support shift parts - setOperationAction(ISD::SRA_PARTS, MVT::i8, Expand); - setOperationAction(ISD::SHL_PARTS, MVT::i8, Expand); - setOperationAction(ISD::SRL_PARTS, MVT::i8, Expand); - - - // PIC16 does not have a SETCC, expand it to SELECT_CC. - setOperationAction(ISD::SETCC, MVT::i8, Expand); - setOperationAction(ISD::SELECT, MVT::i8, Expand); - setOperationAction(ISD::BRCOND, MVT::Other, Expand); - setOperationAction(ISD::BRIND, MVT::Other, Expand); - - setOperationAction(ISD::SELECT_CC, MVT::i8, Custom); - setOperationAction(ISD::BR_CC, MVT::i8, Custom); - - //setOperationAction(ISD::TRUNCATE, MVT::i16, Custom); - setTruncStoreAction(MVT::i16, MVT::i8, Custom); - - // Now deduce the information based on the above mentioned - // actions - computeRegisterProperties(); -} - -std::pair<const TargetRegisterClass*, uint8_t> -PIC16TargetLowering::findRepresentativeClass(EVT VT) const { - switch (VT.getSimpleVT().SimpleTy) { - default: - return TargetLowering::findRepresentativeClass(VT); - case MVT::i16: - return std::make_pair(PIC16::FSR16RegisterClass, 1); - } -} - -// getOutFlag - Extract the flag result if the Op has it. -static SDValue getOutFlag(SDValue &Op) { - // Flag is the last value of the node. - SDValue Flag = Op.getValue(Op.getNode()->getNumValues() - 1); - - assert (Flag.getValueType() == MVT::Flag - && "Node does not have an out Flag"); - - return Flag; -} -// Get the TmpOffset for FrameIndex -unsigned PIC16TargetLowering::GetTmpOffsetForFI(unsigned FI, unsigned size, - MachineFunction &MF) const { - PIC16MachineFunctionInfo *FuncInfo = MF.getInfo<PIC16MachineFunctionInfo>(); - std::map<unsigned, unsigned> &FiTmpOffsetMap = FuncInfo->getFiTmpOffsetMap(); - - std::map<unsigned, unsigned>::iterator - MapIt = FiTmpOffsetMap.find(FI); - if (MapIt != FiTmpOffsetMap.end()) - return MapIt->second; - - // This FI (FrameIndex) is not yet mapped, so map it - FiTmpOffsetMap[FI] = FuncInfo->getTmpSize(); - FuncInfo->setTmpSize(FuncInfo->getTmpSize() + size); - return FiTmpOffsetMap[FI]; -} - -void PIC16TargetLowering::ResetTmpOffsetMap(SelectionDAG &DAG) const { - MachineFunction &MF = DAG.getMachineFunction(); - PIC16MachineFunctionInfo *FuncInfo = MF.getInfo<PIC16MachineFunctionInfo>(); - FuncInfo->getFiTmpOffsetMap().clear(); - FuncInfo->setTmpSize(0); -} - -// 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. -static SDValue getChain(SDValue &Op) { - SDValue Chain = Op.getValue(Op.getNode()->getNumValues() - 1); - - // If the last value returned in Flag then the chain is - // second last value returned. - if (Chain.getValueType() == MVT::Flag) - Chain = Op.getValue(Op.getNode()->getNumValues() - 2); - - // 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; -} - -/// PopulateResults - Helper function to LowerOperation. -/// If a node wants to return multiple results after lowering, -/// it stuffs them into an array of SDValue called Results. - -static void PopulateResults(SDValue N, SmallVectorImpl<SDValue>&Results) { - if (N.getOpcode() == ISD::MERGE_VALUES) { - int NumResults = N.getNumOperands(); - for( int i = 0; i < NumResults; i++) - Results.push_back(N.getOperand(i)); - } - else - Results.push_back(N); -} - -MVT::SimpleValueType -PIC16TargetLowering::getSetCCResultType(EVT ValType) const { - return MVT::i8; -} - -MVT::SimpleValueType -PIC16TargetLowering::getCmpLibcallReturnType() const { - return MVT::i8; -} - -/// The type legalizer framework of generating legalizer can generate libcalls -/// only when the operand/result types are illegal. -/// PIC16 needs to generate libcalls even for the legal types (i8) for some ops. -/// For example an arithmetic right shift. These functions are used to lower -/// such operations that generate libcall for legal types. - -void -PIC16TargetLowering::setPIC16LibcallName(PIC16ISD::PIC16Libcall Call, - const char *Name) { - PIC16LibcallNames[Call] = Name; -} - -const char * -PIC16TargetLowering::getPIC16LibcallName(PIC16ISD::PIC16Libcall Call) const { - return PIC16LibcallNames[Call]; -} - -SDValue -PIC16TargetLowering::MakePIC16Libcall(PIC16ISD::PIC16Libcall Call, - EVT RetVT, const SDValue *Ops, - unsigned NumOps, bool isSigned, - SelectionDAG &DAG, DebugLoc dl) const { - - TargetLowering::ArgListTy Args; - Args.reserve(NumOps); - - TargetLowering::ArgListEntry Entry; - for (unsigned i = 0; i != NumOps; ++i) { - Entry.Node = Ops[i]; - Entry.Ty = Entry.Node.getValueType().getTypeForEVT(*DAG.getContext()); - Entry.isSExt = isSigned; - Entry.isZExt = !isSigned; - Args.push_back(Entry); - } - - SDValue Callee = DAG.getExternalSymbol(getPIC16LibcallName(Call), MVT::i16); - - const Type *RetTy = RetVT.getTypeForEVT(*DAG.getContext()); - std::pair<SDValue,SDValue> CallInfo = - LowerCallTo(DAG.getEntryNode(), RetTy, isSigned, !isSigned, false, - false, 0, CallingConv::C, false, - /*isReturnValueUsed=*/true, - Callee, Args, DAG, dl); - - return CallInfo.first; -} - -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::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"; - case PIC16ISD::PIC16LdWF: return "PIC16ISD::PIC16LdWF"; - case PIC16ISD::PIC16Store: return "PIC16ISD::PIC16Store"; - case PIC16ISD::PIC16StWF: return "PIC16ISD::PIC16StWF"; - 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::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"; - case PIC16ISD::RET: return "PIC16ISD::RET"; - case PIC16ISD::Dummy: return "PIC16ISD::Dummy"; - } -} - -void PIC16TargetLowering::ReplaceNodeResults(SDNode *N, - SmallVectorImpl<SDValue>&Results, - SelectionDAG &DAG) const { - - switch (N->getOpcode()) { - case ISD::GlobalAddress: - Results.push_back(ExpandGlobalAddress(N, DAG)); - return; - case ISD::ExternalSymbol: - Results.push_back(ExpandExternalSymbol(N, DAG)); - return; - case ISD::STORE: - Results.push_back(ExpandStore(N, DAG)); - return; - case ISD::LOAD: - PopulateResults(ExpandLoad(N, DAG), Results); - return; - case ISD::ADD: - // Results.push_back(ExpandAdd(N, DAG)); - return; - case ISD::FrameIndex: - Results.push_back(ExpandFrameIndex(N, DAG)); - return; - default: - assert (0 && "not implemented"); - return; - } -} - -SDValue PIC16TargetLowering::ExpandFrameIndex(SDNode *N, - SelectionDAG &DAG) const { - - // Currently handling FrameIndex of size MVT::i16 only - // One example of this scenario is when return value is written on - // FrameIndex#0 - - if (N->getValueType(0) != MVT::i16) - return SDValue(); - - // Expand the FrameIndex into ExternalSymbol and a Constant node - // The constant will represent the frame index number - // Get the current function frame - MachineFunction &MF = DAG.getMachineFunction(); - const Function *Func = MF.getFunction(); - const std::string Name = Func->getName(); - - FrameIndexSDNode *FR = dyn_cast<FrameIndexSDNode>(SDValue(N,0)); - // FIXME there isn't really debug info here - DebugLoc dl = FR->getDebugLoc(); - - // Expand FrameIndex like GlobalAddress and ExternalSymbol - // Also use Offset field for lo and hi parts. The default - // offset is zero. - - SDValue ES; - int FrameOffset; - SDValue FI = SDValue(N,0); - LegalizeFrameIndex(FI, DAG, ES, FrameOffset); - SDValue Offset = DAG.getConstant(FrameOffset, MVT::i8); - SDValue Lo = DAG.getNode(PIC16ISD::Lo, dl, MVT::i8, ES, Offset); - SDValue Hi = DAG.getNode(PIC16ISD::Hi, dl, MVT::i8, ES, Offset); - return DAG.getNode(ISD::BUILD_PAIR, dl, N->getValueType(0), Lo, Hi); -} - - -SDValue PIC16TargetLowering::ExpandStore(SDNode *N, SelectionDAG &DAG) const { - StoreSDNode *St = cast<StoreSDNode>(N); - SDValue Chain = St->getChain(); - SDValue Src = St->getValue(); - SDValue Ptr = St->getBasePtr(); - EVT ValueType = Src.getValueType(); - unsigned StoreOffset = 0; - DebugLoc dl = N->getDebugLoc(); - - SDValue PtrLo, PtrHi; - LegalizeAddress(Ptr, DAG, PtrLo, PtrHi, StoreOffset, dl); - - if (ValueType == MVT::i8) { - return DAG.getNode (PIC16ISD::PIC16Store, dl, MVT::Other, Chain, Src, - PtrLo, PtrHi, - DAG.getConstant (0 + StoreOffset, MVT::i8)); - } - 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; - // FIXME: This makes unsafe assumptions. The Chain may be a TokenFactor - // created for an unrelated purpose, in which case it may not have - // exactly two operands. Also, even if it does have two operands, they - // may not be the low and high parts of an aligned load that was split. - if (Chain.getOpcode() == ISD::TokenFactor) { - ChainLo = Chain.getOperand(0); - ChainHi = Chain.getOperand(1); - } - SDValue Store1 = DAG.getNode(PIC16ISD::PIC16Store, dl, MVT::Other, - ChainLo, - SrcLo, PtrLo, PtrHi, - DAG.getConstant (0 + StoreOffset, MVT::i8)); - - SDValue Store2 = DAG.getNode(PIC16ISD::PIC16Store, dl, MVT::Other, ChainHi, - SrcHi, PtrLo, PtrHi, - DAG.getConstant (1 + StoreOffset, MVT::i8)); - - return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, getChain(Store1), - getChain(Store2)); - } - 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; - // FIXME: This makes unsafe assumptions; see the FIXME above. - if (Chain.getOpcode() == ISD::TokenFactor) { - ChainLo = Chain.getOperand(0); - ChainHi = Chain.getOperand(1); - } - SDValue ChainLo1 = ChainLo, ChainLo2 = ChainLo, ChainHi1 = ChainHi, - ChainHi2 = ChainHi; - // FIXME: This makes unsafe assumptions; see the FIXME above. - if (ChainLo.getOpcode() == ISD::TokenFactor) { - ChainLo1 = ChainLo.getOperand(0); - ChainLo2 = ChainLo.getOperand(1); - } - // FIXME: This makes unsafe assumptions; see the FIXME above. - if (ChainHi.getOpcode() == ISD::TokenFactor) { - ChainHi1 = ChainHi.getOperand(0); - ChainHi2 = ChainHi.getOperand(1); - } - SDValue Store1 = DAG.getNode(PIC16ISD::PIC16Store, dl, MVT::Other, - ChainLo1, - SrcLo1, PtrLo, PtrHi, - DAG.getConstant (0 + StoreOffset, MVT::i8)); - - SDValue Store2 = DAG.getNode(PIC16ISD::PIC16Store, dl, MVT::Other, ChainLo2, - SrcLo2, PtrLo, PtrHi, - DAG.getConstant (1 + StoreOffset, MVT::i8)); - - SDValue Store3 = DAG.getNode(PIC16ISD::PIC16Store, dl, MVT::Other, ChainHi1, - SrcHi1, PtrLo, PtrHi, - DAG.getConstant (2 + StoreOffset, MVT::i8)); - - SDValue Store4 = DAG.getNode(PIC16ISD::PIC16Store, dl, MVT::Other, ChainHi2, - SrcHi2, PtrLo, PtrHi, - DAG.getConstant (3 + StoreOffset, MVT::i8)); - - SDValue RetLo = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, - getChain(Store1), getChain(Store2)); - SDValue RetHi = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, - getChain(Store3), getChain(Store4)); - return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, RetLo, RetHi); - - } else if (ValueType == MVT::i64) { - SDValue SrcLo, SrcHi; - GetExpandedParts(Src, DAG, SrcLo, SrcHi); - SDValue ChainLo = Chain, ChainHi = Chain; - // FIXME: This makes unsafe assumptions; see the FIXME above. - if (Chain.getOpcode() == ISD::TokenFactor) { - ChainLo = Chain.getOperand(0); - ChainHi = Chain.getOperand(1); - } - SDValue Store1 = DAG.getStore(ChainLo, dl, SrcLo, Ptr, NULL, - 0 + StoreOffset, false, false, 0); - - Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, - DAG.getConstant(4, Ptr.getValueType())); - SDValue Store2 = DAG.getStore(ChainHi, dl, SrcHi, Ptr, NULL, - 1 + StoreOffset, false, false, 0); - - return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Store1, - Store2); - } else { - assert (0 && "value type not supported"); - return SDValue(); - } -} - -SDValue PIC16TargetLowering::ExpandExternalSymbol(SDNode *N, - SelectionDAG &DAG) - const { - ExternalSymbolSDNode *ES = dyn_cast<ExternalSymbolSDNode>(SDValue(N, 0)); - // FIXME there isn't really debug info here - DebugLoc dl = ES->getDebugLoc(); - - SDValue TES = DAG.getTargetExternalSymbol(ES->getSymbol(), MVT::i8); - SDValue Offset = DAG.getConstant(0, MVT::i8); - SDValue Lo = DAG.getNode(PIC16ISD::Lo, dl, MVT::i8, TES, Offset); - SDValue Hi = DAG.getNode(PIC16ISD::Hi, dl, MVT::i8, TES, Offset); - - return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i16, Lo, Hi); -} - -// ExpandGlobalAddress - -SDValue PIC16TargetLowering::ExpandGlobalAddress(SDNode *N, - SelectionDAG &DAG) const { - GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(SDValue(N, 0)); - // FIXME there isn't really debug info here - DebugLoc dl = G->getDebugLoc(); - - SDValue TGA = DAG.getTargetGlobalAddress(G->getGlobal(), N->getDebugLoc(), - MVT::i8, - G->getOffset()); - - SDValue Offset = DAG.getConstant(0, MVT::i8); - SDValue Lo = DAG.getNode(PIC16ISD::Lo, dl, MVT::i8, TGA, Offset); - SDValue Hi = DAG.getNode(PIC16ISD::Hi, dl, MVT::i8, TGA, Offset); - - return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i16, Lo, Hi); -} - -bool PIC16TargetLowering::isDirectAddress(const SDValue &Op) const { - 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) const { - - // 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); - - if (GSDN->getAddressSpace() == PIC16ISD::ROM_SPACE) - return true; - - // Any other address space return it false - return false; -} - - -// GetExpandedParts - This function is on the similiar lines as -// the GetExpandedInteger in type legalizer is. This returns expanded -// parts of Op in Lo and Hi. - -void PIC16TargetLowering::GetExpandedParts(SDValue Op, SelectionDAG &DAG, - SDValue &Lo, SDValue &Hi) const { - SDNode *N = Op.getNode(); - DebugLoc dl = N->getDebugLoc(); - EVT NewVT = getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); - - // Extract the lo component. - Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NewVT, Op, - DAG.getConstant(0, MVT::i8)); - - // extract the hi component - Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NewVT, Op, - DAG.getConstant(1, MVT::i8)); -} - -// Legalize FrameIndex into ExternalSymbol and offset. -void -PIC16TargetLowering::LegalizeFrameIndex(SDValue Op, SelectionDAG &DAG, - SDValue &ES, int &Offset) const { - - MachineFunction &MF = DAG.getMachineFunction(); - const Function *Func = MF.getFunction(); - MachineFrameInfo *MFI = MF.getFrameInfo(); - PIC16MachineFunctionInfo *FuncInfo = MF.getInfo<PIC16MachineFunctionInfo>(); - const std::string Name = Func->getName(); - - FrameIndexSDNode *FR = dyn_cast<FrameIndexSDNode>(Op); - - // FrameIndices are not stack offsets. But they represent the request - // for space on stack. That space requested may be more than one byte. - // Therefore, to calculate the stack offset that a FrameIndex aligns - // with, we need to traverse all the FrameIndices available earlier in - // the list and add their requested size. - unsigned FIndex = FR->getIndex(); - const char *tmpName; - if (FIndex < FuncInfo->getReservedFrameCount()) { - tmpName = ESNames::createESName(PAN::getFrameLabel(Name)); - ES = DAG.getTargetExternalSymbol(tmpName, MVT::i8); - Offset = 0; - for (unsigned i=0; i<FIndex ; ++i) { - Offset += MFI->getObjectSize(i); - } - } else { - // FrameIndex has been made for some temporary storage - tmpName = ESNames::createESName(PAN::getTempdataLabel(Name)); - ES = DAG.getTargetExternalSymbol(tmpName, MVT::i8); - Offset = GetTmpOffsetForFI(FIndex, MFI->getObjectSize(FIndex), MF); - } - - return; -} - -// 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, DebugLoc dl) const { - - // 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) && - (dyn_cast<ConstantSDNode>(OperLeft)->getZExtValue() < 32 )) { - Offset = dyn_cast<ConstantSDNode>(OperLeft)->getZExtValue(); - Ptr = OperRight; - } else if ((OperRight.getOpcode() == ISD::Constant) && - (dyn_cast<ConstantSDNode>(OperRight)->getZExtValue() < 32 )){ - Offset = dyn_cast<ConstantSDNode>(OperRight)->getZExtValue(); - Ptr = OperLeft; - } - } - - // If the pointer is Type i8 and an external symbol - // then treat it as direct address. - // One example for such case is storing and loading - // from function frame during a call - if (Ptr.getValueType() == MVT::i8) { - switch (Ptr.getOpcode()) { - case ISD::TargetExternalSymbol: - Lo = Ptr; - Hi = DAG.getConstant(1, MVT::i8); - return; - } - } - - // Expansion of FrameIndex has Lo/Hi parts - if (isDirectAddress(Ptr)) { - SDValue TFI = Ptr.getOperand(0).getOperand(0); - int FrameOffset; - if (TFI.getOpcode() == ISD::TargetFrameIndex) { - LegalizeFrameIndex(TFI, DAG, Lo, FrameOffset); - Hi = DAG.getConstant(1, MVT::i8); - Offset += FrameOffset; - return; - } else if (TFI.getOpcode() == ISD::TargetExternalSymbol) { - // FrameIndex has already been expanded. - // Now just make use of its expansion - Lo = TFI; - Hi = DAG.getConstant(1, MVT::i8); - SDValue FOffset = Ptr.getOperand(0).getOperand(1); - assert (FOffset.getOpcode() == ISD::Constant && - "Invalid operand of PIC16ISD::Lo"); - Offset += dyn_cast<ConstantSDNode>(FOffset)->getZExtValue(); - return; - } - } - - 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; - } - - // Indirect addresses. Get the hi and lo parts of ptr. - GetExpandedParts(Ptr, DAG, Lo, Hi); - - // Put the hi and lo parts into FSR. - Lo = DAG.getNode(PIC16ISD::MTLO, dl, MVT::i8, Lo); - Hi = DAG.getNode(PIC16ISD::MTHI, dl, MVT::i8, Hi); - - return; -} - -SDValue PIC16TargetLowering::ExpandLoad(SDNode *N, SelectionDAG &DAG) const { - LoadSDNode *LD = dyn_cast<LoadSDNode>(SDValue(N, 0)); - SDValue Chain = LD->getChain(); - SDValue Ptr = LD->getBasePtr(); - DebugLoc dl = LD->getDebugLoc(); - - SDValue Load, Offset; - SDVTList Tys; - EVT 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, dl); - - // Load from the pointer (direct address or FSR) - VT = N->getValueType(0); - unsigned NumLoads = VT.getSizeInBits() / 8; - std::vector<SDValue> PICLoads; - unsigned iter; - EVT 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, dl, Tys, Chain, PtrLo, PtrHi, - Offset); - PICLoads.push_back(Load); - } - } 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 - EVT MemVT = LD->getMemoryVT(); - unsigned MemBytes = MemVT.getSizeInBits() / 8; - // if MVT::i1 is extended to MVT::i8 then MemBytes will be zero - // So set it to one - if (MemBytes == 0) MemBytes = 1; - - 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, dl, Tys, Chain, PtrLo, PtrHi, - Offset); - PICLoads.push_back(Load); - } - - // 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, dl, MVT::i8, Load, - DAG.getConstant(7, MVT::i8)); - for (iter=MemBytes; iter<ExtdBytes; ++iter) { - PICLoads.push_back(SRA); - } - } else if (ISD::isZEXTLoad(N) || ISD::isEXTLoad(N)) { - //} 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]; - } - else if (VT == MVT::i16) { - BP = DAG.getNode(ISD::BUILD_PAIR, dl, VT, PICLoads[0], PICLoads[1]); - if ((MemVT == MVT::i8) || (MemVT == MVT::i1)) - Chain = getChain(PICLoads[0]); - else - Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, - getChain(PICLoads[0]), getChain(PICLoads[1])); - } else if (VT == MVT::i32) { - SDValue BPs[2]; - BPs[0] = DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i16, - PICLoads[0], PICLoads[1]); - BPs[1] = DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i16, - PICLoads[2], PICLoads[3]); - BP = DAG.getNode(ISD::BUILD_PAIR, dl, VT, BPs[0], BPs[1]); - if ((MemVT == MVT::i8) || (MemVT == MVT::i1)) - Chain = getChain(PICLoads[0]); - else if (MemVT == MVT::i16) - Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, - getChain(PICLoads[0]), getChain(PICLoads[1])); - else { - SDValue Chains[2]; - Chains[0] = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, - getChain(PICLoads[0]), getChain(PICLoads[1])); - Chains[1] = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, - getChain(PICLoads[2]), getChain(PICLoads[3])); - Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, - Chains[0], Chains[1]); - } - } - Tys = DAG.getVTList(VT, MVT::Other); - return DAG.getNode(ISD::MERGE_VALUES, dl, Tys, BP, Chain); -} - -SDValue PIC16TargetLowering::LowerShift(SDValue Op, SelectionDAG &DAG) const { - // We should have handled larger operands in type legalizer itself. - assert (Op.getValueType() == MVT::i8 && "illegal shift to lower"); - - SDNode *N = Op.getNode(); - SDValue Value = N->getOperand(0); - SDValue Amt = N->getOperand(1); - PIC16ISD::PIC16Libcall CallCode; - switch (N->getOpcode()) { - case ISD::SRA: - CallCode = PIC16ISD::SRA_I8; - break; - case ISD::SHL: - CallCode = PIC16ISD::SLL_I8; - break; - case ISD::SRL: - CallCode = PIC16ISD::SRL_I8; - break; - default: - assert ( 0 && "This shift is not implemented yet."); - return SDValue(); - } - SmallVector<SDValue, 2> Ops(2); - Ops[0] = Value; - Ops[1] = Amt; - SDValue Call = MakePIC16Libcall(CallCode, N->getValueType(0), &Ops[0], 2, - true, DAG, N->getDebugLoc()); - return Call; -} - -SDValue PIC16TargetLowering::LowerMUL(SDValue Op, SelectionDAG &DAG) const { - // We should have handled larger operands in type legalizer itself. - assert (Op.getValueType() == MVT::i8 && "illegal multiply to lower"); - - SDNode *N = Op.getNode(); - SmallVector<SDValue, 2> Ops(2); - Ops[0] = N->getOperand(0); - Ops[1] = N->getOperand(1); - SDValue Call = MakePIC16Libcall(PIC16ISD::MUL_I8, N->getValueType(0), - &Ops[0], 2, true, DAG, N->getDebugLoc()); - return Call; -} - -void -PIC16TargetLowering::LowerOperationWrapper(SDNode *N, - SmallVectorImpl<SDValue>&Results, - SelectionDAG &DAG) const { - SDValue Op = SDValue(N, 0); - SDValue Res; - unsigned i; - switch (Op.getOpcode()) { - case ISD::LOAD: - Res = ExpandLoad(Op.getNode(), DAG); break; - default: { - // All other operations are handled in LowerOperation. - Res = LowerOperation(Op, DAG); - if (Res.getNode()) - Results.push_back(Res); - - return; - } - } - - N = Res.getNode(); - unsigned NumValues = N->getNumValues(); - for (i = 0; i < NumValues ; i++) { - Results.push_back(SDValue(N, i)); - } -} - -SDValue PIC16TargetLowering::LowerOperation(SDValue Op, - SelectionDAG &DAG) const { - switch (Op.getOpcode()) { - case ISD::ADD: - case ISD::ADDC: - case ISD::ADDE: - return LowerADD(Op, DAG); - case ISD::SUB: - case ISD::SUBC: - case ISD::SUBE: - return LowerSUB(Op, DAG); - case ISD::LOAD: - return ExpandLoad(Op.getNode(), DAG); - case ISD::STORE: - return ExpandStore(Op.getNode(), DAG); - case ISD::MUL: - return LowerMUL(Op, DAG); - case ISD::SHL: - case ISD::SRA: - case ISD::SRL: - return LowerShift(Op, DAG); - case ISD::OR: - case ISD::AND: - case ISD::XOR: - return LowerBinOp(Op, DAG); - case ISD::BR_CC: - return LowerBR_CC(Op, DAG); - case ISD::SELECT_CC: - return LowerSELECT_CC(Op, DAG); - } - return SDValue(); -} - -SDValue PIC16TargetLowering::ConvertToMemOperand(SDValue Op, - SelectionDAG &DAG, - DebugLoc dl) const { - 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(); - - - // Put the value on stack. - // Get a stack slot index and convert to es. - int FI = MF.getFrameInfo()->CreateStackObject(1, 1, false); - const char *tmpName = ESNames::createESName(PAN::getTempdataLabel(FuncName)); - SDValue ES = DAG.getTargetExternalSymbol(tmpName, MVT::i8); - - // Store the value to ES. - SDValue Store = DAG.getNode (PIC16ISD::PIC16Store, dl, MVT::Other, - DAG.getEntryNode(), - Op, ES, - DAG.getConstant (1, MVT::i8), // Banksel. - DAG.getConstant (GetTmpOffsetForFI(FI, 1, MF), - MVT::i8)); - - // Load the value from ES. - SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Other); - SDValue Load = DAG.getNode(PIC16ISD::PIC16Load, dl, Tys, Store, - ES, DAG.getConstant (1, MVT::i8), - DAG.getConstant (GetTmpOffsetForFI(FI, 1, MF), - MVT::i8)); - - return Load.getValue(0); -} - -SDValue PIC16TargetLowering:: -LowerIndirectCallArguments(SDValue Chain, SDValue InFlag, - SDValue DataAddr_Lo, SDValue DataAddr_Hi, - const SmallVectorImpl<ISD::OutputArg> &Outs, - const SmallVectorImpl<SDValue> &OutVals, - const SmallVectorImpl<ISD::InputArg> &Ins, - DebugLoc dl, SelectionDAG &DAG) const { - unsigned NumOps = Outs.size(); - - // 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 PIC16 ABI the arguments come after the return value. - unsigned RetVals = Ins.size(); - for (unsigned i = 0, ArgOffset = RetVals; i < NumOps; i++) { - // Get the arguments - Arg = OutVals[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(ArgOffset, MVT::i8)); - Ops.push_back(InFlag); - - StoreRet = DAG.getNode (PIC16ISD::PIC16StWF, dl, Tys, &Ops[0], Ops.size()); - - Chain = getChain(StoreRet); - InFlag = getOutFlag(StoreRet); - ArgOffset++; - } - return Chain; -} - -SDValue PIC16TargetLowering:: -LowerDirectCallArguments(SDValue ArgLabel, SDValue Chain, SDValue InFlag, - const SmallVectorImpl<ISD::OutputArg> &Outs, - const SmallVectorImpl<SDValue> &OutVals, - DebugLoc dl, SelectionDAG &DAG) const { - unsigned NumOps = Outs.size(); - std::string Name; - SDValue Arg, StoreAt; - EVT ArgVT; - unsigned Size=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. - - // Legalize the address before use - SDValue PtrLo, PtrHi; - unsigned AddressOffset; - int StoreOffset = 0; - LegalizeAddress(ArgLabel, DAG, PtrLo, PtrHi, AddressOffset, dl); - SDValue StoreRet; - - std::vector<SDValue> Ops; - SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Flag); - for (unsigned i=0, Offset = 0; i<NumOps; i++) { - // Get the argument - Arg = OutVals[i]; - StoreOffset = (Offset + AddressOffset); - - // Store the argument on frame - - Ops.clear(); - Ops.push_back(Chain); - Ops.push_back(Arg); - Ops.push_back(PtrLo); - Ops.push_back(PtrHi); - Ops.push_back(DAG.getConstant(StoreOffset, MVT::i8)); - Ops.push_back(InFlag); - - StoreRet = DAG.getNode (PIC16ISD::PIC16StWF, dl, Tys, &Ops[0], Ops.size()); - - Chain = getChain(StoreRet); - InFlag = getOutFlag(StoreRet); - - // Update the frame offset to be used for next argument - ArgVT = Arg.getValueType(); - Size = ArgVT.getSizeInBits(); - Size = Size/8; // Calculate size in bytes - Offset += Size; // Increase the frame offset - } - return Chain; -} - -SDValue PIC16TargetLowering:: -LowerIndirectCallReturn(SDValue Chain, SDValue InFlag, - SDValue DataAddr_Lo, SDValue DataAddr_Hi, - const SmallVectorImpl<ISD::InputArg> &Ins, - DebugLoc dl, SelectionDAG &DAG, - SmallVectorImpl<SDValue> &InVals) const { - unsigned RetVals = Ins.size(); - - // If call does not have anything to return - // then do nothing and go back. - if (RetVals == 0) - return Chain; - - // Call has something to return - 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); - InVals.push_back(LoadRet); - } - return Chain; -} - -SDValue PIC16TargetLowering:: -LowerDirectCallReturn(SDValue RetLabel, SDValue Chain, SDValue InFlag, - const SmallVectorImpl<ISD::InputArg> &Ins, - DebugLoc dl, SelectionDAG &DAG, - SmallVectorImpl<SDValue> &InVals) const { - - // Currently handling primitive types only. They will come in - // i8 parts - unsigned RetVals = Ins.size(); - - // Return immediately if the return type is void - if (RetVals == 0) - return Chain; - - // Call has something to return - - // Legalize the address before use - SDValue LdLo, LdHi; - unsigned LdOffset; - LegalizeAddress(RetLabel, DAG, LdLo, LdHi, LdOffset, dl); - - SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Other, MVT::Flag); - SDValue LoadRet; - - for(unsigned i=0, Offset=0;i<RetVals;i++) { - - LoadRet = DAG.getNode(PIC16ISD::PIC16LdWF, dl, Tys, Chain, LdLo, LdHi, - DAG.getConstant(LdOffset + Offset, MVT::i8), - InFlag); - - InFlag = getOutFlag(LoadRet); - - Chain = getChain(LoadRet); - Offset++; - InVals.push_back(LoadRet); - } - - return Chain; -} - -SDValue -PIC16TargetLowering::LowerReturn(SDValue Chain, - CallingConv::ID CallConv, bool isVarArg, - const SmallVectorImpl<ISD::OutputArg> &Outs, - const SmallVectorImpl<SDValue> &OutVals, - DebugLoc dl, SelectionDAG &DAG) const { - - // Number of values to return - unsigned NumRet = Outs.size(); - - // Function returns value always on stack with the offset starting - // from 0 - MachineFunction &MF = DAG.getMachineFunction(); - const Function *F = MF.getFunction(); - std::string FuncName = F->getName(); - - const char *tmpName = ESNames::createESName(PAN::getFrameLabel(FuncName)); - SDValue ES = DAG.getTargetExternalSymbol(tmpName, MVT::i8); - SDValue BS = DAG.getConstant(1, MVT::i8); - SDValue RetVal; - for(unsigned i=0;i<NumRet; ++i) { - RetVal = OutVals[i]; - Chain = DAG.getNode (PIC16ISD::PIC16Store, dl, MVT::Other, Chain, RetVal, - ES, BS, - DAG.getConstant (i, MVT::i8)); - - } - return DAG.getNode(PIC16ISD::RET, dl, MVT::Other, Chain); -} - -void PIC16TargetLowering:: -GetDataAddress(DebugLoc dl, SDValue Callee, SDValue &Chain, - SDValue &DataAddr_Lo, SDValue &DataAddr_Hi, - SelectionDAG &DAG) const { - 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); - - SDValue Data_Lo, Data_Hi; - SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Other, MVT::Flag); - // Subtract 2 from Address to get the Lower part of DataAddress. - SDVTList VTList = DAG.getVTList(MVT::i8, MVT::Flag); - Data_Lo = DAG.getNode(ISD::SUBC, dl, VTList, Lo, - DAG.getConstant(2, MVT::i8)); - SDValue Ops[3] = { Hi, DAG.getConstant(0, MVT::i8), Data_Lo.getValue(1)}; - Data_Hi = DAG.getNode(ISD::SUBE, dl, VTList, Ops, 3); - SDValue PCLATH = DAG.getNode(PIC16ISD::MTPCLATH, dl, MVT::i8, Data_Hi); - Callee = DAG.getNode(PIC16ISD::PIC16Connect, dl, MVT::i8, Data_Lo, PCLATH); - 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 - - // Subtract 1 from Address to get high part of data address. - Data_Lo = DAG.getNode(ISD::SUBC, dl, VTList, Lo, - DAG.getConstant(1, MVT::i8)); - SDValue HiOps[3] = { Hi, DAG.getConstant(0, MVT::i8), Data_Lo.getValue(1)}; - Data_Hi = DAG.getNode(ISD::SUBE, dl, VTList, HiOps, 3); - PCLATH = DAG.getNode(PIC16ISD::MTPCLATH, dl, MVT::i8, Data_Hi); - - // Use new Lo to make another CALLW - Callee = DAG.getNode(PIC16ISD::PIC16Connect, dl, MVT::i8, Data_Lo, PCLATH); - 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 Chain, SDValue Callee, - CallingConv::ID CallConv, bool isVarArg, - bool &isTailCall, - const SmallVectorImpl<ISD::OutputArg> &Outs, - const SmallVectorImpl<SDValue> &OutVals, - const SmallVectorImpl<ISD::InputArg> &Ins, - DebugLoc dl, SelectionDAG &DAG, - SmallVectorImpl<SDValue> &InVals) const { - // PIC16 target does not yet support tail call optimization. - isTailCall = false; - - assert(Callee.getValueType() == MVT::i16 && - "Don't know how to legalize this call node!!!"); - - // The flag to track if this is a direct or indirect call. - bool IsDirectCall = true; - unsigned RetVals = Ins.size(); - unsigned NumArgs = Outs.size(); - - SDValue DataAddr_Lo, DataAddr_Hi; - if (!isa<GlobalAddressSDNode>(Callee) && - !isa<ExternalSymbolSDNode>(Callee)) { - IsDirectCall = false; // This is indirect call - - // 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. - - // 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); - - // 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. - // Carring the Constant 0 along the CALLSEQSTART - // 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<GlobalAddressSDNode>(Callee)) { - const GlobalValue *GV = G->getGlobal(); - Callee = DAG.getTargetGlobalAddress(GV, dl, 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 - const char *argFrame = ESNames::createESName(PAN::getArgsLabel(Name)); - ArgLabel = DAG.getTargetExternalSymbol(argFrame, MVT::i8); - - // Label for reading return value - const char *retName = ESNames::createESName(PAN::getRetvalLabel(Name)); - 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; - if (IsDirectCall) { - CallArgs = LowerDirectCallArguments(ArgLabel, Chain, OperFlag, - Outs, OutVals, dl, DAG); - Chain = getChain(CallArgs); - OperFlag = getOutFlag(CallArgs); - } else { - CallArgs = LowerIndirectCallArguments(Chain, OperFlag, DataAddr_Lo, - DataAddr_Hi, Outs, OutVals, Ins, - dl, 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, - OperFlag); - Chain = getChain(PICCall); - OperFlag = getOutFlag(PICCall); - - - // Carrying the Constant 0 along the CALLSEQSTART - // because there is nothing else to carry. - SDValue SeqEnd = DAG.getCALLSEQ_END(Chain, ZeroOperand, ZeroOperand, - OperFlag); - Chain = getChain(SeqEnd); - OperFlag = getOutFlag(SeqEnd); - - // Lower the return value reading after the call. - if (IsDirectCall) - return LowerDirectCallReturn(RetLabel, Chain, OperFlag, - Ins, dl, DAG, InVals); - else - return LowerIndirectCallReturn(Chain, OperFlag, DataAddr_Lo, - DataAddr_Hi, Ins, dl, DAG, InVals); -} - -bool PIC16TargetLowering::isDirectLoad(const SDValue Op) const { - if (Op.getOpcode() == PIC16ISD::PIC16Load) - if (Op.getOperand(1).getOpcode() == ISD::TargetGlobalAddress - || Op.getOperand(1).getOpcode() == ISD::TargetExternalSymbol) - return true; - return false; -} - -// NeedToConvertToMemOp - Returns true if one of the operands of the -// operation 'Op' needs to be put into memory. Also returns the -// operand no. of the operand to be converted in 'MemOp'. Remember, PIC16 has -// no instruction that can operation on two registers. Most insns take -// one register and one memory operand (addwf) / Constant (addlw). -bool PIC16TargetLowering::NeedToConvertToMemOp(SDValue Op, unsigned &MemOp, - SelectionDAG &DAG) const { - // If one of the operand is a constant, return false. - if (Op.getOperand(0).getOpcode() == ISD::Constant || - Op.getOperand(1).getOpcode() == ISD::Constant) - return false; - - // Return false if one of the operands is already a direct - // load and that operand has only one use. - if (isDirectLoad(Op.getOperand(0))) { - if (Op.getOperand(0).hasOneUse()) { - // Legal and profitable folding check uses the NodeId of DAG nodes. - // This NodeId is assigned by topological order. Therefore first - // assign topological order then perform legal and profitable check. - // Note:- Though this ordering is done before begining with legalization, - // newly added node during legalization process have NodeId=-1 (NewNode) - // therefore before performing any check proper ordering of the node is - // required. - DAG.AssignTopologicalOrder(); - - // Direct load operands are folded in binary operations. But before folding - // verify if this folding is legal. Fold only if it is legal otherwise - // convert this direct load to a separate memory operation. - if (SelectionDAGISel::IsLegalToFold(Op.getOperand(0), - Op.getNode(), Op.getNode(), - CodeGenOpt::Default)) - return false; - else - MemOp = 0; - } - } - - // For operations that are non-cummutative there is no need to check - // for right operand because folding right operand may result in - // incorrect operation. - if (! SelectionDAG::isCommutativeBinOp(Op.getOpcode())) - return true; - - if (isDirectLoad(Op.getOperand(1))) { - if (Op.getOperand(1).hasOneUse()) { - // Legal and profitable folding check uses the NodeId of DAG nodes. - // This NodeId is assigned by topological order. Therefore first - // assign topological order then perform legal and profitable check. - // Note:- Though this ordering is done before begining with legalization, - // newly added node during legalization process have NodeId=-1 (NewNode) - // therefore before performing any check proper ordering of the node is - // required. - DAG.AssignTopologicalOrder(); - - // Direct load operands are folded in binary operations. But before folding - // verify if this folding is legal. Fold only if it is legal otherwise - // convert this direct load to a separate memory operation. - if (SelectionDAGISel::IsLegalToFold(Op.getOperand(1), - Op.getNode(), Op.getNode(), - CodeGenOpt::Default)) - return false; - else - MemOp = 1; - } - } - return true; -} - -// LowerBinOp - Lower a commutative binary operation that does not -// affect status flag carry. -SDValue PIC16TargetLowering::LowerBinOp(SDValue Op, SelectionDAG &DAG) const { - DebugLoc dl = Op.getDebugLoc(); - - // We should have handled larger operands in type legalizer itself. - assert (Op.getValueType() == MVT::i8 && "illegal Op to lower"); - - unsigned MemOp = 1; - if (NeedToConvertToMemOp(Op, MemOp, DAG)) { - // Put one value on stack. - SDValue NewVal = ConvertToMemOperand (Op.getOperand(MemOp), DAG, dl); - - return DAG.getNode(Op.getOpcode(), dl, MVT::i8, Op.getOperand(MemOp ^ 1), - NewVal); - } - else { - return Op; - } -} - -// LowerADD - Lower all types of ADD operations including the ones -// that affects carry. -SDValue PIC16TargetLowering::LowerADD(SDValue Op, SelectionDAG &DAG) const { - // We should have handled larger operands in type legalizer itself. - assert (Op.getValueType() == MVT::i8 && "illegal add to lower"); - DebugLoc dl = Op.getDebugLoc(); - unsigned MemOp = 1; - if (NeedToConvertToMemOp(Op, MemOp, DAG)) { - // Put one value on stack. - SDValue NewVal = ConvertToMemOperand (Op.getOperand(MemOp), DAG, dl); - - // ADDC and ADDE produce two results. - SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Flag); - - // ADDE has three operands, the last one is the carry bit. - if (Op.getOpcode() == ISD::ADDE) - return DAG.getNode(Op.getOpcode(), dl, Tys, Op.getOperand(MemOp ^ 1), - NewVal, Op.getOperand(2)); - // ADDC has two operands. - else if (Op.getOpcode() == ISD::ADDC) - return DAG.getNode(Op.getOpcode(), dl, Tys, Op.getOperand(MemOp ^ 1), - NewVal); - // ADD it is. It produces only one result. - else - return DAG.getNode(Op.getOpcode(), dl, MVT::i8, Op.getOperand(MemOp ^ 1), - NewVal); - } - else - return Op; -} - -SDValue PIC16TargetLowering::LowerSUB(SDValue Op, SelectionDAG &DAG) const { - DebugLoc dl = Op.getDebugLoc(); - // We should have handled larger operands in type legalizer itself. - assert (Op.getValueType() == MVT::i8 && "illegal sub to lower"); - unsigned MemOp = 1; - SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Flag); - - // Since we don't have an instruction for X - c , - // we can change it to X + (-c) - ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1)); - if (C && (Op.getOpcode() == ISD::SUB)) - { - return DAG.getNode(ISD::ADD, - dl, MVT::i8, Op.getOperand(0), - DAG.getConstant(0-(C->getZExtValue()), MVT::i8)); - } - - if (NeedToConvertToMemOp(Op, MemOp, DAG) || - (isDirectLoad(Op.getOperand(1)) && - (!isDirectLoad(Op.getOperand(0))) && - (Op.getOperand(0).getOpcode() != ISD::Constant))) - { - // Put first operand on stack. - SDValue NewVal = ConvertToMemOperand (Op.getOperand(0), DAG, dl); - - switch (Op.getOpcode()) { - default: - assert (0 && "Opcode unknown."); - case ISD::SUBE: - return DAG.getNode(Op.getOpcode(), - dl, Tys, NewVal, Op.getOperand(1), - Op.getOperand(2)); - break; - case ISD::SUBC: - return DAG.getNode(Op.getOpcode(), - dl, Tys, NewVal, Op.getOperand(1)); - break; - case ISD::SUB: - return DAG.getNode(Op.getOpcode(), - dl, MVT::i8, NewVal, Op.getOperand(1)); - break; - } - } - else - return Op; -} - -void PIC16TargetLowering::InitReservedFrameCount(const Function *F, - SelectionDAG &DAG) const { - MachineFunction &MF = DAG.getMachineFunction(); - PIC16MachineFunctionInfo *FuncInfo = MF.getInfo<PIC16MachineFunctionInfo>(); - - unsigned NumArgs = F->arg_size(); - - bool isVoidFunc = (F->getReturnType()->getTypeID() == Type::VoidTyID); - - if (isVoidFunc) - FuncInfo->setReservedFrameCount(NumArgs); - else - FuncInfo->setReservedFrameCount(NumArgs + 1); -} - -// LowerFormalArguments - Argument values are loaded from the -// <fname>.args + offset. All arguments are already broken to leaglized -// types, so the offset just runs from 0 to NumArgVals - 1. - -SDValue -PIC16TargetLowering::LowerFormalArguments(SDValue Chain, - CallingConv::ID CallConv, - bool isVarArg, - const SmallVectorImpl<ISD::InputArg> &Ins, - DebugLoc dl, - SelectionDAG &DAG, - SmallVectorImpl<SDValue> &InVals) - const { - unsigned NumArgVals = Ins.size(); - - // Get the callee's name to create the <fname>.args label to pass args. - MachineFunction &MF = DAG.getMachineFunction(); - const Function *F = MF.getFunction(); - std::string FuncName = F->getName(); - - // Reset the map of FI and TmpOffset - ResetTmpOffsetMap(DAG); - // Initialize the ReserveFrameCount - InitReservedFrameCount(F, DAG); - - // Create the <fname>.args external symbol. - const char *tmpName = ESNames::createESName(PAN::getArgsLabel(FuncName)); - SDValue ES = DAG.getTargetExternalSymbol(tmpName, MVT::i8); - - // Load arg values from the label + offset. - SDVTList VTs = DAG.getVTList (MVT::i8, MVT::Other); - SDValue BS = DAG.getConstant(1, MVT::i8); - for (unsigned i = 0; i < NumArgVals ; ++i) { - SDValue Offset = DAG.getConstant(i, MVT::i8); - SDValue PICLoad = DAG.getNode(PIC16ISD::PIC16LdArg, dl, VTs, Chain, ES, BS, - Offset); - Chain = getChain(PICLoad); - InVals.push_back(PICLoad); - } - - return Chain; -} - -// Perform DAGCombine of PIC16Load. -// FIXME - Need a more elaborate comment here. -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(); -} - -// For all the functions with arguments some STORE nodes are generated -// that store the argument on the frameindex. However in PIC16 the arguments -// are passed on stack only. Therefore these STORE nodes are redundant. -// To remove these STORE nodes will be removed in PerformStoreCombine -// -// Currently this function is doint nothing and will be updated for removing -// unwanted store operations -SDValue PIC16TargetLowering:: -PerformStoreCombine(SDNode *N, DAGCombinerInfo &DCI) const { - return SDValue(N, 0); - /* - // Storing an undef value is of no use, so remove it - if (isStoringUndef(N, Chain, DAG)) { - return Chain; // remove the store and return the chain - } - //else everything is ok. - return SDValue(N, 0); - */ -} - -SDValue PIC16TargetLowering::PerformDAGCombine(SDNode *N, - DAGCombinerInfo &DCI) const { - switch (N->getOpcode()) { - case ISD::STORE: - return PerformStoreCombine(N, DCI); - case PIC16ISD::PIC16Load: - return PerformPIC16LoadCombine(N, DCI); - } - return SDValue(); -} - -static PIC16CC::CondCodes IntCCToPIC16CC(ISD::CondCode CC) { - switch (CC) { - default: llvm_unreachable("Unknown condition code!"); - case ISD::SETNE: return PIC16CC::NE; - case ISD::SETEQ: return PIC16CC::EQ; - case ISD::SETGT: return PIC16CC::GT; - case ISD::SETGE: return PIC16CC::GE; - case ISD::SETLT: return PIC16CC::LT; - case ISD::SETLE: return PIC16CC::LE; - case ISD::SETULT: return PIC16CC::ULT; - case ISD::SETULE: return PIC16CC::ULE; - case ISD::SETUGE: return PIC16CC::UGE; - case ISD::SETUGT: return PIC16CC::UGT; - } -} - -// Look at LHS/RHS/CC and see if they are a lowered setcc instruction. If so -// set LHS/RHS and SPCC to the LHS/RHS of the setcc and SPCC to the condition. -static void LookThroughSetCC(SDValue &LHS, SDValue &RHS, - ISD::CondCode CC, unsigned &SPCC) { - if (isa<ConstantSDNode>(RHS) && - cast<ConstantSDNode>(RHS)->isNullValue() && - CC == ISD::SETNE && - (LHS.getOpcode() == PIC16ISD::SELECT_ICC && - LHS.getOperand(3).getOpcode() == PIC16ISD::SUBCC) && - isa<ConstantSDNode>(LHS.getOperand(0)) && - isa<ConstantSDNode>(LHS.getOperand(1)) && - cast<ConstantSDNode>(LHS.getOperand(0))->isOne() && - cast<ConstantSDNode>(LHS.getOperand(1))->isNullValue()) { - SDValue CMPCC = LHS.getOperand(3); - SPCC = cast<ConstantSDNode>(LHS.getOperand(2))->getZExtValue(); - LHS = CMPCC.getOperand(0); - RHS = CMPCC.getOperand(1); - } -} - -// Returns appropriate CMP insn and corresponding condition code in PIC16CC -SDValue PIC16TargetLowering::getPIC16Cmp(SDValue LHS, SDValue RHS, - unsigned CC, SDValue &PIC16CC, - SelectionDAG &DAG, DebugLoc dl) const { - PIC16CC::CondCodes CondCode = (PIC16CC::CondCodes) CC; - - // PIC16 sub is literal - W. So Swap the operands and condition if needed. - // i.e. a < 12 can be rewritten as 12 > a. - if (RHS.getOpcode() == ISD::Constant) { - - SDValue Tmp = LHS; - LHS = RHS; - RHS = Tmp; - - switch (CondCode) { - default: break; - case PIC16CC::LT: - CondCode = PIC16CC::GT; - break; - case PIC16CC::GT: - CondCode = PIC16CC::LT; - break; - case PIC16CC::ULT: - CondCode = PIC16CC::UGT; - break; - case PIC16CC::UGT: - CondCode = PIC16CC::ULT; - break; - case PIC16CC::GE: - CondCode = PIC16CC::LE; - break; - case PIC16CC::LE: - CondCode = PIC16CC::GE; - break; - case PIC16CC::ULE: - CondCode = PIC16CC::UGE; - break; - case PIC16CC::UGE: - CondCode = PIC16CC::ULE; - break; - } - } - - PIC16CC = DAG.getConstant(CondCode, MVT::i8); - - // These are signed comparisons. - SDValue Mask = DAG.getConstant(128, MVT::i8); - if (isSignedComparison(CondCode)) { - LHS = DAG.getNode (ISD::XOR, dl, MVT::i8, LHS, Mask); - RHS = DAG.getNode (ISD::XOR, dl, MVT::i8, RHS, Mask); - } - - SDVTList VTs = DAG.getVTList (MVT::i8, MVT::Flag); - // We can use a subtract operation to set the condition codes. But - // we need to put one operand in memory if required. - // Nothing to do if the first operand is already a valid type (direct load - // for subwf and literal for sublw) and it is used by this operation only. - if ((LHS.getOpcode() == ISD::Constant || isDirectLoad(LHS)) - && LHS.hasOneUse()) - return DAG.getNode(PIC16ISD::SUBCC, dl, VTs, LHS, RHS); - - // else convert the first operand to mem. - LHS = ConvertToMemOperand (LHS, DAG, dl); - return DAG.getNode(PIC16ISD::SUBCC, dl, VTs, LHS, RHS); -} - - -SDValue PIC16TargetLowering::LowerSELECT_CC(SDValue Op, - SelectionDAG &DAG) const { - SDValue LHS = Op.getOperand(0); - SDValue RHS = Op.getOperand(1); - ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get(); - SDValue TrueVal = Op.getOperand(2); - SDValue FalseVal = Op.getOperand(3); - unsigned ORIGCC = ~0; - DebugLoc dl = Op.getDebugLoc(); - - // If this is a select_cc of a "setcc", and if the setcc got lowered into - // an CMP[IF]CC/SELECT_[IF]CC pair, find the original compared values. - // i.e. - // A setcc: lhs, rhs, cc is expanded by llvm to - // select_cc: result of setcc, 0, 1, 0, setne - // We can think of it as: - // select_cc: lhs, rhs, 1, 0, cc - LookThroughSetCC(LHS, RHS, CC, ORIGCC); - if (ORIGCC == ~0U) ORIGCC = IntCCToPIC16CC (CC); - - SDValue PIC16CC; - SDValue Cmp = getPIC16Cmp(LHS, RHS, ORIGCC, PIC16CC, DAG, dl); - - return DAG.getNode (PIC16ISD::SELECT_ICC, dl, TrueVal.getValueType(), TrueVal, - FalseVal, PIC16CC, Cmp.getValue(1)); -} - -MachineBasicBlock * -PIC16TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, - MachineBasicBlock *BB) const { - const TargetInstrInfo &TII = *getTargetMachine().getInstrInfo(); - unsigned CC = (PIC16CC::CondCodes)MI->getOperand(3).getImm(); - DebugLoc dl = MI->getDebugLoc(); - - // To "insert" a SELECT_CC instruction, we actually have to insert the diamond - // control-flow pattern. The incoming instruction knows the destination vreg - // to set, the condition code register to branch on, the true/false values to - // select between, and a branch opcode to use. - const BasicBlock *LLVM_BB = BB->getBasicBlock(); - MachineFunction::iterator It = BB; - ++It; - - // thisMBB: - // ... - // TrueVal = ... - // [f]bCC copy1MBB - // fallthrough --> copy0MBB - MachineBasicBlock *thisMBB = BB; - MachineFunction *F = BB->getParent(); - MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB); - MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB); - BuildMI(BB, dl, TII.get(PIC16::pic16brcond)).addMBB(sinkMBB).addImm(CC); - F->insert(It, copy0MBB); - F->insert(It, sinkMBB); - - // Transfer the remainder of BB and its successor edges to sinkMBB. - sinkMBB->splice(sinkMBB->begin(), BB, - llvm::next(MachineBasicBlock::iterator(MI)), - BB->end()); - sinkMBB->transferSuccessorsAndUpdatePHIs(BB); - - // Next, add the true and fallthrough blocks as its successors. - BB->addSuccessor(copy0MBB); - BB->addSuccessor(sinkMBB); - - // copy0MBB: - // %FalseValue = ... - // # fallthrough to sinkMBB - BB = copy0MBB; - - // Update machine-CFG edges - BB->addSuccessor(sinkMBB); - - // sinkMBB: - // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ] - // ... - BB = sinkMBB; - BuildMI(*BB, BB->begin(), dl, - TII.get(PIC16::PHI), MI->getOperand(0).getReg()) - .addReg(MI->getOperand(2).getReg()).addMBB(copy0MBB) - .addReg(MI->getOperand(1).getReg()).addMBB(thisMBB); - - MI->eraseFromParent(); // The pseudo instruction is gone now. - return BB; -} - - -SDValue PIC16TargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const { - SDValue Chain = Op.getOperand(0); - ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get(); - SDValue LHS = Op.getOperand(2); // LHS of the condition. - SDValue RHS = Op.getOperand(3); // RHS of the condition. - SDValue Dest = Op.getOperand(4); // BB to jump to - unsigned ORIGCC = ~0; - DebugLoc dl = Op.getDebugLoc(); - - // If this is a br_cc of a "setcc", and if the setcc got lowered into - // an CMP[IF]CC/SELECT_[IF]CC pair, find the original compared values. - LookThroughSetCC(LHS, RHS, CC, ORIGCC); - if (ORIGCC == ~0U) ORIGCC = IntCCToPIC16CC (CC); - - // Get the Compare insn and condition code. - SDValue PIC16CC; - SDValue Cmp = getPIC16Cmp(LHS, RHS, ORIGCC, PIC16CC, DAG, dl); - - return DAG.getNode(PIC16ISD::BRCOND, dl, MVT::Other, Chain, Dest, PIC16CC, - Cmp.getValue(1)); -} - |