|  | // | 
|  | //                     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(); | 
|  | } | 
|  |  | 
|  | // 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(), 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<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 = Outs[i].Val; | 
|  |  | 
|  | 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, | 
|  | 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 = Outs[i].Val; | 
|  | 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, | 
|  | 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 = Outs[i].Val; | 
|  | 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<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, 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, dl, DAG); | 
|  | Chain = getChain(CallArgs); | 
|  | OperFlag = getOutFlag(CallArgs); | 
|  | } else { | 
|  | CallArgs = LowerIndirectCallArguments(Chain, OperFlag, DataAddr_Lo, | 
|  | DataAddr_Hi, Outs, 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)->getZExtValue() == 0 && | 
|  | 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))->getZExtValue() == 1 && | 
|  | cast<ConstantSDNode>(LHS.getOperand(1))->getZExtValue() == 0) { | 
|  | 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); | 
|  |  | 
|  | // Update machine-CFG edges by first adding all successors of the current | 
|  | // block to the new block which will contain the Phi node for the select. | 
|  | for (MachineBasicBlock::succ_iterator I = BB->succ_begin(), | 
|  | E = BB->succ_end(); I != E; ++I) | 
|  | sinkMBB->addSuccessor(*I); | 
|  | // Next, remove all successors of the current block, and add the true | 
|  | // and fallthrough blocks as its successors. | 
|  | while (!BB->succ_empty()) | 
|  | BB->removeSuccessor(BB->succ_begin()); | 
|  | // 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, dl, TII.get(PIC16::PHI), MI->getOperand(0).getReg()) | 
|  | .addReg(MI->getOperand(2).getReg()).addMBB(copy0MBB) | 
|  | .addReg(MI->getOperand(1).getReg()).addMBB(thisMBB); | 
|  |  | 
|  | F->DeleteMachineInstr(MI);   // 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)); | 
|  | } | 
|  |  |