MSP430ISelLowering.cpp revision 226633
1193323Sed//===-- MSP430ISelLowering.cpp - MSP430 DAG Lowering Implementation ------===// 2193323Sed// 3193323Sed// The LLVM Compiler Infrastructure 4193323Sed// 5193323Sed// This file is distributed under the University of Illinois Open Source 6193323Sed// License. See LICENSE.TXT for details. 7193323Sed// 8193323Sed//===----------------------------------------------------------------------===// 9193323Sed// 10193323Sed// This file implements the MSP430TargetLowering class. 11193323Sed// 12193323Sed//===----------------------------------------------------------------------===// 13193323Sed 14193323Sed#define DEBUG_TYPE "msp430-lower" 15193323Sed 16193323Sed#include "MSP430ISelLowering.h" 17193323Sed#include "MSP430.h" 18200581Srdivacky#include "MSP430MachineFunctionInfo.h" 19193323Sed#include "MSP430TargetMachine.h" 20193323Sed#include "MSP430Subtarget.h" 21193323Sed#include "llvm/DerivedTypes.h" 22193323Sed#include "llvm/Function.h" 23193323Sed#include "llvm/Intrinsics.h" 24193323Sed#include "llvm/CallingConv.h" 25193323Sed#include "llvm/GlobalVariable.h" 26193323Sed#include "llvm/GlobalAlias.h" 27193323Sed#include "llvm/CodeGen/CallingConvLower.h" 28193323Sed#include "llvm/CodeGen/MachineFrameInfo.h" 29193323Sed#include "llvm/CodeGen/MachineFunction.h" 30193323Sed#include "llvm/CodeGen/MachineInstrBuilder.h" 31193323Sed#include "llvm/CodeGen/MachineRegisterInfo.h" 32193323Sed#include "llvm/CodeGen/PseudoSourceValue.h" 33193323Sed#include "llvm/CodeGen/SelectionDAGISel.h" 34203954Srdivacky#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" 35193323Sed#include "llvm/CodeGen/ValueTypes.h" 36200581Srdivacky#include "llvm/Support/CommandLine.h" 37193323Sed#include "llvm/Support/Debug.h" 38198090Srdivacky#include "llvm/Support/ErrorHandling.h" 39198090Srdivacky#include "llvm/Support/raw_ostream.h" 40193323Sed#include "llvm/ADT/VectorExtras.h" 41193323Sedusing namespace llvm; 42193323Sed 43200581Srdivackytypedef enum { 44200581Srdivacky NoHWMult, 45200581Srdivacky HWMultIntr, 46200581Srdivacky HWMultNoIntr 47200581Srdivacky} HWMultUseMode; 48200581Srdivacky 49200581Srdivackystatic cl::opt<HWMultUseMode> 50200581SrdivackyHWMultMode("msp430-hwmult-mode", 51200581Srdivacky cl::desc("Hardware multiplier use mode"), 52200581Srdivacky cl::init(HWMultNoIntr), 53200581Srdivacky cl::values( 54200581Srdivacky clEnumValN(NoHWMult, "no", 55200581Srdivacky "Do not use hardware multiplier"), 56200581Srdivacky clEnumValN(HWMultIntr, "interrupts", 57200581Srdivacky "Assume hardware multiplier can be used inside interrupts"), 58200581Srdivacky clEnumValN(HWMultNoIntr, "use", 59200581Srdivacky "Assume hardware multiplier cannot be used inside interrupts"), 60200581Srdivacky clEnumValEnd)); 61200581Srdivacky 62193323SedMSP430TargetLowering::MSP430TargetLowering(MSP430TargetMachine &tm) : 63198090Srdivacky TargetLowering(tm, new TargetLoweringObjectFileELF()), 64198090Srdivacky Subtarget(*tm.getSubtargetImpl()), TM(tm) { 65193323Sed 66200581Srdivacky TD = getTargetData(); 67200581Srdivacky 68193323Sed // Set up the register classes. 69193323Sed addRegisterClass(MVT::i8, MSP430::GR8RegisterClass); 70193323Sed addRegisterClass(MVT::i16, MSP430::GR16RegisterClass); 71193323Sed 72193323Sed // Compute derived properties from the register classes 73193323Sed computeRegisterProperties(); 74193323Sed 75193323Sed // Provide all sorts of operation actions 76193323Sed 77193323Sed // Division is expensive 78193323Sed setIntDivIsCheap(false); 79193323Sed 80193323Sed setStackPointerRegisterToSaveRestore(MSP430::SPW); 81193323Sed setBooleanContents(ZeroOrOneBooleanContent); 82226633Sdim setBooleanVectorContents(ZeroOrOneBooleanContent); // FIXME: Is this correct? 83208599Srdivacky setSchedulingPreference(Sched::Latency); 84193323Sed 85199481Srdivacky // We have post-incremented loads / stores. 86199481Srdivacky setIndexedLoadAction(ISD::POST_INC, MVT::i8, Legal); 87199481Srdivacky setIndexedLoadAction(ISD::POST_INC, MVT::i16, Legal); 88199481Srdivacky 89199481Srdivacky setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote); 90199481Srdivacky setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote); 91199481Srdivacky setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote); 92199481Srdivacky setLoadExtAction(ISD::SEXTLOAD, MVT::i8, Expand); 93193323Sed setLoadExtAction(ISD::SEXTLOAD, MVT::i16, Expand); 94193323Sed 95193323Sed // We don't have any truncstores 96193323Sed setTruncStoreAction(MVT::i16, MVT::i8, Expand); 97193323Sed 98193323Sed setOperationAction(ISD::SRA, MVT::i8, Custom); 99193323Sed setOperationAction(ISD::SHL, MVT::i8, Custom); 100193323Sed setOperationAction(ISD::SRL, MVT::i8, Custom); 101193323Sed setOperationAction(ISD::SRA, MVT::i16, Custom); 102193323Sed setOperationAction(ISD::SHL, MVT::i16, Custom); 103193323Sed setOperationAction(ISD::SRL, MVT::i16, Custom); 104193323Sed setOperationAction(ISD::ROTL, MVT::i8, Expand); 105193323Sed setOperationAction(ISD::ROTR, MVT::i8, Expand); 106193323Sed setOperationAction(ISD::ROTL, MVT::i16, Expand); 107193323Sed setOperationAction(ISD::ROTR, MVT::i16, Expand); 108193323Sed setOperationAction(ISD::GlobalAddress, MVT::i16, Custom); 109193323Sed setOperationAction(ISD::ExternalSymbol, MVT::i16, Custom); 110207618Srdivacky setOperationAction(ISD::BlockAddress, MVT::i16, Custom); 111193323Sed setOperationAction(ISD::BR_JT, MVT::Other, Expand); 112193323Sed setOperationAction(ISD::BR_CC, MVT::i8, Custom); 113193323Sed setOperationAction(ISD::BR_CC, MVT::i16, Custom); 114193323Sed setOperationAction(ISD::BRCOND, MVT::Other, Expand); 115200581Srdivacky setOperationAction(ISD::SETCC, MVT::i8, Custom); 116200581Srdivacky setOperationAction(ISD::SETCC, MVT::i16, Custom); 117193323Sed setOperationAction(ISD::SELECT, MVT::i8, Expand); 118193323Sed setOperationAction(ISD::SELECT, MVT::i16, Expand); 119193323Sed setOperationAction(ISD::SELECT_CC, MVT::i8, Custom); 120193323Sed setOperationAction(ISD::SELECT_CC, MVT::i16, Custom); 121193323Sed setOperationAction(ISD::SIGN_EXTEND, MVT::i16, Custom); 122198090Srdivacky setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i8, Expand); 123198090Srdivacky setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i16, Expand); 124193323Sed 125198090Srdivacky setOperationAction(ISD::CTTZ, MVT::i8, Expand); 126198090Srdivacky setOperationAction(ISD::CTTZ, MVT::i16, Expand); 127198090Srdivacky setOperationAction(ISD::CTLZ, MVT::i8, Expand); 128198090Srdivacky setOperationAction(ISD::CTLZ, MVT::i16, Expand); 129198090Srdivacky setOperationAction(ISD::CTPOP, MVT::i8, Expand); 130198090Srdivacky setOperationAction(ISD::CTPOP, MVT::i16, Expand); 131198090Srdivacky 132198090Srdivacky setOperationAction(ISD::SHL_PARTS, MVT::i8, Expand); 133198090Srdivacky setOperationAction(ISD::SHL_PARTS, MVT::i16, Expand); 134198090Srdivacky setOperationAction(ISD::SRL_PARTS, MVT::i8, Expand); 135198090Srdivacky setOperationAction(ISD::SRL_PARTS, MVT::i16, Expand); 136198090Srdivacky setOperationAction(ISD::SRA_PARTS, MVT::i8, Expand); 137198090Srdivacky setOperationAction(ISD::SRA_PARTS, MVT::i16, Expand); 138198090Srdivacky 139198090Srdivacky setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); 140198090Srdivacky 141193323Sed // FIXME: Implement efficiently multiplication by a constant 142199481Srdivacky setOperationAction(ISD::MUL, MVT::i8, Expand); 143199481Srdivacky setOperationAction(ISD::MULHS, MVT::i8, Expand); 144199481Srdivacky setOperationAction(ISD::MULHU, MVT::i8, Expand); 145199481Srdivacky setOperationAction(ISD::SMUL_LOHI, MVT::i8, Expand); 146199481Srdivacky setOperationAction(ISD::UMUL_LOHI, MVT::i8, Expand); 147193323Sed setOperationAction(ISD::MUL, MVT::i16, Expand); 148193323Sed setOperationAction(ISD::MULHS, MVT::i16, Expand); 149193323Sed setOperationAction(ISD::MULHU, MVT::i16, Expand); 150193323Sed setOperationAction(ISD::SMUL_LOHI, MVT::i16, Expand); 151193323Sed setOperationAction(ISD::UMUL_LOHI, MVT::i16, Expand); 152193323Sed 153199481Srdivacky setOperationAction(ISD::UDIV, MVT::i8, Expand); 154199481Srdivacky setOperationAction(ISD::UDIVREM, MVT::i8, Expand); 155199481Srdivacky setOperationAction(ISD::UREM, MVT::i8, Expand); 156199481Srdivacky setOperationAction(ISD::SDIV, MVT::i8, Expand); 157199481Srdivacky setOperationAction(ISD::SDIVREM, MVT::i8, Expand); 158199481Srdivacky setOperationAction(ISD::SREM, MVT::i8, Expand); 159193323Sed setOperationAction(ISD::UDIV, MVT::i16, Expand); 160193323Sed setOperationAction(ISD::UDIVREM, MVT::i16, Expand); 161193323Sed setOperationAction(ISD::UREM, MVT::i16, Expand); 162193323Sed setOperationAction(ISD::SDIV, MVT::i16, Expand); 163193323Sed setOperationAction(ISD::SDIVREM, MVT::i16, Expand); 164193323Sed setOperationAction(ISD::SREM, MVT::i16, Expand); 165200581Srdivacky 166200581Srdivacky // Libcalls names. 167200581Srdivacky if (HWMultMode == HWMultIntr) { 168200581Srdivacky setLibcallName(RTLIB::MUL_I8, "__mulqi3hw"); 169200581Srdivacky setLibcallName(RTLIB::MUL_I16, "__mulhi3hw"); 170200581Srdivacky } else if (HWMultMode == HWMultNoIntr) { 171200581Srdivacky setLibcallName(RTLIB::MUL_I8, "__mulqi3hw_noint"); 172200581Srdivacky setLibcallName(RTLIB::MUL_I16, "__mulhi3hw_noint"); 173200581Srdivacky } 174223017Sdim 175223017Sdim setMinFunctionAlignment(1); 176223017Sdim setPrefFunctionAlignment(2); 177193323Sed} 178193323Sed 179207618SrdivackySDValue MSP430TargetLowering::LowerOperation(SDValue Op, 180207618Srdivacky SelectionDAG &DAG) const { 181193323Sed switch (Op.getOpcode()) { 182193323Sed case ISD::SHL: // FALLTHROUGH 183193323Sed case ISD::SRL: 184193323Sed case ISD::SRA: return LowerShifts(Op, DAG); 185193323Sed case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG); 186207618Srdivacky case ISD::BlockAddress: return LowerBlockAddress(Op, DAG); 187193323Sed case ISD::ExternalSymbol: return LowerExternalSymbol(Op, DAG); 188200581Srdivacky case ISD::SETCC: return LowerSETCC(Op, DAG); 189193323Sed case ISD::BR_CC: return LowerBR_CC(Op, DAG); 190193323Sed case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG); 191193323Sed case ISD::SIGN_EXTEND: return LowerSIGN_EXTEND(Op, DAG); 192200581Srdivacky case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG); 193200581Srdivacky case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG); 194193323Sed default: 195198090Srdivacky llvm_unreachable("unimplemented operand"); 196193323Sed return SDValue(); 197193323Sed } 198193323Sed} 199193323Sed 200193323Sed//===----------------------------------------------------------------------===// 201198090Srdivacky// MSP430 Inline Assembly Support 202198090Srdivacky//===----------------------------------------------------------------------===// 203198090Srdivacky 204198090Srdivacky/// getConstraintType - Given a constraint letter, return the type of 205198090Srdivacky/// constraint it is for this target. 206198090SrdivackyTargetLowering::ConstraintType 207198090SrdivackyMSP430TargetLowering::getConstraintType(const std::string &Constraint) const { 208198090Srdivacky if (Constraint.size() == 1) { 209198090Srdivacky switch (Constraint[0]) { 210198090Srdivacky case 'r': 211198090Srdivacky return C_RegisterClass; 212198090Srdivacky default: 213198090Srdivacky break; 214198090Srdivacky } 215198090Srdivacky } 216198090Srdivacky return TargetLowering::getConstraintType(Constraint); 217198090Srdivacky} 218198090Srdivacky 219198090Srdivackystd::pair<unsigned, const TargetRegisterClass*> 220198090SrdivackyMSP430TargetLowering:: 221198090SrdivackygetRegForInlineAsmConstraint(const std::string &Constraint, 222198090Srdivacky EVT VT) const { 223198090Srdivacky if (Constraint.size() == 1) { 224198090Srdivacky // GCC Constraint Letters 225198090Srdivacky switch (Constraint[0]) { 226198090Srdivacky default: break; 227198090Srdivacky case 'r': // GENERAL_REGS 228198090Srdivacky if (VT == MVT::i8) 229198090Srdivacky return std::make_pair(0U, MSP430::GR8RegisterClass); 230198090Srdivacky 231198090Srdivacky return std::make_pair(0U, MSP430::GR16RegisterClass); 232198090Srdivacky } 233198090Srdivacky } 234198090Srdivacky 235198090Srdivacky return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT); 236198090Srdivacky} 237198090Srdivacky 238198090Srdivacky//===----------------------------------------------------------------------===// 239193323Sed// Calling Convention Implementation 240193323Sed//===----------------------------------------------------------------------===// 241193323Sed 242193323Sed#include "MSP430GenCallingConv.inc" 243193323Sed 244198090SrdivackySDValue 245198090SrdivackyMSP430TargetLowering::LowerFormalArguments(SDValue Chain, 246198090Srdivacky CallingConv::ID CallConv, 247198090Srdivacky bool isVarArg, 248198090Srdivacky const SmallVectorImpl<ISD::InputArg> 249198090Srdivacky &Ins, 250198090Srdivacky DebugLoc dl, 251198090Srdivacky SelectionDAG &DAG, 252207618Srdivacky SmallVectorImpl<SDValue> &InVals) 253207618Srdivacky const { 254198090Srdivacky 255198090Srdivacky switch (CallConv) { 256193323Sed default: 257198090Srdivacky llvm_unreachable("Unsupported calling convention"); 258193323Sed case CallingConv::C: 259193323Sed case CallingConv::Fast: 260198090Srdivacky return LowerCCCArguments(Chain, CallConv, isVarArg, Ins, dl, DAG, InVals); 261200581Srdivacky case CallingConv::MSP430_INTR: 262200581Srdivacky if (Ins.empty()) 263200581Srdivacky return Chain; 264200581Srdivacky else { 265207618Srdivacky report_fatal_error("ISRs cannot have arguments"); 266200581Srdivacky return SDValue(); 267200581Srdivacky } 268193323Sed } 269193323Sed} 270193323Sed 271198090SrdivackySDValue 272198090SrdivackyMSP430TargetLowering::LowerCall(SDValue Chain, SDValue Callee, 273198090Srdivacky CallingConv::ID CallConv, bool isVarArg, 274203954Srdivacky bool &isTailCall, 275198090Srdivacky const SmallVectorImpl<ISD::OutputArg> &Outs, 276210299Sed const SmallVectorImpl<SDValue> &OutVals, 277198090Srdivacky const SmallVectorImpl<ISD::InputArg> &Ins, 278198090Srdivacky DebugLoc dl, SelectionDAG &DAG, 279207618Srdivacky SmallVectorImpl<SDValue> &InVals) const { 280203954Srdivacky // MSP430 target does not yet support tail call optimization. 281203954Srdivacky isTailCall = false; 282198090Srdivacky 283198090Srdivacky switch (CallConv) { 284193323Sed default: 285198090Srdivacky llvm_unreachable("Unsupported calling convention"); 286193323Sed case CallingConv::Fast: 287193323Sed case CallingConv::C: 288198090Srdivacky return LowerCCCCallTo(Chain, Callee, CallConv, isVarArg, isTailCall, 289210299Sed Outs, OutVals, Ins, dl, DAG, InVals); 290200581Srdivacky case CallingConv::MSP430_INTR: 291207618Srdivacky report_fatal_error("ISRs cannot be called directly"); 292200581Srdivacky return SDValue(); 293193323Sed } 294193323Sed} 295193323Sed 296193323Sed/// LowerCCCArguments - transform physical registers into virtual registers and 297193323Sed/// generate load operations for arguments places on the stack. 298193323Sed// FIXME: struct return stuff 299193323Sed// FIXME: varargs 300198090SrdivackySDValue 301198090SrdivackyMSP430TargetLowering::LowerCCCArguments(SDValue Chain, 302198090Srdivacky CallingConv::ID CallConv, 303198090Srdivacky bool isVarArg, 304198090Srdivacky const SmallVectorImpl<ISD::InputArg> 305198090Srdivacky &Ins, 306198090Srdivacky DebugLoc dl, 307198090Srdivacky SelectionDAG &DAG, 308207618Srdivacky SmallVectorImpl<SDValue> &InVals) 309207618Srdivacky const { 310193323Sed MachineFunction &MF = DAG.getMachineFunction(); 311193323Sed MachineFrameInfo *MFI = MF.getFrameInfo(); 312193323Sed MachineRegisterInfo &RegInfo = MF.getRegInfo(); 313193323Sed 314193323Sed // Assign locations to all of the incoming arguments. 315193323Sed SmallVector<CCValAssign, 16> ArgLocs; 316223017Sdim CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), 317223017Sdim getTargetMachine(), ArgLocs, *DAG.getContext()); 318198090Srdivacky CCInfo.AnalyzeFormalArguments(Ins, CC_MSP430); 319193323Sed 320193323Sed assert(!isVarArg && "Varargs not supported yet"); 321193323Sed 322193323Sed for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { 323193323Sed CCValAssign &VA = ArgLocs[i]; 324193323Sed if (VA.isRegLoc()) { 325193323Sed // Arguments passed in registers 326198090Srdivacky EVT RegVT = VA.getLocVT(); 327198090Srdivacky switch (RegVT.getSimpleVT().SimpleTy) { 328219077Sdim default: 329198090Srdivacky { 330198090Srdivacky#ifndef NDEBUG 331198090Srdivacky errs() << "LowerFormalArguments Unhandled argument type: " 332198090Srdivacky << RegVT.getSimpleVT().SimpleTy << "\n"; 333198090Srdivacky#endif 334198090Srdivacky llvm_unreachable(0); 335198090Srdivacky } 336193323Sed case MVT::i16: 337193323Sed unsigned VReg = 338193323Sed RegInfo.createVirtualRegister(MSP430::GR16RegisterClass); 339193323Sed RegInfo.addLiveIn(VA.getLocReg(), VReg); 340198090Srdivacky SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, VReg, RegVT); 341193323Sed 342193323Sed // If this is an 8-bit value, it is really passed promoted to 16 343193323Sed // bits. Insert an assert[sz]ext to capture this, then truncate to the 344193323Sed // right size. 345193323Sed if (VA.getLocInfo() == CCValAssign::SExt) 346193323Sed ArgValue = DAG.getNode(ISD::AssertSext, dl, RegVT, ArgValue, 347193323Sed DAG.getValueType(VA.getValVT())); 348193323Sed else if (VA.getLocInfo() == CCValAssign::ZExt) 349193323Sed ArgValue = DAG.getNode(ISD::AssertZext, dl, RegVT, ArgValue, 350193323Sed DAG.getValueType(VA.getValVT())); 351193323Sed 352193323Sed if (VA.getLocInfo() != CCValAssign::Full) 353193323Sed ArgValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), ArgValue); 354193323Sed 355198090Srdivacky InVals.push_back(ArgValue); 356193323Sed } 357193323Sed } else { 358193323Sed // Sanity check 359193323Sed assert(VA.isMemLoc()); 360193323Sed // Load the argument to a virtual register 361193323Sed unsigned ObjSize = VA.getLocVT().getSizeInBits()/8; 362193323Sed if (ObjSize > 2) { 363198090Srdivacky errs() << "LowerFormalArguments Unhandled argument type: " 364218893Sdim << EVT(VA.getLocVT()).getEVTString() 365193323Sed << "\n"; 366193323Sed } 367193323Sed // Create the frame index object for this incoming parameter... 368210299Sed int FI = MFI->CreateFixedObject(ObjSize, VA.getLocMemOffset(), true); 369193323Sed 370193323Sed // Create the SelectionDAG nodes corresponding to a load 371193323Sed //from this parameter 372193323Sed SDValue FIN = DAG.getFrameIndex(FI, MVT::i16); 373198090Srdivacky InVals.push_back(DAG.getLoad(VA.getLocVT(), dl, Chain, FIN, 374218893Sdim MachinePointerInfo::getFixedStack(FI), 375203954Srdivacky false, false, 0)); 376193323Sed } 377193323Sed } 378193323Sed 379198090Srdivacky return Chain; 380193323Sed} 381193323Sed 382198090SrdivackySDValue 383198090SrdivackyMSP430TargetLowering::LowerReturn(SDValue Chain, 384198090Srdivacky CallingConv::ID CallConv, bool isVarArg, 385198090Srdivacky const SmallVectorImpl<ISD::OutputArg> &Outs, 386210299Sed const SmallVectorImpl<SDValue> &OutVals, 387207618Srdivacky DebugLoc dl, SelectionDAG &DAG) const { 388198090Srdivacky 389193323Sed // CCValAssign - represent the assignment of the return value to a location 390193323Sed SmallVector<CCValAssign, 16> RVLocs; 391193323Sed 392200581Srdivacky // ISRs cannot return any value. 393200581Srdivacky if (CallConv == CallingConv::MSP430_INTR && !Outs.empty()) { 394207618Srdivacky report_fatal_error("ISRs cannot return any value"); 395200581Srdivacky return SDValue(); 396200581Srdivacky } 397200581Srdivacky 398193323Sed // CCState - Info about the registers and stack slot. 399223017Sdim CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), 400223017Sdim getTargetMachine(), RVLocs, *DAG.getContext()); 401193323Sed 402198090Srdivacky // Analize return values. 403198090Srdivacky CCInfo.AnalyzeReturn(Outs, RetCC_MSP430); 404193323Sed 405193323Sed // If this is the first return lowered for this function, add the regs to the 406193323Sed // liveout set for the function. 407193323Sed if (DAG.getMachineFunction().getRegInfo().liveout_empty()) { 408193323Sed for (unsigned i = 0; i != RVLocs.size(); ++i) 409193323Sed if (RVLocs[i].isRegLoc()) 410193323Sed DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg()); 411193323Sed } 412193323Sed 413193323Sed SDValue Flag; 414193323Sed 415193323Sed // Copy the result values into the output registers. 416193323Sed for (unsigned i = 0; i != RVLocs.size(); ++i) { 417193323Sed CCValAssign &VA = RVLocs[i]; 418193323Sed assert(VA.isRegLoc() && "Can only return in registers!"); 419193323Sed 420193323Sed Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), 421210299Sed OutVals[i], Flag); 422193323Sed 423193323Sed // Guarantee that all emitted copies are stuck together, 424193323Sed // avoiding something bad. 425193323Sed Flag = Chain.getValue(1); 426193323Sed } 427193323Sed 428200581Srdivacky unsigned Opc = (CallConv == CallingConv::MSP430_INTR ? 429200581Srdivacky MSP430ISD::RETI_FLAG : MSP430ISD::RET_FLAG); 430200581Srdivacky 431193323Sed if (Flag.getNode()) 432200581Srdivacky return DAG.getNode(Opc, dl, MVT::Other, Chain, Flag); 433193323Sed 434193323Sed // Return Void 435200581Srdivacky return DAG.getNode(Opc, dl, MVT::Other, Chain); 436193323Sed} 437193323Sed 438193323Sed/// LowerCCCCallTo - functions arguments are copied from virtual regs to 439193323Sed/// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted. 440193323Sed/// TODO: sret. 441198090SrdivackySDValue 442198090SrdivackyMSP430TargetLowering::LowerCCCCallTo(SDValue Chain, SDValue Callee, 443198090Srdivacky CallingConv::ID CallConv, bool isVarArg, 444198090Srdivacky bool isTailCall, 445198090Srdivacky const SmallVectorImpl<ISD::OutputArg> 446198090Srdivacky &Outs, 447210299Sed const SmallVectorImpl<SDValue> &OutVals, 448198090Srdivacky const SmallVectorImpl<ISD::InputArg> &Ins, 449198090Srdivacky DebugLoc dl, SelectionDAG &DAG, 450207618Srdivacky SmallVectorImpl<SDValue> &InVals) const { 451193323Sed // Analyze operands of the call, assigning locations to each operand. 452193323Sed SmallVector<CCValAssign, 16> ArgLocs; 453223017Sdim CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), 454223017Sdim getTargetMachine(), ArgLocs, *DAG.getContext()); 455193323Sed 456198090Srdivacky CCInfo.AnalyzeCallOperands(Outs, CC_MSP430); 457193323Sed 458193323Sed // Get a count of how many bytes are to be pushed on the stack. 459193323Sed unsigned NumBytes = CCInfo.getNextStackOffset(); 460193323Sed 461193323Sed Chain = DAG.getCALLSEQ_START(Chain ,DAG.getConstant(NumBytes, 462193323Sed getPointerTy(), true)); 463193323Sed 464193323Sed SmallVector<std::pair<unsigned, SDValue>, 4> RegsToPass; 465193323Sed SmallVector<SDValue, 12> MemOpChains; 466193323Sed SDValue StackPtr; 467193323Sed 468193323Sed // Walk the register/memloc assignments, inserting copies/loads. 469193323Sed for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { 470193323Sed CCValAssign &VA = ArgLocs[i]; 471193323Sed 472210299Sed SDValue Arg = OutVals[i]; 473193323Sed 474193323Sed // Promote the value if needed. 475193323Sed switch (VA.getLocInfo()) { 476198090Srdivacky default: llvm_unreachable("Unknown loc info!"); 477193323Sed case CCValAssign::Full: break; 478193323Sed case CCValAssign::SExt: 479193323Sed Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg); 480193323Sed break; 481193323Sed case CCValAssign::ZExt: 482193323Sed Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg); 483193323Sed break; 484193323Sed case CCValAssign::AExt: 485193323Sed Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg); 486193323Sed break; 487193323Sed } 488193323Sed 489193323Sed // Arguments that can be passed on register must be kept at RegsToPass 490193323Sed // vector 491193323Sed if (VA.isRegLoc()) { 492193323Sed RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); 493193323Sed } else { 494193323Sed assert(VA.isMemLoc()); 495193323Sed 496193323Sed if (StackPtr.getNode() == 0) 497193323Sed StackPtr = DAG.getCopyFromReg(Chain, dl, MSP430::SPW, getPointerTy()); 498193323Sed 499193323Sed SDValue PtrOff = DAG.getNode(ISD::ADD, dl, getPointerTy(), 500193323Sed StackPtr, 501193323Sed DAG.getIntPtrConstant(VA.getLocMemOffset())); 502193323Sed 503193323Sed 504193323Sed MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, 505218893Sdim MachinePointerInfo(),false, false, 0)); 506193323Sed } 507193323Sed } 508193323Sed 509193323Sed // Transform all store nodes into one single node because all store nodes are 510193323Sed // independent of each other. 511193323Sed if (!MemOpChains.empty()) 512193323Sed Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, 513193323Sed &MemOpChains[0], MemOpChains.size()); 514193323Sed 515193323Sed // Build a sequence of copy-to-reg nodes chained together with token chain and 516193323Sed // flag operands which copy the outgoing args into registers. The InFlag in 517221345Sdim // necessary since all emitted instructions must be stuck together. 518193323Sed SDValue InFlag; 519193323Sed for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { 520193323Sed Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first, 521193323Sed RegsToPass[i].second, InFlag); 522193323Sed InFlag = Chain.getValue(1); 523193323Sed } 524193323Sed 525193323Sed // If the callee is a GlobalAddress node (quite common, every direct call is) 526193323Sed // turn it into a TargetGlobalAddress node so that legalize doesn't hack it. 527193323Sed // Likewise ExternalSymbol -> TargetExternalSymbol. 528193323Sed if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) 529210299Sed Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i16); 530193323Sed else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee)) 531193323Sed Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i16); 532193323Sed 533193323Sed // Returns a chain & a flag for retval copy to use. 534218893Sdim SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); 535193323Sed SmallVector<SDValue, 8> Ops; 536193323Sed Ops.push_back(Chain); 537193323Sed Ops.push_back(Callee); 538193323Sed 539193323Sed // Add argument registers to the end of the list so that they are 540193323Sed // known live into the call. 541193323Sed for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) 542193323Sed Ops.push_back(DAG.getRegister(RegsToPass[i].first, 543193323Sed RegsToPass[i].second.getValueType())); 544193323Sed 545193323Sed if (InFlag.getNode()) 546193323Sed Ops.push_back(InFlag); 547193323Sed 548193323Sed Chain = DAG.getNode(MSP430ISD::CALL, dl, NodeTys, &Ops[0], Ops.size()); 549193323Sed InFlag = Chain.getValue(1); 550193323Sed 551193323Sed // Create the CALLSEQ_END node. 552193323Sed Chain = DAG.getCALLSEQ_END(Chain, 553193323Sed DAG.getConstant(NumBytes, getPointerTy(), true), 554193323Sed DAG.getConstant(0, getPointerTy(), true), 555193323Sed InFlag); 556193323Sed InFlag = Chain.getValue(1); 557193323Sed 558193323Sed // Handle result values, copying them out of physregs into vregs that we 559193323Sed // return. 560198090Srdivacky return LowerCallResult(Chain, InFlag, CallConv, isVarArg, Ins, dl, 561198090Srdivacky DAG, InVals); 562193323Sed} 563193323Sed 564198090Srdivacky/// LowerCallResult - Lower the result values of a call into the 565198090Srdivacky/// appropriate copies out of appropriate physical registers. 566198090Srdivacky/// 567198090SrdivackySDValue 568193323SedMSP430TargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag, 569198090Srdivacky CallingConv::ID CallConv, bool isVarArg, 570198090Srdivacky const SmallVectorImpl<ISD::InputArg> &Ins, 571198090Srdivacky DebugLoc dl, SelectionDAG &DAG, 572207618Srdivacky SmallVectorImpl<SDValue> &InVals) const { 573193323Sed 574193323Sed // Assign locations to each value returned by this call. 575193323Sed SmallVector<CCValAssign, 16> RVLocs; 576223017Sdim CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), 577223017Sdim getTargetMachine(), RVLocs, *DAG.getContext()); 578193323Sed 579198090Srdivacky CCInfo.AnalyzeCallResult(Ins, RetCC_MSP430); 580193323Sed 581193323Sed // Copy all of the result registers out of their specified physreg. 582193323Sed for (unsigned i = 0; i != RVLocs.size(); ++i) { 583193323Sed Chain = DAG.getCopyFromReg(Chain, dl, RVLocs[i].getLocReg(), 584193323Sed RVLocs[i].getValVT(), InFlag).getValue(1); 585193323Sed InFlag = Chain.getValue(2); 586198090Srdivacky InVals.push_back(Chain.getValue(0)); 587193323Sed } 588193323Sed 589198090Srdivacky return Chain; 590193323Sed} 591193323Sed 592193323SedSDValue MSP430TargetLowering::LowerShifts(SDValue Op, 593207618Srdivacky SelectionDAG &DAG) const { 594193323Sed unsigned Opc = Op.getOpcode(); 595193323Sed SDNode* N = Op.getNode(); 596198090Srdivacky EVT VT = Op.getValueType(); 597193323Sed DebugLoc dl = N->getDebugLoc(); 598193323Sed 599200581Srdivacky // Expand non-constant shifts to loops: 600193323Sed if (!isa<ConstantSDNode>(N->getOperand(1))) 601200581Srdivacky switch (Opc) { 602200581Srdivacky default: 603200581Srdivacky assert(0 && "Invalid shift opcode!"); 604200581Srdivacky case ISD::SHL: 605200581Srdivacky return DAG.getNode(MSP430ISD::SHL, dl, 606200581Srdivacky VT, N->getOperand(0), N->getOperand(1)); 607200581Srdivacky case ISD::SRA: 608200581Srdivacky return DAG.getNode(MSP430ISD::SRA, dl, 609200581Srdivacky VT, N->getOperand(0), N->getOperand(1)); 610200581Srdivacky case ISD::SRL: 611200581Srdivacky return DAG.getNode(MSP430ISD::SRL, dl, 612200581Srdivacky VT, N->getOperand(0), N->getOperand(1)); 613200581Srdivacky } 614193323Sed 615193323Sed uint64_t ShiftAmount = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue(); 616193323Sed 617193323Sed // Expand the stuff into sequence of shifts. 618193323Sed // FIXME: for some shift amounts this might be done better! 619193323Sed // E.g.: foo >> (8 + N) => sxt(swpb(foo)) >> N 620193323Sed SDValue Victim = N->getOperand(0); 621193323Sed 622193323Sed if (Opc == ISD::SRL && ShiftAmount) { 623193323Sed // Emit a special goodness here: 624193323Sed // srl A, 1 => clrc; rrc A 625193323Sed Victim = DAG.getNode(MSP430ISD::RRC, dl, VT, Victim); 626193323Sed ShiftAmount -= 1; 627193323Sed } 628193323Sed 629193323Sed while (ShiftAmount--) 630193323Sed Victim = DAG.getNode((Opc == ISD::SHL ? MSP430ISD::RLA : MSP430ISD::RRA), 631193323Sed dl, VT, Victim); 632193323Sed 633193323Sed return Victim; 634193323Sed} 635193323Sed 636207618SrdivackySDValue MSP430TargetLowering::LowerGlobalAddress(SDValue Op, 637207618Srdivacky SelectionDAG &DAG) const { 638193323Sed const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal(); 639193323Sed int64_t Offset = cast<GlobalAddressSDNode>(Op)->getOffset(); 640193323Sed 641193323Sed // Create the TargetGlobalAddress node, folding in the constant offset. 642210299Sed SDValue Result = DAG.getTargetGlobalAddress(GV, Op.getDebugLoc(), 643210299Sed getPointerTy(), Offset); 644193323Sed return DAG.getNode(MSP430ISD::Wrapper, Op.getDebugLoc(), 645193323Sed getPointerTy(), Result); 646193323Sed} 647193323Sed 648193323SedSDValue MSP430TargetLowering::LowerExternalSymbol(SDValue Op, 649207618Srdivacky SelectionDAG &DAG) const { 650193323Sed DebugLoc dl = Op.getDebugLoc(); 651193323Sed const char *Sym = cast<ExternalSymbolSDNode>(Op)->getSymbol(); 652193323Sed SDValue Result = DAG.getTargetExternalSymbol(Sym, getPointerTy()); 653193323Sed 654193323Sed return DAG.getNode(MSP430ISD::Wrapper, dl, getPointerTy(), Result);; 655193323Sed} 656193323Sed 657207618SrdivackySDValue MSP430TargetLowering::LowerBlockAddress(SDValue Op, 658207618Srdivacky SelectionDAG &DAG) const { 659207618Srdivacky DebugLoc dl = Op.getDebugLoc(); 660207618Srdivacky const BlockAddress *BA = cast<BlockAddressSDNode>(Op)->getBlockAddress(); 661207618Srdivacky SDValue Result = DAG.getBlockAddress(BA, getPointerTy(), /*isTarget=*/true); 662207618Srdivacky 663207618Srdivacky return DAG.getNode(MSP430ISD::Wrapper, dl, getPointerTy(), Result);; 664207618Srdivacky} 665207618Srdivacky 666198396Srdivackystatic SDValue EmitCMP(SDValue &LHS, SDValue &RHS, SDValue &TargetCC, 667193323Sed ISD::CondCode CC, 668193323Sed DebugLoc dl, SelectionDAG &DAG) { 669193323Sed // FIXME: Handle bittests someday 670193323Sed assert(!LHS.getValueType().isFloatingPoint() && "We don't handle FP yet"); 671193323Sed 672193323Sed // FIXME: Handle jump negative someday 673198396Srdivacky MSP430CC::CondCodes TCC = MSP430CC::COND_INVALID; 674193323Sed switch (CC) { 675198090Srdivacky default: llvm_unreachable("Invalid integer condition!"); 676193323Sed case ISD::SETEQ: 677198396Srdivacky TCC = MSP430CC::COND_E; // aka COND_Z 678202375Srdivacky // Minor optimization: if LHS is a constant, swap operands, then the 679199989Srdivacky // constant can be folded into comparison. 680202375Srdivacky if (LHS.getOpcode() == ISD::Constant) 681199989Srdivacky std::swap(LHS, RHS); 682193323Sed break; 683193323Sed case ISD::SETNE: 684198396Srdivacky TCC = MSP430CC::COND_NE; // aka COND_NZ 685202375Srdivacky // Minor optimization: if LHS is a constant, swap operands, then the 686199989Srdivacky // constant can be folded into comparison. 687202375Srdivacky if (LHS.getOpcode() == ISD::Constant) 688199989Srdivacky std::swap(LHS, RHS); 689193323Sed break; 690193323Sed case ISD::SETULE: 691193323Sed std::swap(LHS, RHS); // FALLTHROUGH 692193323Sed case ISD::SETUGE: 693202878Srdivacky // Turn lhs u>= rhs with lhs constant into rhs u< lhs+1, this allows us to 694202878Srdivacky // fold constant into instruction. 695202878Srdivacky if (const ConstantSDNode * C = dyn_cast<ConstantSDNode>(LHS)) { 696202878Srdivacky LHS = RHS; 697202878Srdivacky RHS = DAG.getConstant(C->getSExtValue() + 1, C->getValueType(0)); 698202878Srdivacky TCC = MSP430CC::COND_LO; 699202878Srdivacky break; 700202878Srdivacky } 701198396Srdivacky TCC = MSP430CC::COND_HS; // aka COND_C 702193323Sed break; 703193323Sed case ISD::SETUGT: 704193323Sed std::swap(LHS, RHS); // FALLTHROUGH 705193323Sed case ISD::SETULT: 706202878Srdivacky // Turn lhs u< rhs with lhs constant into rhs u>= lhs+1, this allows us to 707202878Srdivacky // fold constant into instruction. 708202878Srdivacky if (const ConstantSDNode * C = dyn_cast<ConstantSDNode>(LHS)) { 709202878Srdivacky LHS = RHS; 710202878Srdivacky RHS = DAG.getConstant(C->getSExtValue() + 1, C->getValueType(0)); 711202878Srdivacky TCC = MSP430CC::COND_HS; 712202878Srdivacky break; 713202878Srdivacky } 714198396Srdivacky TCC = MSP430CC::COND_LO; // aka COND_NC 715193323Sed break; 716193323Sed case ISD::SETLE: 717193323Sed std::swap(LHS, RHS); // FALLTHROUGH 718193323Sed case ISD::SETGE: 719202878Srdivacky // Turn lhs >= rhs with lhs constant into rhs < lhs+1, this allows us to 720202878Srdivacky // fold constant into instruction. 721202878Srdivacky if (const ConstantSDNode * C = dyn_cast<ConstantSDNode>(LHS)) { 722202878Srdivacky LHS = RHS; 723202878Srdivacky RHS = DAG.getConstant(C->getSExtValue() + 1, C->getValueType(0)); 724202878Srdivacky TCC = MSP430CC::COND_L; 725202878Srdivacky break; 726202878Srdivacky } 727198396Srdivacky TCC = MSP430CC::COND_GE; 728193323Sed break; 729193323Sed case ISD::SETGT: 730193323Sed std::swap(LHS, RHS); // FALLTHROUGH 731193323Sed case ISD::SETLT: 732202878Srdivacky // Turn lhs < rhs with lhs constant into rhs >= lhs+1, this allows us to 733202878Srdivacky // fold constant into instruction. 734202878Srdivacky if (const ConstantSDNode * C = dyn_cast<ConstantSDNode>(LHS)) { 735202878Srdivacky LHS = RHS; 736202878Srdivacky RHS = DAG.getConstant(C->getSExtValue() + 1, C->getValueType(0)); 737202878Srdivacky TCC = MSP430CC::COND_GE; 738202878Srdivacky break; 739202878Srdivacky } 740198396Srdivacky TCC = MSP430CC::COND_L; 741193323Sed break; 742193323Sed } 743193323Sed 744198396Srdivacky TargetCC = DAG.getConstant(TCC, MVT::i8); 745218893Sdim return DAG.getNode(MSP430ISD::CMP, dl, MVT::Glue, LHS, RHS); 746193323Sed} 747193323Sed 748193323Sed 749207618SrdivackySDValue MSP430TargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const { 750193323Sed SDValue Chain = Op.getOperand(0); 751193323Sed ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get(); 752193323Sed SDValue LHS = Op.getOperand(2); 753193323Sed SDValue RHS = Op.getOperand(3); 754193323Sed SDValue Dest = Op.getOperand(4); 755193323Sed DebugLoc dl = Op.getDebugLoc(); 756193323Sed 757198396Srdivacky SDValue TargetCC; 758193323Sed SDValue Flag = EmitCMP(LHS, RHS, TargetCC, CC, dl, DAG); 759193323Sed 760193323Sed return DAG.getNode(MSP430ISD::BR_CC, dl, Op.getValueType(), 761198396Srdivacky Chain, Dest, TargetCC, Flag); 762193323Sed} 763193323Sed 764207618SrdivackySDValue MSP430TargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const { 765200581Srdivacky SDValue LHS = Op.getOperand(0); 766200581Srdivacky SDValue RHS = Op.getOperand(1); 767200581Srdivacky DebugLoc dl = Op.getDebugLoc(); 768200581Srdivacky 769200581Srdivacky // If we are doing an AND and testing against zero, then the CMP 770200581Srdivacky // will not be generated. The AND (or BIT) will generate the condition codes, 771200581Srdivacky // but they are different from CMP. 772202878Srdivacky // FIXME: since we're doing a post-processing, use a pseudoinstr here, so 773202878Srdivacky // lowering & isel wouldn't diverge. 774200581Srdivacky bool andCC = false; 775200581Srdivacky if (ConstantSDNode *RHSC = dyn_cast<ConstantSDNode>(RHS)) { 776200581Srdivacky if (RHSC->isNullValue() && LHS.hasOneUse() && 777200581Srdivacky (LHS.getOpcode() == ISD::AND || 778200581Srdivacky (LHS.getOpcode() == ISD::TRUNCATE && 779200581Srdivacky LHS.getOperand(0).getOpcode() == ISD::AND))) { 780200581Srdivacky andCC = true; 781200581Srdivacky } 782200581Srdivacky } 783200581Srdivacky ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get(); 784200581Srdivacky SDValue TargetCC; 785200581Srdivacky SDValue Flag = EmitCMP(LHS, RHS, TargetCC, CC, dl, DAG); 786200581Srdivacky 787200581Srdivacky // Get the condition codes directly from the status register, if its easy. 788200581Srdivacky // Otherwise a branch will be generated. Note that the AND and BIT 789200581Srdivacky // instructions generate different flags than CMP, the carry bit can be used 790200581Srdivacky // for NE/EQ. 791200581Srdivacky bool Invert = false; 792200581Srdivacky bool Shift = false; 793200581Srdivacky bool Convert = true; 794200581Srdivacky switch (cast<ConstantSDNode>(TargetCC)->getZExtValue()) { 795200581Srdivacky default: 796200581Srdivacky Convert = false; 797200581Srdivacky break; 798200581Srdivacky case MSP430CC::COND_HS: 799200581Srdivacky // Res = SRW & 1, no processing is required 800200581Srdivacky break; 801202878Srdivacky case MSP430CC::COND_LO: 802200581Srdivacky // Res = ~(SRW & 1) 803200581Srdivacky Invert = true; 804200581Srdivacky break; 805202878Srdivacky case MSP430CC::COND_NE: 806200581Srdivacky if (andCC) { 807200581Srdivacky // C = ~Z, thus Res = SRW & 1, no processing is required 808200581Srdivacky } else { 809204642Srdivacky // Res = ~((SRW >> 1) & 1) 810200581Srdivacky Shift = true; 811204642Srdivacky Invert = true; 812200581Srdivacky } 813200581Srdivacky break; 814202878Srdivacky case MSP430CC::COND_E: 815204642Srdivacky Shift = true; 816204642Srdivacky // C = ~Z for AND instruction, thus we can put Res = ~(SRW & 1), however, 817204642Srdivacky // Res = (SRW >> 1) & 1 is 1 word shorter. 818200581Srdivacky break; 819200581Srdivacky } 820200581Srdivacky EVT VT = Op.getValueType(); 821200581Srdivacky SDValue One = DAG.getConstant(1, VT); 822200581Srdivacky if (Convert) { 823200581Srdivacky SDValue SR = DAG.getCopyFromReg(DAG.getEntryNode(), dl, MSP430::SRW, 824202878Srdivacky MVT::i16, Flag); 825200581Srdivacky if (Shift) 826200581Srdivacky // FIXME: somewhere this is turned into a SRL, lower it MSP specific? 827200581Srdivacky SR = DAG.getNode(ISD::SRA, dl, MVT::i16, SR, One); 828200581Srdivacky SR = DAG.getNode(ISD::AND, dl, MVT::i16, SR, One); 829200581Srdivacky if (Invert) 830200581Srdivacky SR = DAG.getNode(ISD::XOR, dl, MVT::i16, SR, One); 831200581Srdivacky return SR; 832200581Srdivacky } else { 833200581Srdivacky SDValue Zero = DAG.getConstant(0, VT); 834218893Sdim SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::Glue); 835200581Srdivacky SmallVector<SDValue, 4> Ops; 836200581Srdivacky Ops.push_back(One); 837200581Srdivacky Ops.push_back(Zero); 838200581Srdivacky Ops.push_back(TargetCC); 839200581Srdivacky Ops.push_back(Flag); 840200581Srdivacky return DAG.getNode(MSP430ISD::SELECT_CC, dl, VTs, &Ops[0], Ops.size()); 841200581Srdivacky } 842200581Srdivacky} 843200581Srdivacky 844207618SrdivackySDValue MSP430TargetLowering::LowerSELECT_CC(SDValue Op, 845207618Srdivacky SelectionDAG &DAG) const { 846193323Sed SDValue LHS = Op.getOperand(0); 847193323Sed SDValue RHS = Op.getOperand(1); 848193323Sed SDValue TrueV = Op.getOperand(2); 849193323Sed SDValue FalseV = Op.getOperand(3); 850193323Sed ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get(); 851193323Sed DebugLoc dl = Op.getDebugLoc(); 852193323Sed 853198396Srdivacky SDValue TargetCC; 854193323Sed SDValue Flag = EmitCMP(LHS, RHS, TargetCC, CC, dl, DAG); 855193323Sed 856218893Sdim SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::Glue); 857193323Sed SmallVector<SDValue, 4> Ops; 858193323Sed Ops.push_back(TrueV); 859193323Sed Ops.push_back(FalseV); 860198396Srdivacky Ops.push_back(TargetCC); 861193323Sed Ops.push_back(Flag); 862193323Sed 863193323Sed return DAG.getNode(MSP430ISD::SELECT_CC, dl, VTs, &Ops[0], Ops.size()); 864193323Sed} 865193323Sed 866193323SedSDValue MSP430TargetLowering::LowerSIGN_EXTEND(SDValue Op, 867207618Srdivacky SelectionDAG &DAG) const { 868193323Sed SDValue Val = Op.getOperand(0); 869198090Srdivacky EVT VT = Op.getValueType(); 870193323Sed DebugLoc dl = Op.getDebugLoc(); 871193323Sed 872193323Sed assert(VT == MVT::i16 && "Only support i16 for now!"); 873193323Sed 874193323Sed return DAG.getNode(ISD::SIGN_EXTEND_INREG, dl, VT, 875193323Sed DAG.getNode(ISD::ANY_EXTEND, dl, VT, Val), 876193323Sed DAG.getValueType(Val.getValueType())); 877193323Sed} 878193323Sed 879207618SrdivackySDValue 880207618SrdivackyMSP430TargetLowering::getReturnAddressFrameIndex(SelectionDAG &DAG) const { 881200581Srdivacky MachineFunction &MF = DAG.getMachineFunction(); 882200581Srdivacky MSP430MachineFunctionInfo *FuncInfo = MF.getInfo<MSP430MachineFunctionInfo>(); 883200581Srdivacky int ReturnAddrIndex = FuncInfo->getRAIndex(); 884200581Srdivacky 885200581Srdivacky if (ReturnAddrIndex == 0) { 886200581Srdivacky // Set up a frame object for the return address. 887200581Srdivacky uint64_t SlotSize = TD->getPointerSize(); 888200581Srdivacky ReturnAddrIndex = MF.getFrameInfo()->CreateFixedObject(SlotSize, -SlotSize, 889210299Sed true); 890200581Srdivacky FuncInfo->setRAIndex(ReturnAddrIndex); 891200581Srdivacky } 892200581Srdivacky 893200581Srdivacky return DAG.getFrameIndex(ReturnAddrIndex, getPointerTy()); 894200581Srdivacky} 895200581Srdivacky 896207618SrdivackySDValue MSP430TargetLowering::LowerRETURNADDR(SDValue Op, 897207618Srdivacky SelectionDAG &DAG) const { 898208599Srdivacky MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); 899208599Srdivacky MFI->setReturnAddressIsTaken(true); 900208599Srdivacky 901200581Srdivacky unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue(); 902200581Srdivacky DebugLoc dl = Op.getDebugLoc(); 903200581Srdivacky 904200581Srdivacky if (Depth > 0) { 905200581Srdivacky SDValue FrameAddr = LowerFRAMEADDR(Op, DAG); 906200581Srdivacky SDValue Offset = 907200581Srdivacky DAG.getConstant(TD->getPointerSize(), MVT::i16); 908200581Srdivacky return DAG.getLoad(getPointerTy(), dl, DAG.getEntryNode(), 909200581Srdivacky DAG.getNode(ISD::ADD, dl, getPointerTy(), 910200581Srdivacky FrameAddr, Offset), 911218893Sdim MachinePointerInfo(), false, false, 0); 912200581Srdivacky } 913200581Srdivacky 914200581Srdivacky // Just load the return address. 915200581Srdivacky SDValue RetAddrFI = getReturnAddressFrameIndex(DAG); 916200581Srdivacky return DAG.getLoad(getPointerTy(), dl, DAG.getEntryNode(), 917218893Sdim RetAddrFI, MachinePointerInfo(), false, false, 0); 918200581Srdivacky} 919200581Srdivacky 920207618SrdivackySDValue MSP430TargetLowering::LowerFRAMEADDR(SDValue Op, 921207618Srdivacky SelectionDAG &DAG) const { 922200581Srdivacky MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); 923200581Srdivacky MFI->setFrameAddressIsTaken(true); 924208599Srdivacky 925200581Srdivacky EVT VT = Op.getValueType(); 926200581Srdivacky DebugLoc dl = Op.getDebugLoc(); // FIXME probably not meaningful 927200581Srdivacky unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue(); 928200581Srdivacky SDValue FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, 929200581Srdivacky MSP430::FPW, VT); 930200581Srdivacky while (Depth--) 931218893Sdim FrameAddr = DAG.getLoad(VT, dl, DAG.getEntryNode(), FrameAddr, 932218893Sdim MachinePointerInfo(), 933203954Srdivacky false, false, 0); 934200581Srdivacky return FrameAddr; 935200581Srdivacky} 936200581Srdivacky 937199481Srdivacky/// getPostIndexedAddressParts - returns true by value, base pointer and 938199481Srdivacky/// offset pointer and addressing mode by reference if this node can be 939199481Srdivacky/// combined with a load / store to form a post-indexed load / store. 940199481Srdivackybool MSP430TargetLowering::getPostIndexedAddressParts(SDNode *N, SDNode *Op, 941199481Srdivacky SDValue &Base, 942199481Srdivacky SDValue &Offset, 943199481Srdivacky ISD::MemIndexedMode &AM, 944199481Srdivacky SelectionDAG &DAG) const { 945199481Srdivacky 946199481Srdivacky LoadSDNode *LD = cast<LoadSDNode>(N); 947199481Srdivacky if (LD->getExtensionType() != ISD::NON_EXTLOAD) 948199481Srdivacky return false; 949199481Srdivacky 950199481Srdivacky EVT VT = LD->getMemoryVT(); 951199481Srdivacky if (VT != MVT::i8 && VT != MVT::i16) 952199481Srdivacky return false; 953199481Srdivacky 954199481Srdivacky if (Op->getOpcode() != ISD::ADD) 955199481Srdivacky return false; 956199481Srdivacky 957199481Srdivacky if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(Op->getOperand(1))) { 958199481Srdivacky uint64_t RHSC = RHS->getZExtValue(); 959199481Srdivacky if ((VT == MVT::i16 && RHSC != 2) || 960199481Srdivacky (VT == MVT::i8 && RHSC != 1)) 961199481Srdivacky return false; 962199481Srdivacky 963199481Srdivacky Base = Op->getOperand(0); 964199481Srdivacky Offset = DAG.getConstant(RHSC, VT); 965199481Srdivacky AM = ISD::POST_INC; 966199481Srdivacky return true; 967199481Srdivacky } 968199481Srdivacky 969199481Srdivacky return false; 970199481Srdivacky} 971199481Srdivacky 972199481Srdivacky 973193323Sedconst char *MSP430TargetLowering::getTargetNodeName(unsigned Opcode) const { 974193323Sed switch (Opcode) { 975193323Sed default: return NULL; 976193323Sed case MSP430ISD::RET_FLAG: return "MSP430ISD::RET_FLAG"; 977200581Srdivacky case MSP430ISD::RETI_FLAG: return "MSP430ISD::RETI_FLAG"; 978193323Sed case MSP430ISD::RRA: return "MSP430ISD::RRA"; 979193323Sed case MSP430ISD::RLA: return "MSP430ISD::RLA"; 980193323Sed case MSP430ISD::RRC: return "MSP430ISD::RRC"; 981193323Sed case MSP430ISD::CALL: return "MSP430ISD::CALL"; 982193323Sed case MSP430ISD::Wrapper: return "MSP430ISD::Wrapper"; 983193323Sed case MSP430ISD::BR_CC: return "MSP430ISD::BR_CC"; 984193323Sed case MSP430ISD::CMP: return "MSP430ISD::CMP"; 985193323Sed case MSP430ISD::SELECT_CC: return "MSP430ISD::SELECT_CC"; 986200581Srdivacky case MSP430ISD::SHL: return "MSP430ISD::SHL"; 987200581Srdivacky case MSP430ISD::SRA: return "MSP430ISD::SRA"; 988193323Sed } 989193323Sed} 990193323Sed 991226633Sdimbool MSP430TargetLowering::isTruncateFree(Type *Ty1, 992226633Sdim Type *Ty2) const { 993203954Srdivacky if (!Ty1->isIntegerTy() || !Ty2->isIntegerTy()) 994202878Srdivacky return false; 995202878Srdivacky 996202878Srdivacky return (Ty1->getPrimitiveSizeInBits() > Ty2->getPrimitiveSizeInBits()); 997202878Srdivacky} 998202878Srdivacky 999202878Srdivackybool MSP430TargetLowering::isTruncateFree(EVT VT1, EVT VT2) const { 1000202878Srdivacky if (!VT1.isInteger() || !VT2.isInteger()) 1001202878Srdivacky return false; 1002202878Srdivacky 1003202878Srdivacky return (VT1.getSizeInBits() > VT2.getSizeInBits()); 1004202878Srdivacky} 1005202878Srdivacky 1006226633Sdimbool MSP430TargetLowering::isZExtFree(Type *Ty1, Type *Ty2) const { 1007202878Srdivacky // MSP430 implicitly zero-extends 8-bit results in 16-bit registers. 1008203954Srdivacky return 0 && Ty1->isIntegerTy(8) && Ty2->isIntegerTy(16); 1009202878Srdivacky} 1010202878Srdivacky 1011202878Srdivackybool MSP430TargetLowering::isZExtFree(EVT VT1, EVT VT2) const { 1012202878Srdivacky // MSP430 implicitly zero-extends 8-bit results in 16-bit registers. 1013202878Srdivacky return 0 && VT1 == MVT::i8 && VT2 == MVT::i16; 1014202878Srdivacky} 1015202878Srdivacky 1016193323Sed//===----------------------------------------------------------------------===// 1017193323Sed// Other Lowering Code 1018193323Sed//===----------------------------------------------------------------------===// 1019193323Sed 1020193323SedMachineBasicBlock* 1021200581SrdivackyMSP430TargetLowering::EmitShiftInstr(MachineInstr *MI, 1022207618Srdivacky MachineBasicBlock *BB) const { 1023200581Srdivacky MachineFunction *F = BB->getParent(); 1024200581Srdivacky MachineRegisterInfo &RI = F->getRegInfo(); 1025200581Srdivacky DebugLoc dl = MI->getDebugLoc(); 1026200581Srdivacky const TargetInstrInfo &TII = *getTargetMachine().getInstrInfo(); 1027200581Srdivacky 1028200581Srdivacky unsigned Opc; 1029200581Srdivacky const TargetRegisterClass * RC; 1030200581Srdivacky switch (MI->getOpcode()) { 1031200581Srdivacky default: 1032200581Srdivacky assert(0 && "Invalid shift opcode!"); 1033200581Srdivacky case MSP430::Shl8: 1034200581Srdivacky Opc = MSP430::SHL8r1; 1035200581Srdivacky RC = MSP430::GR8RegisterClass; 1036200581Srdivacky break; 1037200581Srdivacky case MSP430::Shl16: 1038200581Srdivacky Opc = MSP430::SHL16r1; 1039200581Srdivacky RC = MSP430::GR16RegisterClass; 1040200581Srdivacky break; 1041200581Srdivacky case MSP430::Sra8: 1042200581Srdivacky Opc = MSP430::SAR8r1; 1043200581Srdivacky RC = MSP430::GR8RegisterClass; 1044200581Srdivacky break; 1045200581Srdivacky case MSP430::Sra16: 1046200581Srdivacky Opc = MSP430::SAR16r1; 1047200581Srdivacky RC = MSP430::GR16RegisterClass; 1048200581Srdivacky break; 1049200581Srdivacky case MSP430::Srl8: 1050200581Srdivacky Opc = MSP430::SAR8r1c; 1051200581Srdivacky RC = MSP430::GR8RegisterClass; 1052200581Srdivacky break; 1053200581Srdivacky case MSP430::Srl16: 1054200581Srdivacky Opc = MSP430::SAR16r1c; 1055200581Srdivacky RC = MSP430::GR16RegisterClass; 1056200581Srdivacky break; 1057200581Srdivacky } 1058200581Srdivacky 1059200581Srdivacky const BasicBlock *LLVM_BB = BB->getBasicBlock(); 1060200581Srdivacky MachineFunction::iterator I = BB; 1061200581Srdivacky ++I; 1062200581Srdivacky 1063200581Srdivacky // Create loop block 1064200581Srdivacky MachineBasicBlock *LoopBB = F->CreateMachineBasicBlock(LLVM_BB); 1065200581Srdivacky MachineBasicBlock *RemBB = F->CreateMachineBasicBlock(LLVM_BB); 1066200581Srdivacky 1067200581Srdivacky F->insert(I, LoopBB); 1068200581Srdivacky F->insert(I, RemBB); 1069200581Srdivacky 1070200581Srdivacky // Update machine-CFG edges by transferring all successors of the current 1071200581Srdivacky // block to the block containing instructions after shift. 1072210299Sed RemBB->splice(RemBB->begin(), BB, 1073210299Sed llvm::next(MachineBasicBlock::iterator(MI)), 1074210299Sed BB->end()); 1075210299Sed RemBB->transferSuccessorsAndUpdatePHIs(BB); 1076200581Srdivacky 1077200581Srdivacky // Add adges BB => LoopBB => RemBB, BB => RemBB, LoopBB => LoopBB 1078200581Srdivacky BB->addSuccessor(LoopBB); 1079200581Srdivacky BB->addSuccessor(RemBB); 1080200581Srdivacky LoopBB->addSuccessor(RemBB); 1081200581Srdivacky LoopBB->addSuccessor(LoopBB); 1082200581Srdivacky 1083200581Srdivacky unsigned ShiftAmtReg = RI.createVirtualRegister(MSP430::GR8RegisterClass); 1084200581Srdivacky unsigned ShiftAmtReg2 = RI.createVirtualRegister(MSP430::GR8RegisterClass); 1085200581Srdivacky unsigned ShiftReg = RI.createVirtualRegister(RC); 1086200581Srdivacky unsigned ShiftReg2 = RI.createVirtualRegister(RC); 1087200581Srdivacky unsigned ShiftAmtSrcReg = MI->getOperand(2).getReg(); 1088200581Srdivacky unsigned SrcReg = MI->getOperand(1).getReg(); 1089200581Srdivacky unsigned DstReg = MI->getOperand(0).getReg(); 1090200581Srdivacky 1091200581Srdivacky // BB: 1092200581Srdivacky // cmp 0, N 1093200581Srdivacky // je RemBB 1094202375Srdivacky BuildMI(BB, dl, TII.get(MSP430::CMP8ri)) 1095202375Srdivacky .addReg(ShiftAmtSrcReg).addImm(0); 1096200581Srdivacky BuildMI(BB, dl, TII.get(MSP430::JCC)) 1097200581Srdivacky .addMBB(RemBB) 1098200581Srdivacky .addImm(MSP430CC::COND_E); 1099200581Srdivacky 1100200581Srdivacky // LoopBB: 1101200581Srdivacky // ShiftReg = phi [%SrcReg, BB], [%ShiftReg2, LoopBB] 1102200581Srdivacky // ShiftAmt = phi [%N, BB], [%ShiftAmt2, LoopBB] 1103200581Srdivacky // ShiftReg2 = shift ShiftReg 1104200581Srdivacky // ShiftAmt2 = ShiftAmt - 1; 1105200581Srdivacky BuildMI(LoopBB, dl, TII.get(MSP430::PHI), ShiftReg) 1106200581Srdivacky .addReg(SrcReg).addMBB(BB) 1107200581Srdivacky .addReg(ShiftReg2).addMBB(LoopBB); 1108200581Srdivacky BuildMI(LoopBB, dl, TII.get(MSP430::PHI), ShiftAmtReg) 1109200581Srdivacky .addReg(ShiftAmtSrcReg).addMBB(BB) 1110200581Srdivacky .addReg(ShiftAmtReg2).addMBB(LoopBB); 1111200581Srdivacky BuildMI(LoopBB, dl, TII.get(Opc), ShiftReg2) 1112200581Srdivacky .addReg(ShiftReg); 1113200581Srdivacky BuildMI(LoopBB, dl, TII.get(MSP430::SUB8ri), ShiftAmtReg2) 1114200581Srdivacky .addReg(ShiftAmtReg).addImm(1); 1115200581Srdivacky BuildMI(LoopBB, dl, TII.get(MSP430::JCC)) 1116200581Srdivacky .addMBB(LoopBB) 1117200581Srdivacky .addImm(MSP430CC::COND_NE); 1118200581Srdivacky 1119200581Srdivacky // RemBB: 1120200581Srdivacky // DestReg = phi [%SrcReg, BB], [%ShiftReg, LoopBB] 1121210299Sed BuildMI(*RemBB, RemBB->begin(), dl, TII.get(MSP430::PHI), DstReg) 1122200581Srdivacky .addReg(SrcReg).addMBB(BB) 1123200581Srdivacky .addReg(ShiftReg2).addMBB(LoopBB); 1124200581Srdivacky 1125210299Sed MI->eraseFromParent(); // The pseudo instruction is gone now. 1126200581Srdivacky return RemBB; 1127200581Srdivacky} 1128200581Srdivacky 1129200581SrdivackyMachineBasicBlock* 1130193323SedMSP430TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, 1131207618Srdivacky MachineBasicBlock *BB) const { 1132200581Srdivacky unsigned Opc = MI->getOpcode(); 1133200581Srdivacky 1134200581Srdivacky if (Opc == MSP430::Shl8 || Opc == MSP430::Shl16 || 1135200581Srdivacky Opc == MSP430::Sra8 || Opc == MSP430::Sra16 || 1136200581Srdivacky Opc == MSP430::Srl8 || Opc == MSP430::Srl16) 1137207618Srdivacky return EmitShiftInstr(MI, BB); 1138200581Srdivacky 1139193323Sed const TargetInstrInfo &TII = *getTargetMachine().getInstrInfo(); 1140193323Sed DebugLoc dl = MI->getDebugLoc(); 1141200581Srdivacky 1142200581Srdivacky assert((Opc == MSP430::Select16 || Opc == MSP430::Select8) && 1143193323Sed "Unexpected instr type to insert"); 1144193323Sed 1145193323Sed // To "insert" a SELECT instruction, we actually have to insert the diamond 1146193323Sed // control-flow pattern. The incoming instruction knows the destination vreg 1147193323Sed // to set, the condition code register to branch on, the true/false values to 1148193323Sed // select between, and a branch opcode to use. 1149193323Sed const BasicBlock *LLVM_BB = BB->getBasicBlock(); 1150193323Sed MachineFunction::iterator I = BB; 1151193323Sed ++I; 1152193323Sed 1153193323Sed // thisMBB: 1154193323Sed // ... 1155193323Sed // TrueVal = ... 1156193323Sed // cmpTY ccX, r1, r2 1157193323Sed // jCC copy1MBB 1158193323Sed // fallthrough --> copy0MBB 1159193323Sed MachineBasicBlock *thisMBB = BB; 1160193323Sed MachineFunction *F = BB->getParent(); 1161193323Sed MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB); 1162193323Sed MachineBasicBlock *copy1MBB = F->CreateMachineBasicBlock(LLVM_BB); 1163193323Sed F->insert(I, copy0MBB); 1164193323Sed F->insert(I, copy1MBB); 1165193323Sed // Update machine-CFG edges by transferring all successors of the current 1166193323Sed // block to the new block which will contain the Phi node for the select. 1167210299Sed copy1MBB->splice(copy1MBB->begin(), BB, 1168210299Sed llvm::next(MachineBasicBlock::iterator(MI)), 1169210299Sed BB->end()); 1170210299Sed copy1MBB->transferSuccessorsAndUpdatePHIs(BB); 1171193323Sed // Next, add the true and fallthrough blocks as its successors. 1172193323Sed BB->addSuccessor(copy0MBB); 1173193323Sed BB->addSuccessor(copy1MBB); 1174193323Sed 1175210299Sed BuildMI(BB, dl, TII.get(MSP430::JCC)) 1176210299Sed .addMBB(copy1MBB) 1177210299Sed .addImm(MI->getOperand(3).getImm()); 1178210299Sed 1179193323Sed // copy0MBB: 1180193323Sed // %FalseValue = ... 1181193323Sed // # fallthrough to copy1MBB 1182193323Sed BB = copy0MBB; 1183193323Sed 1184193323Sed // Update machine-CFG edges 1185193323Sed BB->addSuccessor(copy1MBB); 1186193323Sed 1187193323Sed // copy1MBB: 1188193323Sed // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ] 1189193323Sed // ... 1190193323Sed BB = copy1MBB; 1191210299Sed BuildMI(*BB, BB->begin(), dl, TII.get(MSP430::PHI), 1192193323Sed MI->getOperand(0).getReg()) 1193193323Sed .addReg(MI->getOperand(2).getReg()).addMBB(copy0MBB) 1194193323Sed .addReg(MI->getOperand(1).getReg()).addMBB(thisMBB); 1195193323Sed 1196210299Sed MI->eraseFromParent(); // The pseudo instruction is gone now. 1197193323Sed return BB; 1198193323Sed} 1199