1193323Sed//===-- SparcISelLowering.cpp - Sparc 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 interfaces that Sparc uses to lower LLVM code into a 11193323Sed// selection DAG. 12193323Sed// 13193323Sed//===----------------------------------------------------------------------===// 14193323Sed 15193323Sed#include "SparcISelLowering.h" 16263763Sdim#include "MCTargetDesc/SparcMCExpr.h" 17249423Sdim#include "SparcMachineFunctionInfo.h" 18263508Sdim#include "SparcRegisterInfo.h" 19193323Sed#include "SparcTargetMachine.h" 20263763Sdim#include "SparcTargetObjectFile.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/SelectionDAG.h" 27203954Srdivacky#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" 28249423Sdim#include "llvm/IR/DerivedTypes.h" 29249423Sdim#include "llvm/IR/Function.h" 30249423Sdim#include "llvm/IR/Module.h" 31198090Srdivacky#include "llvm/Support/ErrorHandling.h" 32193323Sedusing namespace llvm; 33193323Sed 34193323Sed 35193323Sed//===----------------------------------------------------------------------===// 36193323Sed// Calling Convention Implementation 37193323Sed//===----------------------------------------------------------------------===// 38193323Sed 39218893Sdimstatic bool CC_Sparc_Assign_SRet(unsigned &ValNo, MVT &ValVT, 40218893Sdim MVT &LocVT, CCValAssign::LocInfo &LocInfo, 41218893Sdim ISD::ArgFlagsTy &ArgFlags, CCState &State) 42218893Sdim{ 43218893Sdim assert (ArgFlags.isSRet()); 44218893Sdim 45263508Sdim // Assign SRet argument. 46218893Sdim State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT, 47218893Sdim 0, 48218893Sdim LocVT, LocInfo)); 49218893Sdim return true; 50218893Sdim} 51218893Sdim 52218893Sdimstatic bool CC_Sparc_Assign_f64(unsigned &ValNo, MVT &ValVT, 53218893Sdim MVT &LocVT, CCValAssign::LocInfo &LocInfo, 54218893Sdim ISD::ArgFlagsTy &ArgFlags, CCState &State) 55218893Sdim{ 56234353Sdim static const uint16_t RegList[] = { 57218893Sdim SP::I0, SP::I1, SP::I2, SP::I3, SP::I4, SP::I5 58218893Sdim }; 59263508Sdim // Try to get first reg. 60218893Sdim if (unsigned Reg = State.AllocateReg(RegList, 6)) { 61218893Sdim State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 62218893Sdim } else { 63263508Sdim // Assign whole thing in stack. 64218893Sdim State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT, 65218893Sdim State.AllocateStack(8,4), 66218893Sdim LocVT, LocInfo)); 67218893Sdim return true; 68218893Sdim } 69218893Sdim 70263508Sdim // Try to get second reg. 71218893Sdim if (unsigned Reg = State.AllocateReg(RegList, 6)) 72218893Sdim State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 73218893Sdim else 74218893Sdim State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT, 75218893Sdim State.AllocateStack(4,4), 76218893Sdim LocVT, LocInfo)); 77218893Sdim return true; 78218893Sdim} 79218893Sdim 80251662Sdim// Allocate a full-sized argument for the 64-bit ABI. 81251662Sdimstatic bool CC_Sparc64_Full(unsigned &ValNo, MVT &ValVT, 82251662Sdim MVT &LocVT, CCValAssign::LocInfo &LocInfo, 83251662Sdim ISD::ArgFlagsTy &ArgFlags, CCState &State) { 84263763Sdim assert((LocVT == MVT::f32 || LocVT == MVT::f128 85263763Sdim || LocVT.getSizeInBits() == 64) && 86251662Sdim "Can't handle non-64 bits locations"); 87251662Sdim 88251662Sdim // Stack space is allocated for all arguments starting from [%fp+BIAS+128]. 89263763Sdim unsigned size = (LocVT == MVT::f128) ? 16 : 8; 90263763Sdim unsigned alignment = (LocVT == MVT::f128) ? 16 : 8; 91263763Sdim unsigned Offset = State.AllocateStack(size, alignment); 92251662Sdim unsigned Reg = 0; 93251662Sdim 94251662Sdim if (LocVT == MVT::i64 && Offset < 6*8) 95251662Sdim // Promote integers to %i0-%i5. 96251662Sdim Reg = SP::I0 + Offset/8; 97251662Sdim else if (LocVT == MVT::f64 && Offset < 16*8) 98251662Sdim // Promote doubles to %d0-%d30. (Which LLVM calls D0-D15). 99251662Sdim Reg = SP::D0 + Offset/8; 100251662Sdim else if (LocVT == MVT::f32 && Offset < 16*8) 101251662Sdim // Promote floats to %f1, %f3, ... 102251662Sdim Reg = SP::F1 + Offset/4; 103263763Sdim else if (LocVT == MVT::f128 && Offset < 16*8) 104263763Sdim // Promote long doubles to %q0-%q28. (Which LLVM calls Q0-Q7). 105263763Sdim Reg = SP::Q0 + Offset/16; 106251662Sdim 107251662Sdim // Promote to register when possible, otherwise use the stack slot. 108251662Sdim if (Reg) { 109251662Sdim State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 110251662Sdim return true; 111251662Sdim } 112251662Sdim 113251662Sdim // This argument goes on the stack in an 8-byte slot. 114251662Sdim // When passing floats, LocVT is smaller than 8 bytes. Adjust the offset to 115251662Sdim // the right-aligned float. The first 4 bytes of the stack slot are undefined. 116251662Sdim if (LocVT == MVT::f32) 117251662Sdim Offset += 4; 118251662Sdim 119251662Sdim State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo)); 120251662Sdim return true; 121251662Sdim} 122251662Sdim 123251662Sdim// Allocate a half-sized argument for the 64-bit ABI. 124251662Sdim// 125251662Sdim// This is used when passing { float, int } structs by value in registers. 126251662Sdimstatic bool CC_Sparc64_Half(unsigned &ValNo, MVT &ValVT, 127251662Sdim MVT &LocVT, CCValAssign::LocInfo &LocInfo, 128251662Sdim ISD::ArgFlagsTy &ArgFlags, CCState &State) { 129251662Sdim assert(LocVT.getSizeInBits() == 32 && "Can't handle non-32 bits locations"); 130251662Sdim unsigned Offset = State.AllocateStack(4, 4); 131251662Sdim 132251662Sdim if (LocVT == MVT::f32 && Offset < 16*8) { 133251662Sdim // Promote floats to %f0-%f31. 134251662Sdim State.addLoc(CCValAssign::getReg(ValNo, ValVT, SP::F0 + Offset/4, 135251662Sdim LocVT, LocInfo)); 136251662Sdim return true; 137251662Sdim } 138251662Sdim 139251662Sdim if (LocVT == MVT::i32 && Offset < 6*8) { 140251662Sdim // Promote integers to %i0-%i5, using half the register. 141251662Sdim unsigned Reg = SP::I0 + Offset/8; 142251662Sdim LocVT = MVT::i64; 143251662Sdim LocInfo = CCValAssign::AExt; 144251662Sdim 145251662Sdim // Set the Custom bit if this i32 goes in the high bits of a register. 146251662Sdim if (Offset % 8 == 0) 147251662Sdim State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, 148251662Sdim LocVT, LocInfo)); 149251662Sdim else 150251662Sdim State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 151251662Sdim return true; 152251662Sdim } 153251662Sdim 154251662Sdim State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo)); 155251662Sdim return true; 156251662Sdim} 157251662Sdim 158193323Sed#include "SparcGenCallingConv.inc" 159193323Sed 160251662Sdim// The calling conventions in SparcCallingConv.td are described in terms of the 161251662Sdim// callee's register window. This function translates registers to the 162251662Sdim// corresponding caller window %o register. 163251662Sdimstatic unsigned toCallerWindow(unsigned Reg) { 164251662Sdim assert(SP::I0 + 7 == SP::I7 && SP::O0 + 7 == SP::O7 && "Unexpected enum"); 165251662Sdim if (Reg >= SP::I0 && Reg <= SP::I7) 166251662Sdim return Reg - SP::I0 + SP::O0; 167251662Sdim return Reg; 168251662Sdim} 169251662Sdim 170198090SrdivackySDValue 171198090SrdivackySparcTargetLowering::LowerReturn(SDValue Chain, 172251662Sdim CallingConv::ID CallConv, bool IsVarArg, 173198090Srdivacky const SmallVectorImpl<ISD::OutputArg> &Outs, 174210299Sed const SmallVectorImpl<SDValue> &OutVals, 175263508Sdim SDLoc DL, SelectionDAG &DAG) const { 176251662Sdim if (Subtarget->is64Bit()) 177251662Sdim return LowerReturn_64(Chain, CallConv, IsVarArg, Outs, OutVals, DL, DAG); 178251662Sdim return LowerReturn_32(Chain, CallConv, IsVarArg, Outs, OutVals, DL, DAG); 179251662Sdim} 180198090Srdivacky 181251662SdimSDValue 182251662SdimSparcTargetLowering::LowerReturn_32(SDValue Chain, 183251662Sdim CallingConv::ID CallConv, bool IsVarArg, 184251662Sdim const SmallVectorImpl<ISD::OutputArg> &Outs, 185251662Sdim const SmallVectorImpl<SDValue> &OutVals, 186263508Sdim SDLoc DL, SelectionDAG &DAG) const { 187218893Sdim MachineFunction &MF = DAG.getMachineFunction(); 188218893Sdim 189193323Sed // CCValAssign - represent the assignment of the return value to locations. 190193323Sed SmallVector<CCValAssign, 16> RVLocs; 191193323Sed 192193323Sed // CCState - Info about the registers and stack slot. 193251662Sdim CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), 194239462Sdim DAG.getTarget(), RVLocs, *DAG.getContext()); 195193323Sed 196251662Sdim // Analyze return values. 197251662Sdim CCInfo.AnalyzeReturn(Outs, RetCC_Sparc32); 198193323Sed 199193323Sed SDValue Flag; 200249423Sdim SmallVector<SDValue, 4> RetOps(1, Chain); 201249423Sdim // Make room for the return address offset. 202249423Sdim RetOps.push_back(SDValue()); 203193323Sed 204193323Sed // Copy the result values into the output registers. 205193323Sed for (unsigned i = 0; i != RVLocs.size(); ++i) { 206193323Sed CCValAssign &VA = RVLocs[i]; 207193323Sed assert(VA.isRegLoc() && "Can only return in registers!"); 208193323Sed 209251662Sdim Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), 210210299Sed OutVals[i], Flag); 211193323Sed 212193323Sed // Guarantee that all emitted copies are stuck together with flags. 213193323Sed Flag = Chain.getValue(1); 214249423Sdim RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); 215193323Sed } 216219077Sdim 217263508Sdim unsigned RetAddrOffset = 8; // Call Inst + Delay Slot 218218893Sdim // If the function returns a struct, copy the SRetReturnReg to I0 219218893Sdim if (MF.getFunction()->hasStructRetAttr()) { 220218893Sdim SparcMachineFunctionInfo *SFI = MF.getInfo<SparcMachineFunctionInfo>(); 221218893Sdim unsigned Reg = SFI->getSRetReturnReg(); 222218893Sdim if (!Reg) 223218893Sdim llvm_unreachable("sret virtual register not created in the entry block"); 224251662Sdim SDValue Val = DAG.getCopyFromReg(Chain, DL, Reg, getPointerTy()); 225251662Sdim Chain = DAG.getCopyToReg(Chain, DL, SP::I0, Val, Flag); 226218893Sdim Flag = Chain.getValue(1); 227249423Sdim RetOps.push_back(DAG.getRegister(SP::I0, getPointerTy())); 228219077Sdim RetAddrOffset = 12; // CallInst + Delay Slot + Unimp 229218893Sdim } 230193323Sed 231249423Sdim RetOps[0] = Chain; // Update chain. 232249423Sdim RetOps[1] = DAG.getConstant(RetAddrOffset, MVT::i32); 233219077Sdim 234249423Sdim // Add the flag if we have it. 235193323Sed if (Flag.getNode()) 236249423Sdim RetOps.push_back(Flag); 237249423Sdim 238251662Sdim return DAG.getNode(SPISD::RET_FLAG, DL, MVT::Other, 239249423Sdim &RetOps[0], RetOps.size()); 240193323Sed} 241193323Sed 242251662Sdim// Lower return values for the 64-bit ABI. 243251662Sdim// Return values are passed the exactly the same way as function arguments. 244251662SdimSDValue 245251662SdimSparcTargetLowering::LowerReturn_64(SDValue Chain, 246251662Sdim CallingConv::ID CallConv, bool IsVarArg, 247251662Sdim const SmallVectorImpl<ISD::OutputArg> &Outs, 248251662Sdim const SmallVectorImpl<SDValue> &OutVals, 249263508Sdim SDLoc DL, SelectionDAG &DAG) const { 250251662Sdim // CCValAssign - represent the assignment of the return value to locations. 251251662Sdim SmallVector<CCValAssign, 16> RVLocs; 252251662Sdim 253251662Sdim // CCState - Info about the registers and stack slot. 254251662Sdim CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), 255251662Sdim DAG.getTarget(), RVLocs, *DAG.getContext()); 256251662Sdim 257251662Sdim // Analyze return values. 258263763Sdim CCInfo.AnalyzeReturn(Outs, RetCC_Sparc64); 259251662Sdim 260251662Sdim SDValue Flag; 261251662Sdim SmallVector<SDValue, 4> RetOps(1, Chain); 262251662Sdim 263251662Sdim // The second operand on the return instruction is the return address offset. 264251662Sdim // The return address is always %i7+8 with the 64-bit ABI. 265251662Sdim RetOps.push_back(DAG.getConstant(8, MVT::i32)); 266251662Sdim 267251662Sdim // Copy the result values into the output registers. 268251662Sdim for (unsigned i = 0; i != RVLocs.size(); ++i) { 269251662Sdim CCValAssign &VA = RVLocs[i]; 270251662Sdim assert(VA.isRegLoc() && "Can only return in registers!"); 271251662Sdim SDValue OutVal = OutVals[i]; 272251662Sdim 273251662Sdim // Integer return values must be sign or zero extended by the callee. 274251662Sdim switch (VA.getLocInfo()) { 275251662Sdim case CCValAssign::SExt: 276251662Sdim OutVal = DAG.getNode(ISD::SIGN_EXTEND, DL, VA.getLocVT(), OutVal); 277251662Sdim break; 278251662Sdim case CCValAssign::ZExt: 279251662Sdim OutVal = DAG.getNode(ISD::ZERO_EXTEND, DL, VA.getLocVT(), OutVal); 280251662Sdim break; 281251662Sdim case CCValAssign::AExt: 282251662Sdim OutVal = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), OutVal); 283251662Sdim default: 284251662Sdim break; 285251662Sdim } 286251662Sdim 287251662Sdim // The custom bit on an i32 return value indicates that it should be passed 288251662Sdim // in the high bits of the register. 289251662Sdim if (VA.getValVT() == MVT::i32 && VA.needsCustom()) { 290251662Sdim OutVal = DAG.getNode(ISD::SHL, DL, MVT::i64, OutVal, 291251662Sdim DAG.getConstant(32, MVT::i32)); 292251662Sdim 293251662Sdim // The next value may go in the low bits of the same register. 294251662Sdim // Handle both at once. 295251662Sdim if (i+1 < RVLocs.size() && RVLocs[i+1].getLocReg() == VA.getLocReg()) { 296251662Sdim SDValue NV = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i64, OutVals[i+1]); 297251662Sdim OutVal = DAG.getNode(ISD::OR, DL, MVT::i64, OutVal, NV); 298251662Sdim // Skip the next value, it's already done. 299251662Sdim ++i; 300251662Sdim } 301251662Sdim } 302251662Sdim 303251662Sdim Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), OutVal, Flag); 304251662Sdim 305251662Sdim // Guarantee that all emitted copies are stuck together with flags. 306251662Sdim Flag = Chain.getValue(1); 307251662Sdim RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); 308251662Sdim } 309251662Sdim 310251662Sdim RetOps[0] = Chain; // Update chain. 311251662Sdim 312251662Sdim // Add the flag if we have it. 313251662Sdim if (Flag.getNode()) 314251662Sdim RetOps.push_back(Flag); 315251662Sdim 316251662Sdim return DAG.getNode(SPISD::RET_FLAG, DL, MVT::Other, 317251662Sdim &RetOps[0], RetOps.size()); 318251662Sdim} 319251662Sdim 320249423SdimSDValue SparcTargetLowering:: 321249423SdimLowerFormalArguments(SDValue Chain, 322249423Sdim CallingConv::ID CallConv, 323249423Sdim bool IsVarArg, 324249423Sdim const SmallVectorImpl<ISD::InputArg> &Ins, 325263508Sdim SDLoc DL, 326249423Sdim SelectionDAG &DAG, 327249423Sdim SmallVectorImpl<SDValue> &InVals) const { 328249423Sdim if (Subtarget->is64Bit()) 329249423Sdim return LowerFormalArguments_64(Chain, CallConv, IsVarArg, Ins, 330249423Sdim DL, DAG, InVals); 331249423Sdim return LowerFormalArguments_32(Chain, CallConv, IsVarArg, Ins, 332249423Sdim DL, DAG, InVals); 333249423Sdim} 334249423Sdim 335249423Sdim/// LowerFormalArguments32 - V8 uses a very simple ABI, where all values are 336198090Srdivacky/// passed in either one or two GPRs, including FP values. TODO: we should 337198090Srdivacky/// pass FP values in FP registers for fastcc functions. 338249423SdimSDValue SparcTargetLowering:: 339249423SdimLowerFormalArguments_32(SDValue Chain, 340249423Sdim CallingConv::ID CallConv, 341249423Sdim bool isVarArg, 342249423Sdim const SmallVectorImpl<ISD::InputArg> &Ins, 343263508Sdim SDLoc dl, 344249423Sdim SelectionDAG &DAG, 345249423Sdim SmallVectorImpl<SDValue> &InVals) const { 346193323Sed MachineFunction &MF = DAG.getMachineFunction(); 347193323Sed MachineRegisterInfo &RegInfo = MF.getRegInfo(); 348207618Srdivacky SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>(); 349193323Sed 350198090Srdivacky // Assign locations to all of the incoming arguments. 351198090Srdivacky SmallVector<CCValAssign, 16> ArgLocs; 352223017Sdim CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), 353239462Sdim getTargetMachine(), ArgLocs, *DAG.getContext()); 354198090Srdivacky CCInfo.AnalyzeFormalArguments(Ins, CC_Sparc32); 355198090Srdivacky 356218893Sdim const unsigned StackOffset = 92; 357193323Sed 358198090Srdivacky for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { 359198090Srdivacky CCValAssign &VA = ArgLocs[i]; 360193323Sed 361218893Sdim if (i == 0 && Ins[i].Flags.isSRet()) { 362263508Sdim // Get SRet from [%fp+64]. 363218893Sdim int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, 64, true); 364218893Sdim SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32); 365218893Sdim SDValue Arg = DAG.getLoad(MVT::i32, dl, Chain, FIPtr, 366218893Sdim MachinePointerInfo(), 367234353Sdim false, false, false, 0); 368218893Sdim InVals.push_back(Arg); 369218893Sdim continue; 370218893Sdim } 371193323Sed 372218893Sdim if (VA.isRegLoc()) { 373218893Sdim if (VA.needsCustom()) { 374218893Sdim assert(VA.getLocVT() == MVT::f64); 375218893Sdim unsigned VRegHi = RegInfo.createVirtualRegister(&SP::IntRegsRegClass); 376218893Sdim MF.getRegInfo().addLiveIn(VA.getLocReg(), VRegHi); 377218893Sdim SDValue HiVal = DAG.getCopyFromReg(Chain, dl, VRegHi, MVT::i32); 378193323Sed 379218893Sdim assert(i+1 < e); 380218893Sdim CCValAssign &NextVA = ArgLocs[++i]; 381193323Sed 382193323Sed SDValue LoVal; 383218893Sdim if (NextVA.isMemLoc()) { 384218893Sdim int FrameIdx = MF.getFrameInfo()-> 385218893Sdim CreateFixedObject(4, StackOffset+NextVA.getLocMemOffset(),true); 386193323Sed SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32); 387218893Sdim LoVal = DAG.getLoad(MVT::i32, dl, Chain, FIPtr, 388218893Sdim MachinePointerInfo(), 389234353Sdim false, false, false, 0); 390218893Sdim } else { 391218893Sdim unsigned loReg = MF.addLiveIn(NextVA.getLocReg(), 392219077Sdim &SP::IntRegsRegClass); 393218893Sdim LoVal = DAG.getCopyFromReg(Chain, dl, loReg, MVT::i32); 394193323Sed } 395193323Sed SDValue WholeValue = 396193323Sed DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, LoVal, HiVal); 397218893Sdim WholeValue = DAG.getNode(ISD::BITCAST, dl, MVT::f64, WholeValue); 398218893Sdim InVals.push_back(WholeValue); 399218893Sdim continue; 400218893Sdim } 401218893Sdim unsigned VReg = RegInfo.createVirtualRegister(&SP::IntRegsRegClass); 402218893Sdim MF.getRegInfo().addLiveIn(VA.getLocReg(), VReg); 403218893Sdim SDValue Arg = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32); 404218893Sdim if (VA.getLocVT() == MVT::f32) 405218893Sdim Arg = DAG.getNode(ISD::BITCAST, dl, MVT::f32, Arg); 406218893Sdim else if (VA.getLocVT() != MVT::i32) { 407218893Sdim Arg = DAG.getNode(ISD::AssertSext, dl, MVT::i32, Arg, 408218893Sdim DAG.getValueType(VA.getLocVT())); 409218893Sdim Arg = DAG.getNode(ISD::TRUNCATE, dl, VA.getLocVT(), Arg); 410218893Sdim } 411218893Sdim InVals.push_back(Arg); 412218893Sdim continue; 413218893Sdim } 414193323Sed 415218893Sdim assert(VA.isMemLoc()); 416193323Sed 417218893Sdim unsigned Offset = VA.getLocMemOffset()+StackOffset; 418218893Sdim 419218893Sdim if (VA.needsCustom()) { 420218893Sdim assert(VA.getValVT() == MVT::f64); 421263508Sdim // If it is double-word aligned, just load. 422218893Sdim if (Offset % 8 == 0) { 423218893Sdim int FI = MF.getFrameInfo()->CreateFixedObject(8, 424218893Sdim Offset, 425218893Sdim true); 426218893Sdim SDValue FIPtr = DAG.getFrameIndex(FI, getPointerTy()); 427218893Sdim SDValue Load = DAG.getLoad(VA.getValVT(), dl, Chain, FIPtr, 428218893Sdim MachinePointerInfo(), 429234353Sdim false,false, false, 0); 430218893Sdim InVals.push_back(Load); 431218893Sdim continue; 432193323Sed } 433218893Sdim 434218893Sdim int FI = MF.getFrameInfo()->CreateFixedObject(4, 435218893Sdim Offset, 436218893Sdim true); 437218893Sdim SDValue FIPtr = DAG.getFrameIndex(FI, getPointerTy()); 438218893Sdim SDValue HiVal = DAG.getLoad(MVT::i32, dl, Chain, FIPtr, 439218893Sdim MachinePointerInfo(), 440234353Sdim false, false, false, 0); 441218893Sdim int FI2 = MF.getFrameInfo()->CreateFixedObject(4, 442218893Sdim Offset+4, 443218893Sdim true); 444218893Sdim SDValue FIPtr2 = DAG.getFrameIndex(FI2, getPointerTy()); 445218893Sdim 446218893Sdim SDValue LoVal = DAG.getLoad(MVT::i32, dl, Chain, FIPtr2, 447218893Sdim MachinePointerInfo(), 448234353Sdim false, false, false, 0); 449218893Sdim 450218893Sdim SDValue WholeValue = 451218893Sdim DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, LoVal, HiVal); 452218893Sdim WholeValue = DAG.getNode(ISD::BITCAST, dl, MVT::f64, WholeValue); 453218893Sdim InVals.push_back(WholeValue); 454218893Sdim continue; 455193323Sed } 456218893Sdim 457218893Sdim int FI = MF.getFrameInfo()->CreateFixedObject(4, 458218893Sdim Offset, 459218893Sdim true); 460218893Sdim SDValue FIPtr = DAG.getFrameIndex(FI, getPointerTy()); 461218893Sdim SDValue Load ; 462218893Sdim if (VA.getValVT() == MVT::i32 || VA.getValVT() == MVT::f32) { 463218893Sdim Load = DAG.getLoad(VA.getValVT(), dl, Chain, FIPtr, 464218893Sdim MachinePointerInfo(), 465234353Sdim false, false, false, 0); 466218893Sdim } else { 467218893Sdim ISD::LoadExtType LoadOp = ISD::SEXTLOAD; 468218893Sdim // Sparc is big endian, so add an offset based on the ObjectVT. 469218893Sdim unsigned Offset = 4-std::max(1U, VA.getValVT().getSizeInBits()/8); 470218893Sdim FIPtr = DAG.getNode(ISD::ADD, dl, MVT::i32, FIPtr, 471218893Sdim DAG.getConstant(Offset, MVT::i32)); 472218893Sdim Load = DAG.getExtLoad(LoadOp, dl, MVT::i32, Chain, FIPtr, 473218893Sdim MachinePointerInfo(), 474218893Sdim VA.getValVT(), false, false,0); 475218893Sdim Load = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), Load); 476218893Sdim } 477218893Sdim InVals.push_back(Load); 478193323Sed } 479193323Sed 480218893Sdim if (MF.getFunction()->hasStructRetAttr()) { 481263508Sdim // Copy the SRet Argument to SRetReturnReg. 482218893Sdim SparcMachineFunctionInfo *SFI = MF.getInfo<SparcMachineFunctionInfo>(); 483218893Sdim unsigned Reg = SFI->getSRetReturnReg(); 484218893Sdim if (!Reg) { 485218893Sdim Reg = MF.getRegInfo().createVirtualRegister(&SP::IntRegsRegClass); 486218893Sdim SFI->setSRetReturnReg(Reg); 487218893Sdim } 488218893Sdim SDValue Copy = DAG.getCopyToReg(DAG.getEntryNode(), dl, Reg, InVals[0]); 489218893Sdim Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Copy, Chain); 490218893Sdim } 491218893Sdim 492193323Sed // Store remaining ArgRegs to the stack if this is a varargs function. 493198090Srdivacky if (isVarArg) { 494234353Sdim static const uint16_t ArgRegs[] = { 495218893Sdim SP::I0, SP::I1, SP::I2, SP::I3, SP::I4, SP::I5 496218893Sdim }; 497218893Sdim unsigned NumAllocated = CCInfo.getFirstUnallocated(ArgRegs, 6); 498234353Sdim const uint16_t *CurArgReg = ArgRegs+NumAllocated, *ArgRegEnd = ArgRegs+6; 499218893Sdim unsigned ArgOffset = CCInfo.getNextStackOffset(); 500218893Sdim if (NumAllocated == 6) 501218893Sdim ArgOffset += StackOffset; 502218893Sdim else { 503218893Sdim assert(!ArgOffset); 504218893Sdim ArgOffset = 68+4*NumAllocated; 505218893Sdim } 506218893Sdim 507193323Sed // Remember the vararg offset for the va_start implementation. 508207618Srdivacky FuncInfo->setVarArgsFrameOffset(ArgOffset); 509193323Sed 510198090Srdivacky std::vector<SDValue> OutChains; 511198090Srdivacky 512193323Sed for (; CurArgReg != ArgRegEnd; ++CurArgReg) { 513193323Sed unsigned VReg = RegInfo.createVirtualRegister(&SP::IntRegsRegClass); 514193323Sed MF.getRegInfo().addLiveIn(*CurArgReg, VReg); 515193323Sed SDValue Arg = DAG.getCopyFromReg(DAG.getRoot(), dl, VReg, MVT::i32); 516193323Sed 517199481Srdivacky int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset, 518210299Sed true); 519193323Sed SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32); 520193323Sed 521218893Sdim OutChains.push_back(DAG.getStore(DAG.getRoot(), dl, Arg, FIPtr, 522218893Sdim MachinePointerInfo(), 523203954Srdivacky false, false, 0)); 524193323Sed ArgOffset += 4; 525193323Sed } 526198090Srdivacky 527198090Srdivacky if (!OutChains.empty()) { 528198090Srdivacky OutChains.push_back(Chain); 529198090Srdivacky Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, 530198090Srdivacky &OutChains[0], OutChains.size()); 531198090Srdivacky } 532193323Sed } 533193323Sed 534198090Srdivacky return Chain; 535193323Sed} 536193323Sed 537249423Sdim// Lower formal arguments for the 64 bit ABI. 538249423SdimSDValue SparcTargetLowering:: 539249423SdimLowerFormalArguments_64(SDValue Chain, 540249423Sdim CallingConv::ID CallConv, 541249423Sdim bool IsVarArg, 542249423Sdim const SmallVectorImpl<ISD::InputArg> &Ins, 543263508Sdim SDLoc DL, 544249423Sdim SelectionDAG &DAG, 545249423Sdim SmallVectorImpl<SDValue> &InVals) const { 546249423Sdim MachineFunction &MF = DAG.getMachineFunction(); 547249423Sdim 548249423Sdim // Analyze arguments according to CC_Sparc64. 549249423Sdim SmallVector<CCValAssign, 16> ArgLocs; 550249423Sdim CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), 551249423Sdim getTargetMachine(), ArgLocs, *DAG.getContext()); 552249423Sdim CCInfo.AnalyzeFormalArguments(Ins, CC_Sparc64); 553249423Sdim 554251662Sdim // The argument array begins at %fp+BIAS+128, after the register save area. 555251662Sdim const unsigned ArgArea = 128; 556251662Sdim 557249423Sdim for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { 558249423Sdim CCValAssign &VA = ArgLocs[i]; 559249423Sdim if (VA.isRegLoc()) { 560249423Sdim // This argument is passed in a register. 561249423Sdim // All integer register arguments are promoted by the caller to i64. 562249423Sdim 563249423Sdim // Create a virtual register for the promoted live-in value. 564249423Sdim unsigned VReg = MF.addLiveIn(VA.getLocReg(), 565249423Sdim getRegClassFor(VA.getLocVT())); 566249423Sdim SDValue Arg = DAG.getCopyFromReg(Chain, DL, VReg, VA.getLocVT()); 567249423Sdim 568251662Sdim // Get the high bits for i32 struct elements. 569251662Sdim if (VA.getValVT() == MVT::i32 && VA.needsCustom()) 570251662Sdim Arg = DAG.getNode(ISD::SRL, DL, VA.getLocVT(), Arg, 571251662Sdim DAG.getConstant(32, MVT::i32)); 572251662Sdim 573249423Sdim // The caller promoted the argument, so insert an Assert?ext SDNode so we 574249423Sdim // won't promote the value again in this function. 575249423Sdim switch (VA.getLocInfo()) { 576249423Sdim case CCValAssign::SExt: 577249423Sdim Arg = DAG.getNode(ISD::AssertSext, DL, VA.getLocVT(), Arg, 578249423Sdim DAG.getValueType(VA.getValVT())); 579249423Sdim break; 580249423Sdim case CCValAssign::ZExt: 581249423Sdim Arg = DAG.getNode(ISD::AssertZext, DL, VA.getLocVT(), Arg, 582249423Sdim DAG.getValueType(VA.getValVT())); 583249423Sdim break; 584249423Sdim default: 585249423Sdim break; 586249423Sdim } 587249423Sdim 588249423Sdim // Truncate the register down to the argument type. 589249423Sdim if (VA.isExtInLoc()) 590249423Sdim Arg = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Arg); 591249423Sdim 592249423Sdim InVals.push_back(Arg); 593249423Sdim continue; 594249423Sdim } 595249423Sdim 596249423Sdim // The registers are exhausted. This argument was passed on the stack. 597249423Sdim assert(VA.isMemLoc()); 598251662Sdim // The CC_Sparc64_Full/Half functions compute stack offsets relative to the 599251662Sdim // beginning of the arguments area at %fp+BIAS+128. 600251662Sdim unsigned Offset = VA.getLocMemOffset() + ArgArea; 601251662Sdim unsigned ValSize = VA.getValVT().getSizeInBits() / 8; 602251662Sdim // Adjust offset for extended arguments, SPARC is big-endian. 603251662Sdim // The caller will have written the full slot with extended bytes, but we 604251662Sdim // prefer our own extending loads. 605251662Sdim if (VA.isExtInLoc()) 606251662Sdim Offset += 8 - ValSize; 607251662Sdim int FI = MF.getFrameInfo()->CreateFixedObject(ValSize, Offset, true); 608251662Sdim InVals.push_back(DAG.getLoad(VA.getValVT(), DL, Chain, 609251662Sdim DAG.getFrameIndex(FI, getPointerTy()), 610251662Sdim MachinePointerInfo::getFixedStack(FI), 611251662Sdim false, false, false, 0)); 612249423Sdim } 613251662Sdim 614251662Sdim if (!IsVarArg) 615251662Sdim return Chain; 616251662Sdim 617251662Sdim // This function takes variable arguments, some of which may have been passed 618251662Sdim // in registers %i0-%i5. Variable floating point arguments are never passed 619251662Sdim // in floating point registers. They go on %i0-%i5 or on the stack like 620251662Sdim // integer arguments. 621251662Sdim // 622251662Sdim // The va_start intrinsic needs to know the offset to the first variable 623251662Sdim // argument. 624251662Sdim unsigned ArgOffset = CCInfo.getNextStackOffset(); 625251662Sdim SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>(); 626251662Sdim // Skip the 128 bytes of register save area. 627251662Sdim FuncInfo->setVarArgsFrameOffset(ArgOffset + ArgArea + 628251662Sdim Subtarget->getStackPointerBias()); 629251662Sdim 630251662Sdim // Save the variable arguments that were passed in registers. 631251662Sdim // The caller is required to reserve stack space for 6 arguments regardless 632251662Sdim // of how many arguments were actually passed. 633251662Sdim SmallVector<SDValue, 8> OutChains; 634251662Sdim for (; ArgOffset < 6*8; ArgOffset += 8) { 635251662Sdim unsigned VReg = MF.addLiveIn(SP::I0 + ArgOffset/8, &SP::I64RegsRegClass); 636251662Sdim SDValue VArg = DAG.getCopyFromReg(Chain, DL, VReg, MVT::i64); 637251662Sdim int FI = MF.getFrameInfo()->CreateFixedObject(8, ArgOffset + ArgArea, true); 638251662Sdim OutChains.push_back(DAG.getStore(Chain, DL, VArg, 639251662Sdim DAG.getFrameIndex(FI, getPointerTy()), 640251662Sdim MachinePointerInfo::getFixedStack(FI), 641251662Sdim false, false, 0)); 642251662Sdim } 643251662Sdim 644251662Sdim if (!OutChains.empty()) 645251662Sdim Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, 646251662Sdim &OutChains[0], OutChains.size()); 647251662Sdim 648249423Sdim return Chain; 649249423Sdim} 650249423Sdim 651198090SrdivackySDValue 652239462SdimSparcTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, 653207618Srdivacky SmallVectorImpl<SDValue> &InVals) const { 654251662Sdim if (Subtarget->is64Bit()) 655251662Sdim return LowerCall_64(CLI, InVals); 656251662Sdim return LowerCall_32(CLI, InVals); 657251662Sdim} 658251662Sdim 659263508Sdimstatic bool hasReturnsTwiceAttr(SelectionDAG &DAG, SDValue Callee, 660263508Sdim ImmutableCallSite *CS) { 661263508Sdim if (CS) 662263508Sdim return CS->hasFnAttr(Attribute::ReturnsTwice); 663263508Sdim 664263508Sdim const Function *CalleeFn = 0; 665263508Sdim if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) { 666263508Sdim CalleeFn = dyn_cast<Function>(G->getGlobal()); 667263508Sdim } else if (ExternalSymbolSDNode *E = 668263508Sdim dyn_cast<ExternalSymbolSDNode>(Callee)) { 669263508Sdim const Function *Fn = DAG.getMachineFunction().getFunction(); 670263508Sdim const Module *M = Fn->getParent(); 671263508Sdim const char *CalleeName = E->getSymbol(); 672263508Sdim CalleeFn = M->getFunction(CalleeName); 673263508Sdim } 674263508Sdim 675263508Sdim if (!CalleeFn) 676263508Sdim return false; 677263508Sdim return CalleeFn->hasFnAttribute(Attribute::ReturnsTwice); 678263508Sdim} 679263508Sdim 680251662Sdim// Lower a call for the 32-bit ABI. 681251662SdimSDValue 682251662SdimSparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI, 683251662Sdim SmallVectorImpl<SDValue> &InVals) const { 684239462Sdim SelectionDAG &DAG = CLI.DAG; 685263508Sdim SDLoc &dl = CLI.DL; 686263508Sdim SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs; 687263508Sdim SmallVectorImpl<SDValue> &OutVals = CLI.OutVals; 688263508Sdim SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins; 689239462Sdim SDValue Chain = CLI.Chain; 690239462Sdim SDValue Callee = CLI.Callee; 691239462Sdim bool &isTailCall = CLI.IsTailCall; 692239462Sdim CallingConv::ID CallConv = CLI.CallConv; 693239462Sdim bool isVarArg = CLI.IsVarArg; 694239462Sdim 695203954Srdivacky // Sparc target does not yet support tail call optimization. 696203954Srdivacky isTailCall = false; 697193323Sed 698193323Sed // Analyze operands of the call, assigning locations to each operand. 699193323Sed SmallVector<CCValAssign, 16> ArgLocs; 700223017Sdim CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), 701239462Sdim DAG.getTarget(), ArgLocs, *DAG.getContext()); 702198090Srdivacky CCInfo.AnalyzeCallOperands(Outs, CC_Sparc32); 703193323Sed 704193323Sed // Get the size of the outgoing arguments stack space requirement. 705193323Sed unsigned ArgsSize = CCInfo.getNextStackOffset(); 706193323Sed 707193323Sed // Keep stack frames 8-byte aligned. 708193323Sed ArgsSize = (ArgsSize+7) & ~7; 709193323Sed 710218893Sdim MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); 711218893Sdim 712263508Sdim // Create local copies for byval args. 713218893Sdim SmallVector<SDValue, 8> ByValArgs; 714218893Sdim for (unsigned i = 0, e = Outs.size(); i != e; ++i) { 715218893Sdim ISD::ArgFlagsTy Flags = Outs[i].Flags; 716218893Sdim if (!Flags.isByVal()) 717218893Sdim continue; 718218893Sdim 719218893Sdim SDValue Arg = OutVals[i]; 720218893Sdim unsigned Size = Flags.getByValSize(); 721218893Sdim unsigned Align = Flags.getByValAlign(); 722218893Sdim 723218893Sdim int FI = MFI->CreateStackObject(Size, Align, false); 724218893Sdim SDValue FIPtr = DAG.getFrameIndex(FI, getPointerTy()); 725218893Sdim SDValue SizeNode = DAG.getConstant(Size, MVT::i32); 726218893Sdim 727218893Sdim Chain = DAG.getMemcpy(Chain, dl, FIPtr, Arg, SizeNode, Align, 728263508Sdim false, // isVolatile, 729263508Sdim (Size <= 32), // AlwaysInline if size <= 32 730218893Sdim MachinePointerInfo(), MachinePointerInfo()); 731218893Sdim ByValArgs.push_back(FIPtr); 732218893Sdim } 733218893Sdim 734263508Sdim Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(ArgsSize, true), 735263508Sdim dl); 736193323Sed 737193323Sed SmallVector<std::pair<unsigned, SDValue>, 8> RegsToPass; 738193323Sed SmallVector<SDValue, 8> MemOpChains; 739193323Sed 740218893Sdim const unsigned StackOffset = 92; 741219077Sdim bool hasStructRetAttr = false; 742193323Sed // Walk the register/memloc assignments, inserting copies/loads. 743218893Sdim for (unsigned i = 0, realArgIdx = 0, byvalArgIdx = 0, e = ArgLocs.size(); 744218893Sdim i != e; 745218893Sdim ++i, ++realArgIdx) { 746193323Sed CCValAssign &VA = ArgLocs[i]; 747218893Sdim SDValue Arg = OutVals[realArgIdx]; 748193323Sed 749218893Sdim ISD::ArgFlagsTy Flags = Outs[realArgIdx].Flags; 750218893Sdim 751263508Sdim // Use local copy if it is a byval arg. 752218893Sdim if (Flags.isByVal()) 753218893Sdim Arg = ByValArgs[byvalArgIdx++]; 754218893Sdim 755193323Sed // Promote the value if needed. 756193323Sed switch (VA.getLocInfo()) { 757198090Srdivacky default: llvm_unreachable("Unknown loc info!"); 758193323Sed case CCValAssign::Full: break; 759193323Sed case CCValAssign::SExt: 760218893Sdim Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg); 761193323Sed break; 762193323Sed case CCValAssign::ZExt: 763218893Sdim Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg); 764193323Sed break; 765193323Sed case CCValAssign::AExt: 766218893Sdim Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg); 767193323Sed break; 768218893Sdim case CCValAssign::BCvt: 769218893Sdim Arg = DAG.getNode(ISD::BITCAST, dl, VA.getLocVT(), Arg); 770218893Sdim break; 771193323Sed } 772193323Sed 773218893Sdim if (Flags.isSRet()) { 774218893Sdim assert(VA.needsCustom()); 775218893Sdim // store SRet argument in %sp+64 776218893Sdim SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32); 777218893Sdim SDValue PtrOff = DAG.getIntPtrConstant(64); 778218893Sdim PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff); 779218893Sdim MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, 780218893Sdim MachinePointerInfo(), 781218893Sdim false, false, 0)); 782219077Sdim hasStructRetAttr = true; 783193323Sed continue; 784193323Sed } 785193323Sed 786218893Sdim if (VA.needsCustom()) { 787218893Sdim assert(VA.getLocVT() == MVT::f64); 788193323Sed 789218893Sdim if (VA.isMemLoc()) { 790218893Sdim unsigned Offset = VA.getLocMemOffset() + StackOffset; 791263508Sdim // if it is double-word aligned, just store. 792218893Sdim if (Offset % 8 == 0) { 793218893Sdim SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32); 794218893Sdim SDValue PtrOff = DAG.getIntPtrConstant(Offset); 795218893Sdim PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff); 796218893Sdim MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, 797218893Sdim MachinePointerInfo(), 798218893Sdim false, false, 0)); 799218893Sdim continue; 800218893Sdim } 801193323Sed } 802193323Sed 803193323Sed SDValue StackPtr = DAG.CreateStackTemporary(MVT::f64, MVT::i32); 804218893Sdim SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, 805218893Sdim Arg, StackPtr, MachinePointerInfo(), 806203954Srdivacky false, false, 0); 807193323Sed // Sparc is big-endian, so the high part comes first. 808218893Sdim SDValue Hi = DAG.getLoad(MVT::i32, dl, Store, StackPtr, 809234353Sdim MachinePointerInfo(), false, false, false, 0); 810193323Sed // Increment the pointer to the other half. 811193323Sed StackPtr = DAG.getNode(ISD::ADD, dl, StackPtr.getValueType(), StackPtr, 812193323Sed DAG.getIntPtrConstant(4)); 813193323Sed // Load the low part. 814218893Sdim SDValue Lo = DAG.getLoad(MVT::i32, dl, Store, StackPtr, 815234353Sdim MachinePointerInfo(), false, false, false, 0); 816193323Sed 817218893Sdim if (VA.isRegLoc()) { 818218893Sdim RegsToPass.push_back(std::make_pair(VA.getLocReg(), Hi)); 819218893Sdim assert(i+1 != e); 820218893Sdim CCValAssign &NextVA = ArgLocs[++i]; 821218893Sdim if (NextVA.isRegLoc()) { 822218893Sdim RegsToPass.push_back(std::make_pair(NextVA.getLocReg(), Lo)); 823218893Sdim } else { 824263508Sdim // Store the low part in stack. 825218893Sdim unsigned Offset = NextVA.getLocMemOffset() + StackOffset; 826218893Sdim SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32); 827218893Sdim SDValue PtrOff = DAG.getIntPtrConstant(Offset); 828218893Sdim PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff); 829218893Sdim MemOpChains.push_back(DAG.getStore(Chain, dl, Lo, PtrOff, 830218893Sdim MachinePointerInfo(), 831218893Sdim false, false, 0)); 832218893Sdim } 833193323Sed } else { 834218893Sdim unsigned Offset = VA.getLocMemOffset() + StackOffset; 835218893Sdim // Store the high part. 836218893Sdim SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32); 837218893Sdim SDValue PtrOff = DAG.getIntPtrConstant(Offset); 838218893Sdim PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff); 839218893Sdim MemOpChains.push_back(DAG.getStore(Chain, dl, Hi, PtrOff, 840218893Sdim MachinePointerInfo(), 841218893Sdim false, false, 0)); 842218893Sdim // Store the low part. 843218893Sdim PtrOff = DAG.getIntPtrConstant(Offset+4); 844218893Sdim PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff); 845218893Sdim MemOpChains.push_back(DAG.getStore(Chain, dl, Lo, PtrOff, 846218893Sdim MachinePointerInfo(), 847218893Sdim false, false, 0)); 848193323Sed } 849218893Sdim continue; 850193323Sed } 851193323Sed 852218893Sdim // Arguments that can be passed on register must be kept at 853218893Sdim // RegsToPass vector 854218893Sdim if (VA.isRegLoc()) { 855218893Sdim if (VA.getLocVT() != MVT::f32) { 856218893Sdim RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); 857218893Sdim continue; 858193323Sed } 859218893Sdim Arg = DAG.getNode(ISD::BITCAST, dl, MVT::i32, Arg); 860218893Sdim RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); 861218893Sdim continue; 862193323Sed } 863193323Sed 864218893Sdim assert(VA.isMemLoc()); 865218893Sdim 866218893Sdim // Create a store off the stack pointer for this argument. 867218893Sdim SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32); 868218893Sdim SDValue PtrOff = DAG.getIntPtrConstant(VA.getLocMemOffset()+StackOffset); 869218893Sdim PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff); 870218893Sdim MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, 871218893Sdim MachinePointerInfo(), 872218893Sdim false, false, 0)); 873193323Sed } 874193323Sed 875218893Sdim 876193323Sed // Emit all stores, make sure the occur before any copies into physregs. 877193323Sed if (!MemOpChains.empty()) 878193323Sed Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, 879193323Sed &MemOpChains[0], MemOpChains.size()); 880193323Sed 881193323Sed // Build a sequence of copy-to-reg nodes chained together with token 882193323Sed // chain and flag operands which copy the outgoing args into registers. 883221345Sdim // The InFlag in necessary since all emitted instructions must be 884193323Sed // stuck together. 885193323Sed SDValue InFlag; 886193323Sed for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { 887251662Sdim unsigned Reg = toCallerWindow(RegsToPass[i].first); 888193323Sed Chain = DAG.getCopyToReg(Chain, dl, Reg, RegsToPass[i].second, InFlag); 889193323Sed InFlag = Chain.getValue(1); 890193323Sed } 891193323Sed 892219077Sdim unsigned SRetArgSize = (hasStructRetAttr)? getSRetArgSize(DAG, Callee):0; 893263508Sdim bool hasReturnsTwice = hasReturnsTwiceAttr(DAG, Callee, CLI.CS); 894219077Sdim 895193323Sed // If the callee is a GlobalAddress node (quite common, every direct call is) 896193323Sed // turn it into a TargetGlobalAddress node so that legalize doesn't hack it. 897193323Sed // Likewise ExternalSymbol -> TargetExternalSymbol. 898263763Sdim unsigned TF = ((getTargetMachine().getRelocationModel() == Reloc::PIC_) 899263763Sdim ? SparcMCExpr::VK_Sparc_WPLT30 : 0); 900193323Sed if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) 901263763Sdim Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i32, 0, TF); 902193323Sed else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee)) 903263763Sdim Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32, TF); 904193323Sed 905218893Sdim // Returns a chain & a flag for retval copy to use 906218893Sdim SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); 907218893Sdim SmallVector<SDValue, 8> Ops; 908218893Sdim Ops.push_back(Chain); 909218893Sdim Ops.push_back(Callee); 910219077Sdim if (hasStructRetAttr) 911219077Sdim Ops.push_back(DAG.getTargetConstant(SRetArgSize, MVT::i32)); 912251662Sdim for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) 913251662Sdim Ops.push_back(DAG.getRegister(toCallerWindow(RegsToPass[i].first), 914251662Sdim RegsToPass[i].second.getValueType())); 915263508Sdim 916263508Sdim // Add a register mask operand representing the call-preserved registers. 917263508Sdim const SparcRegisterInfo *TRI = 918263508Sdim ((const SparcTargetMachine&)getTargetMachine()).getRegisterInfo(); 919263508Sdim const uint32_t *Mask = ((hasReturnsTwice) 920263508Sdim ? TRI->getRTCallPreservedMask(CallConv) 921263508Sdim : TRI->getCallPreservedMask(CallConv)); 922263508Sdim assert(Mask && "Missing call preserved mask for calling convention"); 923263508Sdim Ops.push_back(DAG.getRegisterMask(Mask)); 924263508Sdim 925218893Sdim if (InFlag.getNode()) 926218893Sdim Ops.push_back(InFlag); 927218893Sdim 928218893Sdim Chain = DAG.getNode(SPISD::CALL, dl, NodeTys, &Ops[0], Ops.size()); 929193323Sed InFlag = Chain.getValue(1); 930193323Sed 931193323Sed Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(ArgsSize, true), 932263508Sdim DAG.getIntPtrConstant(0, true), InFlag, dl); 933193323Sed InFlag = Chain.getValue(1); 934193323Sed 935193323Sed // Assign locations to each value returned by this call. 936193323Sed SmallVector<CCValAssign, 16> RVLocs; 937223017Sdim CCState RVInfo(CallConv, isVarArg, DAG.getMachineFunction(), 938239462Sdim DAG.getTarget(), RVLocs, *DAG.getContext()); 939193323Sed 940198090Srdivacky RVInfo.AnalyzeCallResult(Ins, RetCC_Sparc32); 941193323Sed 942193323Sed // Copy all of the result registers out of their specified physreg. 943193323Sed for (unsigned i = 0; i != RVLocs.size(); ++i) { 944251662Sdim Chain = DAG.getCopyFromReg(Chain, dl, toCallerWindow(RVLocs[i].getLocReg()), 945193323Sed RVLocs[i].getValVT(), InFlag).getValue(1); 946193323Sed InFlag = Chain.getValue(2); 947198090Srdivacky InVals.push_back(Chain.getValue(0)); 948193323Sed } 949193323Sed 950198090Srdivacky return Chain; 951193323Sed} 952193323Sed 953263508Sdim// This functions returns true if CalleeName is a ABI function that returns 954263508Sdim// a long double (fp128). 955263508Sdimstatic bool isFP128ABICall(const char *CalleeName) 956263508Sdim{ 957263508Sdim static const char *const ABICalls[] = 958263508Sdim { "_Q_add", "_Q_sub", "_Q_mul", "_Q_div", 959263508Sdim "_Q_sqrt", "_Q_neg", 960263508Sdim "_Q_itoq", "_Q_stoq", "_Q_dtoq", "_Q_utoq", 961263508Sdim "_Q_lltoq", "_Q_ulltoq", 962263508Sdim 0 963263508Sdim }; 964263508Sdim for (const char * const *I = ABICalls; *I != 0; ++I) 965263508Sdim if (strcmp(CalleeName, *I) == 0) 966263508Sdim return true; 967263508Sdim return false; 968263508Sdim} 969263508Sdim 970219077Sdimunsigned 971219077SdimSparcTargetLowering::getSRetArgSize(SelectionDAG &DAG, SDValue Callee) const 972219077Sdim{ 973219077Sdim const Function *CalleeFn = 0; 974219077Sdim if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) { 975219077Sdim CalleeFn = dyn_cast<Function>(G->getGlobal()); 976219077Sdim } else if (ExternalSymbolSDNode *E = 977219077Sdim dyn_cast<ExternalSymbolSDNode>(Callee)) { 978219077Sdim const Function *Fn = DAG.getMachineFunction().getFunction(); 979219077Sdim const Module *M = Fn->getParent(); 980263508Sdim const char *CalleeName = E->getSymbol(); 981263508Sdim CalleeFn = M->getFunction(CalleeName); 982263508Sdim if (!CalleeFn && isFP128ABICall(CalleeName)) 983263508Sdim return 16; // Return sizeof(fp128) 984219077Sdim } 985193323Sed 986219077Sdim if (!CalleeFn) 987219077Sdim return 0; 988193323Sed 989219077Sdim assert(CalleeFn->hasStructRetAttr() && 990219077Sdim "Callee does not have the StructRet attribute."); 991219077Sdim 992226633Sdim PointerType *Ty = cast<PointerType>(CalleeFn->arg_begin()->getType()); 993226633Sdim Type *ElementTy = Ty->getElementType(); 994243830Sdim return getDataLayout()->getTypeAllocSize(ElementTy); 995219077Sdim} 996219077Sdim 997251662Sdim 998251662Sdim// Fixup floating point arguments in the ... part of a varargs call. 999251662Sdim// 1000251662Sdim// The SPARC v9 ABI requires that floating point arguments are treated the same 1001251662Sdim// as integers when calling a varargs function. This does not apply to the 1002251662Sdim// fixed arguments that are part of the function's prototype. 1003251662Sdim// 1004251662Sdim// This function post-processes a CCValAssign array created by 1005251662Sdim// AnalyzeCallOperands(). 1006251662Sdimstatic void fixupVariableFloatArgs(SmallVectorImpl<CCValAssign> &ArgLocs, 1007251662Sdim ArrayRef<ISD::OutputArg> Outs) { 1008251662Sdim for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { 1009251662Sdim const CCValAssign &VA = ArgLocs[i]; 1010263763Sdim MVT ValTy = VA.getLocVT(); 1011251662Sdim // FIXME: What about f32 arguments? C promotes them to f64 when calling 1012251662Sdim // varargs functions. 1013263763Sdim if (!VA.isRegLoc() || (ValTy != MVT::f64 && ValTy != MVT::f128)) 1014251662Sdim continue; 1015251662Sdim // The fixed arguments to a varargs function still go in FP registers. 1016251662Sdim if (Outs[VA.getValNo()].IsFixed) 1017251662Sdim continue; 1018251662Sdim 1019251662Sdim // This floating point argument should be reassigned. 1020251662Sdim CCValAssign NewVA; 1021251662Sdim 1022251662Sdim // Determine the offset into the argument array. 1023263763Sdim unsigned firstReg = (ValTy == MVT::f64) ? SP::D0 : SP::Q0; 1024263763Sdim unsigned argSize = (ValTy == MVT::f64) ? 8 : 16; 1025263763Sdim unsigned Offset = argSize * (VA.getLocReg() - firstReg); 1026251662Sdim assert(Offset < 16*8 && "Offset out of range, bad register enum?"); 1027251662Sdim 1028251662Sdim if (Offset < 6*8) { 1029251662Sdim // This argument should go in %i0-%i5. 1030251662Sdim unsigned IReg = SP::I0 + Offset/8; 1031263763Sdim if (ValTy == MVT::f64) 1032263763Sdim // Full register, just bitconvert into i64. 1033263763Sdim NewVA = CCValAssign::getReg(VA.getValNo(), VA.getValVT(), 1034263763Sdim IReg, MVT::i64, CCValAssign::BCvt); 1035263763Sdim else { 1036263763Sdim assert(ValTy == MVT::f128 && "Unexpected type!"); 1037263763Sdim // Full register, just bitconvert into i128 -- We will lower this into 1038263763Sdim // two i64s in LowerCall_64. 1039263763Sdim NewVA = CCValAssign::getCustomReg(VA.getValNo(), VA.getValVT(), 1040263763Sdim IReg, MVT::i128, CCValAssign::BCvt); 1041263763Sdim } 1042251662Sdim } else { 1043251662Sdim // This needs to go to memory, we're out of integer registers. 1044251662Sdim NewVA = CCValAssign::getMem(VA.getValNo(), VA.getValVT(), 1045251662Sdim Offset, VA.getLocVT(), VA.getLocInfo()); 1046251662Sdim } 1047251662Sdim ArgLocs[i] = NewVA; 1048251662Sdim } 1049251662Sdim} 1050251662Sdim 1051251662Sdim// Lower a call for the 64-bit ABI. 1052251662SdimSDValue 1053251662SdimSparcTargetLowering::LowerCall_64(TargetLowering::CallLoweringInfo &CLI, 1054251662Sdim SmallVectorImpl<SDValue> &InVals) const { 1055251662Sdim SelectionDAG &DAG = CLI.DAG; 1056263508Sdim SDLoc DL = CLI.DL; 1057251662Sdim SDValue Chain = CLI.Chain; 1058251662Sdim 1059263508Sdim // Sparc target does not yet support tail call optimization. 1060263508Sdim CLI.IsTailCall = false; 1061263508Sdim 1062251662Sdim // Analyze operands of the call, assigning locations to each operand. 1063251662Sdim SmallVector<CCValAssign, 16> ArgLocs; 1064251662Sdim CCState CCInfo(CLI.CallConv, CLI.IsVarArg, DAG.getMachineFunction(), 1065251662Sdim DAG.getTarget(), ArgLocs, *DAG.getContext()); 1066251662Sdim CCInfo.AnalyzeCallOperands(CLI.Outs, CC_Sparc64); 1067251662Sdim 1068251662Sdim // Get the size of the outgoing arguments stack space requirement. 1069251662Sdim // The stack offset computed by CC_Sparc64 includes all arguments. 1070251662Sdim // Called functions expect 6 argument words to exist in the stack frame, used 1071251662Sdim // or not. 1072251662Sdim unsigned ArgsSize = std::max(6*8u, CCInfo.getNextStackOffset()); 1073251662Sdim 1074251662Sdim // Keep stack frames 16-byte aligned. 1075251662Sdim ArgsSize = RoundUpToAlignment(ArgsSize, 16); 1076251662Sdim 1077251662Sdim // Varargs calls require special treatment. 1078251662Sdim if (CLI.IsVarArg) 1079251662Sdim fixupVariableFloatArgs(ArgLocs, CLI.Outs); 1080251662Sdim 1081251662Sdim // Adjust the stack pointer to make room for the arguments. 1082251662Sdim // FIXME: Use hasReservedCallFrame to avoid %sp adjustments around all calls 1083251662Sdim // with more than 6 arguments. 1084263508Sdim Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(ArgsSize, true), 1085263508Sdim DL); 1086251662Sdim 1087251662Sdim // Collect the set of registers to pass to the function and their values. 1088251662Sdim // This will be emitted as a sequence of CopyToReg nodes glued to the call 1089251662Sdim // instruction. 1090251662Sdim SmallVector<std::pair<unsigned, SDValue>, 8> RegsToPass; 1091251662Sdim 1092251662Sdim // Collect chains from all the memory opeations that copy arguments to the 1093251662Sdim // stack. They must follow the stack pointer adjustment above and precede the 1094251662Sdim // call instruction itself. 1095251662Sdim SmallVector<SDValue, 8> MemOpChains; 1096251662Sdim 1097251662Sdim for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { 1098251662Sdim const CCValAssign &VA = ArgLocs[i]; 1099251662Sdim SDValue Arg = CLI.OutVals[i]; 1100251662Sdim 1101251662Sdim // Promote the value if needed. 1102251662Sdim switch (VA.getLocInfo()) { 1103251662Sdim default: 1104251662Sdim llvm_unreachable("Unknown location info!"); 1105251662Sdim case CCValAssign::Full: 1106251662Sdim break; 1107251662Sdim case CCValAssign::SExt: 1108251662Sdim Arg = DAG.getNode(ISD::SIGN_EXTEND, DL, VA.getLocVT(), Arg); 1109251662Sdim break; 1110251662Sdim case CCValAssign::ZExt: 1111251662Sdim Arg = DAG.getNode(ISD::ZERO_EXTEND, DL, VA.getLocVT(), Arg); 1112251662Sdim break; 1113251662Sdim case CCValAssign::AExt: 1114251662Sdim Arg = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), Arg); 1115251662Sdim break; 1116251662Sdim case CCValAssign::BCvt: 1117263763Sdim // fixupVariableFloatArgs() may create bitcasts from f128 to i128. But 1118263763Sdim // SPARC does not support i128 natively. Lower it into two i64, see below. 1119263763Sdim if (!VA.needsCustom() || VA.getValVT() != MVT::f128 1120263763Sdim || VA.getLocVT() != MVT::i128) 1121263763Sdim Arg = DAG.getNode(ISD::BITCAST, DL, VA.getLocVT(), Arg); 1122251662Sdim break; 1123251662Sdim } 1124251662Sdim 1125251662Sdim if (VA.isRegLoc()) { 1126263763Sdim if (VA.needsCustom() && VA.getValVT() == MVT::f128 1127263763Sdim && VA.getLocVT() == MVT::i128) { 1128263763Sdim // Store and reload into the interger register reg and reg+1. 1129263763Sdim unsigned Offset = 8 * (VA.getLocReg() - SP::I0); 1130263763Sdim unsigned StackOffset = Offset + Subtarget->getStackPointerBias() + 128; 1131263763Sdim SDValue StackPtr = DAG.getRegister(SP::O6, getPointerTy()); 1132263763Sdim SDValue HiPtrOff = DAG.getIntPtrConstant(StackOffset); 1133263763Sdim HiPtrOff = DAG.getNode(ISD::ADD, DL, getPointerTy(), StackPtr, 1134263763Sdim HiPtrOff); 1135263763Sdim SDValue LoPtrOff = DAG.getIntPtrConstant(StackOffset + 8); 1136263763Sdim LoPtrOff = DAG.getNode(ISD::ADD, DL, getPointerTy(), StackPtr, 1137263763Sdim LoPtrOff); 1138263763Sdim 1139263763Sdim // Store to %sp+BIAS+128+Offset 1140263763Sdim SDValue Store = DAG.getStore(Chain, DL, Arg, HiPtrOff, 1141263763Sdim MachinePointerInfo(), 1142263763Sdim false, false, 0); 1143263763Sdim // Load into Reg and Reg+1 1144263763Sdim SDValue Hi64 = DAG.getLoad(MVT::i64, DL, Store, HiPtrOff, 1145263763Sdim MachinePointerInfo(), 1146263763Sdim false, false, false, 0); 1147263763Sdim SDValue Lo64 = DAG.getLoad(MVT::i64, DL, Store, LoPtrOff, 1148263763Sdim MachinePointerInfo(), 1149263763Sdim false, false, false, 0); 1150263763Sdim RegsToPass.push_back(std::make_pair(toCallerWindow(VA.getLocReg()), 1151263763Sdim Hi64)); 1152263763Sdim RegsToPass.push_back(std::make_pair(toCallerWindow(VA.getLocReg()+1), 1153263763Sdim Lo64)); 1154263763Sdim continue; 1155263763Sdim } 1156263763Sdim 1157251662Sdim // The custom bit on an i32 return value indicates that it should be 1158251662Sdim // passed in the high bits of the register. 1159251662Sdim if (VA.getValVT() == MVT::i32 && VA.needsCustom()) { 1160251662Sdim Arg = DAG.getNode(ISD::SHL, DL, MVT::i64, Arg, 1161251662Sdim DAG.getConstant(32, MVT::i32)); 1162251662Sdim 1163251662Sdim // The next value may go in the low bits of the same register. 1164251662Sdim // Handle both at once. 1165251662Sdim if (i+1 < ArgLocs.size() && ArgLocs[i+1].isRegLoc() && 1166251662Sdim ArgLocs[i+1].getLocReg() == VA.getLocReg()) { 1167251662Sdim SDValue NV = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i64, 1168251662Sdim CLI.OutVals[i+1]); 1169251662Sdim Arg = DAG.getNode(ISD::OR, DL, MVT::i64, Arg, NV); 1170251662Sdim // Skip the next value, it's already done. 1171251662Sdim ++i; 1172251662Sdim } 1173251662Sdim } 1174251662Sdim RegsToPass.push_back(std::make_pair(toCallerWindow(VA.getLocReg()), Arg)); 1175251662Sdim continue; 1176251662Sdim } 1177251662Sdim 1178251662Sdim assert(VA.isMemLoc()); 1179251662Sdim 1180251662Sdim // Create a store off the stack pointer for this argument. 1181251662Sdim SDValue StackPtr = DAG.getRegister(SP::O6, getPointerTy()); 1182251662Sdim // The argument area starts at %fp+BIAS+128 in the callee frame, 1183251662Sdim // %sp+BIAS+128 in ours. 1184251662Sdim SDValue PtrOff = DAG.getIntPtrConstant(VA.getLocMemOffset() + 1185251662Sdim Subtarget->getStackPointerBias() + 1186251662Sdim 128); 1187251662Sdim PtrOff = DAG.getNode(ISD::ADD, DL, getPointerTy(), StackPtr, PtrOff); 1188251662Sdim MemOpChains.push_back(DAG.getStore(Chain, DL, Arg, PtrOff, 1189251662Sdim MachinePointerInfo(), 1190251662Sdim false, false, 0)); 1191251662Sdim } 1192251662Sdim 1193251662Sdim // Emit all stores, make sure they occur before the call. 1194251662Sdim if (!MemOpChains.empty()) 1195251662Sdim Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, 1196251662Sdim &MemOpChains[0], MemOpChains.size()); 1197251662Sdim 1198251662Sdim // Build a sequence of CopyToReg nodes glued together with token chain and 1199251662Sdim // glue operands which copy the outgoing args into registers. The InGlue is 1200251662Sdim // necessary since all emitted instructions must be stuck together in order 1201251662Sdim // to pass the live physical registers. 1202251662Sdim SDValue InGlue; 1203251662Sdim for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { 1204251662Sdim Chain = DAG.getCopyToReg(Chain, DL, 1205251662Sdim RegsToPass[i].first, RegsToPass[i].second, InGlue); 1206251662Sdim InGlue = Chain.getValue(1); 1207251662Sdim } 1208251662Sdim 1209251662Sdim // If the callee is a GlobalAddress node (quite common, every direct call is) 1210251662Sdim // turn it into a TargetGlobalAddress node so that legalize doesn't hack it. 1211251662Sdim // Likewise ExternalSymbol -> TargetExternalSymbol. 1212251662Sdim SDValue Callee = CLI.Callee; 1213263508Sdim bool hasReturnsTwice = hasReturnsTwiceAttr(DAG, Callee, CLI.CS); 1214263763Sdim unsigned TF = ((getTargetMachine().getRelocationModel() == Reloc::PIC_) 1215263763Sdim ? SparcMCExpr::VK_Sparc_WPLT30 : 0); 1216251662Sdim if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) 1217263763Sdim Callee = DAG.getTargetGlobalAddress(G->getGlobal(), DL, getPointerTy(), 0, 1218263763Sdim TF); 1219251662Sdim else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee)) 1220263763Sdim Callee = DAG.getTargetExternalSymbol(E->getSymbol(), getPointerTy(), TF); 1221251662Sdim 1222251662Sdim // Build the operands for the call instruction itself. 1223251662Sdim SmallVector<SDValue, 8> Ops; 1224251662Sdim Ops.push_back(Chain); 1225251662Sdim Ops.push_back(Callee); 1226251662Sdim for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) 1227251662Sdim Ops.push_back(DAG.getRegister(RegsToPass[i].first, 1228251662Sdim RegsToPass[i].second.getValueType())); 1229251662Sdim 1230263508Sdim // Add a register mask operand representing the call-preserved registers. 1231263508Sdim const SparcRegisterInfo *TRI = 1232263508Sdim ((const SparcTargetMachine&)getTargetMachine()).getRegisterInfo(); 1233263508Sdim const uint32_t *Mask = ((hasReturnsTwice) 1234263508Sdim ? TRI->getRTCallPreservedMask(CLI.CallConv) 1235263508Sdim : TRI->getCallPreservedMask(CLI.CallConv)); 1236263508Sdim assert(Mask && "Missing call preserved mask for calling convention"); 1237263508Sdim Ops.push_back(DAG.getRegisterMask(Mask)); 1238263508Sdim 1239251662Sdim // Make sure the CopyToReg nodes are glued to the call instruction which 1240251662Sdim // consumes the registers. 1241251662Sdim if (InGlue.getNode()) 1242251662Sdim Ops.push_back(InGlue); 1243251662Sdim 1244251662Sdim // Now the call itself. 1245251662Sdim SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); 1246251662Sdim Chain = DAG.getNode(SPISD::CALL, DL, NodeTys, &Ops[0], Ops.size()); 1247251662Sdim InGlue = Chain.getValue(1); 1248251662Sdim 1249251662Sdim // Revert the stack pointer immediately after the call. 1250251662Sdim Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(ArgsSize, true), 1251263508Sdim DAG.getIntPtrConstant(0, true), InGlue, DL); 1252251662Sdim InGlue = Chain.getValue(1); 1253251662Sdim 1254251662Sdim // Now extract the return values. This is more or less the same as 1255251662Sdim // LowerFormalArguments_64. 1256251662Sdim 1257251662Sdim // Assign locations to each value returned by this call. 1258251662Sdim SmallVector<CCValAssign, 16> RVLocs; 1259251662Sdim CCState RVInfo(CLI.CallConv, CLI.IsVarArg, DAG.getMachineFunction(), 1260251662Sdim DAG.getTarget(), RVLocs, *DAG.getContext()); 1261251662Sdim 1262263763Sdim // Set inreg flag manually for codegen generated library calls that 1263263763Sdim // return float. 1264263763Sdim if (CLI.Ins.size() == 1 && CLI.Ins[0].VT == MVT::f32 && CLI.CS == 0) 1265263763Sdim CLI.Ins[0].Flags.setInReg(); 1266263763Sdim 1267263763Sdim RVInfo.AnalyzeCallResult(CLI.Ins, RetCC_Sparc64); 1268263763Sdim 1269251662Sdim // Copy all of the result registers out of their specified physreg. 1270251662Sdim for (unsigned i = 0; i != RVLocs.size(); ++i) { 1271251662Sdim CCValAssign &VA = RVLocs[i]; 1272251662Sdim unsigned Reg = toCallerWindow(VA.getLocReg()); 1273251662Sdim 1274251662Sdim // When returning 'inreg {i32, i32 }', two consecutive i32 arguments can 1275251662Sdim // reside in the same register in the high and low bits. Reuse the 1276251662Sdim // CopyFromReg previous node to avoid duplicate copies. 1277251662Sdim SDValue RV; 1278251662Sdim if (RegisterSDNode *SrcReg = dyn_cast<RegisterSDNode>(Chain.getOperand(1))) 1279251662Sdim if (SrcReg->getReg() == Reg && Chain->getOpcode() == ISD::CopyFromReg) 1280251662Sdim RV = Chain.getValue(0); 1281251662Sdim 1282251662Sdim // But usually we'll create a new CopyFromReg for a different register. 1283251662Sdim if (!RV.getNode()) { 1284251662Sdim RV = DAG.getCopyFromReg(Chain, DL, Reg, RVLocs[i].getLocVT(), InGlue); 1285251662Sdim Chain = RV.getValue(1); 1286251662Sdim InGlue = Chain.getValue(2); 1287251662Sdim } 1288251662Sdim 1289251662Sdim // Get the high bits for i32 struct elements. 1290251662Sdim if (VA.getValVT() == MVT::i32 && VA.needsCustom()) 1291251662Sdim RV = DAG.getNode(ISD::SRL, DL, VA.getLocVT(), RV, 1292251662Sdim DAG.getConstant(32, MVT::i32)); 1293251662Sdim 1294251662Sdim // The callee promoted the return value, so insert an Assert?ext SDNode so 1295251662Sdim // we won't promote the value again in this function. 1296251662Sdim switch (VA.getLocInfo()) { 1297251662Sdim case CCValAssign::SExt: 1298251662Sdim RV = DAG.getNode(ISD::AssertSext, DL, VA.getLocVT(), RV, 1299251662Sdim DAG.getValueType(VA.getValVT())); 1300251662Sdim break; 1301251662Sdim case CCValAssign::ZExt: 1302251662Sdim RV = DAG.getNode(ISD::AssertZext, DL, VA.getLocVT(), RV, 1303251662Sdim DAG.getValueType(VA.getValVT())); 1304251662Sdim break; 1305251662Sdim default: 1306251662Sdim break; 1307251662Sdim } 1308251662Sdim 1309251662Sdim // Truncate the register down to the return value type. 1310251662Sdim if (VA.isExtInLoc()) 1311251662Sdim RV = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), RV); 1312251662Sdim 1313251662Sdim InVals.push_back(RV); 1314251662Sdim } 1315251662Sdim 1316251662Sdim return Chain; 1317251662Sdim} 1318251662Sdim 1319193323Sed//===----------------------------------------------------------------------===// 1320193323Sed// TargetLowering Implementation 1321193323Sed//===----------------------------------------------------------------------===// 1322193323Sed 1323193323Sed/// IntCondCCodeToICC - Convert a DAG integer condition code to a SPARC ICC 1324193323Sed/// condition. 1325193323Sedstatic SPCC::CondCodes IntCondCCodeToICC(ISD::CondCode CC) { 1326193323Sed switch (CC) { 1327198090Srdivacky default: llvm_unreachable("Unknown integer condition code!"); 1328193323Sed case ISD::SETEQ: return SPCC::ICC_E; 1329193323Sed case ISD::SETNE: return SPCC::ICC_NE; 1330193323Sed case ISD::SETLT: return SPCC::ICC_L; 1331193323Sed case ISD::SETGT: return SPCC::ICC_G; 1332193323Sed case ISD::SETLE: return SPCC::ICC_LE; 1333193323Sed case ISD::SETGE: return SPCC::ICC_GE; 1334193323Sed case ISD::SETULT: return SPCC::ICC_CS; 1335193323Sed case ISD::SETULE: return SPCC::ICC_LEU; 1336193323Sed case ISD::SETUGT: return SPCC::ICC_GU; 1337193323Sed case ISD::SETUGE: return SPCC::ICC_CC; 1338193323Sed } 1339193323Sed} 1340193323Sed 1341193323Sed/// FPCondCCodeToFCC - Convert a DAG floatingp oint condition code to a SPARC 1342193323Sed/// FCC condition. 1343193323Sedstatic SPCC::CondCodes FPCondCCodeToFCC(ISD::CondCode CC) { 1344193323Sed switch (CC) { 1345198090Srdivacky default: llvm_unreachable("Unknown fp condition code!"); 1346193323Sed case ISD::SETEQ: 1347193323Sed case ISD::SETOEQ: return SPCC::FCC_E; 1348193323Sed case ISD::SETNE: 1349193323Sed case ISD::SETUNE: return SPCC::FCC_NE; 1350193323Sed case ISD::SETLT: 1351193323Sed case ISD::SETOLT: return SPCC::FCC_L; 1352193323Sed case ISD::SETGT: 1353193323Sed case ISD::SETOGT: return SPCC::FCC_G; 1354193323Sed case ISD::SETLE: 1355193323Sed case ISD::SETOLE: return SPCC::FCC_LE; 1356193323Sed case ISD::SETGE: 1357193323Sed case ISD::SETOGE: return SPCC::FCC_GE; 1358193323Sed case ISD::SETULT: return SPCC::FCC_UL; 1359193323Sed case ISD::SETULE: return SPCC::FCC_ULE; 1360193323Sed case ISD::SETUGT: return SPCC::FCC_UG; 1361193323Sed case ISD::SETUGE: return SPCC::FCC_UGE; 1362193323Sed case ISD::SETUO: return SPCC::FCC_U; 1363193323Sed case ISD::SETO: return SPCC::FCC_O; 1364193323Sed case ISD::SETONE: return SPCC::FCC_LG; 1365193323Sed case ISD::SETUEQ: return SPCC::FCC_UE; 1366193323Sed } 1367193323Sed} 1368193323Sed 1369193323SedSparcTargetLowering::SparcTargetLowering(TargetMachine &TM) 1370263763Sdim : TargetLowering(TM, new SparcELFTargetObjectFile()) { 1371249423Sdim Subtarget = &TM.getSubtarget<SparcSubtarget>(); 1372193323Sed 1373193323Sed // Set up the register classes. 1374239462Sdim addRegisterClass(MVT::i32, &SP::IntRegsRegClass); 1375239462Sdim addRegisterClass(MVT::f32, &SP::FPRegsRegClass); 1376239462Sdim addRegisterClass(MVT::f64, &SP::DFPRegsRegClass); 1377263508Sdim addRegisterClass(MVT::f128, &SP::QFPRegsRegClass); 1378249423Sdim if (Subtarget->is64Bit()) 1379249423Sdim addRegisterClass(MVT::i64, &SP::I64RegsRegClass); 1380193323Sed 1381193323Sed // Turn FP extload into load/fextend 1382193323Sed setLoadExtAction(ISD::EXTLOAD, MVT::f32, Expand); 1383263508Sdim setLoadExtAction(ISD::EXTLOAD, MVT::f64, Expand); 1384263508Sdim 1385193323Sed // Sparc doesn't have i1 sign extending load 1386193323Sed setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote); 1387263508Sdim 1388193323Sed // Turn FP truncstore into trunc + store. 1389193323Sed setTruncStoreAction(MVT::f64, MVT::f32, Expand); 1390263508Sdim setTruncStoreAction(MVT::f128, MVT::f32, Expand); 1391263508Sdim setTruncStoreAction(MVT::f128, MVT::f64, Expand); 1392193323Sed 1393193323Sed // Custom legalize GlobalAddress nodes into LO/HI parts. 1394251662Sdim setOperationAction(ISD::GlobalAddress, getPointerTy(), Custom); 1395251662Sdim setOperationAction(ISD::GlobalTLSAddress, getPointerTy(), Custom); 1396251662Sdim setOperationAction(ISD::ConstantPool, getPointerTy(), Custom); 1397263508Sdim setOperationAction(ISD::BlockAddress, getPointerTy(), Custom); 1398193323Sed 1399193323Sed // Sparc doesn't have sext_inreg, replace them with shl/sra 1400193323Sed setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16, Expand); 1401193323Sed setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8 , Expand); 1402193323Sed setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1 , Expand); 1403193323Sed 1404193323Sed // Sparc has no REM or DIVREM operations. 1405193323Sed setOperationAction(ISD::UREM, MVT::i32, Expand); 1406193323Sed setOperationAction(ISD::SREM, MVT::i32, Expand); 1407193323Sed setOperationAction(ISD::SDIVREM, MVT::i32, Expand); 1408193323Sed setOperationAction(ISD::UDIVREM, MVT::i32, Expand); 1409193323Sed 1410263508Sdim // ... nor does SparcV9. 1411263508Sdim if (Subtarget->is64Bit()) { 1412263508Sdim setOperationAction(ISD::UREM, MVT::i64, Expand); 1413263508Sdim setOperationAction(ISD::SREM, MVT::i64, Expand); 1414263508Sdim setOperationAction(ISD::SDIVREM, MVT::i64, Expand); 1415263508Sdim setOperationAction(ISD::UDIVREM, MVT::i64, Expand); 1416263508Sdim } 1417263508Sdim 1418193323Sed // Custom expand fp<->sint 1419193323Sed setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom); 1420193323Sed setOperationAction(ISD::SINT_TO_FP, MVT::i32, Custom); 1421263508Sdim setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom); 1422263508Sdim setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom); 1423193323Sed 1424263508Sdim // Custom Expand fp<->uint 1425263508Sdim setOperationAction(ISD::FP_TO_UINT, MVT::i32, Custom); 1426263508Sdim setOperationAction(ISD::UINT_TO_FP, MVT::i32, Custom); 1427263508Sdim setOperationAction(ISD::FP_TO_UINT, MVT::i64, Custom); 1428263508Sdim setOperationAction(ISD::UINT_TO_FP, MVT::i64, Custom); 1429193323Sed 1430218893Sdim setOperationAction(ISD::BITCAST, MVT::f32, Expand); 1431218893Sdim setOperationAction(ISD::BITCAST, MVT::i32, Expand); 1432193323Sed 1433193323Sed // Sparc has no select or setcc: expand to SELECT_CC. 1434193323Sed setOperationAction(ISD::SELECT, MVT::i32, Expand); 1435193323Sed setOperationAction(ISD::SELECT, MVT::f32, Expand); 1436193323Sed setOperationAction(ISD::SELECT, MVT::f64, Expand); 1437263508Sdim setOperationAction(ISD::SELECT, MVT::f128, Expand); 1438263508Sdim 1439193323Sed setOperationAction(ISD::SETCC, MVT::i32, Expand); 1440193323Sed setOperationAction(ISD::SETCC, MVT::f32, Expand); 1441193323Sed setOperationAction(ISD::SETCC, MVT::f64, Expand); 1442263508Sdim setOperationAction(ISD::SETCC, MVT::f128, Expand); 1443193323Sed 1444193323Sed // Sparc doesn't have BRCOND either, it has BR_CC. 1445193323Sed setOperationAction(ISD::BRCOND, MVT::Other, Expand); 1446193323Sed setOperationAction(ISD::BRIND, MVT::Other, Expand); 1447193323Sed setOperationAction(ISD::BR_JT, MVT::Other, Expand); 1448193323Sed setOperationAction(ISD::BR_CC, MVT::i32, Custom); 1449193323Sed setOperationAction(ISD::BR_CC, MVT::f32, Custom); 1450193323Sed setOperationAction(ISD::BR_CC, MVT::f64, Custom); 1451263508Sdim setOperationAction(ISD::BR_CC, MVT::f128, Custom); 1452193323Sed 1453193323Sed setOperationAction(ISD::SELECT_CC, MVT::i32, Custom); 1454193323Sed setOperationAction(ISD::SELECT_CC, MVT::f32, Custom); 1455193323Sed setOperationAction(ISD::SELECT_CC, MVT::f64, Custom); 1456263508Sdim setOperationAction(ISD::SELECT_CC, MVT::f128, Custom); 1457193323Sed 1458249423Sdim if (Subtarget->is64Bit()) { 1459263508Sdim setOperationAction(ISD::ADDC, MVT::i64, Custom); 1460263508Sdim setOperationAction(ISD::ADDE, MVT::i64, Custom); 1461263508Sdim setOperationAction(ISD::SUBC, MVT::i64, Custom); 1462263508Sdim setOperationAction(ISD::SUBE, MVT::i64, Custom); 1463263508Sdim setOperationAction(ISD::BITCAST, MVT::f64, Expand); 1464263508Sdim setOperationAction(ISD::BITCAST, MVT::i64, Expand); 1465263508Sdim setOperationAction(ISD::SELECT, MVT::i64, Expand); 1466263508Sdim setOperationAction(ISD::SETCC, MVT::i64, Expand); 1467249423Sdim setOperationAction(ISD::BR_CC, MVT::i64, Custom); 1468249423Sdim setOperationAction(ISD::SELECT_CC, MVT::i64, Custom); 1469263508Sdim 1470263763Sdim setOperationAction(ISD::CTPOP, MVT::i64, 1471263763Sdim Subtarget->usePopc() ? Legal : Expand); 1472263508Sdim setOperationAction(ISD::CTTZ , MVT::i64, Expand); 1473263508Sdim setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i64, Expand); 1474263508Sdim setOperationAction(ISD::CTLZ , MVT::i64, Expand); 1475263508Sdim setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i64, Expand); 1476263508Sdim setOperationAction(ISD::BSWAP, MVT::i64, Expand); 1477263508Sdim setOperationAction(ISD::ROTL , MVT::i64, Expand); 1478263508Sdim setOperationAction(ISD::ROTR , MVT::i64, Expand); 1479263508Sdim setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64, Custom); 1480249423Sdim } 1481249423Sdim 1482263763Sdim // ATOMICs. 1483263763Sdim // FIXME: We insert fences for each atomics and generate sub-optimal code 1484263763Sdim // for PSO/TSO. Also, implement other atomicrmw operations. 1485193323Sed 1486263763Sdim setInsertFencesForAtomic(true); 1487263763Sdim 1488263763Sdim setOperationAction(ISD::ATOMIC_SWAP, MVT::i32, Legal); 1489263763Sdim setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i32, 1490263763Sdim (Subtarget->isV9() ? Legal: Expand)); 1491263763Sdim 1492263763Sdim 1493263763Sdim setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Legal); 1494263763Sdim 1495263763Sdim // Custom Lower Atomic LOAD/STORE 1496263763Sdim setOperationAction(ISD::ATOMIC_LOAD, MVT::i32, Custom); 1497263763Sdim setOperationAction(ISD::ATOMIC_STORE, MVT::i32, Custom); 1498263763Sdim 1499263763Sdim if (Subtarget->is64Bit()) { 1500263763Sdim setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i64, Legal); 1501263763Sdim setOperationAction(ISD::ATOMIC_SWAP, MVT::i64, Legal); 1502263763Sdim setOperationAction(ISD::ATOMIC_LOAD, MVT::i64, Custom); 1503263763Sdim setOperationAction(ISD::ATOMIC_STORE, MVT::i64, Custom); 1504263763Sdim } 1505263763Sdim 1506263508Sdim if (!Subtarget->isV9()) { 1507263508Sdim // SparcV8 does not have FNEGD and FABSD. 1508263508Sdim setOperationAction(ISD::FNEG, MVT::f64, Custom); 1509263508Sdim setOperationAction(ISD::FABS, MVT::f64, Custom); 1510263508Sdim } 1511263508Sdim 1512263508Sdim setOperationAction(ISD::FSIN , MVT::f128, Expand); 1513263508Sdim setOperationAction(ISD::FCOS , MVT::f128, Expand); 1514263508Sdim setOperationAction(ISD::FSINCOS, MVT::f128, Expand); 1515263508Sdim setOperationAction(ISD::FREM , MVT::f128, Expand); 1516263508Sdim setOperationAction(ISD::FMA , MVT::f128, Expand); 1517193323Sed setOperationAction(ISD::FSIN , MVT::f64, Expand); 1518193323Sed setOperationAction(ISD::FCOS , MVT::f64, Expand); 1519249423Sdim setOperationAction(ISD::FSINCOS, MVT::f64, Expand); 1520193323Sed setOperationAction(ISD::FREM , MVT::f64, Expand); 1521224145Sdim setOperationAction(ISD::FMA , MVT::f64, Expand); 1522193323Sed setOperationAction(ISD::FSIN , MVT::f32, Expand); 1523193323Sed setOperationAction(ISD::FCOS , MVT::f32, Expand); 1524249423Sdim setOperationAction(ISD::FSINCOS, MVT::f32, Expand); 1525193323Sed setOperationAction(ISD::FREM , MVT::f32, Expand); 1526224145Sdim setOperationAction(ISD::FMA , MVT::f32, Expand); 1527193323Sed setOperationAction(ISD::CTTZ , MVT::i32, Expand); 1528234353Sdim setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i32, Expand); 1529193323Sed setOperationAction(ISD::CTLZ , MVT::i32, Expand); 1530234353Sdim setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i32, Expand); 1531193323Sed setOperationAction(ISD::ROTL , MVT::i32, Expand); 1532193323Sed setOperationAction(ISD::ROTR , MVT::i32, Expand); 1533193323Sed setOperationAction(ISD::BSWAP, MVT::i32, Expand); 1534263508Sdim setOperationAction(ISD::FCOPYSIGN, MVT::f128, Expand); 1535193323Sed setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand); 1536193323Sed setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand); 1537263508Sdim setOperationAction(ISD::FPOW , MVT::f128, Expand); 1538193323Sed setOperationAction(ISD::FPOW , MVT::f64, Expand); 1539193323Sed setOperationAction(ISD::FPOW , MVT::f32, Expand); 1540193323Sed 1541193323Sed setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand); 1542193323Sed setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand); 1543193323Sed setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand); 1544193323Sed 1545193323Sed // FIXME: Sparc provides these multiplies, but we don't have them yet. 1546193323Sed setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand); 1547193323Sed setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand); 1548193323Sed 1549263508Sdim if (Subtarget->is64Bit()) { 1550263508Sdim setOperationAction(ISD::UMUL_LOHI, MVT::i64, Expand); 1551263508Sdim setOperationAction(ISD::SMUL_LOHI, MVT::i64, Expand); 1552263508Sdim setOperationAction(ISD::MULHU, MVT::i64, Expand); 1553263508Sdim setOperationAction(ISD::MULHS, MVT::i64, Expand); 1554263763Sdim 1555263763Sdim setOperationAction(ISD::UMULO, MVT::i64, Custom); 1556263763Sdim setOperationAction(ISD::SMULO, MVT::i64, Custom); 1557263763Sdim 1558263763Sdim setOperationAction(ISD::SHL_PARTS, MVT::i64, Expand); 1559263763Sdim setOperationAction(ISD::SRA_PARTS, MVT::i64, Expand); 1560263763Sdim setOperationAction(ISD::SRL_PARTS, MVT::i64, Expand); 1561263508Sdim } 1562193323Sed 1563193323Sed // VASTART needs to be custom lowered to use the VarArgsFrameIndex. 1564193323Sed setOperationAction(ISD::VASTART , MVT::Other, Custom); 1565193323Sed // VAARG needs to be lowered to not do unaligned accesses for doubles. 1566193323Sed setOperationAction(ISD::VAARG , MVT::Other, Custom); 1567193323Sed 1568263763Sdim setOperationAction(ISD::TRAP , MVT::Other, Legal); 1569263763Sdim 1570193323Sed // Use the default implementation. 1571193323Sed setOperationAction(ISD::VACOPY , MVT::Other, Expand); 1572193323Sed setOperationAction(ISD::VAEND , MVT::Other, Expand); 1573193323Sed setOperationAction(ISD::STACKSAVE , MVT::Other, Expand); 1574193323Sed setOperationAction(ISD::STACKRESTORE , MVT::Other, Expand); 1575193323Sed setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32 , Custom); 1576193323Sed 1577263508Sdim setExceptionPointerRegister(SP::I0); 1578263508Sdim setExceptionSelectorRegister(SP::I1); 1579193323Sed 1580193323Sed setStackPointerRegisterToSaveRestore(SP::O6); 1581193323Sed 1582263763Sdim setOperationAction(ISD::CTPOP, MVT::i32, 1583263763Sdim Subtarget->usePopc() ? Legal : Expand); 1584193323Sed 1585263508Sdim if (Subtarget->isV9() && Subtarget->hasHardQuad()) { 1586263508Sdim setOperationAction(ISD::LOAD, MVT::f128, Legal); 1587263508Sdim setOperationAction(ISD::STORE, MVT::f128, Legal); 1588263508Sdim } else { 1589263508Sdim setOperationAction(ISD::LOAD, MVT::f128, Custom); 1590263508Sdim setOperationAction(ISD::STORE, MVT::f128, Custom); 1591263508Sdim } 1592263508Sdim 1593263508Sdim if (Subtarget->hasHardQuad()) { 1594263508Sdim setOperationAction(ISD::FADD, MVT::f128, Legal); 1595263508Sdim setOperationAction(ISD::FSUB, MVT::f128, Legal); 1596263508Sdim setOperationAction(ISD::FMUL, MVT::f128, Legal); 1597263508Sdim setOperationAction(ISD::FDIV, MVT::f128, Legal); 1598263508Sdim setOperationAction(ISD::FSQRT, MVT::f128, Legal); 1599263508Sdim setOperationAction(ISD::FP_EXTEND, MVT::f128, Legal); 1600263508Sdim setOperationAction(ISD::FP_ROUND, MVT::f64, Legal); 1601263508Sdim if (Subtarget->isV9()) { 1602263508Sdim setOperationAction(ISD::FNEG, MVT::f128, Legal); 1603263508Sdim setOperationAction(ISD::FABS, MVT::f128, Legal); 1604263508Sdim } else { 1605263508Sdim setOperationAction(ISD::FNEG, MVT::f128, Custom); 1606263508Sdim setOperationAction(ISD::FABS, MVT::f128, Custom); 1607263508Sdim } 1608263508Sdim 1609263508Sdim if (!Subtarget->is64Bit()) { 1610263508Sdim setLibcallName(RTLIB::FPTOSINT_F128_I64, "_Q_qtoll"); 1611263508Sdim setLibcallName(RTLIB::FPTOUINT_F128_I64, "_Q_qtoull"); 1612263508Sdim setLibcallName(RTLIB::SINTTOFP_I64_F128, "_Q_lltoq"); 1613263508Sdim setLibcallName(RTLIB::UINTTOFP_I64_F128, "_Q_ulltoq"); 1614263508Sdim } 1615263508Sdim 1616263508Sdim } else { 1617263508Sdim // Custom legalize f128 operations. 1618263508Sdim 1619263508Sdim setOperationAction(ISD::FADD, MVT::f128, Custom); 1620263508Sdim setOperationAction(ISD::FSUB, MVT::f128, Custom); 1621263508Sdim setOperationAction(ISD::FMUL, MVT::f128, Custom); 1622263508Sdim setOperationAction(ISD::FDIV, MVT::f128, Custom); 1623263508Sdim setOperationAction(ISD::FSQRT, MVT::f128, Custom); 1624263508Sdim setOperationAction(ISD::FNEG, MVT::f128, Custom); 1625263508Sdim setOperationAction(ISD::FABS, MVT::f128, Custom); 1626263508Sdim 1627263508Sdim setOperationAction(ISD::FP_EXTEND, MVT::f128, Custom); 1628263508Sdim setOperationAction(ISD::FP_ROUND, MVT::f64, Custom); 1629263508Sdim setOperationAction(ISD::FP_ROUND, MVT::f32, Custom); 1630263508Sdim 1631263508Sdim // Setup Runtime library names. 1632263508Sdim if (Subtarget->is64Bit()) { 1633263508Sdim setLibcallName(RTLIB::ADD_F128, "_Qp_add"); 1634263508Sdim setLibcallName(RTLIB::SUB_F128, "_Qp_sub"); 1635263508Sdim setLibcallName(RTLIB::MUL_F128, "_Qp_mul"); 1636263508Sdim setLibcallName(RTLIB::DIV_F128, "_Qp_div"); 1637263508Sdim setLibcallName(RTLIB::SQRT_F128, "_Qp_sqrt"); 1638263508Sdim setLibcallName(RTLIB::FPTOSINT_F128_I32, "_Qp_qtoi"); 1639263508Sdim setLibcallName(RTLIB::FPTOUINT_F128_I32, "_Qp_qtoui"); 1640263508Sdim setLibcallName(RTLIB::SINTTOFP_I32_F128, "_Qp_itoq"); 1641263508Sdim setLibcallName(RTLIB::UINTTOFP_I32_F128, "_Qp_uitoq"); 1642263508Sdim setLibcallName(RTLIB::FPTOSINT_F128_I64, "_Qp_qtox"); 1643263508Sdim setLibcallName(RTLIB::FPTOUINT_F128_I64, "_Qp_qtoux"); 1644263508Sdim setLibcallName(RTLIB::SINTTOFP_I64_F128, "_Qp_xtoq"); 1645263508Sdim setLibcallName(RTLIB::UINTTOFP_I64_F128, "_Qp_uxtoq"); 1646263508Sdim setLibcallName(RTLIB::FPEXT_F32_F128, "_Qp_stoq"); 1647263508Sdim setLibcallName(RTLIB::FPEXT_F64_F128, "_Qp_dtoq"); 1648263508Sdim setLibcallName(RTLIB::FPROUND_F128_F32, "_Qp_qtos"); 1649263508Sdim setLibcallName(RTLIB::FPROUND_F128_F64, "_Qp_qtod"); 1650263508Sdim } else { 1651263508Sdim setLibcallName(RTLIB::ADD_F128, "_Q_add"); 1652263508Sdim setLibcallName(RTLIB::SUB_F128, "_Q_sub"); 1653263508Sdim setLibcallName(RTLIB::MUL_F128, "_Q_mul"); 1654263508Sdim setLibcallName(RTLIB::DIV_F128, "_Q_div"); 1655263508Sdim setLibcallName(RTLIB::SQRT_F128, "_Q_sqrt"); 1656263508Sdim setLibcallName(RTLIB::FPTOSINT_F128_I32, "_Q_qtoi"); 1657263508Sdim setLibcallName(RTLIB::FPTOUINT_F128_I32, "_Q_qtou"); 1658263508Sdim setLibcallName(RTLIB::SINTTOFP_I32_F128, "_Q_itoq"); 1659263508Sdim setLibcallName(RTLIB::UINTTOFP_I32_F128, "_Q_utoq"); 1660263508Sdim setLibcallName(RTLIB::FPTOSINT_F128_I64, "_Q_qtoll"); 1661263508Sdim setLibcallName(RTLIB::FPTOUINT_F128_I64, "_Q_qtoull"); 1662263508Sdim setLibcallName(RTLIB::SINTTOFP_I64_F128, "_Q_lltoq"); 1663263508Sdim setLibcallName(RTLIB::UINTTOFP_I64_F128, "_Q_ulltoq"); 1664263508Sdim setLibcallName(RTLIB::FPEXT_F32_F128, "_Q_stoq"); 1665263508Sdim setLibcallName(RTLIB::FPEXT_F64_F128, "_Q_dtoq"); 1666263508Sdim setLibcallName(RTLIB::FPROUND_F128_F32, "_Q_qtos"); 1667263508Sdim setLibcallName(RTLIB::FPROUND_F128_F64, "_Q_qtod"); 1668263508Sdim } 1669263508Sdim } 1670263508Sdim 1671223017Sdim setMinFunctionAlignment(2); 1672223017Sdim 1673193323Sed computeRegisterProperties(); 1674193323Sed} 1675193323Sed 1676193323Sedconst char *SparcTargetLowering::getTargetNodeName(unsigned Opcode) const { 1677193323Sed switch (Opcode) { 1678193323Sed default: return 0; 1679193323Sed case SPISD::CMPICC: return "SPISD::CMPICC"; 1680193323Sed case SPISD::CMPFCC: return "SPISD::CMPFCC"; 1681193323Sed case SPISD::BRICC: return "SPISD::BRICC"; 1682249423Sdim case SPISD::BRXCC: return "SPISD::BRXCC"; 1683193323Sed case SPISD::BRFCC: return "SPISD::BRFCC"; 1684193323Sed case SPISD::SELECT_ICC: return "SPISD::SELECT_ICC"; 1685249423Sdim case SPISD::SELECT_XCC: return "SPISD::SELECT_XCC"; 1686193323Sed case SPISD::SELECT_FCC: return "SPISD::SELECT_FCC"; 1687193323Sed case SPISD::Hi: return "SPISD::Hi"; 1688193323Sed case SPISD::Lo: return "SPISD::Lo"; 1689193323Sed case SPISD::FTOI: return "SPISD::FTOI"; 1690193323Sed case SPISD::ITOF: return "SPISD::ITOF"; 1691263508Sdim case SPISD::FTOX: return "SPISD::FTOX"; 1692263508Sdim case SPISD::XTOF: return "SPISD::XTOF"; 1693193323Sed case SPISD::CALL: return "SPISD::CALL"; 1694193323Sed case SPISD::RET_FLAG: return "SPISD::RET_FLAG"; 1695218893Sdim case SPISD::GLOBAL_BASE_REG: return "SPISD::GLOBAL_BASE_REG"; 1696218893Sdim case SPISD::FLUSHW: return "SPISD::FLUSHW"; 1697263508Sdim case SPISD::TLS_ADD: return "SPISD::TLS_ADD"; 1698263508Sdim case SPISD::TLS_LD: return "SPISD::TLS_LD"; 1699263508Sdim case SPISD::TLS_CALL: return "SPISD::TLS_CALL"; 1700193323Sed } 1701193323Sed} 1702193323Sed 1703263508SdimEVT SparcTargetLowering::getSetCCResultType(LLVMContext &, EVT VT) const { 1704263508Sdim if (!VT.isVector()) 1705263508Sdim return MVT::i32; 1706263508Sdim return VT.changeVectorElementTypeToInteger(); 1707263508Sdim} 1708263508Sdim 1709193323Sed/// isMaskedValueZeroForTargetNode - Return true if 'Op & Mask' is known to 1710193323Sed/// be zero. Op is expected to be a target specific node. Used by DAG 1711193323Sed/// combiner. 1712263508Sdimvoid SparcTargetLowering::computeMaskedBitsForTargetNode 1713263508Sdim (const SDValue Op, 1714263508Sdim APInt &KnownZero, 1715263508Sdim APInt &KnownOne, 1716263508Sdim const SelectionDAG &DAG, 1717263508Sdim unsigned Depth) const { 1718193323Sed APInt KnownZero2, KnownOne2; 1719234353Sdim KnownZero = KnownOne = APInt(KnownZero.getBitWidth(), 0); 1720193323Sed 1721193323Sed switch (Op.getOpcode()) { 1722193323Sed default: break; 1723193323Sed case SPISD::SELECT_ICC: 1724249423Sdim case SPISD::SELECT_XCC: 1725193323Sed case SPISD::SELECT_FCC: 1726234353Sdim DAG.ComputeMaskedBits(Op.getOperand(1), KnownZero, KnownOne, Depth+1); 1727234353Sdim DAG.ComputeMaskedBits(Op.getOperand(0), KnownZero2, KnownOne2, Depth+1); 1728193323Sed assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); 1729193323Sed assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); 1730193323Sed 1731193323Sed // Only known if known in both the LHS and RHS. 1732193323Sed KnownOne &= KnownOne2; 1733193323Sed KnownZero &= KnownZero2; 1734193323Sed break; 1735193323Sed } 1736193323Sed} 1737193323Sed 1738193323Sed// Look at LHS/RHS/CC and see if they are a lowered setcc instruction. If so 1739193323Sed// set LHS/RHS and SPCC to the LHS/RHS of the setcc and SPCC to the condition. 1740193323Sedstatic void LookThroughSetCC(SDValue &LHS, SDValue &RHS, 1741193323Sed ISD::CondCode CC, unsigned &SPCC) { 1742193323Sed if (isa<ConstantSDNode>(RHS) && 1743210299Sed cast<ConstantSDNode>(RHS)->isNullValue() && 1744193323Sed CC == ISD::SETNE && 1745249423Sdim (((LHS.getOpcode() == SPISD::SELECT_ICC || 1746249423Sdim LHS.getOpcode() == SPISD::SELECT_XCC) && 1747193323Sed LHS.getOperand(3).getOpcode() == SPISD::CMPICC) || 1748193323Sed (LHS.getOpcode() == SPISD::SELECT_FCC && 1749193323Sed LHS.getOperand(3).getOpcode() == SPISD::CMPFCC)) && 1750193323Sed isa<ConstantSDNode>(LHS.getOperand(0)) && 1751193323Sed isa<ConstantSDNode>(LHS.getOperand(1)) && 1752210299Sed cast<ConstantSDNode>(LHS.getOperand(0))->isOne() && 1753210299Sed cast<ConstantSDNode>(LHS.getOperand(1))->isNullValue()) { 1754193323Sed SDValue CMPCC = LHS.getOperand(3); 1755193323Sed SPCC = cast<ConstantSDNode>(LHS.getOperand(2))->getZExtValue(); 1756193323Sed LHS = CMPCC.getOperand(0); 1757193323Sed RHS = CMPCC.getOperand(1); 1758193323Sed } 1759193323Sed} 1760193323Sed 1761251662Sdim// Convert to a target node and set target flags. 1762251662SdimSDValue SparcTargetLowering::withTargetFlags(SDValue Op, unsigned TF, 1763251662Sdim SelectionDAG &DAG) const { 1764251662Sdim if (const GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Op)) 1765251662Sdim return DAG.getTargetGlobalAddress(GA->getGlobal(), 1766263508Sdim SDLoc(GA), 1767251662Sdim GA->getValueType(0), 1768251662Sdim GA->getOffset(), TF); 1769198090Srdivacky 1770251662Sdim if (const ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Op)) 1771251662Sdim return DAG.getTargetConstantPool(CP->getConstVal(), 1772251662Sdim CP->getValueType(0), 1773251662Sdim CP->getAlignment(), 1774251662Sdim CP->getOffset(), TF); 1775218893Sdim 1776263508Sdim if (const BlockAddressSDNode *BA = dyn_cast<BlockAddressSDNode>(Op)) 1777263508Sdim return DAG.getTargetBlockAddress(BA->getBlockAddress(), 1778263508Sdim Op.getValueType(), 1779263508Sdim 0, 1780263508Sdim TF); 1781263508Sdim 1782251662Sdim if (const ExternalSymbolSDNode *ES = dyn_cast<ExternalSymbolSDNode>(Op)) 1783251662Sdim return DAG.getTargetExternalSymbol(ES->getSymbol(), 1784251662Sdim ES->getValueType(0), TF); 1785251662Sdim 1786251662Sdim llvm_unreachable("Unhandled address SDNode"); 1787193323Sed} 1788193323Sed 1789251662Sdim// Split Op into high and low parts according to HiTF and LoTF. 1790251662Sdim// Return an ADD node combining the parts. 1791251662SdimSDValue SparcTargetLowering::makeHiLoPair(SDValue Op, 1792251662Sdim unsigned HiTF, unsigned LoTF, 1793251662Sdim SelectionDAG &DAG) const { 1794263508Sdim SDLoc DL(Op); 1795251662Sdim EVT VT = Op.getValueType(); 1796251662Sdim SDValue Hi = DAG.getNode(SPISD::Hi, DL, VT, withTargetFlags(Op, HiTF, DAG)); 1797251662Sdim SDValue Lo = DAG.getNode(SPISD::Lo, DL, VT, withTargetFlags(Op, LoTF, DAG)); 1798251662Sdim return DAG.getNode(ISD::ADD, DL, VT, Hi, Lo); 1799251662Sdim} 1800251662Sdim 1801251662Sdim// Build SDNodes for producing an address from a GlobalAddress, ConstantPool, 1802251662Sdim// or ExternalSymbol SDNode. 1803251662SdimSDValue SparcTargetLowering::makeAddress(SDValue Op, SelectionDAG &DAG) const { 1804263508Sdim SDLoc DL(Op); 1805251662Sdim EVT VT = getPointerTy(); 1806251662Sdim 1807251662Sdim // Handle PIC mode first. 1808251662Sdim if (getTargetMachine().getRelocationModel() == Reloc::PIC_) { 1809251662Sdim // This is the pic32 code model, the GOT is known to be smaller than 4GB. 1810263763Sdim SDValue HiLo = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_GOT22, 1811263763Sdim SparcMCExpr::VK_Sparc_GOT10, DAG); 1812251662Sdim SDValue GlobalBase = DAG.getNode(SPISD::GLOBAL_BASE_REG, DL, VT); 1813251662Sdim SDValue AbsAddr = DAG.getNode(ISD::ADD, DL, VT, GlobalBase, HiLo); 1814263508Sdim // GLOBAL_BASE_REG codegen'ed with call. Inform MFI that this 1815263508Sdim // function has calls. 1816263508Sdim MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); 1817263508Sdim MFI->setHasCalls(true); 1818251662Sdim return DAG.getLoad(VT, DL, DAG.getEntryNode(), AbsAddr, 1819251662Sdim MachinePointerInfo::getGOT(), false, false, false, 0); 1820251662Sdim } 1821251662Sdim 1822251662Sdim // This is one of the absolute code models. 1823251662Sdim switch(getTargetMachine().getCodeModel()) { 1824251662Sdim default: 1825251662Sdim llvm_unreachable("Unsupported absolute code model"); 1826251662Sdim case CodeModel::Small: 1827251662Sdim // abs32. 1828263763Sdim return makeHiLoPair(Op, SparcMCExpr::VK_Sparc_HI, 1829263763Sdim SparcMCExpr::VK_Sparc_LO, DAG); 1830251662Sdim case CodeModel::Medium: { 1831251662Sdim // abs44. 1832263763Sdim SDValue H44 = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_H44, 1833263763Sdim SparcMCExpr::VK_Sparc_M44, DAG); 1834251662Sdim H44 = DAG.getNode(ISD::SHL, DL, VT, H44, DAG.getConstant(12, MVT::i32)); 1835263763Sdim SDValue L44 = withTargetFlags(Op, SparcMCExpr::VK_Sparc_L44, DAG); 1836251662Sdim L44 = DAG.getNode(SPISD::Lo, DL, VT, L44); 1837251662Sdim return DAG.getNode(ISD::ADD, DL, VT, H44, L44); 1838251662Sdim } 1839251662Sdim case CodeModel::Large: { 1840251662Sdim // abs64. 1841263763Sdim SDValue Hi = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_HH, 1842263763Sdim SparcMCExpr::VK_Sparc_HM, DAG); 1843251662Sdim Hi = DAG.getNode(ISD::SHL, DL, VT, Hi, DAG.getConstant(32, MVT::i32)); 1844263763Sdim SDValue Lo = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_HI, 1845263763Sdim SparcMCExpr::VK_Sparc_LO, DAG); 1846251662Sdim return DAG.getNode(ISD::ADD, DL, VT, Hi, Lo); 1847251662Sdim } 1848251662Sdim } 1849251662Sdim} 1850251662Sdim 1851251662SdimSDValue SparcTargetLowering::LowerGlobalAddress(SDValue Op, 1852251662Sdim SelectionDAG &DAG) const { 1853251662Sdim return makeAddress(Op, DAG); 1854251662Sdim} 1855251662Sdim 1856198090SrdivackySDValue SparcTargetLowering::LowerConstantPool(SDValue Op, 1857207618Srdivacky SelectionDAG &DAG) const { 1858251662Sdim return makeAddress(Op, DAG); 1859193323Sed} 1860193323Sed 1861263508SdimSDValue SparcTargetLowering::LowerBlockAddress(SDValue Op, 1862263508Sdim SelectionDAG &DAG) const { 1863263508Sdim return makeAddress(Op, DAG); 1864193323Sed} 1865193323Sed 1866263508SdimSDValue SparcTargetLowering::LowerGlobalTLSAddress(SDValue Op, 1867263508Sdim SelectionDAG &DAG) const { 1868263508Sdim 1869263508Sdim GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(Op); 1870263508Sdim SDLoc DL(GA); 1871263508Sdim const GlobalValue *GV = GA->getGlobal(); 1872263508Sdim EVT PtrVT = getPointerTy(); 1873263508Sdim 1874263508Sdim TLSModel::Model model = getTargetMachine().getTLSModel(GV); 1875263508Sdim 1876263508Sdim if (model == TLSModel::GeneralDynamic || model == TLSModel::LocalDynamic) { 1877263763Sdim unsigned HiTF = ((model == TLSModel::GeneralDynamic) 1878263763Sdim ? SparcMCExpr::VK_Sparc_TLS_GD_HI22 1879263763Sdim : SparcMCExpr::VK_Sparc_TLS_LDM_HI22); 1880263763Sdim unsigned LoTF = ((model == TLSModel::GeneralDynamic) 1881263763Sdim ? SparcMCExpr::VK_Sparc_TLS_GD_LO10 1882263763Sdim : SparcMCExpr::VK_Sparc_TLS_LDM_LO10); 1883263763Sdim unsigned addTF = ((model == TLSModel::GeneralDynamic) 1884263763Sdim ? SparcMCExpr::VK_Sparc_TLS_GD_ADD 1885263763Sdim : SparcMCExpr::VK_Sparc_TLS_LDM_ADD); 1886263763Sdim unsigned callTF = ((model == TLSModel::GeneralDynamic) 1887263763Sdim ? SparcMCExpr::VK_Sparc_TLS_GD_CALL 1888263763Sdim : SparcMCExpr::VK_Sparc_TLS_LDM_CALL); 1889263508Sdim 1890263508Sdim SDValue HiLo = makeHiLoPair(Op, HiTF, LoTF, DAG); 1891263508Sdim SDValue Base = DAG.getNode(SPISD::GLOBAL_BASE_REG, DL, PtrVT); 1892263508Sdim SDValue Argument = DAG.getNode(SPISD::TLS_ADD, DL, PtrVT, Base, HiLo, 1893263508Sdim withTargetFlags(Op, addTF, DAG)); 1894263508Sdim 1895263508Sdim SDValue Chain = DAG.getEntryNode(); 1896263508Sdim SDValue InFlag; 1897263508Sdim 1898263508Sdim Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(1, true), DL); 1899263508Sdim Chain = DAG.getCopyToReg(Chain, DL, SP::O0, Argument, InFlag); 1900263508Sdim InFlag = Chain.getValue(1); 1901263508Sdim SDValue Callee = DAG.getTargetExternalSymbol("__tls_get_addr", PtrVT); 1902263508Sdim SDValue Symbol = withTargetFlags(Op, callTF, DAG); 1903263508Sdim 1904263508Sdim SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); 1905263508Sdim SmallVector<SDValue, 4> Ops; 1906263508Sdim Ops.push_back(Chain); 1907263508Sdim Ops.push_back(Callee); 1908263508Sdim Ops.push_back(Symbol); 1909263508Sdim Ops.push_back(DAG.getRegister(SP::O0, PtrVT)); 1910263508Sdim const uint32_t *Mask = getTargetMachine() 1911263508Sdim .getRegisterInfo()->getCallPreservedMask(CallingConv::C); 1912263508Sdim assert(Mask && "Missing call preserved mask for calling convention"); 1913263508Sdim Ops.push_back(DAG.getRegisterMask(Mask)); 1914263508Sdim Ops.push_back(InFlag); 1915263508Sdim Chain = DAG.getNode(SPISD::TLS_CALL, DL, NodeTys, &Ops[0], Ops.size()); 1916263508Sdim InFlag = Chain.getValue(1); 1917263508Sdim Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(1, true), 1918263508Sdim DAG.getIntPtrConstant(0, true), InFlag, DL); 1919263508Sdim InFlag = Chain.getValue(1); 1920263508Sdim SDValue Ret = DAG.getCopyFromReg(Chain, DL, SP::O0, PtrVT, InFlag); 1921263508Sdim 1922263508Sdim if (model != TLSModel::LocalDynamic) 1923263508Sdim return Ret; 1924263508Sdim 1925263508Sdim SDValue Hi = DAG.getNode(SPISD::Hi, DL, PtrVT, 1926263763Sdim withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LDO_HIX22, DAG)); 1927263508Sdim SDValue Lo = DAG.getNode(SPISD::Lo, DL, PtrVT, 1928263763Sdim withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LDO_LOX10, DAG)); 1929263508Sdim HiLo = DAG.getNode(ISD::XOR, DL, PtrVT, Hi, Lo); 1930263508Sdim return DAG.getNode(SPISD::TLS_ADD, DL, PtrVT, Ret, HiLo, 1931263763Sdim withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LDO_ADD, DAG)); 1932263508Sdim } 1933263508Sdim 1934263508Sdim if (model == TLSModel::InitialExec) { 1935263763Sdim unsigned ldTF = ((PtrVT == MVT::i64)? SparcMCExpr::VK_Sparc_TLS_IE_LDX 1936263763Sdim : SparcMCExpr::VK_Sparc_TLS_IE_LD); 1937263508Sdim 1938263508Sdim SDValue Base = DAG.getNode(SPISD::GLOBAL_BASE_REG, DL, PtrVT); 1939263508Sdim 1940263508Sdim // GLOBAL_BASE_REG codegen'ed with call. Inform MFI that this 1941263508Sdim // function has calls. 1942263508Sdim MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); 1943263508Sdim MFI->setHasCalls(true); 1944263508Sdim 1945263508Sdim SDValue TGA = makeHiLoPair(Op, 1946263763Sdim SparcMCExpr::VK_Sparc_TLS_IE_HI22, 1947263763Sdim SparcMCExpr::VK_Sparc_TLS_IE_LO10, DAG); 1948263508Sdim SDValue Ptr = DAG.getNode(ISD::ADD, DL, PtrVT, Base, TGA); 1949263508Sdim SDValue Offset = DAG.getNode(SPISD::TLS_LD, 1950263508Sdim DL, PtrVT, Ptr, 1951263508Sdim withTargetFlags(Op, ldTF, DAG)); 1952263508Sdim return DAG.getNode(SPISD::TLS_ADD, DL, PtrVT, 1953263508Sdim DAG.getRegister(SP::G7, PtrVT), Offset, 1954263763Sdim withTargetFlags(Op, 1955263763Sdim SparcMCExpr::VK_Sparc_TLS_IE_ADD, DAG)); 1956263508Sdim } 1957263508Sdim 1958263508Sdim assert(model == TLSModel::LocalExec); 1959263508Sdim SDValue Hi = DAG.getNode(SPISD::Hi, DL, PtrVT, 1960263763Sdim withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LE_HIX22, DAG)); 1961263508Sdim SDValue Lo = DAG.getNode(SPISD::Lo, DL, PtrVT, 1962263763Sdim withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LE_LOX10, DAG)); 1963263508Sdim SDValue Offset = DAG.getNode(ISD::XOR, DL, PtrVT, Hi, Lo); 1964263508Sdim 1965263508Sdim return DAG.getNode(ISD::ADD, DL, PtrVT, 1966263508Sdim DAG.getRegister(SP::G7, PtrVT), Offset); 1967193323Sed} 1968193323Sed 1969263508SdimSDValue 1970263508SdimSparcTargetLowering::LowerF128_LibCallArg(SDValue Chain, ArgListTy &Args, 1971263508Sdim SDValue Arg, SDLoc DL, 1972263508Sdim SelectionDAG &DAG) const { 1973263508Sdim MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); 1974263508Sdim EVT ArgVT = Arg.getValueType(); 1975263508Sdim Type *ArgTy = ArgVT.getTypeForEVT(*DAG.getContext()); 1976263508Sdim 1977263508Sdim ArgListEntry Entry; 1978263508Sdim Entry.Node = Arg; 1979263508Sdim Entry.Ty = ArgTy; 1980263508Sdim 1981263508Sdim if (ArgTy->isFP128Ty()) { 1982263508Sdim // Create a stack object and pass the pointer to the library function. 1983263508Sdim int FI = MFI->CreateStackObject(16, 8, false); 1984263508Sdim SDValue FIPtr = DAG.getFrameIndex(FI, getPointerTy()); 1985263508Sdim Chain = DAG.getStore(Chain, 1986263508Sdim DL, 1987263508Sdim Entry.Node, 1988263508Sdim FIPtr, 1989263508Sdim MachinePointerInfo(), 1990263508Sdim false, 1991263508Sdim false, 1992263508Sdim 8); 1993263508Sdim 1994263508Sdim Entry.Node = FIPtr; 1995263508Sdim Entry.Ty = PointerType::getUnqual(ArgTy); 1996263508Sdim } 1997263508Sdim Args.push_back(Entry); 1998263508Sdim return Chain; 1999263508Sdim} 2000263508Sdim 2001263508SdimSDValue 2002263508SdimSparcTargetLowering::LowerF128Op(SDValue Op, SelectionDAG &DAG, 2003263508Sdim const char *LibFuncName, 2004263508Sdim unsigned numArgs) const { 2005263508Sdim 2006263508Sdim ArgListTy Args; 2007263508Sdim 2008263508Sdim MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); 2009263508Sdim 2010263508Sdim SDValue Callee = DAG.getExternalSymbol(LibFuncName, getPointerTy()); 2011263508Sdim Type *RetTy = Op.getValueType().getTypeForEVT(*DAG.getContext()); 2012263508Sdim Type *RetTyABI = RetTy; 2013263508Sdim SDValue Chain = DAG.getEntryNode(); 2014263508Sdim SDValue RetPtr; 2015263508Sdim 2016263508Sdim if (RetTy->isFP128Ty()) { 2017263508Sdim // Create a Stack Object to receive the return value of type f128. 2018263508Sdim ArgListEntry Entry; 2019263508Sdim int RetFI = MFI->CreateStackObject(16, 8, false); 2020263508Sdim RetPtr = DAG.getFrameIndex(RetFI, getPointerTy()); 2021263508Sdim Entry.Node = RetPtr; 2022263508Sdim Entry.Ty = PointerType::getUnqual(RetTy); 2023263508Sdim if (!Subtarget->is64Bit()) 2024263508Sdim Entry.isSRet = true; 2025263508Sdim Entry.isReturned = false; 2026263508Sdim Args.push_back(Entry); 2027263508Sdim RetTyABI = Type::getVoidTy(*DAG.getContext()); 2028263508Sdim } 2029263508Sdim 2030263508Sdim assert(Op->getNumOperands() >= numArgs && "Not enough operands!"); 2031263508Sdim for (unsigned i = 0, e = numArgs; i != e; ++i) { 2032263508Sdim Chain = LowerF128_LibCallArg(Chain, Args, Op.getOperand(i), SDLoc(Op), DAG); 2033263508Sdim } 2034263508Sdim TargetLowering:: 2035263508Sdim CallLoweringInfo CLI(Chain, 2036263508Sdim RetTyABI, 2037263508Sdim false, false, false, false, 2038263508Sdim 0, CallingConv::C, 2039263508Sdim false, false, true, 2040263508Sdim Callee, Args, DAG, SDLoc(Op)); 2041263508Sdim std::pair<SDValue, SDValue> CallInfo = LowerCallTo(CLI); 2042263508Sdim 2043263508Sdim // chain is in second result. 2044263508Sdim if (RetTyABI == RetTy) 2045263508Sdim return CallInfo.first; 2046263508Sdim 2047263508Sdim assert (RetTy->isFP128Ty() && "Unexpected return type!"); 2048263508Sdim 2049263508Sdim Chain = CallInfo.second; 2050263508Sdim 2051263508Sdim // Load RetPtr to get the return value. 2052263508Sdim return DAG.getLoad(Op.getValueType(), 2053263508Sdim SDLoc(Op), 2054263508Sdim Chain, 2055263508Sdim RetPtr, 2056263508Sdim MachinePointerInfo(), 2057263508Sdim false, false, false, 8); 2058263508Sdim} 2059263508Sdim 2060263508SdimSDValue 2061263508SdimSparcTargetLowering::LowerF128Compare(SDValue LHS, SDValue RHS, 2062263508Sdim unsigned &SPCC, 2063263508Sdim SDLoc DL, 2064263508Sdim SelectionDAG &DAG) const { 2065263508Sdim 2066263508Sdim const char *LibCall = 0; 2067263508Sdim bool is64Bit = Subtarget->is64Bit(); 2068263508Sdim switch(SPCC) { 2069263508Sdim default: llvm_unreachable("Unhandled conditional code!"); 2070263508Sdim case SPCC::FCC_E : LibCall = is64Bit? "_Qp_feq" : "_Q_feq"; break; 2071263508Sdim case SPCC::FCC_NE : LibCall = is64Bit? "_Qp_fne" : "_Q_fne"; break; 2072263508Sdim case SPCC::FCC_L : LibCall = is64Bit? "_Qp_flt" : "_Q_flt"; break; 2073263508Sdim case SPCC::FCC_G : LibCall = is64Bit? "_Qp_fgt" : "_Q_fgt"; break; 2074263508Sdim case SPCC::FCC_LE : LibCall = is64Bit? "_Qp_fle" : "_Q_fle"; break; 2075263508Sdim case SPCC::FCC_GE : LibCall = is64Bit? "_Qp_fge" : "_Q_fge"; break; 2076263508Sdim case SPCC::FCC_UL : 2077263508Sdim case SPCC::FCC_ULE: 2078263508Sdim case SPCC::FCC_UG : 2079263508Sdim case SPCC::FCC_UGE: 2080263508Sdim case SPCC::FCC_U : 2081263508Sdim case SPCC::FCC_O : 2082263508Sdim case SPCC::FCC_LG : 2083263508Sdim case SPCC::FCC_UE : LibCall = is64Bit? "_Qp_cmp" : "_Q_cmp"; break; 2084263508Sdim } 2085263508Sdim 2086263508Sdim SDValue Callee = DAG.getExternalSymbol(LibCall, getPointerTy()); 2087263508Sdim Type *RetTy = Type::getInt32Ty(*DAG.getContext()); 2088263508Sdim ArgListTy Args; 2089263508Sdim SDValue Chain = DAG.getEntryNode(); 2090263508Sdim Chain = LowerF128_LibCallArg(Chain, Args, LHS, DL, DAG); 2091263508Sdim Chain = LowerF128_LibCallArg(Chain, Args, RHS, DL, DAG); 2092263508Sdim 2093263508Sdim TargetLowering:: 2094263508Sdim CallLoweringInfo CLI(Chain, 2095263508Sdim RetTy, 2096263508Sdim false, false, false, false, 2097263508Sdim 0, CallingConv::C, 2098263508Sdim false, false, true, 2099263508Sdim Callee, Args, DAG, DL); 2100263508Sdim 2101263508Sdim std::pair<SDValue, SDValue> CallInfo = LowerCallTo(CLI); 2102263508Sdim 2103263508Sdim // result is in first, and chain is in second result. 2104263508Sdim SDValue Result = CallInfo.first; 2105263508Sdim 2106263508Sdim switch(SPCC) { 2107263508Sdim default: { 2108263508Sdim SDValue RHS = DAG.getTargetConstant(0, Result.getValueType()); 2109263508Sdim SPCC = SPCC::ICC_NE; 2110263508Sdim return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS); 2111263508Sdim } 2112263508Sdim case SPCC::FCC_UL : { 2113263508Sdim SDValue Mask = DAG.getTargetConstant(1, Result.getValueType()); 2114263508Sdim Result = DAG.getNode(ISD::AND, DL, Result.getValueType(), Result, Mask); 2115263508Sdim SDValue RHS = DAG.getTargetConstant(0, Result.getValueType()); 2116263508Sdim SPCC = SPCC::ICC_NE; 2117263508Sdim return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS); 2118263508Sdim } 2119263508Sdim case SPCC::FCC_ULE: { 2120263508Sdim SDValue RHS = DAG.getTargetConstant(2, Result.getValueType()); 2121263508Sdim SPCC = SPCC::ICC_NE; 2122263508Sdim return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS); 2123263508Sdim } 2124263508Sdim case SPCC::FCC_UG : { 2125263508Sdim SDValue RHS = DAG.getTargetConstant(1, Result.getValueType()); 2126263508Sdim SPCC = SPCC::ICC_G; 2127263508Sdim return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS); 2128263508Sdim } 2129263508Sdim case SPCC::FCC_UGE: { 2130263508Sdim SDValue RHS = DAG.getTargetConstant(1, Result.getValueType()); 2131263508Sdim SPCC = SPCC::ICC_NE; 2132263508Sdim return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS); 2133263508Sdim } 2134263508Sdim 2135263508Sdim case SPCC::FCC_U : { 2136263508Sdim SDValue RHS = DAG.getTargetConstant(3, Result.getValueType()); 2137263508Sdim SPCC = SPCC::ICC_E; 2138263508Sdim return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS); 2139263508Sdim } 2140263508Sdim case SPCC::FCC_O : { 2141263508Sdim SDValue RHS = DAG.getTargetConstant(3, Result.getValueType()); 2142263508Sdim SPCC = SPCC::ICC_NE; 2143263508Sdim return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS); 2144263508Sdim } 2145263508Sdim case SPCC::FCC_LG : { 2146263508Sdim SDValue Mask = DAG.getTargetConstant(3, Result.getValueType()); 2147263508Sdim Result = DAG.getNode(ISD::AND, DL, Result.getValueType(), Result, Mask); 2148263508Sdim SDValue RHS = DAG.getTargetConstant(0, Result.getValueType()); 2149263508Sdim SPCC = SPCC::ICC_NE; 2150263508Sdim return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS); 2151263508Sdim } 2152263508Sdim case SPCC::FCC_UE : { 2153263508Sdim SDValue Mask = DAG.getTargetConstant(3, Result.getValueType()); 2154263508Sdim Result = DAG.getNode(ISD::AND, DL, Result.getValueType(), Result, Mask); 2155263508Sdim SDValue RHS = DAG.getTargetConstant(0, Result.getValueType()); 2156263508Sdim SPCC = SPCC::ICC_E; 2157263508Sdim return DAG.getNode(SPISD::CMPICC, DL, MVT::Glue, Result, RHS); 2158263508Sdim } 2159263508Sdim } 2160263508Sdim} 2161263508Sdim 2162263508Sdimstatic SDValue 2163263508SdimLowerF128_FPEXTEND(SDValue Op, SelectionDAG &DAG, 2164263508Sdim const SparcTargetLowering &TLI) { 2165263508Sdim 2166263508Sdim if (Op.getOperand(0).getValueType() == MVT::f64) 2167263508Sdim return TLI.LowerF128Op(Op, DAG, 2168263508Sdim TLI.getLibcallName(RTLIB::FPEXT_F64_F128), 1); 2169263508Sdim 2170263508Sdim if (Op.getOperand(0).getValueType() == MVT::f32) 2171263508Sdim return TLI.LowerF128Op(Op, DAG, 2172263508Sdim TLI.getLibcallName(RTLIB::FPEXT_F32_F128), 1); 2173263508Sdim 2174263508Sdim llvm_unreachable("fpextend with non-float operand!"); 2175263508Sdim return SDValue(0, 0); 2176263508Sdim} 2177263508Sdim 2178263508Sdimstatic SDValue 2179263508SdimLowerF128_FPROUND(SDValue Op, SelectionDAG &DAG, 2180263508Sdim const SparcTargetLowering &TLI) { 2181263508Sdim // FP_ROUND on f64 and f32 are legal. 2182263508Sdim if (Op.getOperand(0).getValueType() != MVT::f128) 2183263508Sdim return Op; 2184263508Sdim 2185263508Sdim if (Op.getValueType() == MVT::f64) 2186263508Sdim return TLI.LowerF128Op(Op, DAG, 2187263508Sdim TLI.getLibcallName(RTLIB::FPROUND_F128_F64), 1); 2188263508Sdim if (Op.getValueType() == MVT::f32) 2189263508Sdim return TLI.LowerF128Op(Op, DAG, 2190263508Sdim TLI.getLibcallName(RTLIB::FPROUND_F128_F32), 1); 2191263508Sdim 2192263508Sdim llvm_unreachable("fpround to non-float!"); 2193263508Sdim return SDValue(0, 0); 2194263508Sdim} 2195263508Sdim 2196263508Sdimstatic SDValue LowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG, 2197263508Sdim const SparcTargetLowering &TLI, 2198263508Sdim bool hasHardQuad) { 2199263508Sdim SDLoc dl(Op); 2200263508Sdim EVT VT = Op.getValueType(); 2201263508Sdim assert(VT == MVT::i32 || VT == MVT::i64); 2202263508Sdim 2203263508Sdim // Expand f128 operations to fp128 abi calls. 2204263508Sdim if (Op.getOperand(0).getValueType() == MVT::f128 2205263508Sdim && (!hasHardQuad || !TLI.isTypeLegal(VT))) { 2206263508Sdim const char *libName = TLI.getLibcallName(VT == MVT::i32 2207263508Sdim ? RTLIB::FPTOSINT_F128_I32 2208263508Sdim : RTLIB::FPTOSINT_F128_I64); 2209263508Sdim return TLI.LowerF128Op(Op, DAG, libName, 1); 2210263508Sdim } 2211263508Sdim 2212263508Sdim // Expand if the resulting type is illegal. 2213263508Sdim if (!TLI.isTypeLegal(VT)) 2214263508Sdim return SDValue(0, 0); 2215263508Sdim 2216263508Sdim // Otherwise, Convert the fp value to integer in an FP register. 2217263508Sdim if (VT == MVT::i32) 2218263508Sdim Op = DAG.getNode(SPISD::FTOI, dl, MVT::f32, Op.getOperand(0)); 2219263508Sdim else 2220263508Sdim Op = DAG.getNode(SPISD::FTOX, dl, MVT::f64, Op.getOperand(0)); 2221263508Sdim 2222263508Sdim return DAG.getNode(ISD::BITCAST, dl, VT, Op); 2223263508Sdim} 2224263508Sdim 2225263508Sdimstatic SDValue LowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG, 2226263508Sdim const SparcTargetLowering &TLI, 2227263508Sdim bool hasHardQuad) { 2228263508Sdim SDLoc dl(Op); 2229263508Sdim EVT OpVT = Op.getOperand(0).getValueType(); 2230263508Sdim assert(OpVT == MVT::i32 || (OpVT == MVT::i64)); 2231263508Sdim 2232263508Sdim EVT floatVT = (OpVT == MVT::i32) ? MVT::f32 : MVT::f64; 2233263508Sdim 2234263508Sdim // Expand f128 operations to fp128 ABI calls. 2235263508Sdim if (Op.getValueType() == MVT::f128 2236263508Sdim && (!hasHardQuad || !TLI.isTypeLegal(OpVT))) { 2237263508Sdim const char *libName = TLI.getLibcallName(OpVT == MVT::i32 2238263508Sdim ? RTLIB::SINTTOFP_I32_F128 2239263508Sdim : RTLIB::SINTTOFP_I64_F128); 2240263508Sdim return TLI.LowerF128Op(Op, DAG, libName, 1); 2241263508Sdim } 2242263508Sdim 2243263508Sdim // Expand if the operand type is illegal. 2244263508Sdim if (!TLI.isTypeLegal(OpVT)) 2245263508Sdim return SDValue(0, 0); 2246263508Sdim 2247263508Sdim // Otherwise, Convert the int value to FP in an FP register. 2248263508Sdim SDValue Tmp = DAG.getNode(ISD::BITCAST, dl, floatVT, Op.getOperand(0)); 2249263508Sdim unsigned opcode = (OpVT == MVT::i32)? SPISD::ITOF : SPISD::XTOF; 2250263508Sdim return DAG.getNode(opcode, dl, Op.getValueType(), Tmp); 2251263508Sdim} 2252263508Sdim 2253263508Sdimstatic SDValue LowerFP_TO_UINT(SDValue Op, SelectionDAG &DAG, 2254263508Sdim const SparcTargetLowering &TLI, 2255263508Sdim bool hasHardQuad) { 2256263508Sdim SDLoc dl(Op); 2257263508Sdim EVT VT = Op.getValueType(); 2258263508Sdim 2259263508Sdim // Expand if it does not involve f128 or the target has support for 2260263508Sdim // quad floating point instructions and the resulting type is legal. 2261263508Sdim if (Op.getOperand(0).getValueType() != MVT::f128 || 2262263508Sdim (hasHardQuad && TLI.isTypeLegal(VT))) 2263263508Sdim return SDValue(0, 0); 2264263508Sdim 2265263508Sdim assert(VT == MVT::i32 || VT == MVT::i64); 2266263508Sdim 2267263508Sdim return TLI.LowerF128Op(Op, DAG, 2268263508Sdim TLI.getLibcallName(VT == MVT::i32 2269263508Sdim ? RTLIB::FPTOUINT_F128_I32 2270263508Sdim : RTLIB::FPTOUINT_F128_I64), 2271263508Sdim 1); 2272263508Sdim} 2273263508Sdim 2274263508Sdimstatic SDValue LowerUINT_TO_FP(SDValue Op, SelectionDAG &DAG, 2275263508Sdim const SparcTargetLowering &TLI, 2276263508Sdim bool hasHardQuad) { 2277263508Sdim SDLoc dl(Op); 2278263508Sdim EVT OpVT = Op.getOperand(0).getValueType(); 2279263508Sdim assert(OpVT == MVT::i32 || OpVT == MVT::i64); 2280263508Sdim 2281263508Sdim // Expand if it does not involve f128 or the target has support for 2282263508Sdim // quad floating point instructions and the operand type is legal. 2283263508Sdim if (Op.getValueType() != MVT::f128 || (hasHardQuad && TLI.isTypeLegal(OpVT))) 2284263508Sdim return SDValue(0, 0); 2285263508Sdim 2286263508Sdim return TLI.LowerF128Op(Op, DAG, 2287263508Sdim TLI.getLibcallName(OpVT == MVT::i32 2288263508Sdim ? RTLIB::UINTTOFP_I32_F128 2289263508Sdim : RTLIB::UINTTOFP_I64_F128), 2290263508Sdim 1); 2291263508Sdim} 2292263508Sdim 2293263508Sdimstatic SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG, 2294263508Sdim const SparcTargetLowering &TLI, 2295263508Sdim bool hasHardQuad) { 2296193323Sed SDValue Chain = Op.getOperand(0); 2297193323Sed ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get(); 2298193323Sed SDValue LHS = Op.getOperand(2); 2299193323Sed SDValue RHS = Op.getOperand(3); 2300193323Sed SDValue Dest = Op.getOperand(4); 2301263508Sdim SDLoc dl(Op); 2302193323Sed unsigned Opc, SPCC = ~0U; 2303193323Sed 2304193323Sed // If this is a br_cc of a "setcc", and if the setcc got lowered into 2305193323Sed // an CMP[IF]CC/SELECT_[IF]CC pair, find the original compared values. 2306193323Sed LookThroughSetCC(LHS, RHS, CC, SPCC); 2307193323Sed 2308193323Sed // Get the condition flag. 2309193323Sed SDValue CompareFlag; 2310249423Sdim if (LHS.getValueType().isInteger()) { 2311263508Sdim CompareFlag = DAG.getNode(SPISD::CMPICC, dl, MVT::Glue, LHS, RHS); 2312193323Sed if (SPCC == ~0U) SPCC = IntCondCCodeToICC(CC); 2313249423Sdim // 32-bit compares use the icc flags, 64-bit uses the xcc flags. 2314249423Sdim Opc = LHS.getValueType() == MVT::i32 ? SPISD::BRICC : SPISD::BRXCC; 2315193323Sed } else { 2316263508Sdim if (!hasHardQuad && LHS.getValueType() == MVT::f128) { 2317263508Sdim if (SPCC == ~0U) SPCC = FPCondCCodeToFCC(CC); 2318263508Sdim CompareFlag = TLI.LowerF128Compare(LHS, RHS, SPCC, dl, DAG); 2319263508Sdim Opc = SPISD::BRICC; 2320263508Sdim } else { 2321263508Sdim CompareFlag = DAG.getNode(SPISD::CMPFCC, dl, MVT::Glue, LHS, RHS); 2322263508Sdim if (SPCC == ~0U) SPCC = FPCondCCodeToFCC(CC); 2323263508Sdim Opc = SPISD::BRFCC; 2324263508Sdim } 2325193323Sed } 2326193323Sed return DAG.getNode(Opc, dl, MVT::Other, Chain, Dest, 2327193323Sed DAG.getConstant(SPCC, MVT::i32), CompareFlag); 2328193323Sed} 2329193323Sed 2330263508Sdimstatic SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG, 2331263508Sdim const SparcTargetLowering &TLI, 2332263508Sdim bool hasHardQuad) { 2333193323Sed SDValue LHS = Op.getOperand(0); 2334193323Sed SDValue RHS = Op.getOperand(1); 2335193323Sed ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get(); 2336193323Sed SDValue TrueVal = Op.getOperand(2); 2337193323Sed SDValue FalseVal = Op.getOperand(3); 2338263508Sdim SDLoc dl(Op); 2339193323Sed unsigned Opc, SPCC = ~0U; 2340193323Sed 2341193323Sed // If this is a select_cc of a "setcc", and if the setcc got lowered into 2342193323Sed // an CMP[IF]CC/SELECT_[IF]CC pair, find the original compared values. 2343193323Sed LookThroughSetCC(LHS, RHS, CC, SPCC); 2344193323Sed 2345193323Sed SDValue CompareFlag; 2346249423Sdim if (LHS.getValueType().isInteger()) { 2347263508Sdim CompareFlag = DAG.getNode(SPISD::CMPICC, dl, MVT::Glue, LHS, RHS); 2348249423Sdim Opc = LHS.getValueType() == MVT::i32 ? 2349249423Sdim SPISD::SELECT_ICC : SPISD::SELECT_XCC; 2350193323Sed if (SPCC == ~0U) SPCC = IntCondCCodeToICC(CC); 2351193323Sed } else { 2352263508Sdim if (!hasHardQuad && LHS.getValueType() == MVT::f128) { 2353263508Sdim if (SPCC == ~0U) SPCC = FPCondCCodeToFCC(CC); 2354263508Sdim CompareFlag = TLI.LowerF128Compare(LHS, RHS, SPCC, dl, DAG); 2355263508Sdim Opc = SPISD::SELECT_ICC; 2356263508Sdim } else { 2357263508Sdim CompareFlag = DAG.getNode(SPISD::CMPFCC, dl, MVT::Glue, LHS, RHS); 2358263508Sdim Opc = SPISD::SELECT_FCC; 2359263508Sdim if (SPCC == ~0U) SPCC = FPCondCCodeToFCC(CC); 2360263508Sdim } 2361193323Sed } 2362193323Sed return DAG.getNode(Opc, dl, TrueVal.getValueType(), TrueVal, FalseVal, 2363193323Sed DAG.getConstant(SPCC, MVT::i32), CompareFlag); 2364193323Sed} 2365193323Sed 2366193323Sedstatic SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG, 2367207618Srdivacky const SparcTargetLowering &TLI) { 2368207618Srdivacky MachineFunction &MF = DAG.getMachineFunction(); 2369207618Srdivacky SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>(); 2370207618Srdivacky 2371263508Sdim // Need frame address to find the address of VarArgsFrameIndex. 2372263508Sdim MF.getFrameInfo()->setFrameAddressIsTaken(true); 2373263508Sdim 2374193323Sed // vastart just stores the address of the VarArgsFrameIndex slot into the 2375193323Sed // memory location argument. 2376263508Sdim SDLoc DL(Op); 2377207618Srdivacky SDValue Offset = 2378251662Sdim DAG.getNode(ISD::ADD, DL, TLI.getPointerTy(), 2379251662Sdim DAG.getRegister(SP::I6, TLI.getPointerTy()), 2380251662Sdim DAG.getIntPtrConstant(FuncInfo->getVarArgsFrameOffset())); 2381193323Sed const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue(); 2382251662Sdim return DAG.getStore(Op.getOperand(0), DL, Offset, Op.getOperand(1), 2383218893Sdim MachinePointerInfo(SV), false, false, 0); 2384193323Sed} 2385193323Sed 2386193323Sedstatic SDValue LowerVAARG(SDValue Op, SelectionDAG &DAG) { 2387193323Sed SDNode *Node = Op.getNode(); 2388198090Srdivacky EVT VT = Node->getValueType(0); 2389193323Sed SDValue InChain = Node->getOperand(0); 2390193323Sed SDValue VAListPtr = Node->getOperand(1); 2391251662Sdim EVT PtrVT = VAListPtr.getValueType(); 2392193323Sed const Value *SV = cast<SrcValueSDNode>(Node->getOperand(2))->getValue(); 2393263508Sdim SDLoc DL(Node); 2394251662Sdim SDValue VAList = DAG.getLoad(PtrVT, DL, InChain, VAListPtr, 2395234353Sdim MachinePointerInfo(SV), false, false, false, 0); 2396251662Sdim // Increment the pointer, VAList, to the next vaarg. 2397251662Sdim SDValue NextPtr = DAG.getNode(ISD::ADD, DL, PtrVT, VAList, 2398251662Sdim DAG.getIntPtrConstant(VT.getSizeInBits()/8)); 2399251662Sdim // Store the incremented VAList to the legalized pointer. 2400251662Sdim InChain = DAG.getStore(VAList.getValue(1), DL, NextPtr, 2401218893Sdim VAListPtr, MachinePointerInfo(SV), false, false, 0); 2402251662Sdim // Load the actual argument out of the pointer VAList. 2403251662Sdim // We can't count on greater alignment than the word size. 2404251662Sdim return DAG.getLoad(VT, DL, InChain, VAList, MachinePointerInfo(), 2405251662Sdim false, false, false, 2406251662Sdim std::min(PtrVT.getSizeInBits(), VT.getSizeInBits())/8); 2407193323Sed} 2408193323Sed 2409263508Sdimstatic SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG, 2410263508Sdim const SparcSubtarget *Subtarget) { 2411193323Sed SDValue Chain = Op.getOperand(0); // Legalize the chain. 2412193323Sed SDValue Size = Op.getOperand(1); // Legalize the size. 2413263508Sdim EVT VT = Size->getValueType(0); 2414263508Sdim SDLoc dl(Op); 2415193323Sed 2416193323Sed unsigned SPReg = SP::O6; 2417263508Sdim SDValue SP = DAG.getCopyFromReg(Chain, dl, SPReg, VT); 2418263508Sdim SDValue NewSP = DAG.getNode(ISD::SUB, dl, VT, SP, Size); // Value 2419193323Sed Chain = DAG.getCopyToReg(SP.getValue(1), dl, SPReg, NewSP); // Output chain 2420193323Sed 2421193323Sed // The resultant pointer is actually 16 words from the bottom of the stack, 2422193323Sed // to provide a register spill area. 2423263508Sdim unsigned regSpillArea = Subtarget->is64Bit() ? 128 : 96; 2424263508Sdim regSpillArea += Subtarget->getStackPointerBias(); 2425263508Sdim 2426263508Sdim SDValue NewVal = DAG.getNode(ISD::ADD, dl, VT, NewSP, 2427263508Sdim DAG.getConstant(regSpillArea, VT)); 2428193323Sed SDValue Ops[2] = { NewVal, Chain }; 2429193323Sed return DAG.getMergeValues(Ops, 2, dl); 2430193323Sed} 2431193323Sed 2432193323Sed 2433218893Sdimstatic SDValue getFLUSHW(SDValue Op, SelectionDAG &DAG) { 2434263508Sdim SDLoc dl(Op); 2435218893Sdim SDValue Chain = DAG.getNode(SPISD::FLUSHW, 2436218893Sdim dl, MVT::Other, DAG.getEntryNode()); 2437218893Sdim return Chain; 2438218893Sdim} 2439218893Sdim 2440263763Sdimstatic SDValue getFRAMEADDR(uint64_t depth, SDValue Op, SelectionDAG &DAG, 2441263763Sdim const SparcSubtarget *Subtarget) { 2442218893Sdim MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); 2443218893Sdim MFI->setFrameAddressIsTaken(true); 2444218893Sdim 2445218893Sdim EVT VT = Op.getValueType(); 2446263508Sdim SDLoc dl(Op); 2447218893Sdim unsigned FrameReg = SP::I6; 2448263763Sdim unsigned stackBias = Subtarget->getStackPointerBias(); 2449218893Sdim 2450263763Sdim SDValue FrameAddr; 2451218893Sdim 2452263763Sdim if (depth == 0) { 2453218893Sdim FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, FrameReg, VT); 2454263763Sdim if (Subtarget->is64Bit()) 2455263763Sdim FrameAddr = DAG.getNode(ISD::ADD, dl, VT, FrameAddr, 2456263763Sdim DAG.getIntPtrConstant(stackBias)); 2457263763Sdim return FrameAddr; 2458263763Sdim } 2459218893Sdim 2460263763Sdim // flush first to make sure the windowed registers' values are in stack 2461263763Sdim SDValue Chain = getFLUSHW(Op, DAG); 2462263763Sdim FrameAddr = DAG.getCopyFromReg(Chain, dl, FrameReg, VT); 2463263763Sdim 2464263763Sdim unsigned Offset = (Subtarget->is64Bit()) ? (stackBias + 112) : 56; 2465263763Sdim 2466263763Sdim while (depth--) { 2467263763Sdim SDValue Ptr = DAG.getNode(ISD::ADD, dl, VT, FrameAddr, 2468263763Sdim DAG.getIntPtrConstant(Offset)); 2469263763Sdim FrameAddr = DAG.getLoad(VT, dl, Chain, Ptr, MachinePointerInfo(), 2470263763Sdim false, false, false, 0); 2471218893Sdim } 2472263763Sdim if (Subtarget->is64Bit()) 2473263763Sdim FrameAddr = DAG.getNode(ISD::ADD, dl, VT, FrameAddr, 2474263763Sdim DAG.getIntPtrConstant(stackBias)); 2475218893Sdim return FrameAddr; 2476218893Sdim} 2477218893Sdim 2478263763Sdim 2479263763Sdimstatic SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG, 2480263763Sdim const SparcSubtarget *Subtarget) { 2481263763Sdim 2482263763Sdim uint64_t depth = Op.getConstantOperandVal(0); 2483263763Sdim 2484263763Sdim return getFRAMEADDR(depth, Op, DAG, Subtarget); 2485263763Sdim 2486263763Sdim} 2487263763Sdim 2488263508Sdimstatic SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG, 2489263763Sdim const SparcTargetLowering &TLI, 2490263763Sdim const SparcSubtarget *Subtarget) { 2491263508Sdim MachineFunction &MF = DAG.getMachineFunction(); 2492263508Sdim MachineFrameInfo *MFI = MF.getFrameInfo(); 2493218893Sdim MFI->setReturnAddressIsTaken(true); 2494218893Sdim 2495218893Sdim EVT VT = Op.getValueType(); 2496263508Sdim SDLoc dl(Op); 2497218893Sdim uint64_t depth = Op.getConstantOperandVal(0); 2498218893Sdim 2499218893Sdim SDValue RetAddr; 2500263508Sdim if (depth == 0) { 2501263508Sdim unsigned RetReg = MF.addLiveIn(SP::I7, 2502263508Sdim TLI.getRegClassFor(TLI.getPointerTy())); 2503218893Sdim RetAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, RetReg, VT); 2504263763Sdim return RetAddr; 2505263763Sdim } 2506263508Sdim 2507263763Sdim // Need frame address to find return address of the caller. 2508263763Sdim SDValue FrameAddr = getFRAMEADDR(depth - 1, Op, DAG, Subtarget); 2509218893Sdim 2510263763Sdim unsigned Offset = (Subtarget->is64Bit()) ? 120 : 60; 2511263763Sdim SDValue Ptr = DAG.getNode(ISD::ADD, 2512263763Sdim dl, VT, 2513263763Sdim FrameAddr, 2514263763Sdim DAG.getIntPtrConstant(Offset)); 2515263763Sdim RetAddr = DAG.getLoad(VT, dl, DAG.getEntryNode(), Ptr, 2516263763Sdim MachinePointerInfo(), false, false, false, 0); 2517263763Sdim 2518218893Sdim return RetAddr; 2519218893Sdim} 2520218893Sdim 2521263508Sdimstatic SDValue LowerF64Op(SDValue Op, SelectionDAG &DAG, unsigned opcode) 2522263508Sdim{ 2523263508Sdim SDLoc dl(Op); 2524263508Sdim 2525263508Sdim assert(Op.getValueType() == MVT::f64 && "LowerF64Op called on non-double!"); 2526263508Sdim assert(opcode == ISD::FNEG || opcode == ISD::FABS); 2527263508Sdim 2528263508Sdim // Lower fneg/fabs on f64 to fneg/fabs on f32. 2529263508Sdim // fneg f64 => fneg f32:sub_even, fmov f32:sub_odd. 2530263508Sdim // fabs f64 => fabs f32:sub_even, fmov f32:sub_odd. 2531263508Sdim 2532263508Sdim SDValue SrcReg64 = Op.getOperand(0); 2533263508Sdim SDValue Hi32 = DAG.getTargetExtractSubreg(SP::sub_even, dl, MVT::f32, 2534263508Sdim SrcReg64); 2535263508Sdim SDValue Lo32 = DAG.getTargetExtractSubreg(SP::sub_odd, dl, MVT::f32, 2536263508Sdim SrcReg64); 2537263508Sdim 2538263508Sdim Hi32 = DAG.getNode(opcode, dl, MVT::f32, Hi32); 2539263508Sdim 2540263508Sdim SDValue DstReg64 = SDValue(DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF, 2541263508Sdim dl, MVT::f64), 0); 2542263508Sdim DstReg64 = DAG.getTargetInsertSubreg(SP::sub_even, dl, MVT::f64, 2543263508Sdim DstReg64, Hi32); 2544263508Sdim DstReg64 = DAG.getTargetInsertSubreg(SP::sub_odd, dl, MVT::f64, 2545263508Sdim DstReg64, Lo32); 2546263508Sdim return DstReg64; 2547263508Sdim} 2548263508Sdim 2549263508Sdim// Lower a f128 load into two f64 loads. 2550263508Sdimstatic SDValue LowerF128Load(SDValue Op, SelectionDAG &DAG) 2551263508Sdim{ 2552263508Sdim SDLoc dl(Op); 2553263508Sdim LoadSDNode *LdNode = dyn_cast<LoadSDNode>(Op.getNode()); 2554263508Sdim assert(LdNode && LdNode->getOffset().getOpcode() == ISD::UNDEF 2555263508Sdim && "Unexpected node type"); 2556263508Sdim 2557263508Sdim unsigned alignment = LdNode->getAlignment(); 2558263508Sdim if (alignment > 8) 2559263508Sdim alignment = 8; 2560263508Sdim 2561263508Sdim SDValue Hi64 = DAG.getLoad(MVT::f64, 2562263508Sdim dl, 2563263508Sdim LdNode->getChain(), 2564263508Sdim LdNode->getBasePtr(), 2565263508Sdim LdNode->getPointerInfo(), 2566263508Sdim false, false, false, alignment); 2567263508Sdim EVT addrVT = LdNode->getBasePtr().getValueType(); 2568263508Sdim SDValue LoPtr = DAG.getNode(ISD::ADD, dl, addrVT, 2569263508Sdim LdNode->getBasePtr(), 2570263508Sdim DAG.getConstant(8, addrVT)); 2571263508Sdim SDValue Lo64 = DAG.getLoad(MVT::f64, 2572263508Sdim dl, 2573263508Sdim LdNode->getChain(), 2574263508Sdim LoPtr, 2575263508Sdim LdNode->getPointerInfo(), 2576263508Sdim false, false, false, alignment); 2577263508Sdim 2578263508Sdim SDValue SubRegEven = DAG.getTargetConstant(SP::sub_even64, MVT::i32); 2579263508Sdim SDValue SubRegOdd = DAG.getTargetConstant(SP::sub_odd64, MVT::i32); 2580263508Sdim 2581263508Sdim SDNode *InFP128 = DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF, 2582263508Sdim dl, MVT::f128); 2583263508Sdim InFP128 = DAG.getMachineNode(TargetOpcode::INSERT_SUBREG, dl, 2584263508Sdim MVT::f128, 2585263508Sdim SDValue(InFP128, 0), 2586263508Sdim Hi64, 2587263508Sdim SubRegEven); 2588263508Sdim InFP128 = DAG.getMachineNode(TargetOpcode::INSERT_SUBREG, dl, 2589263508Sdim MVT::f128, 2590263508Sdim SDValue(InFP128, 0), 2591263508Sdim Lo64, 2592263508Sdim SubRegOdd); 2593263508Sdim SDValue OutChains[2] = { SDValue(Hi64.getNode(), 1), 2594263508Sdim SDValue(Lo64.getNode(), 1) }; 2595263508Sdim SDValue OutChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, 2596263508Sdim &OutChains[0], 2); 2597263508Sdim SDValue Ops[2] = {SDValue(InFP128,0), OutChain}; 2598263508Sdim return DAG.getMergeValues(Ops, 2, dl); 2599263508Sdim} 2600263508Sdim 2601263508Sdim// Lower a f128 store into two f64 stores. 2602263508Sdimstatic SDValue LowerF128Store(SDValue Op, SelectionDAG &DAG) { 2603263508Sdim SDLoc dl(Op); 2604263508Sdim StoreSDNode *StNode = dyn_cast<StoreSDNode>(Op.getNode()); 2605263508Sdim assert(StNode && StNode->getOffset().getOpcode() == ISD::UNDEF 2606263508Sdim && "Unexpected node type"); 2607263508Sdim SDValue SubRegEven = DAG.getTargetConstant(SP::sub_even64, MVT::i32); 2608263508Sdim SDValue SubRegOdd = DAG.getTargetConstant(SP::sub_odd64, MVT::i32); 2609263508Sdim 2610263508Sdim SDNode *Hi64 = DAG.getMachineNode(TargetOpcode::EXTRACT_SUBREG, 2611263508Sdim dl, 2612263508Sdim MVT::f64, 2613263508Sdim StNode->getValue(), 2614263508Sdim SubRegEven); 2615263508Sdim SDNode *Lo64 = DAG.getMachineNode(TargetOpcode::EXTRACT_SUBREG, 2616263508Sdim dl, 2617263508Sdim MVT::f64, 2618263508Sdim StNode->getValue(), 2619263508Sdim SubRegOdd); 2620263508Sdim 2621263508Sdim unsigned alignment = StNode->getAlignment(); 2622263508Sdim if (alignment > 8) 2623263508Sdim alignment = 8; 2624263508Sdim 2625263508Sdim SDValue OutChains[2]; 2626263508Sdim OutChains[0] = DAG.getStore(StNode->getChain(), 2627263508Sdim dl, 2628263508Sdim SDValue(Hi64, 0), 2629263508Sdim StNode->getBasePtr(), 2630263508Sdim MachinePointerInfo(), 2631263508Sdim false, false, alignment); 2632263508Sdim EVT addrVT = StNode->getBasePtr().getValueType(); 2633263508Sdim SDValue LoPtr = DAG.getNode(ISD::ADD, dl, addrVT, 2634263508Sdim StNode->getBasePtr(), 2635263508Sdim DAG.getConstant(8, addrVT)); 2636263508Sdim OutChains[1] = DAG.getStore(StNode->getChain(), 2637263508Sdim dl, 2638263508Sdim SDValue(Lo64, 0), 2639263508Sdim LoPtr, 2640263508Sdim MachinePointerInfo(), 2641263508Sdim false, false, alignment); 2642263508Sdim return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, 2643263508Sdim &OutChains[0], 2); 2644263508Sdim} 2645263508Sdim 2646263763Sdimstatic SDValue LowerFNEGorFABS(SDValue Op, SelectionDAG &DAG, bool isV9) { 2647263763Sdim assert((Op.getOpcode() == ISD::FNEG || Op.getOpcode() == ISD::FABS) && "invalid"); 2648263508Sdim 2649263508Sdim if (Op.getValueType() == MVT::f64) 2650263763Sdim return LowerF64Op(Op, DAG, Op.getOpcode()); 2651263508Sdim if (Op.getValueType() != MVT::f128) 2652263508Sdim return Op; 2653263508Sdim 2654263763Sdim // Lower fabs/fneg on f128 to fabs/fneg on f64 2655263763Sdim // fabs/fneg f128 => fabs/fneg f64:sub_even64, fmov f64:sub_odd64 2656263508Sdim 2657263508Sdim SDLoc dl(Op); 2658263508Sdim SDValue SrcReg128 = Op.getOperand(0); 2659263508Sdim SDValue Hi64 = DAG.getTargetExtractSubreg(SP::sub_even64, dl, MVT::f64, 2660263508Sdim SrcReg128); 2661263508Sdim SDValue Lo64 = DAG.getTargetExtractSubreg(SP::sub_odd64, dl, MVT::f64, 2662263508Sdim SrcReg128); 2663263508Sdim if (isV9) 2664263508Sdim Hi64 = DAG.getNode(Op.getOpcode(), dl, MVT::f64, Hi64); 2665263508Sdim else 2666263763Sdim Hi64 = LowerF64Op(Hi64, DAG, Op.getOpcode()); 2667263508Sdim 2668263508Sdim SDValue DstReg128 = SDValue(DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF, 2669263508Sdim dl, MVT::f128), 0); 2670263508Sdim DstReg128 = DAG.getTargetInsertSubreg(SP::sub_even64, dl, MVT::f128, 2671263508Sdim DstReg128, Hi64); 2672263508Sdim DstReg128 = DAG.getTargetInsertSubreg(SP::sub_odd64, dl, MVT::f128, 2673263508Sdim DstReg128, Lo64); 2674263508Sdim return DstReg128; 2675263508Sdim} 2676263508Sdim 2677263508Sdimstatic SDValue LowerADDC_ADDE_SUBC_SUBE(SDValue Op, SelectionDAG &DAG) { 2678263508Sdim 2679263508Sdim if (Op.getValueType() != MVT::i64) 2680263508Sdim return Op; 2681263508Sdim 2682263508Sdim SDLoc dl(Op); 2683263508Sdim SDValue Src1 = Op.getOperand(0); 2684263508Sdim SDValue Src1Lo = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Src1); 2685263508Sdim SDValue Src1Hi = DAG.getNode(ISD::SRL, dl, MVT::i64, Src1, 2686263508Sdim DAG.getConstant(32, MVT::i64)); 2687263508Sdim Src1Hi = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Src1Hi); 2688263508Sdim 2689263508Sdim SDValue Src2 = Op.getOperand(1); 2690263508Sdim SDValue Src2Lo = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Src2); 2691263508Sdim SDValue Src2Hi = DAG.getNode(ISD::SRL, dl, MVT::i64, Src2, 2692263508Sdim DAG.getConstant(32, MVT::i64)); 2693263508Sdim Src2Hi = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Src2Hi); 2694263508Sdim 2695263508Sdim 2696263508Sdim bool hasChain = false; 2697263508Sdim unsigned hiOpc = Op.getOpcode(); 2698263508Sdim switch (Op.getOpcode()) { 2699263508Sdim default: llvm_unreachable("Invalid opcode"); 2700263508Sdim case ISD::ADDC: hiOpc = ISD::ADDE; break; 2701263508Sdim case ISD::ADDE: hasChain = true; break; 2702263508Sdim case ISD::SUBC: hiOpc = ISD::SUBE; break; 2703263508Sdim case ISD::SUBE: hasChain = true; break; 2704263508Sdim } 2705263508Sdim SDValue Lo; 2706263508Sdim SDVTList VTs = DAG.getVTList(MVT::i32, MVT::Glue); 2707263508Sdim if (hasChain) { 2708263508Sdim Lo = DAG.getNode(Op.getOpcode(), dl, VTs, Src1Lo, Src2Lo, 2709263508Sdim Op.getOperand(2)); 2710263508Sdim } else { 2711263508Sdim Lo = DAG.getNode(Op.getOpcode(), dl, VTs, Src1Lo, Src2Lo); 2712263508Sdim } 2713263508Sdim SDValue Hi = DAG.getNode(hiOpc, dl, VTs, Src1Hi, Src2Hi, Lo.getValue(1)); 2714263508Sdim SDValue Carry = Hi.getValue(1); 2715263508Sdim 2716263508Sdim Lo = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i64, Lo); 2717263508Sdim Hi = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i64, Hi); 2718263508Sdim Hi = DAG.getNode(ISD::SHL, dl, MVT::i64, Hi, 2719263508Sdim DAG.getConstant(32, MVT::i64)); 2720263508Sdim 2721263508Sdim SDValue Dst = DAG.getNode(ISD::OR, dl, MVT::i64, Hi, Lo); 2722263508Sdim SDValue Ops[2] = { Dst, Carry }; 2723263508Sdim return DAG.getMergeValues(Ops, 2, dl); 2724263508Sdim} 2725263508Sdim 2726263763Sdim// Custom lower UMULO/SMULO for SPARC. This code is similar to ExpandNode() 2727263763Sdim// in LegalizeDAG.cpp except the order of arguments to the library function. 2728263763Sdimstatic SDValue LowerUMULO_SMULO(SDValue Op, SelectionDAG &DAG, 2729263763Sdim const SparcTargetLowering &TLI) 2730263763Sdim{ 2731263763Sdim unsigned opcode = Op.getOpcode(); 2732263763Sdim assert((opcode == ISD::UMULO || opcode == ISD::SMULO) && "Invalid Opcode."); 2733263763Sdim 2734263763Sdim bool isSigned = (opcode == ISD::SMULO); 2735263763Sdim EVT VT = MVT::i64; 2736263763Sdim EVT WideVT = MVT::i128; 2737263763Sdim SDLoc dl(Op); 2738263763Sdim SDValue LHS = Op.getOperand(0); 2739263763Sdim 2740263763Sdim if (LHS.getValueType() != VT) 2741263763Sdim return Op; 2742263763Sdim 2743263763Sdim SDValue ShiftAmt = DAG.getConstant(63, VT); 2744263763Sdim 2745263763Sdim SDValue RHS = Op.getOperand(1); 2746263763Sdim SDValue HiLHS = DAG.getNode(ISD::SRA, dl, VT, LHS, ShiftAmt); 2747263763Sdim SDValue HiRHS = DAG.getNode(ISD::SRA, dl, MVT::i64, RHS, ShiftAmt); 2748263763Sdim SDValue Args[] = { HiLHS, LHS, HiRHS, RHS }; 2749263763Sdim 2750263763Sdim SDValue MulResult = TLI.makeLibCall(DAG, 2751263763Sdim RTLIB::MUL_I128, WideVT, 2752263763Sdim Args, 4, isSigned, dl).first; 2753263763Sdim SDValue BottomHalf = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, VT, 2754263763Sdim MulResult, DAG.getIntPtrConstant(0)); 2755263763Sdim SDValue TopHalf = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, VT, 2756263763Sdim MulResult, DAG.getIntPtrConstant(1)); 2757263763Sdim if (isSigned) { 2758263763Sdim SDValue Tmp1 = DAG.getNode(ISD::SRA, dl, VT, BottomHalf, ShiftAmt); 2759263763Sdim TopHalf = DAG.getSetCC(dl, MVT::i32, TopHalf, Tmp1, ISD::SETNE); 2760263763Sdim } else { 2761263763Sdim TopHalf = DAG.getSetCC(dl, MVT::i32, TopHalf, DAG.getConstant(0, VT), 2762263763Sdim ISD::SETNE); 2763263763Sdim } 2764263763Sdim // MulResult is a node with an illegal type. Because such things are not 2765263763Sdim // generally permitted during this phase of legalization, delete the 2766263763Sdim // node. The above EXTRACT_ELEMENT nodes should have been folded. 2767263763Sdim DAG.DeleteNode(MulResult.getNode()); 2768263763Sdim 2769263763Sdim SDValue Ops[2] = { BottomHalf, TopHalf } ; 2770263763Sdim return DAG.getMergeValues(Ops, 2, dl); 2771263763Sdim} 2772263763Sdim 2773263763Sdimstatic SDValue LowerATOMIC_LOAD_STORE(SDValue Op, SelectionDAG &DAG) { 2774263763Sdim // Monotonic load/stores are legal. 2775263763Sdim if (cast<AtomicSDNode>(Op)->getOrdering() <= Monotonic) 2776263763Sdim return Op; 2777263763Sdim 2778263763Sdim // Otherwise, expand with a fence. 2779263763Sdim return SDValue(); 2780263763Sdim} 2781263763Sdim 2782263763Sdim 2783193323SedSDValue SparcTargetLowering:: 2784207618SrdivackyLowerOperation(SDValue Op, SelectionDAG &DAG) const { 2785263508Sdim 2786263508Sdim bool hasHardQuad = Subtarget->hasHardQuad(); 2787263508Sdim bool isV9 = Subtarget->isV9(); 2788263508Sdim 2789193323Sed switch (Op.getOpcode()) { 2790198090Srdivacky default: llvm_unreachable("Should not custom lower this!"); 2791263508Sdim 2792263763Sdim case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG, *this, 2793263763Sdim Subtarget); 2794263763Sdim case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG, 2795263763Sdim Subtarget); 2796263508Sdim case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG); 2797198090Srdivacky case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG); 2798263508Sdim case ISD::BlockAddress: return LowerBlockAddress(Op, DAG); 2799198090Srdivacky case ISD::ConstantPool: return LowerConstantPool(Op, DAG); 2800263508Sdim case ISD::FP_TO_SINT: return LowerFP_TO_SINT(Op, DAG, *this, 2801263508Sdim hasHardQuad); 2802263508Sdim case ISD::SINT_TO_FP: return LowerSINT_TO_FP(Op, DAG, *this, 2803263508Sdim hasHardQuad); 2804263508Sdim case ISD::FP_TO_UINT: return LowerFP_TO_UINT(Op, DAG, *this, 2805263508Sdim hasHardQuad); 2806263508Sdim case ISD::UINT_TO_FP: return LowerUINT_TO_FP(Op, DAG, *this, 2807263508Sdim hasHardQuad); 2808263508Sdim case ISD::BR_CC: return LowerBR_CC(Op, DAG, *this, 2809263508Sdim hasHardQuad); 2810263508Sdim case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG, *this, 2811263508Sdim hasHardQuad); 2812193323Sed case ISD::VASTART: return LowerVASTART(Op, DAG, *this); 2813193323Sed case ISD::VAARG: return LowerVAARG(Op, DAG); 2814263508Sdim case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG, 2815263508Sdim Subtarget); 2816263508Sdim 2817263508Sdim case ISD::LOAD: return LowerF128Load(Op, DAG); 2818263508Sdim case ISD::STORE: return LowerF128Store(Op, DAG); 2819263508Sdim case ISD::FADD: return LowerF128Op(Op, DAG, 2820263508Sdim getLibcallName(RTLIB::ADD_F128), 2); 2821263508Sdim case ISD::FSUB: return LowerF128Op(Op, DAG, 2822263508Sdim getLibcallName(RTLIB::SUB_F128), 2); 2823263508Sdim case ISD::FMUL: return LowerF128Op(Op, DAG, 2824263508Sdim getLibcallName(RTLIB::MUL_F128), 2); 2825263508Sdim case ISD::FDIV: return LowerF128Op(Op, DAG, 2826263508Sdim getLibcallName(RTLIB::DIV_F128), 2); 2827263508Sdim case ISD::FSQRT: return LowerF128Op(Op, DAG, 2828263508Sdim getLibcallName(RTLIB::SQRT_F128),1); 2829263763Sdim case ISD::FABS: 2830263763Sdim case ISD::FNEG: return LowerFNEGorFABS(Op, DAG, isV9); 2831263508Sdim case ISD::FP_EXTEND: return LowerF128_FPEXTEND(Op, DAG, *this); 2832263508Sdim case ISD::FP_ROUND: return LowerF128_FPROUND(Op, DAG, *this); 2833263508Sdim case ISD::ADDC: 2834263508Sdim case ISD::ADDE: 2835263508Sdim case ISD::SUBC: 2836263508Sdim case ISD::SUBE: return LowerADDC_ADDE_SUBC_SUBE(Op, DAG); 2837263763Sdim case ISD::UMULO: 2838263763Sdim case ISD::SMULO: return LowerUMULO_SMULO(Op, DAG, *this); 2839263763Sdim case ISD::ATOMIC_LOAD: 2840263763Sdim case ISD::ATOMIC_STORE: return LowerATOMIC_LOAD_STORE(Op, DAG); 2841193323Sed } 2842193323Sed} 2843193323Sed 2844193323SedMachineBasicBlock * 2845193323SedSparcTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, 2846207618Srdivacky MachineBasicBlock *BB) const { 2847193323Sed switch (MI->getOpcode()) { 2848198090Srdivacky default: llvm_unreachable("Unknown SELECT_CC!"); 2849193323Sed case SP::SELECT_CC_Int_ICC: 2850193323Sed case SP::SELECT_CC_FP_ICC: 2851193323Sed case SP::SELECT_CC_DFP_ICC: 2852263508Sdim case SP::SELECT_CC_QFP_ICC: 2853263763Sdim return expandSelectCC(MI, BB, SP::BCOND); 2854193323Sed case SP::SELECT_CC_Int_FCC: 2855193323Sed case SP::SELECT_CC_FP_FCC: 2856193323Sed case SP::SELECT_CC_DFP_FCC: 2857263508Sdim case SP::SELECT_CC_QFP_FCC: 2858263763Sdim return expandSelectCC(MI, BB, SP::FBCOND); 2859263763Sdim 2860263763Sdim case SP::ATOMIC_LOAD_ADD_32: 2861263763Sdim return expandAtomicRMW(MI, BB, SP::ADDrr); 2862263763Sdim case SP::ATOMIC_LOAD_ADD_64: 2863263763Sdim return expandAtomicRMW(MI, BB, SP::ADDXrr); 2864263763Sdim case SP::ATOMIC_LOAD_SUB_32: 2865263763Sdim return expandAtomicRMW(MI, BB, SP::SUBrr); 2866263763Sdim case SP::ATOMIC_LOAD_SUB_64: 2867263763Sdim return expandAtomicRMW(MI, BB, SP::SUBXrr); 2868263763Sdim case SP::ATOMIC_LOAD_AND_32: 2869263763Sdim return expandAtomicRMW(MI, BB, SP::ANDrr); 2870263763Sdim case SP::ATOMIC_LOAD_AND_64: 2871263763Sdim return expandAtomicRMW(MI, BB, SP::ANDXrr); 2872263763Sdim case SP::ATOMIC_LOAD_OR_32: 2873263763Sdim return expandAtomicRMW(MI, BB, SP::ORrr); 2874263763Sdim case SP::ATOMIC_LOAD_OR_64: 2875263763Sdim return expandAtomicRMW(MI, BB, SP::ORXrr); 2876263763Sdim case SP::ATOMIC_LOAD_XOR_32: 2877263763Sdim return expandAtomicRMW(MI, BB, SP::XORrr); 2878263763Sdim case SP::ATOMIC_LOAD_XOR_64: 2879263763Sdim return expandAtomicRMW(MI, BB, SP::XORXrr); 2880263763Sdim case SP::ATOMIC_LOAD_NAND_32: 2881263763Sdim return expandAtomicRMW(MI, BB, SP::ANDrr); 2882263763Sdim case SP::ATOMIC_LOAD_NAND_64: 2883263763Sdim return expandAtomicRMW(MI, BB, SP::ANDXrr); 2884263763Sdim 2885263763Sdim case SP::ATOMIC_SWAP_64: 2886263763Sdim return expandAtomicRMW(MI, BB, 0); 2887263763Sdim 2888263763Sdim case SP::ATOMIC_LOAD_MAX_32: 2889263763Sdim return expandAtomicRMW(MI, BB, SP::MOVICCrr, SPCC::ICC_G); 2890263763Sdim case SP::ATOMIC_LOAD_MAX_64: 2891263763Sdim return expandAtomicRMW(MI, BB, SP::MOVXCCrr, SPCC::ICC_G); 2892263763Sdim case SP::ATOMIC_LOAD_MIN_32: 2893263763Sdim return expandAtomicRMW(MI, BB, SP::MOVICCrr, SPCC::ICC_LE); 2894263763Sdim case SP::ATOMIC_LOAD_MIN_64: 2895263763Sdim return expandAtomicRMW(MI, BB, SP::MOVXCCrr, SPCC::ICC_LE); 2896263763Sdim case SP::ATOMIC_LOAD_UMAX_32: 2897263763Sdim return expandAtomicRMW(MI, BB, SP::MOVICCrr, SPCC::ICC_GU); 2898263763Sdim case SP::ATOMIC_LOAD_UMAX_64: 2899263763Sdim return expandAtomicRMW(MI, BB, SP::MOVXCCrr, SPCC::ICC_GU); 2900263763Sdim case SP::ATOMIC_LOAD_UMIN_32: 2901263763Sdim return expandAtomicRMW(MI, BB, SP::MOVICCrr, SPCC::ICC_LEU); 2902263763Sdim case SP::ATOMIC_LOAD_UMIN_64: 2903263763Sdim return expandAtomicRMW(MI, BB, SP::MOVXCCrr, SPCC::ICC_LEU); 2904193323Sed } 2905263763Sdim} 2906193323Sed 2907263763SdimMachineBasicBlock* 2908263763SdimSparcTargetLowering::expandSelectCC(MachineInstr *MI, 2909263763Sdim MachineBasicBlock *BB, 2910263763Sdim unsigned BROpcode) const { 2911263763Sdim const TargetInstrInfo &TII = *getTargetMachine().getInstrInfo(); 2912263763Sdim DebugLoc dl = MI->getDebugLoc(); 2913263763Sdim unsigned CC = (SPCC::CondCodes)MI->getOperand(3).getImm(); 2914193323Sed 2915193323Sed // To "insert" a SELECT_CC instruction, we actually have to insert the diamond 2916193323Sed // control-flow pattern. The incoming instruction knows the destination vreg 2917193323Sed // to set, the condition code register to branch on, the true/false values to 2918193323Sed // select between, and a branch opcode to use. 2919193323Sed const BasicBlock *LLVM_BB = BB->getBasicBlock(); 2920193323Sed MachineFunction::iterator It = BB; 2921193323Sed ++It; 2922193323Sed 2923193323Sed // thisMBB: 2924193323Sed // ... 2925193323Sed // TrueVal = ... 2926193323Sed // [f]bCC copy1MBB 2927193323Sed // fallthrough --> copy0MBB 2928193323Sed MachineBasicBlock *thisMBB = BB; 2929193323Sed MachineFunction *F = BB->getParent(); 2930193323Sed MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB); 2931193323Sed MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB); 2932218893Sdim F->insert(It, copy0MBB); 2933218893Sdim F->insert(It, sinkMBB); 2934210299Sed 2935210299Sed // Transfer the remainder of BB and its successor edges to sinkMBB. 2936210299Sed sinkMBB->splice(sinkMBB->begin(), BB, 2937210299Sed llvm::next(MachineBasicBlock::iterator(MI)), 2938210299Sed BB->end()); 2939210299Sed sinkMBB->transferSuccessorsAndUpdatePHIs(BB); 2940210299Sed 2941210299Sed // Add the true and fallthrough blocks as its successors. 2942210299Sed BB->addSuccessor(copy0MBB); 2943210299Sed BB->addSuccessor(sinkMBB); 2944210299Sed 2945193323Sed BuildMI(BB, dl, TII.get(BROpcode)).addMBB(sinkMBB).addImm(CC); 2946193323Sed 2947193323Sed // copy0MBB: 2948193323Sed // %FalseValue = ... 2949193323Sed // # fallthrough to sinkMBB 2950193323Sed BB = copy0MBB; 2951193323Sed 2952193323Sed // Update machine-CFG edges 2953193323Sed BB->addSuccessor(sinkMBB); 2954193323Sed 2955193323Sed // sinkMBB: 2956193323Sed // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ] 2957193323Sed // ... 2958193323Sed BB = sinkMBB; 2959210299Sed BuildMI(*BB, BB->begin(), dl, TII.get(SP::PHI), MI->getOperand(0).getReg()) 2960193323Sed .addReg(MI->getOperand(2).getReg()).addMBB(copy0MBB) 2961193323Sed .addReg(MI->getOperand(1).getReg()).addMBB(thisMBB); 2962193323Sed 2963210299Sed MI->eraseFromParent(); // The pseudo instruction is gone now. 2964193323Sed return BB; 2965193323Sed} 2966193323Sed 2967263763SdimMachineBasicBlock* 2968263763SdimSparcTargetLowering::expandAtomicRMW(MachineInstr *MI, 2969263763Sdim MachineBasicBlock *MBB, 2970263763Sdim unsigned Opcode, 2971263763Sdim unsigned CondCode) const { 2972263763Sdim const TargetInstrInfo &TII = *getTargetMachine().getInstrInfo(); 2973263763Sdim MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo(); 2974263763Sdim DebugLoc DL = MI->getDebugLoc(); 2975263763Sdim 2976263763Sdim // MI is an atomic read-modify-write instruction of the form: 2977263763Sdim // 2978263763Sdim // rd = atomicrmw<op> addr, rs2 2979263763Sdim // 2980263763Sdim // All three operands are registers. 2981263763Sdim unsigned DestReg = MI->getOperand(0).getReg(); 2982263763Sdim unsigned AddrReg = MI->getOperand(1).getReg(); 2983263763Sdim unsigned Rs2Reg = MI->getOperand(2).getReg(); 2984263763Sdim 2985263763Sdim // SelectionDAG has already inserted memory barriers before and after MI, so 2986263763Sdim // we simply have to implement the operatiuon in terms of compare-and-swap. 2987263763Sdim // 2988263763Sdim // %val0 = load %addr 2989263763Sdim // loop: 2990263763Sdim // %val = phi %val0, %dest 2991263763Sdim // %upd = op %val, %rs2 2992263763Sdim // %dest = cas %addr, %val, %upd 2993263763Sdim // cmp %val, %dest 2994263763Sdim // bne loop 2995263763Sdim // done: 2996263763Sdim // 2997263763Sdim bool is64Bit = SP::I64RegsRegClass.hasSubClassEq(MRI.getRegClass(DestReg)); 2998263763Sdim const TargetRegisterClass *ValueRC = 2999263763Sdim is64Bit ? &SP::I64RegsRegClass : &SP::IntRegsRegClass; 3000263763Sdim unsigned Val0Reg = MRI.createVirtualRegister(ValueRC); 3001263763Sdim 3002263763Sdim BuildMI(*MBB, MI, DL, TII.get(is64Bit ? SP::LDXri : SP::LDri), Val0Reg) 3003263763Sdim .addReg(AddrReg).addImm(0); 3004263763Sdim 3005263763Sdim // Split the basic block MBB before MI and insert the loop block in the hole. 3006263763Sdim MachineFunction::iterator MFI = MBB; 3007263763Sdim const BasicBlock *LLVM_BB = MBB->getBasicBlock(); 3008263763Sdim MachineFunction *MF = MBB->getParent(); 3009263763Sdim MachineBasicBlock *LoopMBB = MF->CreateMachineBasicBlock(LLVM_BB); 3010263763Sdim MachineBasicBlock *DoneMBB = MF->CreateMachineBasicBlock(LLVM_BB); 3011263763Sdim ++MFI; 3012263763Sdim MF->insert(MFI, LoopMBB); 3013263763Sdim MF->insert(MFI, DoneMBB); 3014263763Sdim 3015263763Sdim // Move MI and following instructions to DoneMBB. 3016263763Sdim DoneMBB->splice(DoneMBB->begin(), MBB, MI, MBB->end()); 3017263763Sdim DoneMBB->transferSuccessorsAndUpdatePHIs(MBB); 3018263763Sdim 3019263763Sdim // Connect the CFG again. 3020263763Sdim MBB->addSuccessor(LoopMBB); 3021263763Sdim LoopMBB->addSuccessor(LoopMBB); 3022263763Sdim LoopMBB->addSuccessor(DoneMBB); 3023263763Sdim 3024263763Sdim // Build the loop block. 3025263763Sdim unsigned ValReg = MRI.createVirtualRegister(ValueRC); 3026263763Sdim // Opcode == 0 means try to write Rs2Reg directly (ATOMIC_SWAP). 3027263763Sdim unsigned UpdReg = (Opcode ? MRI.createVirtualRegister(ValueRC) : Rs2Reg); 3028263763Sdim 3029263763Sdim BuildMI(LoopMBB, DL, TII.get(SP::PHI), ValReg) 3030263763Sdim .addReg(Val0Reg).addMBB(MBB) 3031263763Sdim .addReg(DestReg).addMBB(LoopMBB); 3032263763Sdim 3033263763Sdim if (CondCode) { 3034263763Sdim // This is one of the min/max operations. We need a CMPrr followed by a 3035263763Sdim // MOVXCC/MOVICC. 3036263763Sdim BuildMI(LoopMBB, DL, TII.get(SP::CMPrr)).addReg(ValReg).addReg(Rs2Reg); 3037263763Sdim BuildMI(LoopMBB, DL, TII.get(Opcode), UpdReg) 3038263763Sdim .addReg(ValReg).addReg(Rs2Reg).addImm(CondCode); 3039263763Sdim } else if (Opcode) { 3040263763Sdim BuildMI(LoopMBB, DL, TII.get(Opcode), UpdReg) 3041263763Sdim .addReg(ValReg).addReg(Rs2Reg); 3042263763Sdim } 3043263763Sdim 3044263763Sdim if (MI->getOpcode() == SP::ATOMIC_LOAD_NAND_32 || 3045263763Sdim MI->getOpcode() == SP::ATOMIC_LOAD_NAND_64) { 3046263763Sdim unsigned TmpReg = UpdReg; 3047263763Sdim UpdReg = MRI.createVirtualRegister(ValueRC); 3048263763Sdim BuildMI(LoopMBB, DL, TII.get(SP::XORri), UpdReg).addReg(TmpReg).addImm(-1); 3049263763Sdim } 3050263763Sdim 3051263763Sdim BuildMI(LoopMBB, DL, TII.get(is64Bit ? SP::CASXrr : SP::CASrr), DestReg) 3052263763Sdim .addReg(AddrReg).addReg(ValReg).addReg(UpdReg) 3053263763Sdim .setMemRefs(MI->memoperands_begin(), MI->memoperands_end()); 3054263763Sdim BuildMI(LoopMBB, DL, TII.get(SP::CMPrr)).addReg(ValReg).addReg(DestReg); 3055263763Sdim BuildMI(LoopMBB, DL, TII.get(is64Bit ? SP::BPXCC : SP::BCOND)) 3056263763Sdim .addMBB(LoopMBB).addImm(SPCC::ICC_NE); 3057263763Sdim 3058263763Sdim MI->eraseFromParent(); 3059263763Sdim return DoneMBB; 3060263763Sdim} 3061263763Sdim 3062193323Sed//===----------------------------------------------------------------------===// 3063193323Sed// Sparc Inline Assembly Support 3064193323Sed//===----------------------------------------------------------------------===// 3065193323Sed 3066193323Sed/// getConstraintType - Given a constraint letter, return the type of 3067193323Sed/// constraint it is for this target. 3068193323SedSparcTargetLowering::ConstraintType 3069193323SedSparcTargetLowering::getConstraintType(const std::string &Constraint) const { 3070193323Sed if (Constraint.size() == 1) { 3071193323Sed switch (Constraint[0]) { 3072193323Sed default: break; 3073193323Sed case 'r': return C_RegisterClass; 3074263763Sdim case 'I': // SIMM13 3075263763Sdim return C_Other; 3076193323Sed } 3077193323Sed } 3078193323Sed 3079193323Sed return TargetLowering::getConstraintType(Constraint); 3080193323Sed} 3081193323Sed 3082263763SdimTargetLowering::ConstraintWeight SparcTargetLowering:: 3083263763SdimgetSingleConstraintMatchWeight(AsmOperandInfo &info, 3084263763Sdim const char *constraint) const { 3085263763Sdim ConstraintWeight weight = CW_Invalid; 3086263763Sdim Value *CallOperandVal = info.CallOperandVal; 3087263763Sdim // If we don't have a value, we can't do a match, 3088263763Sdim // but allow it at the lowest weight. 3089263763Sdim if (CallOperandVal == NULL) 3090263763Sdim return CW_Default; 3091263763Sdim 3092263763Sdim // Look at the constraint type. 3093263763Sdim switch (*constraint) { 3094263763Sdim default: 3095263763Sdim weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint); 3096263763Sdim break; 3097263763Sdim case 'I': // SIMM13 3098263763Sdim if (ConstantInt *C = dyn_cast<ConstantInt>(info.CallOperandVal)) { 3099263763Sdim if (isInt<13>(C->getSExtValue())) 3100263763Sdim weight = CW_Constant; 3101263763Sdim } 3102263763Sdim break; 3103263763Sdim } 3104263763Sdim return weight; 3105263763Sdim} 3106263763Sdim 3107263763Sdim/// LowerAsmOperandForConstraint - Lower the specified operand into the Ops 3108263763Sdim/// vector. If it is invalid, don't add anything to Ops. 3109263763Sdimvoid SparcTargetLowering:: 3110263763SdimLowerAsmOperandForConstraint(SDValue Op, 3111263763Sdim std::string &Constraint, 3112263763Sdim std::vector<SDValue> &Ops, 3113263763Sdim SelectionDAG &DAG) const { 3114263763Sdim SDValue Result(0, 0); 3115263763Sdim 3116263763Sdim // Only support length 1 constraints for now. 3117263763Sdim if (Constraint.length() > 1) 3118263763Sdim return; 3119263763Sdim 3120263763Sdim char ConstraintLetter = Constraint[0]; 3121263763Sdim switch (ConstraintLetter) { 3122263763Sdim default: break; 3123263763Sdim case 'I': 3124263763Sdim if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) { 3125263763Sdim if (isInt<13>(C->getSExtValue())) { 3126263763Sdim Result = DAG.getTargetConstant(C->getSExtValue(), Op.getValueType()); 3127263763Sdim break; 3128263763Sdim } 3129263763Sdim return; 3130263763Sdim } 3131263763Sdim } 3132263763Sdim 3133263763Sdim if (Result.getNode()) { 3134263763Sdim Ops.push_back(Result); 3135263763Sdim return; 3136263763Sdim } 3137263763Sdim TargetLowering::LowerAsmOperandForConstraint(Op, Constraint, Ops, DAG); 3138263763Sdim} 3139263763Sdim 3140193323Sedstd::pair<unsigned, const TargetRegisterClass*> 3141193323SedSparcTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint, 3142263508Sdim MVT VT) const { 3143193323Sed if (Constraint.size() == 1) { 3144193323Sed switch (Constraint[0]) { 3145193323Sed case 'r': 3146239462Sdim return std::make_pair(0U, &SP::IntRegsRegClass); 3147193323Sed } 3148263763Sdim } else if (!Constraint.empty() && Constraint.size() <= 5 3149263763Sdim && Constraint[0] == '{' && *(Constraint.end()-1) == '}') { 3150263763Sdim // constraint = '{r<d>}' 3151263763Sdim // Remove the braces from around the name. 3152263763Sdim StringRef name(Constraint.data()+1, Constraint.size()-2); 3153263763Sdim // Handle register aliases: 3154263763Sdim // r0-r7 -> g0-g7 3155263763Sdim // r8-r15 -> o0-o7 3156263763Sdim // r16-r23 -> l0-l7 3157263763Sdim // r24-r31 -> i0-i7 3158263763Sdim uint64_t intVal = 0; 3159263763Sdim if (name.substr(0, 1).equals("r") 3160263763Sdim && !name.substr(1).getAsInteger(10, intVal) && intVal <= 31) { 3161263763Sdim const char regTypes[] = { 'g', 'o', 'l', 'i' }; 3162263763Sdim char regType = regTypes[intVal/8]; 3163263763Sdim char regIdx = '0' + (intVal % 8); 3164263763Sdim char tmp[] = { '{', regType, regIdx, '}', 0 }; 3165263763Sdim std::string newConstraint = std::string(tmp); 3166263763Sdim return TargetLowering::getRegForInlineAsmConstraint(newConstraint, VT); 3167263763Sdim } 3168193323Sed } 3169193323Sed 3170193323Sed return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT); 3171193323Sed} 3172193323Sed 3173193323Sedbool 3174193323SedSparcTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const { 3175193323Sed // The Sparc target isn't yet aware of offsets. 3176193323Sed return false; 3177193323Sed} 3178263508Sdim 3179263508Sdimvoid SparcTargetLowering::ReplaceNodeResults(SDNode *N, 3180263508Sdim SmallVectorImpl<SDValue>& Results, 3181263508Sdim SelectionDAG &DAG) const { 3182263508Sdim 3183263508Sdim SDLoc dl(N); 3184263508Sdim 3185263508Sdim RTLIB::Libcall libCall = RTLIB::UNKNOWN_LIBCALL; 3186263508Sdim 3187263508Sdim switch (N->getOpcode()) { 3188263508Sdim default: 3189263508Sdim llvm_unreachable("Do not know how to custom type legalize this operation!"); 3190263508Sdim 3191263508Sdim case ISD::FP_TO_SINT: 3192263508Sdim case ISD::FP_TO_UINT: 3193263508Sdim // Custom lower only if it involves f128 or i64. 3194263508Sdim if (N->getOperand(0).getValueType() != MVT::f128 3195263508Sdim || N->getValueType(0) != MVT::i64) 3196263508Sdim return; 3197263508Sdim libCall = ((N->getOpcode() == ISD::FP_TO_SINT) 3198263508Sdim ? RTLIB::FPTOSINT_F128_I64 3199263508Sdim : RTLIB::FPTOUINT_F128_I64); 3200263508Sdim 3201263508Sdim Results.push_back(LowerF128Op(SDValue(N, 0), 3202263508Sdim DAG, 3203263508Sdim getLibcallName(libCall), 3204263508Sdim 1)); 3205263508Sdim return; 3206263508Sdim 3207263508Sdim case ISD::SINT_TO_FP: 3208263508Sdim case ISD::UINT_TO_FP: 3209263508Sdim // Custom lower only if it involves f128 or i64. 3210263508Sdim if (N->getValueType(0) != MVT::f128 3211263508Sdim || N->getOperand(0).getValueType() != MVT::i64) 3212263508Sdim return; 3213263508Sdim 3214263508Sdim libCall = ((N->getOpcode() == ISD::SINT_TO_FP) 3215263508Sdim ? RTLIB::SINTTOFP_I64_F128 3216263508Sdim : RTLIB::UINTTOFP_I64_F128); 3217263508Sdim 3218263508Sdim Results.push_back(LowerF128Op(SDValue(N, 0), 3219263508Sdim DAG, 3220263508Sdim getLibcallName(libCall), 3221263508Sdim 1)); 3222263508Sdim return; 3223263508Sdim } 3224263508Sdim} 3225