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" 19249423Sdim#include "MSP430Subtarget.h" 20193323Sed#include "MSP430TargetMachine.h" 21193323Sed#include "llvm/CodeGen/CallingConvLower.h" 22193323Sed#include "llvm/CodeGen/MachineFrameInfo.h" 23193323Sed#include "llvm/CodeGen/MachineFunction.h" 24193323Sed#include "llvm/CodeGen/MachineInstrBuilder.h" 25193323Sed#include "llvm/CodeGen/MachineRegisterInfo.h" 26193323Sed#include "llvm/CodeGen/SelectionDAGISel.h" 27203954Srdivacky#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" 28193323Sed#include "llvm/CodeGen/ValueTypes.h" 29249423Sdim#include "llvm/IR/CallingConv.h" 30249423Sdim#include "llvm/IR/DerivedTypes.h" 31249423Sdim#include "llvm/IR/Function.h" 32249423Sdim#include "llvm/IR/GlobalAlias.h" 33249423Sdim#include "llvm/IR/GlobalVariable.h" 34249423Sdim#include "llvm/IR/Intrinsics.h" 35200581Srdivacky#include "llvm/Support/CommandLine.h" 36193323Sed#include "llvm/Support/Debug.h" 37198090Srdivacky#include "llvm/Support/ErrorHandling.h" 38198090Srdivacky#include "llvm/Support/raw_ostream.h" 39193323Sedusing namespace llvm; 40193323Sed 41200581Srdivackytypedef enum { 42200581Srdivacky NoHWMult, 43200581Srdivacky HWMultIntr, 44200581Srdivacky HWMultNoIntr 45200581Srdivacky} HWMultUseMode; 46200581Srdivacky 47200581Srdivackystatic cl::opt<HWMultUseMode> 48263508SdimHWMultMode("msp430-hwmult-mode", cl::Hidden, 49200581Srdivacky cl::desc("Hardware multiplier use mode"), 50200581Srdivacky cl::init(HWMultNoIntr), 51200581Srdivacky cl::values( 52200581Srdivacky clEnumValN(NoHWMult, "no", 53200581Srdivacky "Do not use hardware multiplier"), 54200581Srdivacky clEnumValN(HWMultIntr, "interrupts", 55200581Srdivacky "Assume hardware multiplier can be used inside interrupts"), 56200581Srdivacky clEnumValN(HWMultNoIntr, "use", 57200581Srdivacky "Assume hardware multiplier cannot be used inside interrupts"), 58200581Srdivacky clEnumValEnd)); 59200581Srdivacky 60193323SedMSP430TargetLowering::MSP430TargetLowering(MSP430TargetMachine &tm) : 61198090Srdivacky TargetLowering(tm, new TargetLoweringObjectFileELF()), 62239462Sdim Subtarget(*tm.getSubtargetImpl()) { 63193323Sed 64243830Sdim TD = getDataLayout(); 65200581Srdivacky 66193323Sed // Set up the register classes. 67239462Sdim addRegisterClass(MVT::i8, &MSP430::GR8RegClass); 68239462Sdim addRegisterClass(MVT::i16, &MSP430::GR16RegClass); 69193323Sed 70193323Sed // Compute derived properties from the register classes 71193323Sed computeRegisterProperties(); 72193323Sed 73193323Sed // Provide all sorts of operation actions 74193323Sed 75193323Sed // Division is expensive 76193323Sed setIntDivIsCheap(false); 77193323Sed 78193323Sed setStackPointerRegisterToSaveRestore(MSP430::SPW); 79193323Sed setBooleanContents(ZeroOrOneBooleanContent); 80226633Sdim setBooleanVectorContents(ZeroOrOneBooleanContent); // FIXME: Is this correct? 81193323Sed 82199481Srdivacky // We have post-incremented loads / stores. 83199481Srdivacky setIndexedLoadAction(ISD::POST_INC, MVT::i8, Legal); 84199481Srdivacky setIndexedLoadAction(ISD::POST_INC, MVT::i16, Legal); 85199481Srdivacky 86199481Srdivacky setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote); 87199481Srdivacky setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote); 88199481Srdivacky setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote); 89199481Srdivacky setLoadExtAction(ISD::SEXTLOAD, MVT::i8, Expand); 90193323Sed setLoadExtAction(ISD::SEXTLOAD, MVT::i16, Expand); 91193323Sed 92193323Sed // We don't have any truncstores 93193323Sed setTruncStoreAction(MVT::i16, MVT::i8, Expand); 94193323Sed 95193323Sed setOperationAction(ISD::SRA, MVT::i8, Custom); 96193323Sed setOperationAction(ISD::SHL, MVT::i8, Custom); 97193323Sed setOperationAction(ISD::SRL, MVT::i8, Custom); 98193323Sed setOperationAction(ISD::SRA, MVT::i16, Custom); 99193323Sed setOperationAction(ISD::SHL, MVT::i16, Custom); 100193323Sed setOperationAction(ISD::SRL, MVT::i16, Custom); 101193323Sed setOperationAction(ISD::ROTL, MVT::i8, Expand); 102193323Sed setOperationAction(ISD::ROTR, MVT::i8, Expand); 103193323Sed setOperationAction(ISD::ROTL, MVT::i16, Expand); 104193323Sed setOperationAction(ISD::ROTR, MVT::i16, Expand); 105193323Sed setOperationAction(ISD::GlobalAddress, MVT::i16, Custom); 106193323Sed setOperationAction(ISD::ExternalSymbol, MVT::i16, Custom); 107207618Srdivacky setOperationAction(ISD::BlockAddress, MVT::i16, Custom); 108193323Sed setOperationAction(ISD::BR_JT, MVT::Other, Expand); 109193323Sed setOperationAction(ISD::BR_CC, MVT::i8, Custom); 110193323Sed setOperationAction(ISD::BR_CC, MVT::i16, Custom); 111193323Sed setOperationAction(ISD::BRCOND, MVT::Other, Expand); 112200581Srdivacky setOperationAction(ISD::SETCC, MVT::i8, Custom); 113200581Srdivacky setOperationAction(ISD::SETCC, MVT::i16, Custom); 114193323Sed setOperationAction(ISD::SELECT, MVT::i8, Expand); 115193323Sed setOperationAction(ISD::SELECT, MVT::i16, Expand); 116193323Sed setOperationAction(ISD::SELECT_CC, MVT::i8, Custom); 117193323Sed setOperationAction(ISD::SELECT_CC, MVT::i16, Custom); 118193323Sed setOperationAction(ISD::SIGN_EXTEND, MVT::i16, Custom); 119198090Srdivacky setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i8, Expand); 120198090Srdivacky setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i16, Expand); 121193323Sed 122198090Srdivacky setOperationAction(ISD::CTTZ, MVT::i8, Expand); 123198090Srdivacky setOperationAction(ISD::CTTZ, MVT::i16, Expand); 124234353Sdim setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i8, Expand); 125234353Sdim setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i16, Expand); 126198090Srdivacky setOperationAction(ISD::CTLZ, MVT::i8, Expand); 127198090Srdivacky setOperationAction(ISD::CTLZ, MVT::i16, Expand); 128234353Sdim setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i8, Expand); 129234353Sdim setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i16, Expand); 130198090Srdivacky setOperationAction(ISD::CTPOP, MVT::i8, Expand); 131198090Srdivacky setOperationAction(ISD::CTPOP, MVT::i16, Expand); 132198090Srdivacky 133198090Srdivacky setOperationAction(ISD::SHL_PARTS, MVT::i8, Expand); 134198090Srdivacky setOperationAction(ISD::SHL_PARTS, MVT::i16, Expand); 135198090Srdivacky setOperationAction(ISD::SRL_PARTS, MVT::i8, Expand); 136198090Srdivacky setOperationAction(ISD::SRL_PARTS, MVT::i16, Expand); 137198090Srdivacky setOperationAction(ISD::SRA_PARTS, MVT::i8, Expand); 138198090Srdivacky setOperationAction(ISD::SRA_PARTS, MVT::i16, Expand); 139198090Srdivacky 140198090Srdivacky setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); 141198090Srdivacky 142193323Sed // FIXME: Implement efficiently multiplication by a constant 143199481Srdivacky setOperationAction(ISD::MUL, MVT::i8, Expand); 144199481Srdivacky setOperationAction(ISD::MULHS, MVT::i8, Expand); 145199481Srdivacky setOperationAction(ISD::MULHU, MVT::i8, Expand); 146199481Srdivacky setOperationAction(ISD::SMUL_LOHI, MVT::i8, Expand); 147199481Srdivacky setOperationAction(ISD::UMUL_LOHI, MVT::i8, Expand); 148193323Sed setOperationAction(ISD::MUL, MVT::i16, Expand); 149193323Sed setOperationAction(ISD::MULHS, MVT::i16, Expand); 150193323Sed setOperationAction(ISD::MULHU, MVT::i16, Expand); 151193323Sed setOperationAction(ISD::SMUL_LOHI, MVT::i16, Expand); 152193323Sed setOperationAction(ISD::UMUL_LOHI, MVT::i16, Expand); 153193323Sed 154199481Srdivacky setOperationAction(ISD::UDIV, MVT::i8, Expand); 155199481Srdivacky setOperationAction(ISD::UDIVREM, MVT::i8, Expand); 156199481Srdivacky setOperationAction(ISD::UREM, MVT::i8, Expand); 157199481Srdivacky setOperationAction(ISD::SDIV, MVT::i8, Expand); 158199481Srdivacky setOperationAction(ISD::SDIVREM, MVT::i8, Expand); 159199481Srdivacky setOperationAction(ISD::SREM, MVT::i8, Expand); 160193323Sed setOperationAction(ISD::UDIV, MVT::i16, Expand); 161193323Sed setOperationAction(ISD::UDIVREM, MVT::i16, Expand); 162193323Sed setOperationAction(ISD::UREM, MVT::i16, Expand); 163193323Sed setOperationAction(ISD::SDIV, MVT::i16, Expand); 164193323Sed setOperationAction(ISD::SDIVREM, MVT::i16, Expand); 165193323Sed setOperationAction(ISD::SREM, MVT::i16, Expand); 166200581Srdivacky 167249423Sdim // varargs support 168249423Sdim setOperationAction(ISD::VASTART, MVT::Other, Custom); 169249423Sdim setOperationAction(ISD::VAARG, MVT::Other, Expand); 170249423Sdim setOperationAction(ISD::VAEND, MVT::Other, Expand); 171249423Sdim setOperationAction(ISD::VACOPY, MVT::Other, Expand); 172263508Sdim setOperationAction(ISD::JumpTable, MVT::i16, Custom); 173249423Sdim 174200581Srdivacky // Libcalls names. 175200581Srdivacky if (HWMultMode == HWMultIntr) { 176200581Srdivacky setLibcallName(RTLIB::MUL_I8, "__mulqi3hw"); 177200581Srdivacky setLibcallName(RTLIB::MUL_I16, "__mulhi3hw"); 178200581Srdivacky } else if (HWMultMode == HWMultNoIntr) { 179200581Srdivacky setLibcallName(RTLIB::MUL_I8, "__mulqi3hw_noint"); 180200581Srdivacky setLibcallName(RTLIB::MUL_I16, "__mulhi3hw_noint"); 181200581Srdivacky } 182223017Sdim 183223017Sdim setMinFunctionAlignment(1); 184223017Sdim setPrefFunctionAlignment(2); 185193323Sed} 186193323Sed 187207618SrdivackySDValue MSP430TargetLowering::LowerOperation(SDValue Op, 188207618Srdivacky SelectionDAG &DAG) const { 189193323Sed switch (Op.getOpcode()) { 190193323Sed case ISD::SHL: // FALLTHROUGH 191193323Sed case ISD::SRL: 192193323Sed case ISD::SRA: return LowerShifts(Op, DAG); 193193323Sed case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG); 194207618Srdivacky case ISD::BlockAddress: return LowerBlockAddress(Op, DAG); 195193323Sed case ISD::ExternalSymbol: return LowerExternalSymbol(Op, DAG); 196200581Srdivacky case ISD::SETCC: return LowerSETCC(Op, DAG); 197193323Sed case ISD::BR_CC: return LowerBR_CC(Op, DAG); 198193323Sed case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG); 199193323Sed case ISD::SIGN_EXTEND: return LowerSIGN_EXTEND(Op, DAG); 200200581Srdivacky case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG); 201200581Srdivacky case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG); 202249423Sdim case ISD::VASTART: return LowerVASTART(Op, DAG); 203263508Sdim case ISD::JumpTable: return LowerJumpTable(Op, DAG); 204193323Sed default: 205198090Srdivacky llvm_unreachable("unimplemented operand"); 206193323Sed } 207193323Sed} 208193323Sed 209193323Sed//===----------------------------------------------------------------------===// 210198090Srdivacky// MSP430 Inline Assembly Support 211198090Srdivacky//===----------------------------------------------------------------------===// 212198090Srdivacky 213198090Srdivacky/// getConstraintType - Given a constraint letter, return the type of 214198090Srdivacky/// constraint it is for this target. 215198090SrdivackyTargetLowering::ConstraintType 216198090SrdivackyMSP430TargetLowering::getConstraintType(const std::string &Constraint) const { 217198090Srdivacky if (Constraint.size() == 1) { 218198090Srdivacky switch (Constraint[0]) { 219198090Srdivacky case 'r': 220198090Srdivacky return C_RegisterClass; 221198090Srdivacky default: 222198090Srdivacky break; 223198090Srdivacky } 224198090Srdivacky } 225198090Srdivacky return TargetLowering::getConstraintType(Constraint); 226198090Srdivacky} 227198090Srdivacky 228198090Srdivackystd::pair<unsigned, const TargetRegisterClass*> 229198090SrdivackyMSP430TargetLowering:: 230198090SrdivackygetRegForInlineAsmConstraint(const std::string &Constraint, 231263508Sdim MVT VT) const { 232198090Srdivacky if (Constraint.size() == 1) { 233198090Srdivacky // GCC Constraint Letters 234198090Srdivacky switch (Constraint[0]) { 235198090Srdivacky default: break; 236198090Srdivacky case 'r': // GENERAL_REGS 237198090Srdivacky if (VT == MVT::i8) 238239462Sdim return std::make_pair(0U, &MSP430::GR8RegClass); 239198090Srdivacky 240239462Sdim return std::make_pair(0U, &MSP430::GR16RegClass); 241198090Srdivacky } 242198090Srdivacky } 243198090Srdivacky 244198090Srdivacky return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT); 245198090Srdivacky} 246198090Srdivacky 247198090Srdivacky//===----------------------------------------------------------------------===// 248193323Sed// Calling Convention Implementation 249193323Sed//===----------------------------------------------------------------------===// 250193323Sed 251193323Sed#include "MSP430GenCallingConv.inc" 252193323Sed 253263508Sdim/// For each argument in a function store the number of pieces it is composed 254263508Sdim/// of. 255263508Sdimtemplate<typename ArgT> 256263508Sdimstatic void ParseFunctionArgs(const SmallVectorImpl<ArgT> &Args, 257263508Sdim SmallVectorImpl<unsigned> &Out) { 258263508Sdim unsigned CurrentArgIndex = ~0U; 259263508Sdim for (unsigned i = 0, e = Args.size(); i != e; i++) { 260263508Sdim if (CurrentArgIndex == Args[i].OrigArgIndex) { 261263508Sdim Out.back()++; 262263508Sdim } else { 263263508Sdim Out.push_back(1); 264263508Sdim CurrentArgIndex++; 265263508Sdim } 266263508Sdim } 267263508Sdim} 268263508Sdim 269263508Sdimstatic void AnalyzeVarArgs(CCState &State, 270263508Sdim const SmallVectorImpl<ISD::OutputArg> &Outs) { 271263508Sdim State.AnalyzeCallOperands(Outs, CC_MSP430_AssignStack); 272263508Sdim} 273263508Sdim 274263508Sdimstatic void AnalyzeVarArgs(CCState &State, 275263508Sdim const SmallVectorImpl<ISD::InputArg> &Ins) { 276263508Sdim State.AnalyzeFormalArguments(Ins, CC_MSP430_AssignStack); 277263508Sdim} 278263508Sdim 279263508Sdim/// Analyze incoming and outgoing function arguments. We need custom C++ code 280263508Sdim/// to handle special constraints in the ABI like reversing the order of the 281263508Sdim/// pieces of splitted arguments. In addition, all pieces of a certain argument 282263508Sdim/// have to be passed either using registers or the stack but never mixing both. 283263508Sdimtemplate<typename ArgT> 284263508Sdimstatic void AnalyzeArguments(CCState &State, 285263508Sdim SmallVectorImpl<CCValAssign> &ArgLocs, 286263508Sdim const SmallVectorImpl<ArgT> &Args) { 287263508Sdim static const uint16_t RegList[] = { 288263508Sdim MSP430::R15W, MSP430::R14W, MSP430::R13W, MSP430::R12W 289263508Sdim }; 290263508Sdim static const unsigned NbRegs = array_lengthof(RegList); 291263508Sdim 292263508Sdim if (State.isVarArg()) { 293263508Sdim AnalyzeVarArgs(State, Args); 294263508Sdim return; 295263508Sdim } 296263508Sdim 297263508Sdim SmallVector<unsigned, 4> ArgsParts; 298263508Sdim ParseFunctionArgs(Args, ArgsParts); 299263508Sdim 300263508Sdim unsigned RegsLeft = NbRegs; 301263508Sdim bool UseStack = false; 302263508Sdim unsigned ValNo = 0; 303263508Sdim 304263508Sdim for (unsigned i = 0, e = ArgsParts.size(); i != e; i++) { 305263508Sdim MVT ArgVT = Args[ValNo].VT; 306263508Sdim ISD::ArgFlagsTy ArgFlags = Args[ValNo].Flags; 307263508Sdim MVT LocVT = ArgVT; 308263508Sdim CCValAssign::LocInfo LocInfo = CCValAssign::Full; 309263508Sdim 310263508Sdim // Promote i8 to i16 311263508Sdim if (LocVT == MVT::i8) { 312263508Sdim LocVT = MVT::i16; 313263508Sdim if (ArgFlags.isSExt()) 314263508Sdim LocInfo = CCValAssign::SExt; 315263508Sdim else if (ArgFlags.isZExt()) 316263508Sdim LocInfo = CCValAssign::ZExt; 317263508Sdim else 318263508Sdim LocInfo = CCValAssign::AExt; 319263508Sdim } 320263508Sdim 321263508Sdim // Handle byval arguments 322263508Sdim if (ArgFlags.isByVal()) { 323263508Sdim State.HandleByVal(ValNo++, ArgVT, LocVT, LocInfo, 2, 2, ArgFlags); 324263508Sdim continue; 325263508Sdim } 326263508Sdim 327263508Sdim unsigned Parts = ArgsParts[i]; 328263508Sdim 329263508Sdim if (!UseStack && Parts <= RegsLeft) { 330263508Sdim unsigned FirstVal = ValNo; 331263508Sdim for (unsigned j = 0; j < Parts; j++) { 332263508Sdim unsigned Reg = State.AllocateReg(RegList, NbRegs); 333263508Sdim State.addLoc(CCValAssign::getReg(ValNo++, ArgVT, Reg, LocVT, LocInfo)); 334263508Sdim RegsLeft--; 335263508Sdim } 336263508Sdim 337263508Sdim // Reverse the order of the pieces to agree with the "big endian" format 338263508Sdim // required in the calling convention ABI. 339263508Sdim SmallVectorImpl<CCValAssign>::iterator B = ArgLocs.begin() + FirstVal; 340263508Sdim std::reverse(B, B + Parts); 341263508Sdim } else { 342263508Sdim UseStack = true; 343263508Sdim for (unsigned j = 0; j < Parts; j++) 344263508Sdim CC_MSP430_AssignStack(ValNo++, ArgVT, LocVT, LocInfo, ArgFlags, State); 345263508Sdim } 346263508Sdim } 347263508Sdim} 348263508Sdim 349263508Sdimstatic void AnalyzeRetResult(CCState &State, 350263508Sdim const SmallVectorImpl<ISD::InputArg> &Ins) { 351263508Sdim State.AnalyzeCallResult(Ins, RetCC_MSP430); 352263508Sdim} 353263508Sdim 354263508Sdimstatic void AnalyzeRetResult(CCState &State, 355263508Sdim const SmallVectorImpl<ISD::OutputArg> &Outs) { 356263508Sdim State.AnalyzeReturn(Outs, RetCC_MSP430); 357263508Sdim} 358263508Sdim 359263508Sdimtemplate<typename ArgT> 360263508Sdimstatic void AnalyzeReturnValues(CCState &State, 361263508Sdim SmallVectorImpl<CCValAssign> &RVLocs, 362263508Sdim const SmallVectorImpl<ArgT> &Args) { 363263508Sdim AnalyzeRetResult(State, Args); 364263508Sdim 365263508Sdim // Reverse splitted return values to get the "big endian" format required 366263508Sdim // to agree with the calling convention ABI. 367263508Sdim std::reverse(RVLocs.begin(), RVLocs.end()); 368263508Sdim} 369263508Sdim 370198090SrdivackySDValue 371198090SrdivackyMSP430TargetLowering::LowerFormalArguments(SDValue Chain, 372198090Srdivacky CallingConv::ID CallConv, 373198090Srdivacky bool isVarArg, 374198090Srdivacky const SmallVectorImpl<ISD::InputArg> 375198090Srdivacky &Ins, 376263508Sdim SDLoc dl, 377198090Srdivacky SelectionDAG &DAG, 378207618Srdivacky SmallVectorImpl<SDValue> &InVals) 379207618Srdivacky const { 380198090Srdivacky 381198090Srdivacky switch (CallConv) { 382193323Sed default: 383198090Srdivacky llvm_unreachable("Unsupported calling convention"); 384193323Sed case CallingConv::C: 385193323Sed case CallingConv::Fast: 386198090Srdivacky return LowerCCCArguments(Chain, CallConv, isVarArg, Ins, dl, DAG, InVals); 387200581Srdivacky case CallingConv::MSP430_INTR: 388234353Sdim if (Ins.empty()) 389234353Sdim return Chain; 390207618Srdivacky report_fatal_error("ISRs cannot have arguments"); 391193323Sed } 392193323Sed} 393193323Sed 394198090SrdivackySDValue 395239462SdimMSP430TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, 396207618Srdivacky SmallVectorImpl<SDValue> &InVals) const { 397239462Sdim SelectionDAG &DAG = CLI.DAG; 398263508Sdim SDLoc &dl = CLI.DL; 399263508Sdim SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs; 400263508Sdim SmallVectorImpl<SDValue> &OutVals = CLI.OutVals; 401263508Sdim SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins; 402239462Sdim SDValue Chain = CLI.Chain; 403239462Sdim SDValue Callee = CLI.Callee; 404239462Sdim bool &isTailCall = CLI.IsTailCall; 405239462Sdim CallingConv::ID CallConv = CLI.CallConv; 406239462Sdim bool isVarArg = CLI.IsVarArg; 407239462Sdim 408203954Srdivacky // MSP430 target does not yet support tail call optimization. 409203954Srdivacky isTailCall = false; 410198090Srdivacky 411198090Srdivacky switch (CallConv) { 412193323Sed default: 413198090Srdivacky llvm_unreachable("Unsupported calling convention"); 414193323Sed case CallingConv::Fast: 415193323Sed case CallingConv::C: 416198090Srdivacky return LowerCCCCallTo(Chain, Callee, CallConv, isVarArg, isTailCall, 417210299Sed Outs, OutVals, Ins, dl, DAG, InVals); 418200581Srdivacky case CallingConv::MSP430_INTR: 419207618Srdivacky report_fatal_error("ISRs cannot be called directly"); 420193323Sed } 421193323Sed} 422193323Sed 423193323Sed/// LowerCCCArguments - transform physical registers into virtual registers and 424193323Sed/// generate load operations for arguments places on the stack. 425193323Sed// FIXME: struct return stuff 426198090SrdivackySDValue 427198090SrdivackyMSP430TargetLowering::LowerCCCArguments(SDValue Chain, 428198090Srdivacky CallingConv::ID CallConv, 429198090Srdivacky bool isVarArg, 430198090Srdivacky const SmallVectorImpl<ISD::InputArg> 431198090Srdivacky &Ins, 432263508Sdim SDLoc dl, 433198090Srdivacky SelectionDAG &DAG, 434207618Srdivacky SmallVectorImpl<SDValue> &InVals) 435207618Srdivacky const { 436193323Sed MachineFunction &MF = DAG.getMachineFunction(); 437193323Sed MachineFrameInfo *MFI = MF.getFrameInfo(); 438193323Sed MachineRegisterInfo &RegInfo = MF.getRegInfo(); 439249423Sdim MSP430MachineFunctionInfo *FuncInfo = MF.getInfo<MSP430MachineFunctionInfo>(); 440193323Sed 441193323Sed // Assign locations to all of the incoming arguments. 442193323Sed SmallVector<CCValAssign, 16> ArgLocs; 443223017Sdim CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), 444239462Sdim getTargetMachine(), ArgLocs, *DAG.getContext()); 445263508Sdim AnalyzeArguments(CCInfo, ArgLocs, Ins); 446193323Sed 447249423Sdim // Create frame index for the start of the first vararg value 448249423Sdim if (isVarArg) { 449249423Sdim unsigned Offset = CCInfo.getNextStackOffset(); 450249423Sdim FuncInfo->setVarArgsFrameIndex(MFI->CreateFixedObject(1, Offset, true)); 451249423Sdim } 452193323Sed 453193323Sed for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { 454193323Sed CCValAssign &VA = ArgLocs[i]; 455193323Sed if (VA.isRegLoc()) { 456193323Sed // Arguments passed in registers 457198090Srdivacky EVT RegVT = VA.getLocVT(); 458198090Srdivacky switch (RegVT.getSimpleVT().SimpleTy) { 459219077Sdim default: 460198090Srdivacky { 461198090Srdivacky#ifndef NDEBUG 462198090Srdivacky errs() << "LowerFormalArguments Unhandled argument type: " 463198090Srdivacky << RegVT.getSimpleVT().SimpleTy << "\n"; 464198090Srdivacky#endif 465198090Srdivacky llvm_unreachable(0); 466198090Srdivacky } 467193323Sed case MVT::i16: 468239462Sdim unsigned VReg = RegInfo.createVirtualRegister(&MSP430::GR16RegClass); 469193323Sed RegInfo.addLiveIn(VA.getLocReg(), VReg); 470198090Srdivacky SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, VReg, RegVT); 471193323Sed 472193323Sed // If this is an 8-bit value, it is really passed promoted to 16 473193323Sed // bits. Insert an assert[sz]ext to capture this, then truncate to the 474193323Sed // right size. 475193323Sed if (VA.getLocInfo() == CCValAssign::SExt) 476193323Sed ArgValue = DAG.getNode(ISD::AssertSext, dl, RegVT, ArgValue, 477193323Sed DAG.getValueType(VA.getValVT())); 478193323Sed else if (VA.getLocInfo() == CCValAssign::ZExt) 479193323Sed ArgValue = DAG.getNode(ISD::AssertZext, dl, RegVT, ArgValue, 480193323Sed DAG.getValueType(VA.getValVT())); 481193323Sed 482193323Sed if (VA.getLocInfo() != CCValAssign::Full) 483193323Sed ArgValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), ArgValue); 484193323Sed 485198090Srdivacky InVals.push_back(ArgValue); 486193323Sed } 487193323Sed } else { 488193323Sed // Sanity check 489193323Sed assert(VA.isMemLoc()); 490249423Sdim 491249423Sdim SDValue InVal; 492249423Sdim ISD::ArgFlagsTy Flags = Ins[i].Flags; 493249423Sdim 494249423Sdim if (Flags.isByVal()) { 495249423Sdim int FI = MFI->CreateFixedObject(Flags.getByValSize(), 496249423Sdim VA.getLocMemOffset(), true); 497249423Sdim InVal = DAG.getFrameIndex(FI, getPointerTy()); 498249423Sdim } else { 499249423Sdim // Load the argument to a virtual register 500249423Sdim unsigned ObjSize = VA.getLocVT().getSizeInBits()/8; 501249423Sdim if (ObjSize > 2) { 502249423Sdim errs() << "LowerFormalArguments Unhandled argument type: " 503249423Sdim << EVT(VA.getLocVT()).getEVTString() 504249423Sdim << "\n"; 505249423Sdim } 506249423Sdim // Create the frame index object for this incoming parameter... 507249423Sdim int FI = MFI->CreateFixedObject(ObjSize, VA.getLocMemOffset(), true); 508249423Sdim 509249423Sdim // Create the SelectionDAG nodes corresponding to a load 510249423Sdim //from this parameter 511249423Sdim SDValue FIN = DAG.getFrameIndex(FI, MVT::i16); 512249423Sdim InVal = DAG.getLoad(VA.getLocVT(), dl, Chain, FIN, 513249423Sdim MachinePointerInfo::getFixedStack(FI), 514249423Sdim false, false, false, 0); 515193323Sed } 516193323Sed 517249423Sdim InVals.push_back(InVal); 518193323Sed } 519193323Sed } 520193323Sed 521198090Srdivacky return Chain; 522193323Sed} 523193323Sed 524198090SrdivackySDValue 525198090SrdivackyMSP430TargetLowering::LowerReturn(SDValue Chain, 526198090Srdivacky CallingConv::ID CallConv, bool isVarArg, 527198090Srdivacky const SmallVectorImpl<ISD::OutputArg> &Outs, 528210299Sed const SmallVectorImpl<SDValue> &OutVals, 529263508Sdim SDLoc dl, SelectionDAG &DAG) const { 530198090Srdivacky 531193323Sed // CCValAssign - represent the assignment of the return value to a location 532193323Sed SmallVector<CCValAssign, 16> RVLocs; 533193323Sed 534200581Srdivacky // ISRs cannot return any value. 535234353Sdim if (CallConv == CallingConv::MSP430_INTR && !Outs.empty()) 536207618Srdivacky report_fatal_error("ISRs cannot return any value"); 537200581Srdivacky 538193323Sed // CCState - Info about the registers and stack slot. 539223017Sdim CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), 540239462Sdim getTargetMachine(), RVLocs, *DAG.getContext()); 541193323Sed 542198090Srdivacky // Analize return values. 543263508Sdim AnalyzeReturnValues(CCInfo, RVLocs, Outs); 544193323Sed 545193323Sed SDValue Flag; 546249423Sdim SmallVector<SDValue, 4> RetOps(1, Chain); 547193323Sed 548193323Sed // Copy the result values into the output registers. 549193323Sed for (unsigned i = 0; i != RVLocs.size(); ++i) { 550193323Sed CCValAssign &VA = RVLocs[i]; 551193323Sed assert(VA.isRegLoc() && "Can only return in registers!"); 552193323Sed 553193323Sed Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), 554210299Sed OutVals[i], Flag); 555193323Sed 556193323Sed // Guarantee that all emitted copies are stuck together, 557193323Sed // avoiding something bad. 558193323Sed Flag = Chain.getValue(1); 559249423Sdim RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); 560193323Sed } 561193323Sed 562200581Srdivacky unsigned Opc = (CallConv == CallingConv::MSP430_INTR ? 563200581Srdivacky MSP430ISD::RETI_FLAG : MSP430ISD::RET_FLAG); 564200581Srdivacky 565249423Sdim RetOps[0] = Chain; // Update chain. 566249423Sdim 567249423Sdim // Add the flag if we have it. 568193323Sed if (Flag.getNode()) 569249423Sdim RetOps.push_back(Flag); 570193323Sed 571249423Sdim return DAG.getNode(Opc, dl, MVT::Other, &RetOps[0], RetOps.size()); 572193323Sed} 573193323Sed 574193323Sed/// LowerCCCCallTo - functions arguments are copied from virtual regs to 575193323Sed/// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted. 576263508Sdim// TODO: sret. 577198090SrdivackySDValue 578198090SrdivackyMSP430TargetLowering::LowerCCCCallTo(SDValue Chain, SDValue Callee, 579198090Srdivacky CallingConv::ID CallConv, bool isVarArg, 580198090Srdivacky bool isTailCall, 581198090Srdivacky const SmallVectorImpl<ISD::OutputArg> 582198090Srdivacky &Outs, 583210299Sed const SmallVectorImpl<SDValue> &OutVals, 584198090Srdivacky const SmallVectorImpl<ISD::InputArg> &Ins, 585263508Sdim SDLoc dl, SelectionDAG &DAG, 586207618Srdivacky SmallVectorImpl<SDValue> &InVals) const { 587193323Sed // Analyze operands of the call, assigning locations to each operand. 588193323Sed SmallVector<CCValAssign, 16> ArgLocs; 589223017Sdim CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), 590239462Sdim getTargetMachine(), ArgLocs, *DAG.getContext()); 591263508Sdim AnalyzeArguments(CCInfo, ArgLocs, Outs); 592193323Sed 593193323Sed // Get a count of how many bytes are to be pushed on the stack. 594193323Sed unsigned NumBytes = CCInfo.getNextStackOffset(); 595193323Sed 596193323Sed Chain = DAG.getCALLSEQ_START(Chain ,DAG.getConstant(NumBytes, 597263508Sdim getPointerTy(), true), 598263508Sdim dl); 599193323Sed 600193323Sed SmallVector<std::pair<unsigned, SDValue>, 4> RegsToPass; 601193323Sed SmallVector<SDValue, 12> MemOpChains; 602193323Sed SDValue StackPtr; 603193323Sed 604193323Sed // Walk the register/memloc assignments, inserting copies/loads. 605193323Sed for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { 606193323Sed CCValAssign &VA = ArgLocs[i]; 607193323Sed 608210299Sed SDValue Arg = OutVals[i]; 609193323Sed 610193323Sed // Promote the value if needed. 611193323Sed switch (VA.getLocInfo()) { 612198090Srdivacky default: llvm_unreachable("Unknown loc info!"); 613193323Sed case CCValAssign::Full: break; 614193323Sed case CCValAssign::SExt: 615193323Sed Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg); 616193323Sed break; 617193323Sed case CCValAssign::ZExt: 618193323Sed Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg); 619193323Sed break; 620193323Sed case CCValAssign::AExt: 621193323Sed Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg); 622193323Sed break; 623193323Sed } 624193323Sed 625193323Sed // Arguments that can be passed on register must be kept at RegsToPass 626193323Sed // vector 627193323Sed if (VA.isRegLoc()) { 628193323Sed RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); 629193323Sed } else { 630193323Sed assert(VA.isMemLoc()); 631193323Sed 632193323Sed if (StackPtr.getNode() == 0) 633193323Sed StackPtr = DAG.getCopyFromReg(Chain, dl, MSP430::SPW, getPointerTy()); 634193323Sed 635193323Sed SDValue PtrOff = DAG.getNode(ISD::ADD, dl, getPointerTy(), 636193323Sed StackPtr, 637193323Sed DAG.getIntPtrConstant(VA.getLocMemOffset())); 638193323Sed 639249423Sdim SDValue MemOp; 640249423Sdim ISD::ArgFlagsTy Flags = Outs[i].Flags; 641193323Sed 642249423Sdim if (Flags.isByVal()) { 643249423Sdim SDValue SizeNode = DAG.getConstant(Flags.getByValSize(), MVT::i16); 644249423Sdim MemOp = DAG.getMemcpy(Chain, dl, PtrOff, Arg, SizeNode, 645249423Sdim Flags.getByValAlign(), 646249423Sdim /*isVolatile*/false, 647249423Sdim /*AlwaysInline=*/true, 648249423Sdim MachinePointerInfo(), 649249423Sdim MachinePointerInfo()); 650249423Sdim } else { 651249423Sdim MemOp = DAG.getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo(), 652249423Sdim false, false, 0); 653249423Sdim } 654249423Sdim 655249423Sdim MemOpChains.push_back(MemOp); 656193323Sed } 657193323Sed } 658193323Sed 659193323Sed // Transform all store nodes into one single node because all store nodes are 660193323Sed // independent of each other. 661193323Sed if (!MemOpChains.empty()) 662193323Sed Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, 663193323Sed &MemOpChains[0], MemOpChains.size()); 664193323Sed 665193323Sed // Build a sequence of copy-to-reg nodes chained together with token chain and 666193323Sed // flag operands which copy the outgoing args into registers. The InFlag in 667221345Sdim // necessary since all emitted instructions must be stuck together. 668193323Sed SDValue InFlag; 669193323Sed for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { 670193323Sed Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first, 671193323Sed RegsToPass[i].second, InFlag); 672193323Sed InFlag = Chain.getValue(1); 673193323Sed } 674193323Sed 675193323Sed // If the callee is a GlobalAddress node (quite common, every direct call is) 676193323Sed // turn it into a TargetGlobalAddress node so that legalize doesn't hack it. 677193323Sed // Likewise ExternalSymbol -> TargetExternalSymbol. 678193323Sed if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) 679210299Sed Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i16); 680193323Sed else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee)) 681193323Sed Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i16); 682193323Sed 683193323Sed // Returns a chain & a flag for retval copy to use. 684218893Sdim SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); 685193323Sed SmallVector<SDValue, 8> Ops; 686193323Sed Ops.push_back(Chain); 687193323Sed Ops.push_back(Callee); 688193323Sed 689193323Sed // Add argument registers to the end of the list so that they are 690193323Sed // known live into the call. 691193323Sed for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) 692193323Sed Ops.push_back(DAG.getRegister(RegsToPass[i].first, 693193323Sed RegsToPass[i].second.getValueType())); 694193323Sed 695193323Sed if (InFlag.getNode()) 696193323Sed Ops.push_back(InFlag); 697193323Sed 698193323Sed Chain = DAG.getNode(MSP430ISD::CALL, dl, NodeTys, &Ops[0], Ops.size()); 699193323Sed InFlag = Chain.getValue(1); 700193323Sed 701193323Sed // Create the CALLSEQ_END node. 702193323Sed Chain = DAG.getCALLSEQ_END(Chain, 703193323Sed DAG.getConstant(NumBytes, getPointerTy(), true), 704193323Sed DAG.getConstant(0, getPointerTy(), true), 705263508Sdim InFlag, dl); 706193323Sed InFlag = Chain.getValue(1); 707193323Sed 708193323Sed // Handle result values, copying them out of physregs into vregs that we 709193323Sed // return. 710198090Srdivacky return LowerCallResult(Chain, InFlag, CallConv, isVarArg, Ins, dl, 711198090Srdivacky DAG, InVals); 712193323Sed} 713193323Sed 714198090Srdivacky/// LowerCallResult - Lower the result values of a call into the 715198090Srdivacky/// appropriate copies out of appropriate physical registers. 716198090Srdivacky/// 717198090SrdivackySDValue 718193323SedMSP430TargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag, 719198090Srdivacky CallingConv::ID CallConv, bool isVarArg, 720198090Srdivacky const SmallVectorImpl<ISD::InputArg> &Ins, 721263508Sdim SDLoc dl, SelectionDAG &DAG, 722207618Srdivacky SmallVectorImpl<SDValue> &InVals) const { 723193323Sed 724193323Sed // Assign locations to each value returned by this call. 725193323Sed SmallVector<CCValAssign, 16> RVLocs; 726223017Sdim CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), 727239462Sdim getTargetMachine(), RVLocs, *DAG.getContext()); 728193323Sed 729263508Sdim AnalyzeReturnValues(CCInfo, RVLocs, Ins); 730193323Sed 731193323Sed // Copy all of the result registers out of their specified physreg. 732193323Sed for (unsigned i = 0; i != RVLocs.size(); ++i) { 733193323Sed Chain = DAG.getCopyFromReg(Chain, dl, RVLocs[i].getLocReg(), 734193323Sed RVLocs[i].getValVT(), InFlag).getValue(1); 735193323Sed InFlag = Chain.getValue(2); 736198090Srdivacky InVals.push_back(Chain.getValue(0)); 737193323Sed } 738193323Sed 739198090Srdivacky return Chain; 740193323Sed} 741193323Sed 742193323SedSDValue MSP430TargetLowering::LowerShifts(SDValue Op, 743207618Srdivacky SelectionDAG &DAG) const { 744193323Sed unsigned Opc = Op.getOpcode(); 745193323Sed SDNode* N = Op.getNode(); 746198090Srdivacky EVT VT = Op.getValueType(); 747263508Sdim SDLoc dl(N); 748193323Sed 749200581Srdivacky // Expand non-constant shifts to loops: 750193323Sed if (!isa<ConstantSDNode>(N->getOperand(1))) 751200581Srdivacky switch (Opc) { 752234353Sdim default: llvm_unreachable("Invalid shift opcode!"); 753200581Srdivacky case ISD::SHL: 754200581Srdivacky return DAG.getNode(MSP430ISD::SHL, dl, 755200581Srdivacky VT, N->getOperand(0), N->getOperand(1)); 756200581Srdivacky case ISD::SRA: 757200581Srdivacky return DAG.getNode(MSP430ISD::SRA, dl, 758200581Srdivacky VT, N->getOperand(0), N->getOperand(1)); 759200581Srdivacky case ISD::SRL: 760200581Srdivacky return DAG.getNode(MSP430ISD::SRL, dl, 761200581Srdivacky VT, N->getOperand(0), N->getOperand(1)); 762200581Srdivacky } 763193323Sed 764193323Sed uint64_t ShiftAmount = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue(); 765193323Sed 766193323Sed // Expand the stuff into sequence of shifts. 767193323Sed // FIXME: for some shift amounts this might be done better! 768193323Sed // E.g.: foo >> (8 + N) => sxt(swpb(foo)) >> N 769193323Sed SDValue Victim = N->getOperand(0); 770193323Sed 771193323Sed if (Opc == ISD::SRL && ShiftAmount) { 772193323Sed // Emit a special goodness here: 773193323Sed // srl A, 1 => clrc; rrc A 774193323Sed Victim = DAG.getNode(MSP430ISD::RRC, dl, VT, Victim); 775193323Sed ShiftAmount -= 1; 776193323Sed } 777193323Sed 778193323Sed while (ShiftAmount--) 779193323Sed Victim = DAG.getNode((Opc == ISD::SHL ? MSP430ISD::RLA : MSP430ISD::RRA), 780193323Sed dl, VT, Victim); 781193323Sed 782193323Sed return Victim; 783193323Sed} 784193323Sed 785207618SrdivackySDValue MSP430TargetLowering::LowerGlobalAddress(SDValue Op, 786207618Srdivacky SelectionDAG &DAG) const { 787193323Sed const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal(); 788193323Sed int64_t Offset = cast<GlobalAddressSDNode>(Op)->getOffset(); 789193323Sed 790193323Sed // Create the TargetGlobalAddress node, folding in the constant offset. 791263508Sdim SDValue Result = DAG.getTargetGlobalAddress(GV, SDLoc(Op), 792210299Sed getPointerTy(), Offset); 793263508Sdim return DAG.getNode(MSP430ISD::Wrapper, SDLoc(Op), 794193323Sed getPointerTy(), Result); 795193323Sed} 796193323Sed 797193323SedSDValue MSP430TargetLowering::LowerExternalSymbol(SDValue Op, 798207618Srdivacky SelectionDAG &DAG) const { 799263508Sdim SDLoc dl(Op); 800193323Sed const char *Sym = cast<ExternalSymbolSDNode>(Op)->getSymbol(); 801193323Sed SDValue Result = DAG.getTargetExternalSymbol(Sym, getPointerTy()); 802193323Sed 803234353Sdim return DAG.getNode(MSP430ISD::Wrapper, dl, getPointerTy(), Result); 804193323Sed} 805193323Sed 806207618SrdivackySDValue MSP430TargetLowering::LowerBlockAddress(SDValue Op, 807207618Srdivacky SelectionDAG &DAG) const { 808263508Sdim SDLoc dl(Op); 809207618Srdivacky const BlockAddress *BA = cast<BlockAddressSDNode>(Op)->getBlockAddress(); 810243830Sdim SDValue Result = DAG.getTargetBlockAddress(BA, getPointerTy()); 811207618Srdivacky 812234353Sdim return DAG.getNode(MSP430ISD::Wrapper, dl, getPointerTy(), Result); 813207618Srdivacky} 814207618Srdivacky 815198396Srdivackystatic SDValue EmitCMP(SDValue &LHS, SDValue &RHS, SDValue &TargetCC, 816193323Sed ISD::CondCode CC, 817263508Sdim SDLoc dl, SelectionDAG &DAG) { 818193323Sed // FIXME: Handle bittests someday 819193323Sed assert(!LHS.getValueType().isFloatingPoint() && "We don't handle FP yet"); 820193323Sed 821193323Sed // FIXME: Handle jump negative someday 822198396Srdivacky MSP430CC::CondCodes TCC = MSP430CC::COND_INVALID; 823193323Sed switch (CC) { 824198090Srdivacky default: llvm_unreachable("Invalid integer condition!"); 825193323Sed case ISD::SETEQ: 826198396Srdivacky TCC = MSP430CC::COND_E; // aka COND_Z 827202375Srdivacky // Minor optimization: if LHS is a constant, swap operands, then the 828199989Srdivacky // constant can be folded into comparison. 829202375Srdivacky if (LHS.getOpcode() == ISD::Constant) 830199989Srdivacky std::swap(LHS, RHS); 831193323Sed break; 832193323Sed case ISD::SETNE: 833198396Srdivacky TCC = MSP430CC::COND_NE; // aka COND_NZ 834202375Srdivacky // Minor optimization: if LHS is a constant, swap operands, then the 835199989Srdivacky // constant can be folded into comparison. 836202375Srdivacky if (LHS.getOpcode() == ISD::Constant) 837199989Srdivacky std::swap(LHS, RHS); 838193323Sed break; 839193323Sed case ISD::SETULE: 840193323Sed std::swap(LHS, RHS); // FALLTHROUGH 841193323Sed case ISD::SETUGE: 842202878Srdivacky // Turn lhs u>= rhs with lhs constant into rhs u< lhs+1, this allows us to 843202878Srdivacky // fold constant into instruction. 844202878Srdivacky if (const ConstantSDNode * C = dyn_cast<ConstantSDNode>(LHS)) { 845202878Srdivacky LHS = RHS; 846202878Srdivacky RHS = DAG.getConstant(C->getSExtValue() + 1, C->getValueType(0)); 847202878Srdivacky TCC = MSP430CC::COND_LO; 848202878Srdivacky break; 849202878Srdivacky } 850198396Srdivacky TCC = MSP430CC::COND_HS; // aka COND_C 851193323Sed break; 852193323Sed case ISD::SETUGT: 853193323Sed std::swap(LHS, RHS); // FALLTHROUGH 854193323Sed case ISD::SETULT: 855202878Srdivacky // Turn lhs u< rhs with lhs constant into rhs u>= lhs+1, this allows us to 856202878Srdivacky // fold constant into instruction. 857202878Srdivacky if (const ConstantSDNode * C = dyn_cast<ConstantSDNode>(LHS)) { 858202878Srdivacky LHS = RHS; 859202878Srdivacky RHS = DAG.getConstant(C->getSExtValue() + 1, C->getValueType(0)); 860202878Srdivacky TCC = MSP430CC::COND_HS; 861202878Srdivacky break; 862202878Srdivacky } 863198396Srdivacky TCC = MSP430CC::COND_LO; // aka COND_NC 864193323Sed break; 865193323Sed case ISD::SETLE: 866193323Sed std::swap(LHS, RHS); // FALLTHROUGH 867193323Sed case ISD::SETGE: 868202878Srdivacky // Turn lhs >= rhs with lhs constant into rhs < lhs+1, this allows us to 869202878Srdivacky // fold constant into instruction. 870202878Srdivacky if (const ConstantSDNode * C = dyn_cast<ConstantSDNode>(LHS)) { 871202878Srdivacky LHS = RHS; 872202878Srdivacky RHS = DAG.getConstant(C->getSExtValue() + 1, C->getValueType(0)); 873202878Srdivacky TCC = MSP430CC::COND_L; 874202878Srdivacky break; 875202878Srdivacky } 876198396Srdivacky TCC = MSP430CC::COND_GE; 877193323Sed break; 878193323Sed case ISD::SETGT: 879193323Sed std::swap(LHS, RHS); // FALLTHROUGH 880193323Sed case ISD::SETLT: 881202878Srdivacky // Turn lhs < rhs with lhs constant into rhs >= lhs+1, this allows us to 882202878Srdivacky // fold constant into instruction. 883202878Srdivacky if (const ConstantSDNode * C = dyn_cast<ConstantSDNode>(LHS)) { 884202878Srdivacky LHS = RHS; 885202878Srdivacky RHS = DAG.getConstant(C->getSExtValue() + 1, C->getValueType(0)); 886202878Srdivacky TCC = MSP430CC::COND_GE; 887202878Srdivacky break; 888202878Srdivacky } 889198396Srdivacky TCC = MSP430CC::COND_L; 890193323Sed break; 891193323Sed } 892193323Sed 893198396Srdivacky TargetCC = DAG.getConstant(TCC, MVT::i8); 894218893Sdim return DAG.getNode(MSP430ISD::CMP, dl, MVT::Glue, LHS, RHS); 895193323Sed} 896193323Sed 897193323Sed 898207618SrdivackySDValue MSP430TargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const { 899193323Sed SDValue Chain = Op.getOperand(0); 900193323Sed ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get(); 901193323Sed SDValue LHS = Op.getOperand(2); 902193323Sed SDValue RHS = Op.getOperand(3); 903193323Sed SDValue Dest = Op.getOperand(4); 904263508Sdim SDLoc dl (Op); 905193323Sed 906198396Srdivacky SDValue TargetCC; 907193323Sed SDValue Flag = EmitCMP(LHS, RHS, TargetCC, CC, dl, DAG); 908193323Sed 909193323Sed return DAG.getNode(MSP430ISD::BR_CC, dl, Op.getValueType(), 910198396Srdivacky Chain, Dest, TargetCC, Flag); 911193323Sed} 912193323Sed 913207618SrdivackySDValue MSP430TargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const { 914200581Srdivacky SDValue LHS = Op.getOperand(0); 915200581Srdivacky SDValue RHS = Op.getOperand(1); 916263508Sdim SDLoc dl (Op); 917200581Srdivacky 918200581Srdivacky // If we are doing an AND and testing against zero, then the CMP 919200581Srdivacky // will not be generated. The AND (or BIT) will generate the condition codes, 920200581Srdivacky // but they are different from CMP. 921202878Srdivacky // FIXME: since we're doing a post-processing, use a pseudoinstr here, so 922202878Srdivacky // lowering & isel wouldn't diverge. 923200581Srdivacky bool andCC = false; 924200581Srdivacky if (ConstantSDNode *RHSC = dyn_cast<ConstantSDNode>(RHS)) { 925200581Srdivacky if (RHSC->isNullValue() && LHS.hasOneUse() && 926200581Srdivacky (LHS.getOpcode() == ISD::AND || 927200581Srdivacky (LHS.getOpcode() == ISD::TRUNCATE && 928200581Srdivacky LHS.getOperand(0).getOpcode() == ISD::AND))) { 929200581Srdivacky andCC = true; 930200581Srdivacky } 931200581Srdivacky } 932200581Srdivacky ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get(); 933200581Srdivacky SDValue TargetCC; 934200581Srdivacky SDValue Flag = EmitCMP(LHS, RHS, TargetCC, CC, dl, DAG); 935200581Srdivacky 936200581Srdivacky // Get the condition codes directly from the status register, if its easy. 937200581Srdivacky // Otherwise a branch will be generated. Note that the AND and BIT 938200581Srdivacky // instructions generate different flags than CMP, the carry bit can be used 939200581Srdivacky // for NE/EQ. 940200581Srdivacky bool Invert = false; 941200581Srdivacky bool Shift = false; 942200581Srdivacky bool Convert = true; 943200581Srdivacky switch (cast<ConstantSDNode>(TargetCC)->getZExtValue()) { 944200581Srdivacky default: 945200581Srdivacky Convert = false; 946200581Srdivacky break; 947200581Srdivacky case MSP430CC::COND_HS: 948200581Srdivacky // Res = SRW & 1, no processing is required 949200581Srdivacky break; 950202878Srdivacky case MSP430CC::COND_LO: 951200581Srdivacky // Res = ~(SRW & 1) 952200581Srdivacky Invert = true; 953200581Srdivacky break; 954202878Srdivacky case MSP430CC::COND_NE: 955200581Srdivacky if (andCC) { 956200581Srdivacky // C = ~Z, thus Res = SRW & 1, no processing is required 957200581Srdivacky } else { 958204642Srdivacky // Res = ~((SRW >> 1) & 1) 959200581Srdivacky Shift = true; 960204642Srdivacky Invert = true; 961200581Srdivacky } 962200581Srdivacky break; 963202878Srdivacky case MSP430CC::COND_E: 964204642Srdivacky Shift = true; 965204642Srdivacky // C = ~Z for AND instruction, thus we can put Res = ~(SRW & 1), however, 966204642Srdivacky // Res = (SRW >> 1) & 1 is 1 word shorter. 967200581Srdivacky break; 968200581Srdivacky } 969200581Srdivacky EVT VT = Op.getValueType(); 970200581Srdivacky SDValue One = DAG.getConstant(1, VT); 971200581Srdivacky if (Convert) { 972200581Srdivacky SDValue SR = DAG.getCopyFromReg(DAG.getEntryNode(), dl, MSP430::SRW, 973202878Srdivacky MVT::i16, Flag); 974200581Srdivacky if (Shift) 975200581Srdivacky // FIXME: somewhere this is turned into a SRL, lower it MSP specific? 976200581Srdivacky SR = DAG.getNode(ISD::SRA, dl, MVT::i16, SR, One); 977200581Srdivacky SR = DAG.getNode(ISD::AND, dl, MVT::i16, SR, One); 978200581Srdivacky if (Invert) 979200581Srdivacky SR = DAG.getNode(ISD::XOR, dl, MVT::i16, SR, One); 980200581Srdivacky return SR; 981200581Srdivacky } else { 982200581Srdivacky SDValue Zero = DAG.getConstant(0, VT); 983218893Sdim SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::Glue); 984200581Srdivacky SmallVector<SDValue, 4> Ops; 985200581Srdivacky Ops.push_back(One); 986200581Srdivacky Ops.push_back(Zero); 987200581Srdivacky Ops.push_back(TargetCC); 988200581Srdivacky Ops.push_back(Flag); 989200581Srdivacky return DAG.getNode(MSP430ISD::SELECT_CC, dl, VTs, &Ops[0], Ops.size()); 990200581Srdivacky } 991200581Srdivacky} 992200581Srdivacky 993207618SrdivackySDValue MSP430TargetLowering::LowerSELECT_CC(SDValue Op, 994207618Srdivacky SelectionDAG &DAG) const { 995193323Sed SDValue LHS = Op.getOperand(0); 996193323Sed SDValue RHS = Op.getOperand(1); 997193323Sed SDValue TrueV = Op.getOperand(2); 998193323Sed SDValue FalseV = Op.getOperand(3); 999193323Sed ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get(); 1000263508Sdim SDLoc dl (Op); 1001193323Sed 1002198396Srdivacky SDValue TargetCC; 1003193323Sed SDValue Flag = EmitCMP(LHS, RHS, TargetCC, CC, dl, DAG); 1004193323Sed 1005218893Sdim SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::Glue); 1006193323Sed SmallVector<SDValue, 4> Ops; 1007193323Sed Ops.push_back(TrueV); 1008193323Sed Ops.push_back(FalseV); 1009198396Srdivacky Ops.push_back(TargetCC); 1010193323Sed Ops.push_back(Flag); 1011193323Sed 1012193323Sed return DAG.getNode(MSP430ISD::SELECT_CC, dl, VTs, &Ops[0], Ops.size()); 1013193323Sed} 1014193323Sed 1015193323SedSDValue MSP430TargetLowering::LowerSIGN_EXTEND(SDValue Op, 1016207618Srdivacky SelectionDAG &DAG) const { 1017193323Sed SDValue Val = Op.getOperand(0); 1018198090Srdivacky EVT VT = Op.getValueType(); 1019263508Sdim SDLoc dl(Op); 1020193323Sed 1021193323Sed assert(VT == MVT::i16 && "Only support i16 for now!"); 1022193323Sed 1023193323Sed return DAG.getNode(ISD::SIGN_EXTEND_INREG, dl, VT, 1024193323Sed DAG.getNode(ISD::ANY_EXTEND, dl, VT, Val), 1025193323Sed DAG.getValueType(Val.getValueType())); 1026193323Sed} 1027193323Sed 1028207618SrdivackySDValue 1029207618SrdivackyMSP430TargetLowering::getReturnAddressFrameIndex(SelectionDAG &DAG) const { 1030200581Srdivacky MachineFunction &MF = DAG.getMachineFunction(); 1031200581Srdivacky MSP430MachineFunctionInfo *FuncInfo = MF.getInfo<MSP430MachineFunctionInfo>(); 1032200581Srdivacky int ReturnAddrIndex = FuncInfo->getRAIndex(); 1033200581Srdivacky 1034200581Srdivacky if (ReturnAddrIndex == 0) { 1035200581Srdivacky // Set up a frame object for the return address. 1036200581Srdivacky uint64_t SlotSize = TD->getPointerSize(); 1037200581Srdivacky ReturnAddrIndex = MF.getFrameInfo()->CreateFixedObject(SlotSize, -SlotSize, 1038210299Sed true); 1039200581Srdivacky FuncInfo->setRAIndex(ReturnAddrIndex); 1040200581Srdivacky } 1041200581Srdivacky 1042200581Srdivacky return DAG.getFrameIndex(ReturnAddrIndex, getPointerTy()); 1043200581Srdivacky} 1044200581Srdivacky 1045207618SrdivackySDValue MSP430TargetLowering::LowerRETURNADDR(SDValue Op, 1046207618Srdivacky SelectionDAG &DAG) const { 1047208599Srdivacky MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); 1048208599Srdivacky MFI->setReturnAddressIsTaken(true); 1049208599Srdivacky 1050200581Srdivacky unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue(); 1051263508Sdim SDLoc dl(Op); 1052200581Srdivacky 1053200581Srdivacky if (Depth > 0) { 1054200581Srdivacky SDValue FrameAddr = LowerFRAMEADDR(Op, DAG); 1055200581Srdivacky SDValue Offset = 1056200581Srdivacky DAG.getConstant(TD->getPointerSize(), MVT::i16); 1057200581Srdivacky return DAG.getLoad(getPointerTy(), dl, DAG.getEntryNode(), 1058200581Srdivacky DAG.getNode(ISD::ADD, dl, getPointerTy(), 1059200581Srdivacky FrameAddr, Offset), 1060234353Sdim MachinePointerInfo(), false, false, false, 0); 1061200581Srdivacky } 1062200581Srdivacky 1063200581Srdivacky // Just load the return address. 1064200581Srdivacky SDValue RetAddrFI = getReturnAddressFrameIndex(DAG); 1065200581Srdivacky return DAG.getLoad(getPointerTy(), dl, DAG.getEntryNode(), 1066234353Sdim RetAddrFI, MachinePointerInfo(), false, false, false, 0); 1067200581Srdivacky} 1068200581Srdivacky 1069207618SrdivackySDValue MSP430TargetLowering::LowerFRAMEADDR(SDValue Op, 1070207618Srdivacky SelectionDAG &DAG) const { 1071200581Srdivacky MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); 1072200581Srdivacky MFI->setFrameAddressIsTaken(true); 1073208599Srdivacky 1074200581Srdivacky EVT VT = Op.getValueType(); 1075263508Sdim SDLoc dl(Op); // FIXME probably not meaningful 1076200581Srdivacky unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue(); 1077200581Srdivacky SDValue FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, 1078200581Srdivacky MSP430::FPW, VT); 1079200581Srdivacky while (Depth--) 1080218893Sdim FrameAddr = DAG.getLoad(VT, dl, DAG.getEntryNode(), FrameAddr, 1081218893Sdim MachinePointerInfo(), 1082234353Sdim false, false, false, 0); 1083200581Srdivacky return FrameAddr; 1084200581Srdivacky} 1085200581Srdivacky 1086249423SdimSDValue MSP430TargetLowering::LowerVASTART(SDValue Op, 1087249423Sdim SelectionDAG &DAG) const { 1088249423Sdim MachineFunction &MF = DAG.getMachineFunction(); 1089249423Sdim MSP430MachineFunctionInfo *FuncInfo = MF.getInfo<MSP430MachineFunctionInfo>(); 1090249423Sdim 1091249423Sdim // Frame index of first vararg argument 1092249423Sdim SDValue FrameIndex = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(), 1093249423Sdim getPointerTy()); 1094249423Sdim const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue(); 1095249423Sdim 1096249423Sdim // Create a store of the frame index to the location operand 1097263508Sdim return DAG.getStore(Op.getOperand(0), SDLoc(Op), FrameIndex, 1098249423Sdim Op.getOperand(1), MachinePointerInfo(SV), 1099249423Sdim false, false, 0); 1100249423Sdim} 1101249423Sdim 1102263508SdimSDValue MSP430TargetLowering::LowerJumpTable(SDValue Op, 1103263508Sdim SelectionDAG &DAG) const { 1104263508Sdim JumpTableSDNode *JT = cast<JumpTableSDNode>(Op); 1105263508Sdim SDValue Result = DAG.getTargetJumpTable(JT->getIndex(), getPointerTy()); 1106263508Sdim return DAG.getNode(MSP430ISD::Wrapper, SDLoc(JT), 1107263508Sdim getPointerTy(), Result); 1108263508Sdim} 1109263508Sdim 1110199481Srdivacky/// getPostIndexedAddressParts - returns true by value, base pointer and 1111199481Srdivacky/// offset pointer and addressing mode by reference if this node can be 1112199481Srdivacky/// combined with a load / store to form a post-indexed load / store. 1113199481Srdivackybool MSP430TargetLowering::getPostIndexedAddressParts(SDNode *N, SDNode *Op, 1114199481Srdivacky SDValue &Base, 1115199481Srdivacky SDValue &Offset, 1116199481Srdivacky ISD::MemIndexedMode &AM, 1117199481Srdivacky SelectionDAG &DAG) const { 1118199481Srdivacky 1119199481Srdivacky LoadSDNode *LD = cast<LoadSDNode>(N); 1120199481Srdivacky if (LD->getExtensionType() != ISD::NON_EXTLOAD) 1121199481Srdivacky return false; 1122199481Srdivacky 1123199481Srdivacky EVT VT = LD->getMemoryVT(); 1124199481Srdivacky if (VT != MVT::i8 && VT != MVT::i16) 1125199481Srdivacky return false; 1126199481Srdivacky 1127199481Srdivacky if (Op->getOpcode() != ISD::ADD) 1128199481Srdivacky return false; 1129199481Srdivacky 1130199481Srdivacky if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(Op->getOperand(1))) { 1131199481Srdivacky uint64_t RHSC = RHS->getZExtValue(); 1132199481Srdivacky if ((VT == MVT::i16 && RHSC != 2) || 1133199481Srdivacky (VT == MVT::i8 && RHSC != 1)) 1134199481Srdivacky return false; 1135199481Srdivacky 1136199481Srdivacky Base = Op->getOperand(0); 1137199481Srdivacky Offset = DAG.getConstant(RHSC, VT); 1138199481Srdivacky AM = ISD::POST_INC; 1139199481Srdivacky return true; 1140199481Srdivacky } 1141199481Srdivacky 1142199481Srdivacky return false; 1143199481Srdivacky} 1144199481Srdivacky 1145199481Srdivacky 1146193323Sedconst char *MSP430TargetLowering::getTargetNodeName(unsigned Opcode) const { 1147193323Sed switch (Opcode) { 1148193323Sed default: return NULL; 1149193323Sed case MSP430ISD::RET_FLAG: return "MSP430ISD::RET_FLAG"; 1150200581Srdivacky case MSP430ISD::RETI_FLAG: return "MSP430ISD::RETI_FLAG"; 1151193323Sed case MSP430ISD::RRA: return "MSP430ISD::RRA"; 1152193323Sed case MSP430ISD::RLA: return "MSP430ISD::RLA"; 1153193323Sed case MSP430ISD::RRC: return "MSP430ISD::RRC"; 1154193323Sed case MSP430ISD::CALL: return "MSP430ISD::CALL"; 1155193323Sed case MSP430ISD::Wrapper: return "MSP430ISD::Wrapper"; 1156193323Sed case MSP430ISD::BR_CC: return "MSP430ISD::BR_CC"; 1157193323Sed case MSP430ISD::CMP: return "MSP430ISD::CMP"; 1158193323Sed case MSP430ISD::SELECT_CC: return "MSP430ISD::SELECT_CC"; 1159200581Srdivacky case MSP430ISD::SHL: return "MSP430ISD::SHL"; 1160200581Srdivacky case MSP430ISD::SRA: return "MSP430ISD::SRA"; 1161193323Sed } 1162193323Sed} 1163193323Sed 1164226633Sdimbool MSP430TargetLowering::isTruncateFree(Type *Ty1, 1165226633Sdim Type *Ty2) const { 1166203954Srdivacky if (!Ty1->isIntegerTy() || !Ty2->isIntegerTy()) 1167202878Srdivacky return false; 1168202878Srdivacky 1169202878Srdivacky return (Ty1->getPrimitiveSizeInBits() > Ty2->getPrimitiveSizeInBits()); 1170202878Srdivacky} 1171202878Srdivacky 1172202878Srdivackybool MSP430TargetLowering::isTruncateFree(EVT VT1, EVT VT2) const { 1173202878Srdivacky if (!VT1.isInteger() || !VT2.isInteger()) 1174202878Srdivacky return false; 1175202878Srdivacky 1176202878Srdivacky return (VT1.getSizeInBits() > VT2.getSizeInBits()); 1177202878Srdivacky} 1178202878Srdivacky 1179226633Sdimbool MSP430TargetLowering::isZExtFree(Type *Ty1, Type *Ty2) const { 1180202878Srdivacky // MSP430 implicitly zero-extends 8-bit results in 16-bit registers. 1181203954Srdivacky return 0 && Ty1->isIntegerTy(8) && Ty2->isIntegerTy(16); 1182202878Srdivacky} 1183202878Srdivacky 1184202878Srdivackybool MSP430TargetLowering::isZExtFree(EVT VT1, EVT VT2) const { 1185202878Srdivacky // MSP430 implicitly zero-extends 8-bit results in 16-bit registers. 1186202878Srdivacky return 0 && VT1 == MVT::i8 && VT2 == MVT::i16; 1187202878Srdivacky} 1188202878Srdivacky 1189249423Sdimbool MSP430TargetLowering::isZExtFree(SDValue Val, EVT VT2) const { 1190249423Sdim return isZExtFree(Val.getValueType(), VT2); 1191249423Sdim} 1192249423Sdim 1193193323Sed//===----------------------------------------------------------------------===// 1194193323Sed// Other Lowering Code 1195193323Sed//===----------------------------------------------------------------------===// 1196193323Sed 1197193323SedMachineBasicBlock* 1198200581SrdivackyMSP430TargetLowering::EmitShiftInstr(MachineInstr *MI, 1199207618Srdivacky MachineBasicBlock *BB) const { 1200200581Srdivacky MachineFunction *F = BB->getParent(); 1201200581Srdivacky MachineRegisterInfo &RI = F->getRegInfo(); 1202200581Srdivacky DebugLoc dl = MI->getDebugLoc(); 1203200581Srdivacky const TargetInstrInfo &TII = *getTargetMachine().getInstrInfo(); 1204200581Srdivacky 1205200581Srdivacky unsigned Opc; 1206200581Srdivacky const TargetRegisterClass * RC; 1207200581Srdivacky switch (MI->getOpcode()) { 1208234353Sdim default: llvm_unreachable("Invalid shift opcode!"); 1209200581Srdivacky case MSP430::Shl8: 1210200581Srdivacky Opc = MSP430::SHL8r1; 1211239462Sdim RC = &MSP430::GR8RegClass; 1212200581Srdivacky break; 1213200581Srdivacky case MSP430::Shl16: 1214200581Srdivacky Opc = MSP430::SHL16r1; 1215239462Sdim RC = &MSP430::GR16RegClass; 1216200581Srdivacky break; 1217200581Srdivacky case MSP430::Sra8: 1218200581Srdivacky Opc = MSP430::SAR8r1; 1219239462Sdim RC = &MSP430::GR8RegClass; 1220200581Srdivacky break; 1221200581Srdivacky case MSP430::Sra16: 1222200581Srdivacky Opc = MSP430::SAR16r1; 1223239462Sdim RC = &MSP430::GR16RegClass; 1224200581Srdivacky break; 1225200581Srdivacky case MSP430::Srl8: 1226200581Srdivacky Opc = MSP430::SAR8r1c; 1227239462Sdim RC = &MSP430::GR8RegClass; 1228200581Srdivacky break; 1229200581Srdivacky case MSP430::Srl16: 1230200581Srdivacky Opc = MSP430::SAR16r1c; 1231239462Sdim RC = &MSP430::GR16RegClass; 1232200581Srdivacky break; 1233200581Srdivacky } 1234200581Srdivacky 1235200581Srdivacky const BasicBlock *LLVM_BB = BB->getBasicBlock(); 1236200581Srdivacky MachineFunction::iterator I = BB; 1237200581Srdivacky ++I; 1238200581Srdivacky 1239200581Srdivacky // Create loop block 1240200581Srdivacky MachineBasicBlock *LoopBB = F->CreateMachineBasicBlock(LLVM_BB); 1241200581Srdivacky MachineBasicBlock *RemBB = F->CreateMachineBasicBlock(LLVM_BB); 1242200581Srdivacky 1243200581Srdivacky F->insert(I, LoopBB); 1244200581Srdivacky F->insert(I, RemBB); 1245200581Srdivacky 1246200581Srdivacky // Update machine-CFG edges by transferring all successors of the current 1247200581Srdivacky // block to the block containing instructions after shift. 1248210299Sed RemBB->splice(RemBB->begin(), BB, 1249210299Sed llvm::next(MachineBasicBlock::iterator(MI)), 1250210299Sed BB->end()); 1251210299Sed RemBB->transferSuccessorsAndUpdatePHIs(BB); 1252200581Srdivacky 1253200581Srdivacky // Add adges BB => LoopBB => RemBB, BB => RemBB, LoopBB => LoopBB 1254200581Srdivacky BB->addSuccessor(LoopBB); 1255200581Srdivacky BB->addSuccessor(RemBB); 1256200581Srdivacky LoopBB->addSuccessor(RemBB); 1257200581Srdivacky LoopBB->addSuccessor(LoopBB); 1258200581Srdivacky 1259239462Sdim unsigned ShiftAmtReg = RI.createVirtualRegister(&MSP430::GR8RegClass); 1260239462Sdim unsigned ShiftAmtReg2 = RI.createVirtualRegister(&MSP430::GR8RegClass); 1261200581Srdivacky unsigned ShiftReg = RI.createVirtualRegister(RC); 1262200581Srdivacky unsigned ShiftReg2 = RI.createVirtualRegister(RC); 1263200581Srdivacky unsigned ShiftAmtSrcReg = MI->getOperand(2).getReg(); 1264200581Srdivacky unsigned SrcReg = MI->getOperand(1).getReg(); 1265200581Srdivacky unsigned DstReg = MI->getOperand(0).getReg(); 1266200581Srdivacky 1267200581Srdivacky // BB: 1268200581Srdivacky // cmp 0, N 1269200581Srdivacky // je RemBB 1270202375Srdivacky BuildMI(BB, dl, TII.get(MSP430::CMP8ri)) 1271202375Srdivacky .addReg(ShiftAmtSrcReg).addImm(0); 1272200581Srdivacky BuildMI(BB, dl, TII.get(MSP430::JCC)) 1273200581Srdivacky .addMBB(RemBB) 1274200581Srdivacky .addImm(MSP430CC::COND_E); 1275200581Srdivacky 1276200581Srdivacky // LoopBB: 1277200581Srdivacky // ShiftReg = phi [%SrcReg, BB], [%ShiftReg2, LoopBB] 1278200581Srdivacky // ShiftAmt = phi [%N, BB], [%ShiftAmt2, LoopBB] 1279200581Srdivacky // ShiftReg2 = shift ShiftReg 1280200581Srdivacky // ShiftAmt2 = ShiftAmt - 1; 1281200581Srdivacky BuildMI(LoopBB, dl, TII.get(MSP430::PHI), ShiftReg) 1282200581Srdivacky .addReg(SrcReg).addMBB(BB) 1283200581Srdivacky .addReg(ShiftReg2).addMBB(LoopBB); 1284200581Srdivacky BuildMI(LoopBB, dl, TII.get(MSP430::PHI), ShiftAmtReg) 1285200581Srdivacky .addReg(ShiftAmtSrcReg).addMBB(BB) 1286200581Srdivacky .addReg(ShiftAmtReg2).addMBB(LoopBB); 1287200581Srdivacky BuildMI(LoopBB, dl, TII.get(Opc), ShiftReg2) 1288200581Srdivacky .addReg(ShiftReg); 1289200581Srdivacky BuildMI(LoopBB, dl, TII.get(MSP430::SUB8ri), ShiftAmtReg2) 1290200581Srdivacky .addReg(ShiftAmtReg).addImm(1); 1291200581Srdivacky BuildMI(LoopBB, dl, TII.get(MSP430::JCC)) 1292200581Srdivacky .addMBB(LoopBB) 1293200581Srdivacky .addImm(MSP430CC::COND_NE); 1294200581Srdivacky 1295200581Srdivacky // RemBB: 1296200581Srdivacky // DestReg = phi [%SrcReg, BB], [%ShiftReg, LoopBB] 1297210299Sed BuildMI(*RemBB, RemBB->begin(), dl, TII.get(MSP430::PHI), DstReg) 1298200581Srdivacky .addReg(SrcReg).addMBB(BB) 1299200581Srdivacky .addReg(ShiftReg2).addMBB(LoopBB); 1300200581Srdivacky 1301210299Sed MI->eraseFromParent(); // The pseudo instruction is gone now. 1302200581Srdivacky return RemBB; 1303200581Srdivacky} 1304200581Srdivacky 1305200581SrdivackyMachineBasicBlock* 1306193323SedMSP430TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, 1307207618Srdivacky MachineBasicBlock *BB) const { 1308200581Srdivacky unsigned Opc = MI->getOpcode(); 1309200581Srdivacky 1310200581Srdivacky if (Opc == MSP430::Shl8 || Opc == MSP430::Shl16 || 1311200581Srdivacky Opc == MSP430::Sra8 || Opc == MSP430::Sra16 || 1312200581Srdivacky Opc == MSP430::Srl8 || Opc == MSP430::Srl16) 1313207618Srdivacky return EmitShiftInstr(MI, BB); 1314200581Srdivacky 1315193323Sed const TargetInstrInfo &TII = *getTargetMachine().getInstrInfo(); 1316193323Sed DebugLoc dl = MI->getDebugLoc(); 1317200581Srdivacky 1318200581Srdivacky assert((Opc == MSP430::Select16 || Opc == MSP430::Select8) && 1319193323Sed "Unexpected instr type to insert"); 1320193323Sed 1321193323Sed // To "insert" a SELECT instruction, we actually have to insert the diamond 1322193323Sed // control-flow pattern. The incoming instruction knows the destination vreg 1323193323Sed // to set, the condition code register to branch on, the true/false values to 1324193323Sed // select between, and a branch opcode to use. 1325193323Sed const BasicBlock *LLVM_BB = BB->getBasicBlock(); 1326193323Sed MachineFunction::iterator I = BB; 1327193323Sed ++I; 1328193323Sed 1329193323Sed // thisMBB: 1330193323Sed // ... 1331193323Sed // TrueVal = ... 1332193323Sed // cmpTY ccX, r1, r2 1333193323Sed // jCC copy1MBB 1334193323Sed // fallthrough --> copy0MBB 1335193323Sed MachineBasicBlock *thisMBB = BB; 1336193323Sed MachineFunction *F = BB->getParent(); 1337193323Sed MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB); 1338193323Sed MachineBasicBlock *copy1MBB = F->CreateMachineBasicBlock(LLVM_BB); 1339193323Sed F->insert(I, copy0MBB); 1340193323Sed F->insert(I, copy1MBB); 1341193323Sed // Update machine-CFG edges by transferring all successors of the current 1342193323Sed // block to the new block which will contain the Phi node for the select. 1343210299Sed copy1MBB->splice(copy1MBB->begin(), BB, 1344210299Sed llvm::next(MachineBasicBlock::iterator(MI)), 1345210299Sed BB->end()); 1346210299Sed copy1MBB->transferSuccessorsAndUpdatePHIs(BB); 1347193323Sed // Next, add the true and fallthrough blocks as its successors. 1348193323Sed BB->addSuccessor(copy0MBB); 1349193323Sed BB->addSuccessor(copy1MBB); 1350193323Sed 1351210299Sed BuildMI(BB, dl, TII.get(MSP430::JCC)) 1352210299Sed .addMBB(copy1MBB) 1353210299Sed .addImm(MI->getOperand(3).getImm()); 1354210299Sed 1355193323Sed // copy0MBB: 1356193323Sed // %FalseValue = ... 1357193323Sed // # fallthrough to copy1MBB 1358193323Sed BB = copy0MBB; 1359193323Sed 1360193323Sed // Update machine-CFG edges 1361193323Sed BB->addSuccessor(copy1MBB); 1362193323Sed 1363193323Sed // copy1MBB: 1364193323Sed // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ] 1365193323Sed // ... 1366193323Sed BB = copy1MBB; 1367210299Sed BuildMI(*BB, BB->begin(), dl, TII.get(MSP430::PHI), 1368193323Sed MI->getOperand(0).getReg()) 1369193323Sed .addReg(MI->getOperand(2).getReg()).addMBB(copy0MBB) 1370193323Sed .addReg(MI->getOperand(1).getReg()).addMBB(thisMBB); 1371193323Sed 1372210299Sed MI->eraseFromParent(); // The pseudo instruction is gone now. 1373193323Sed return BB; 1374193323Sed} 1375