1204642Srdivacky//===-- MBlazeISelLowering.cpp - MBlaze DAG Lowering Implementation -------===// 2204642Srdivacky// 3204642Srdivacky// The LLVM Compiler Infrastructure 4204642Srdivacky// 5204642Srdivacky// This file is distributed under the University of Illinois Open Source 6204642Srdivacky// License. See LICENSE.TXT for details. 7204642Srdivacky// 8204642Srdivacky//===----------------------------------------------------------------------===// 9204642Srdivacky// 10204642Srdivacky// This file defines the interfaces that MBlaze uses to lower LLVM code into a 11204642Srdivacky// selection DAG. 12204642Srdivacky// 13204642Srdivacky//===----------------------------------------------------------------------===// 14204642Srdivacky 15204642Srdivacky#define DEBUG_TYPE "mblaze-lower" 16204642Srdivacky#include "MBlazeISelLowering.h" 17204642Srdivacky#include "MBlazeMachineFunction.h" 18249423Sdim#include "MBlazeSubtarget.h" 19204642Srdivacky#include "MBlazeTargetMachine.h" 20204642Srdivacky#include "MBlazeTargetObjectFile.h" 21204642Srdivacky#include "llvm/CodeGen/CallingConvLower.h" 22204642Srdivacky#include "llvm/CodeGen/MachineFrameInfo.h" 23204642Srdivacky#include "llvm/CodeGen/MachineFunction.h" 24204642Srdivacky#include "llvm/CodeGen/MachineInstrBuilder.h" 25204642Srdivacky#include "llvm/CodeGen/MachineRegisterInfo.h" 26204642Srdivacky#include "llvm/CodeGen/SelectionDAGISel.h" 27204642Srdivacky#include "llvm/CodeGen/ValueTypes.h" 28249423Sdim#include "llvm/IR/CallingConv.h" 29249423Sdim#include "llvm/IR/DerivedTypes.h" 30249423Sdim#include "llvm/IR/Function.h" 31249423Sdim#include "llvm/IR/GlobalVariable.h" 32249423Sdim#include "llvm/IR/Intrinsics.h" 33204642Srdivacky#include "llvm/Support/Debug.h" 34204642Srdivacky#include "llvm/Support/ErrorHandling.h" 35204642Srdivacky#include "llvm/Support/raw_ostream.h" 36204642Srdivackyusing namespace llvm; 37204642Srdivacky 38218893Sdimstatic bool CC_MBlaze_AssignReg(unsigned &ValNo, MVT &ValVT, MVT &LocVT, 39218893Sdim CCValAssign::LocInfo &LocInfo, 40218893Sdim ISD::ArgFlagsTy &ArgFlags, 41218893Sdim CCState &State); 42218893Sdim 43204642Srdivackyconst char *MBlazeTargetLowering::getTargetNodeName(unsigned Opcode) const { 44204642Srdivacky switch (Opcode) { 45204642Srdivacky case MBlazeISD::JmpLink : return "MBlazeISD::JmpLink"; 46204642Srdivacky case MBlazeISD::GPRel : return "MBlazeISD::GPRel"; 47204642Srdivacky case MBlazeISD::Wrap : return "MBlazeISD::Wrap"; 48204642Srdivacky case MBlazeISD::ICmp : return "MBlazeISD::ICmp"; 49204642Srdivacky case MBlazeISD::Ret : return "MBlazeISD::Ret"; 50204642Srdivacky case MBlazeISD::Select_CC : return "MBlazeISD::Select_CC"; 51204642Srdivacky default : return NULL; 52204642Srdivacky } 53204642Srdivacky} 54204642Srdivacky 55204642SrdivackyMBlazeTargetLowering::MBlazeTargetLowering(MBlazeTargetMachine &TM) 56204642Srdivacky : TargetLowering(TM, new MBlazeTargetObjectFile()) { 57204642Srdivacky Subtarget = &TM.getSubtarget<MBlazeSubtarget>(); 58204642Srdivacky 59204642Srdivacky // MBlaze does not have i1 type, so use i32 for 60204642Srdivacky // setcc operations results (slt, sgt, ...). 61204642Srdivacky setBooleanContents(ZeroOrOneBooleanContent); 62226633Sdim setBooleanVectorContents(ZeroOrOneBooleanContent); // FIXME: Is this correct? 63204642Srdivacky 64204642Srdivacky // Set up the register classes 65239462Sdim addRegisterClass(MVT::i32, &MBlaze::GPRRegClass); 66204642Srdivacky if (Subtarget->hasFPU()) { 67239462Sdim addRegisterClass(MVT::f32, &MBlaze::GPRRegClass); 68204642Srdivacky setOperationAction(ISD::ConstantFP, MVT::f32, Legal); 69204642Srdivacky } 70204642Srdivacky 71204642Srdivacky // Floating point operations which are not supported 72204642Srdivacky setOperationAction(ISD::FREM, MVT::f32, Expand); 73224145Sdim setOperationAction(ISD::FMA, MVT::f32, Expand); 74204642Srdivacky setOperationAction(ISD::UINT_TO_FP, MVT::i8, Expand); 75204642Srdivacky setOperationAction(ISD::UINT_TO_FP, MVT::i16, Expand); 76204642Srdivacky setOperationAction(ISD::UINT_TO_FP, MVT::i32, Expand); 77204642Srdivacky setOperationAction(ISD::FP_TO_UINT, MVT::i32, Expand); 78204642Srdivacky setOperationAction(ISD::FP_ROUND, MVT::f32, Expand); 79204642Srdivacky setOperationAction(ISD::FP_ROUND, MVT::f64, Expand); 80204642Srdivacky setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand); 81204642Srdivacky setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand); 82204642Srdivacky setOperationAction(ISD::FSIN, MVT::f32, Expand); 83204642Srdivacky setOperationAction(ISD::FCOS, MVT::f32, Expand); 84249423Sdim setOperationAction(ISD::FSINCOS, MVT::f32, Expand); 85204642Srdivacky setOperationAction(ISD::FPOWI, MVT::f32, Expand); 86204642Srdivacky setOperationAction(ISD::FPOW, MVT::f32, Expand); 87204642Srdivacky setOperationAction(ISD::FLOG, MVT::f32, Expand); 88204642Srdivacky setOperationAction(ISD::FLOG2, MVT::f32, Expand); 89204642Srdivacky setOperationAction(ISD::FLOG10, MVT::f32, Expand); 90204642Srdivacky setOperationAction(ISD::FEXP, MVT::f32, Expand); 91204642Srdivacky 92204642Srdivacky // Load extented operations for i1 types must be promoted 93204642Srdivacky setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote); 94204642Srdivacky setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote); 95204642Srdivacky setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote); 96204642Srdivacky 97218893Sdim // Sign extended loads must be expanded 98218893Sdim setLoadExtAction(ISD::SEXTLOAD, MVT::i8, Expand); 99218893Sdim setLoadExtAction(ISD::SEXTLOAD, MVT::i16, Expand); 100218893Sdim 101204642Srdivacky // MBlaze has no REM or DIVREM operations. 102204642Srdivacky setOperationAction(ISD::UREM, MVT::i32, Expand); 103204642Srdivacky setOperationAction(ISD::SREM, MVT::i32, Expand); 104204642Srdivacky setOperationAction(ISD::SDIVREM, MVT::i32, Expand); 105204642Srdivacky setOperationAction(ISD::UDIVREM, MVT::i32, Expand); 106204642Srdivacky 107204642Srdivacky // If the processor doesn't support multiply then expand it 108204642Srdivacky if (!Subtarget->hasMul()) { 109204642Srdivacky setOperationAction(ISD::MUL, MVT::i32, Expand); 110204642Srdivacky } 111204642Srdivacky 112204642Srdivacky // If the processor doesn't support 64-bit multiply then expand 113204642Srdivacky if (!Subtarget->hasMul() || !Subtarget->hasMul64()) { 114204642Srdivacky setOperationAction(ISD::MULHS, MVT::i32, Expand); 115204642Srdivacky setOperationAction(ISD::MULHS, MVT::i64, Expand); 116204642Srdivacky setOperationAction(ISD::MULHU, MVT::i32, Expand); 117204642Srdivacky setOperationAction(ISD::MULHU, MVT::i64, Expand); 118204642Srdivacky } 119204642Srdivacky 120204642Srdivacky // If the processor doesn't support division then expand 121204642Srdivacky if (!Subtarget->hasDiv()) { 122204642Srdivacky setOperationAction(ISD::UDIV, MVT::i32, Expand); 123204642Srdivacky setOperationAction(ISD::SDIV, MVT::i32, Expand); 124204642Srdivacky } 125204642Srdivacky 126204642Srdivacky // Expand unsupported conversions 127218893Sdim setOperationAction(ISD::BITCAST, MVT::f32, Expand); 128218893Sdim setOperationAction(ISD::BITCAST, MVT::i32, Expand); 129204642Srdivacky 130204642Srdivacky // Expand SELECT_CC 131204642Srdivacky setOperationAction(ISD::SELECT_CC, MVT::Other, Expand); 132204642Srdivacky 133204642Srdivacky // MBlaze doesn't have MUL_LOHI 134204642Srdivacky setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand); 135204642Srdivacky setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand); 136204642Srdivacky setOperationAction(ISD::SMUL_LOHI, MVT::i64, Expand); 137204642Srdivacky setOperationAction(ISD::UMUL_LOHI, MVT::i64, Expand); 138204642Srdivacky 139204642Srdivacky // Used by legalize types to correctly generate the setcc result. 140204642Srdivacky // Without this, every float setcc comes with a AND/OR with the result, 141204642Srdivacky // we don't want this, since the fpcmp result goes to a flag register, 142204642Srdivacky // which is used implicitly by brcond and select operations. 143204642Srdivacky AddPromotedToType(ISD::SETCC, MVT::i1, MVT::i32); 144204642Srdivacky AddPromotedToType(ISD::SELECT, MVT::i1, MVT::i32); 145204642Srdivacky AddPromotedToType(ISD::SELECT_CC, MVT::i1, MVT::i32); 146204642Srdivacky 147204642Srdivacky // MBlaze Custom Operations 148204642Srdivacky setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); 149204642Srdivacky setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom); 150204642Srdivacky setOperationAction(ISD::JumpTable, MVT::i32, Custom); 151204642Srdivacky setOperationAction(ISD::ConstantPool, MVT::i32, Custom); 152204642Srdivacky 153204961Srdivacky // Variable Argument support 154204961Srdivacky setOperationAction(ISD::VASTART, MVT::Other, Custom); 155204961Srdivacky setOperationAction(ISD::VAEND, MVT::Other, Expand); 156204961Srdivacky setOperationAction(ISD::VAARG, MVT::Other, Expand); 157204961Srdivacky setOperationAction(ISD::VACOPY, MVT::Other, Expand); 158204961Srdivacky 159204961Srdivacky 160204642Srdivacky // Operations not directly supported by MBlaze. 161204642Srdivacky setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand); 162204642Srdivacky setOperationAction(ISD::BR_JT, MVT::Other, Expand); 163249423Sdim setOperationAction(ISD::BR_CC, MVT::f32, Expand); 164249423Sdim setOperationAction(ISD::BR_CC, MVT::i32, Expand); 165204642Srdivacky setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); 166204642Srdivacky setOperationAction(ISD::ROTL, MVT::i32, Expand); 167204642Srdivacky setOperationAction(ISD::ROTR, MVT::i32, Expand); 168204642Srdivacky setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand); 169204642Srdivacky setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand); 170204642Srdivacky setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand); 171204642Srdivacky setOperationAction(ISD::CTLZ, MVT::i32, Expand); 172234353Sdim setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i32, Expand); 173204642Srdivacky setOperationAction(ISD::CTTZ, MVT::i32, Expand); 174234353Sdim setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i32, Expand); 175204642Srdivacky setOperationAction(ISD::CTPOP, MVT::i32, Expand); 176204642Srdivacky setOperationAction(ISD::BSWAP, MVT::i32, Expand); 177204642Srdivacky 178204642Srdivacky // We don't have line number support yet. 179204642Srdivacky setOperationAction(ISD::EH_LABEL, MVT::Other, Expand); 180204642Srdivacky 181204642Srdivacky // Use the default for now 182204642Srdivacky setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); 183204642Srdivacky setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand); 184204642Srdivacky 185204642Srdivacky // MBlaze doesn't have extending float->double load/store 186204642Srdivacky setLoadExtAction(ISD::EXTLOAD, MVT::f32, Expand); 187204642Srdivacky setTruncStoreAction(MVT::f64, MVT::f32, Expand); 188204642Srdivacky 189223017Sdim setMinFunctionAlignment(2); 190223017Sdim 191204642Srdivacky setStackPointerRegisterToSaveRestore(MBlaze::R1); 192204642Srdivacky computeRegisterProperties(); 193204642Srdivacky} 194204642Srdivacky 195226633SdimEVT MBlazeTargetLowering::getSetCCResultType(EVT VT) const { 196204642Srdivacky return MVT::i32; 197204642Srdivacky} 198204642Srdivacky 199207618SrdivackySDValue MBlazeTargetLowering::LowerOperation(SDValue Op, 200207618Srdivacky SelectionDAG &DAG) const { 201204642Srdivacky switch (Op.getOpcode()) 202204642Srdivacky { 203204642Srdivacky case ISD::ConstantPool: return LowerConstantPool(Op, DAG); 204204642Srdivacky case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG); 205204642Srdivacky case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG); 206204642Srdivacky case ISD::JumpTable: return LowerJumpTable(Op, DAG); 207204642Srdivacky case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG); 208204961Srdivacky case ISD::VASTART: return LowerVASTART(Op, DAG); 209204642Srdivacky } 210204642Srdivacky return SDValue(); 211204642Srdivacky} 212204642Srdivacky 213204642Srdivacky//===----------------------------------------------------------------------===// 214204642Srdivacky// Lower helper functions 215204642Srdivacky//===----------------------------------------------------------------------===// 216207618SrdivackyMachineBasicBlock* 217207618SrdivackyMBlazeTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, 218218893Sdim MachineBasicBlock *MBB) 219218893Sdim const { 220204642Srdivacky switch (MI->getOpcode()) { 221234353Sdim default: llvm_unreachable("Unexpected instr type to insert"); 222218893Sdim 223204642Srdivacky case MBlaze::ShiftRL: 224204642Srdivacky case MBlaze::ShiftRA: 225218893Sdim case MBlaze::ShiftL: 226218893Sdim return EmitCustomShift(MI, MBB); 227204642Srdivacky 228218893Sdim case MBlaze::Select_FCC: 229218893Sdim case MBlaze::Select_CC: 230218893Sdim return EmitCustomSelect(MI, MBB); 231204642Srdivacky 232218893Sdim case MBlaze::CAS32: 233218893Sdim case MBlaze::SWP32: 234218893Sdim case MBlaze::LAA32: 235218893Sdim case MBlaze::LAS32: 236218893Sdim case MBlaze::LAD32: 237218893Sdim case MBlaze::LAO32: 238218893Sdim case MBlaze::LAX32: 239218893Sdim case MBlaze::LAN32: 240218893Sdim return EmitCustomAtomic(MI, MBB); 241210299Sed 242218893Sdim case MBlaze::MEMBARRIER: 243218893Sdim // The Microblaze does not need memory barriers. Just delete the pseudo 244218893Sdim // instruction and finish. 245218893Sdim MI->eraseFromParent(); 246218893Sdim return MBB; 247218893Sdim } 248218893Sdim} 249210299Sed 250218893SdimMachineBasicBlock* 251218893SdimMBlazeTargetLowering::EmitCustomShift(MachineInstr *MI, 252218893Sdim MachineBasicBlock *MBB) const { 253218893Sdim const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); 254218893Sdim DebugLoc dl = MI->getDebugLoc(); 255210299Sed 256218893Sdim // To "insert" a shift left instruction, we actually have to insert a 257218893Sdim // simple loop. The incoming instruction knows the destination vreg to 258218893Sdim // set, the source vreg to operate over and the shift amount. 259218893Sdim const BasicBlock *LLVM_BB = MBB->getBasicBlock(); 260218893Sdim MachineFunction::iterator It = MBB; 261218893Sdim ++It; 262204642Srdivacky 263218893Sdim // start: 264218893Sdim // andi samt, samt, 31 265218893Sdim // beqid samt, finish 266218893Sdim // add dst, src, r0 267218893Sdim // loop: 268218893Sdim // addik samt, samt, -1 269218893Sdim // sra dst, dst 270218893Sdim // bneid samt, loop 271218893Sdim // nop 272218893Sdim // finish: 273218893Sdim MachineFunction *F = MBB->getParent(); 274218893Sdim MachineRegisterInfo &R = F->getRegInfo(); 275218893Sdim MachineBasicBlock *loop = F->CreateMachineBasicBlock(LLVM_BB); 276218893Sdim MachineBasicBlock *finish = F->CreateMachineBasicBlock(LLVM_BB); 277218893Sdim F->insert(It, loop); 278218893Sdim F->insert(It, finish); 279204642Srdivacky 280221345Sdim // Update machine-CFG edges by transferring adding all successors and 281218893Sdim // remaining instructions from the current block to the new block which 282218893Sdim // will contain the Phi node for the select. 283218893Sdim finish->splice(finish->begin(), MBB, 284218893Sdim llvm::next(MachineBasicBlock::iterator(MI)), 285218893Sdim MBB->end()); 286218893Sdim finish->transferSuccessorsAndUpdatePHIs(MBB); 287204642Srdivacky 288218893Sdim // Add the true and fallthrough blocks as its successors. 289218893Sdim MBB->addSuccessor(loop); 290218893Sdim MBB->addSuccessor(finish); 291204642Srdivacky 292218893Sdim // Next, add the finish block as a successor of the loop block 293218893Sdim loop->addSuccessor(finish); 294218893Sdim loop->addSuccessor(loop); 295204642Srdivacky 296239462Sdim unsigned IAMT = R.createVirtualRegister(&MBlaze::GPRRegClass); 297218893Sdim BuildMI(MBB, dl, TII->get(MBlaze::ANDI), IAMT) 298218893Sdim .addReg(MI->getOperand(2).getReg()) 299218893Sdim .addImm(31); 300204642Srdivacky 301239462Sdim unsigned IVAL = R.createVirtualRegister(&MBlaze::GPRRegClass); 302218893Sdim BuildMI(MBB, dl, TII->get(MBlaze::ADDIK), IVAL) 303218893Sdim .addReg(MI->getOperand(1).getReg()) 304218893Sdim .addImm(0); 305204642Srdivacky 306218893Sdim BuildMI(MBB, dl, TII->get(MBlaze::BEQID)) 307218893Sdim .addReg(IAMT) 308218893Sdim .addMBB(finish); 309204642Srdivacky 310239462Sdim unsigned DST = R.createVirtualRegister(&MBlaze::GPRRegClass); 311239462Sdim unsigned NDST = R.createVirtualRegister(&MBlaze::GPRRegClass); 312218893Sdim BuildMI(loop, dl, TII->get(MBlaze::PHI), DST) 313218893Sdim .addReg(IVAL).addMBB(MBB) 314218893Sdim .addReg(NDST).addMBB(loop); 315204642Srdivacky 316239462Sdim unsigned SAMT = R.createVirtualRegister(&MBlaze::GPRRegClass); 317239462Sdim unsigned NAMT = R.createVirtualRegister(&MBlaze::GPRRegClass); 318218893Sdim BuildMI(loop, dl, TII->get(MBlaze::PHI), SAMT) 319218893Sdim .addReg(IAMT).addMBB(MBB) 320218893Sdim .addReg(NAMT).addMBB(loop); 321204642Srdivacky 322218893Sdim if (MI->getOpcode() == MBlaze::ShiftL) 323218893Sdim BuildMI(loop, dl, TII->get(MBlaze::ADD), NDST).addReg(DST).addReg(DST); 324218893Sdim else if (MI->getOpcode() == MBlaze::ShiftRA) 325218893Sdim BuildMI(loop, dl, TII->get(MBlaze::SRA), NDST).addReg(DST); 326218893Sdim else if (MI->getOpcode() == MBlaze::ShiftRL) 327218893Sdim BuildMI(loop, dl, TII->get(MBlaze::SRL), NDST).addReg(DST); 328218893Sdim else 329218893Sdim llvm_unreachable("Cannot lower unknown shift instruction"); 330204642Srdivacky 331218893Sdim BuildMI(loop, dl, TII->get(MBlaze::ADDIK), NAMT) 332218893Sdim .addReg(SAMT) 333218893Sdim .addImm(-1); 334204642Srdivacky 335218893Sdim BuildMI(loop, dl, TII->get(MBlaze::BNEID)) 336218893Sdim .addReg(NAMT) 337218893Sdim .addMBB(loop); 338218893Sdim 339218893Sdim BuildMI(*finish, finish->begin(), dl, 340218893Sdim TII->get(MBlaze::PHI), MI->getOperand(0).getReg()) 341218893Sdim .addReg(IVAL).addMBB(MBB) 342218893Sdim .addReg(NDST).addMBB(loop); 343218893Sdim 344218893Sdim // The pseudo instruction is no longer needed so remove it 345218893Sdim MI->eraseFromParent(); 346218893Sdim return finish; 347218893Sdim} 348218893Sdim 349218893SdimMachineBasicBlock* 350218893SdimMBlazeTargetLowering::EmitCustomSelect(MachineInstr *MI, 351218893Sdim MachineBasicBlock *MBB) const { 352218893Sdim const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); 353218893Sdim DebugLoc dl = MI->getDebugLoc(); 354218893Sdim 355218893Sdim // To "insert" a SELECT_CC instruction, we actually have to insert the 356218893Sdim // diamond control-flow pattern. The incoming instruction knows the 357218893Sdim // destination vreg to set, the condition code register to branch on, the 358218893Sdim // true/false values to select between, and a branch opcode to use. 359218893Sdim const BasicBlock *LLVM_BB = MBB->getBasicBlock(); 360218893Sdim MachineFunction::iterator It = MBB; 361218893Sdim ++It; 362218893Sdim 363218893Sdim // thisMBB: 364218893Sdim // ... 365218893Sdim // TrueVal = ... 366218893Sdim // setcc r1, r2, r3 367218893Sdim // bNE r1, r0, copy1MBB 368218893Sdim // fallthrough --> copy0MBB 369218893Sdim MachineFunction *F = MBB->getParent(); 370218893Sdim MachineBasicBlock *flsBB = F->CreateMachineBasicBlock(LLVM_BB); 371218893Sdim MachineBasicBlock *dneBB = F->CreateMachineBasicBlock(LLVM_BB); 372218893Sdim 373218893Sdim unsigned Opc; 374218893Sdim switch (MI->getOperand(4).getImm()) { 375218893Sdim default: llvm_unreachable("Unknown branch condition"); 376218893Sdim case MBlazeCC::EQ: Opc = MBlaze::BEQID; break; 377218893Sdim case MBlazeCC::NE: Opc = MBlaze::BNEID; break; 378218893Sdim case MBlazeCC::GT: Opc = MBlaze::BGTID; break; 379218893Sdim case MBlazeCC::LT: Opc = MBlaze::BLTID; break; 380218893Sdim case MBlazeCC::GE: Opc = MBlaze::BGEID; break; 381218893Sdim case MBlazeCC::LE: Opc = MBlaze::BLEID; break; 382218893Sdim } 383218893Sdim 384218893Sdim F->insert(It, flsBB); 385218893Sdim F->insert(It, dneBB); 386218893Sdim 387218893Sdim // Transfer the remainder of MBB and its successor edges to dneBB. 388218893Sdim dneBB->splice(dneBB->begin(), MBB, 389218893Sdim llvm::next(MachineBasicBlock::iterator(MI)), 390218893Sdim MBB->end()); 391218893Sdim dneBB->transferSuccessorsAndUpdatePHIs(MBB); 392218893Sdim 393218893Sdim MBB->addSuccessor(flsBB); 394218893Sdim MBB->addSuccessor(dneBB); 395218893Sdim flsBB->addSuccessor(dneBB); 396218893Sdim 397218893Sdim BuildMI(MBB, dl, TII->get(Opc)) 398218893Sdim .addReg(MI->getOperand(3).getReg()) 399218893Sdim .addMBB(dneBB); 400218893Sdim 401218893Sdim // sinkMBB: 402218893Sdim // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ] 403218893Sdim // ... 404218893Sdim //BuildMI(dneBB, dl, TII->get(MBlaze::PHI), MI->getOperand(0).getReg()) 405218893Sdim // .addReg(MI->getOperand(1).getReg()).addMBB(flsBB) 406218893Sdim // .addReg(MI->getOperand(2).getReg()).addMBB(BB); 407218893Sdim 408218893Sdim BuildMI(*dneBB, dneBB->begin(), dl, 409218893Sdim TII->get(MBlaze::PHI), MI->getOperand(0).getReg()) 410218893Sdim .addReg(MI->getOperand(2).getReg()).addMBB(flsBB) 411218893Sdim .addReg(MI->getOperand(1).getReg()).addMBB(MBB); 412218893Sdim 413218893Sdim MI->eraseFromParent(); // The pseudo instruction is gone now. 414218893Sdim return dneBB; 415218893Sdim} 416218893Sdim 417218893SdimMachineBasicBlock* 418218893SdimMBlazeTargetLowering::EmitCustomAtomic(MachineInstr *MI, 419218893Sdim MachineBasicBlock *MBB) const { 420218893Sdim const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); 421218893Sdim DebugLoc dl = MI->getDebugLoc(); 422218893Sdim 423218893Sdim // All atomic instructions on the Microblaze are implemented using the 424218893Sdim // load-linked / store-conditional style atomic instruction sequences. 425218893Sdim // Thus, all operations will look something like the following: 426223017Sdim // 427218893Sdim // start: 428218893Sdim // lwx RV, RP, 0 429218893Sdim // <do stuff> 430218893Sdim // swx RV, RP, 0 431218893Sdim // addic RC, R0, 0 432218893Sdim // bneid RC, start 433218893Sdim // 434218893Sdim // exit: 435218893Sdim // 436218893Sdim // To "insert" a shift left instruction, we actually have to insert a 437218893Sdim // simple loop. The incoming instruction knows the destination vreg to 438218893Sdim // set, the source vreg to operate over and the shift amount. 439218893Sdim const BasicBlock *LLVM_BB = MBB->getBasicBlock(); 440218893Sdim MachineFunction::iterator It = MBB; 441218893Sdim ++It; 442218893Sdim 443218893Sdim // start: 444218893Sdim // andi samt, samt, 31 445218893Sdim // beqid samt, finish 446218893Sdim // add dst, src, r0 447218893Sdim // loop: 448218893Sdim // addik samt, samt, -1 449218893Sdim // sra dst, dst 450218893Sdim // bneid samt, loop 451218893Sdim // nop 452218893Sdim // finish: 453218893Sdim MachineFunction *F = MBB->getParent(); 454218893Sdim MachineRegisterInfo &R = F->getRegInfo(); 455218893Sdim 456218893Sdim // Create the start and exit basic blocks for the atomic operation 457218893Sdim MachineBasicBlock *start = F->CreateMachineBasicBlock(LLVM_BB); 458218893Sdim MachineBasicBlock *exit = F->CreateMachineBasicBlock(LLVM_BB); 459218893Sdim F->insert(It, start); 460218893Sdim F->insert(It, exit); 461218893Sdim 462221345Sdim // Update machine-CFG edges by transferring adding all successors and 463218893Sdim // remaining instructions from the current block to the new block which 464218893Sdim // will contain the Phi node for the select. 465218893Sdim exit->splice(exit->begin(), MBB, llvm::next(MachineBasicBlock::iterator(MI)), 466218893Sdim MBB->end()); 467218893Sdim exit->transferSuccessorsAndUpdatePHIs(MBB); 468218893Sdim 469218893Sdim // Add the fallthrough block as its successors. 470218893Sdim MBB->addSuccessor(start); 471218893Sdim 472218893Sdim BuildMI(start, dl, TII->get(MBlaze::LWX), MI->getOperand(0).getReg()) 473218893Sdim .addReg(MI->getOperand(1).getReg()) 474218893Sdim .addReg(MBlaze::R0); 475218893Sdim 476218893Sdim MachineBasicBlock *final = start; 477218893Sdim unsigned finalReg = 0; 478218893Sdim 479218893Sdim switch (MI->getOpcode()) { 480218893Sdim default: llvm_unreachable("Cannot lower unknown atomic instruction!"); 481218893Sdim 482218893Sdim case MBlaze::SWP32: 483218893Sdim finalReg = MI->getOperand(2).getReg(); 484218893Sdim start->addSuccessor(exit); 485218893Sdim start->addSuccessor(start); 486218893Sdim break; 487218893Sdim 488218893Sdim case MBlaze::LAN32: 489218893Sdim case MBlaze::LAX32: 490218893Sdim case MBlaze::LAO32: 491218893Sdim case MBlaze::LAD32: 492218893Sdim case MBlaze::LAS32: 493218893Sdim case MBlaze::LAA32: { 494218893Sdim unsigned opcode = 0; 495218893Sdim switch (MI->getOpcode()) { 496218893Sdim default: llvm_unreachable("Cannot lower unknown atomic load!"); 497218893Sdim case MBlaze::LAA32: opcode = MBlaze::ADDIK; break; 498218893Sdim case MBlaze::LAS32: opcode = MBlaze::RSUBIK; break; 499218893Sdim case MBlaze::LAD32: opcode = MBlaze::AND; break; 500218893Sdim case MBlaze::LAO32: opcode = MBlaze::OR; break; 501218893Sdim case MBlaze::LAX32: opcode = MBlaze::XOR; break; 502218893Sdim case MBlaze::LAN32: opcode = MBlaze::AND; break; 503204642Srdivacky } 504204642Srdivacky 505239462Sdim finalReg = R.createVirtualRegister(&MBlaze::GPRRegClass); 506218893Sdim start->addSuccessor(exit); 507218893Sdim start->addSuccessor(start); 508204642Srdivacky 509218893Sdim BuildMI(start, dl, TII->get(opcode), finalReg) 510218893Sdim .addReg(MI->getOperand(0).getReg()) 511218893Sdim .addReg(MI->getOperand(2).getReg()); 512204642Srdivacky 513218893Sdim if (MI->getOpcode() == MBlaze::LAN32) { 514218893Sdim unsigned tmp = finalReg; 515239462Sdim finalReg = R.createVirtualRegister(&MBlaze::GPRRegClass); 516218893Sdim BuildMI(start, dl, TII->get(MBlaze::XORI), finalReg) 517218893Sdim .addReg(tmp) 518218893Sdim .addImm(-1); 519218893Sdim } 520218893Sdim break; 521218893Sdim } 522204642Srdivacky 523218893Sdim case MBlaze::CAS32: { 524218893Sdim finalReg = MI->getOperand(3).getReg(); 525218893Sdim final = F->CreateMachineBasicBlock(LLVM_BB); 526210299Sed 527218893Sdim F->insert(It, final); 528218893Sdim start->addSuccessor(exit); 529218893Sdim start->addSuccessor(final); 530218893Sdim final->addSuccessor(exit); 531218893Sdim final->addSuccessor(start); 532204642Srdivacky 533239462Sdim unsigned CMP = R.createVirtualRegister(&MBlaze::GPRRegClass); 534218893Sdim BuildMI(start, dl, TII->get(MBlaze::CMP), CMP) 535218893Sdim .addReg(MI->getOperand(0).getReg()) 536218893Sdim .addReg(MI->getOperand(2).getReg()); 537204642Srdivacky 538218893Sdim BuildMI(start, dl, TII->get(MBlaze::BNEID)) 539218893Sdim .addReg(CMP) 540218893Sdim .addMBB(exit); 541218893Sdim 542218893Sdim final->moveAfter(start); 543218893Sdim exit->moveAfter(final); 544218893Sdim break; 545204642Srdivacky } 546204642Srdivacky } 547218893Sdim 548239462Sdim unsigned CHK = R.createVirtualRegister(&MBlaze::GPRRegClass); 549218893Sdim BuildMI(final, dl, TII->get(MBlaze::SWX)) 550218893Sdim .addReg(finalReg) 551218893Sdim .addReg(MI->getOperand(1).getReg()) 552218893Sdim .addReg(MBlaze::R0); 553218893Sdim 554218893Sdim BuildMI(final, dl, TII->get(MBlaze::ADDIC), CHK) 555218893Sdim .addReg(MBlaze::R0) 556218893Sdim .addImm(0); 557218893Sdim 558218893Sdim BuildMI(final, dl, TII->get(MBlaze::BNEID)) 559218893Sdim .addReg(CHK) 560218893Sdim .addMBB(start); 561218893Sdim 562218893Sdim // The pseudo instruction is no longer needed so remove it 563218893Sdim MI->eraseFromParent(); 564218893Sdim return exit; 565204642Srdivacky} 566204642Srdivacky 567204642Srdivacky//===----------------------------------------------------------------------===// 568204642Srdivacky// Misc Lower Operation implementation 569204642Srdivacky//===----------------------------------------------------------------------===// 570204642Srdivacky// 571204642Srdivacky 572207618SrdivackySDValue MBlazeTargetLowering::LowerSELECT_CC(SDValue Op, 573207618Srdivacky SelectionDAG &DAG) const { 574204642Srdivacky SDValue LHS = Op.getOperand(0); 575204642Srdivacky SDValue RHS = Op.getOperand(1); 576204642Srdivacky SDValue TrueVal = Op.getOperand(2); 577204642Srdivacky SDValue FalseVal = Op.getOperand(3); 578204642Srdivacky DebugLoc dl = Op.getDebugLoc(); 579204642Srdivacky unsigned Opc; 580204642Srdivacky 581204642Srdivacky SDValue CompareFlag; 582204642Srdivacky if (LHS.getValueType() == MVT::i32) { 583204642Srdivacky Opc = MBlazeISD::Select_CC; 584204642Srdivacky CompareFlag = DAG.getNode(MBlazeISD::ICmp, dl, MVT::i32, LHS, RHS) 585204642Srdivacky .getValue(1); 586204642Srdivacky } else { 587218893Sdim llvm_unreachable("Cannot lower select_cc with unknown type"); 588204642Srdivacky } 589218893Sdim 590204642Srdivacky return DAG.getNode(Opc, dl, TrueVal.getValueType(), TrueVal, FalseVal, 591204642Srdivacky CompareFlag); 592204642Srdivacky} 593204642Srdivacky 594204642SrdivackySDValue MBlazeTargetLowering:: 595207618SrdivackyLowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const { 596204642Srdivacky // FIXME there isn't actually debug info here 597204642Srdivacky DebugLoc dl = Op.getDebugLoc(); 598207618Srdivacky const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal(); 599210299Sed SDValue GA = DAG.getTargetGlobalAddress(GV, dl, MVT::i32); 600204642Srdivacky 601204642Srdivacky return DAG.getNode(MBlazeISD::Wrap, dl, MVT::i32, GA); 602204642Srdivacky} 603204642Srdivacky 604204642SrdivackySDValue MBlazeTargetLowering:: 605207618SrdivackyLowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const { 606204642Srdivacky llvm_unreachable("TLS not implemented for MicroBlaze."); 607204642Srdivacky} 608204642Srdivacky 609204642SrdivackySDValue MBlazeTargetLowering:: 610207618SrdivackyLowerJumpTable(SDValue Op, SelectionDAG &DAG) const { 611204642Srdivacky SDValue ResNode; 612204642Srdivacky SDValue HiPart; 613204642Srdivacky // FIXME there isn't actually debug info here 614204642Srdivacky DebugLoc dl = Op.getDebugLoc(); 615204642Srdivacky 616204642Srdivacky EVT PtrVT = Op.getValueType(); 617204642Srdivacky JumpTableSDNode *JT = cast<JumpTableSDNode>(Op); 618204642Srdivacky 619218893Sdim SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT, 0); 620204642Srdivacky return DAG.getNode(MBlazeISD::Wrap, dl, MVT::i32, JTI); 621204642Srdivacky} 622204642Srdivacky 623204642SrdivackySDValue MBlazeTargetLowering:: 624207618SrdivackyLowerConstantPool(SDValue Op, SelectionDAG &DAG) const { 625204642Srdivacky SDValue ResNode; 626204642Srdivacky ConstantPoolSDNode *N = cast<ConstantPoolSDNode>(Op); 627207618Srdivacky const Constant *C = N->getConstVal(); 628204642Srdivacky DebugLoc dl = Op.getDebugLoc(); 629204642Srdivacky 630204642Srdivacky SDValue CP = DAG.getTargetConstantPool(C, MVT::i32, N->getAlignment(), 631218893Sdim N->getOffset(), 0); 632204642Srdivacky return DAG.getNode(MBlazeISD::Wrap, dl, MVT::i32, CP); 633204642Srdivacky} 634204642Srdivacky 635207618SrdivackySDValue MBlazeTargetLowering::LowerVASTART(SDValue Op, 636207618Srdivacky SelectionDAG &DAG) const { 637207618Srdivacky MachineFunction &MF = DAG.getMachineFunction(); 638207618Srdivacky MBlazeFunctionInfo *FuncInfo = MF.getInfo<MBlazeFunctionInfo>(); 639207618Srdivacky 640204961Srdivacky DebugLoc dl = Op.getDebugLoc(); 641207618Srdivacky SDValue FI = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(), 642207618Srdivacky getPointerTy()); 643204961Srdivacky 644204961Srdivacky // vastart just stores the address of the VarArgsFrameIndex slot into the 645204961Srdivacky // memory location argument. 646204961Srdivacky const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue(); 647218893Sdim return DAG.getStore(Op.getOperand(0), dl, FI, Op.getOperand(1), 648218893Sdim MachinePointerInfo(SV), 649204961Srdivacky false, false, 0); 650204961Srdivacky} 651204961Srdivacky 652204642Srdivacky//===----------------------------------------------------------------------===// 653204642Srdivacky// Calling Convention Implementation 654204642Srdivacky//===----------------------------------------------------------------------===// 655204642Srdivacky 656204642Srdivacky#include "MBlazeGenCallingConv.inc" 657204642Srdivacky 658218893Sdimstatic bool CC_MBlaze_AssignReg(unsigned &ValNo, MVT &ValVT, MVT &LocVT, 659218893Sdim CCValAssign::LocInfo &LocInfo, 660218893Sdim ISD::ArgFlagsTy &ArgFlags, 661218893Sdim CCState &State) { 662234353Sdim static const uint16_t ArgRegs[] = { 663204961Srdivacky MBlaze::R5, MBlaze::R6, MBlaze::R7, 664204961Srdivacky MBlaze::R8, MBlaze::R9, MBlaze::R10 665204961Srdivacky }; 666204961Srdivacky 667218893Sdim const unsigned NumArgRegs = array_lengthof(ArgRegs); 668218893Sdim unsigned Reg = State.AllocateReg(ArgRegs, NumArgRegs); 669218893Sdim if (!Reg) return false; 670204961Srdivacky 671218893Sdim unsigned SizeInBytes = ValVT.getSizeInBits() >> 3; 672218893Sdim State.AllocateStack(SizeInBytes, SizeInBytes); 673218893Sdim State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); 674204961Srdivacky 675218893Sdim return true; 676204961Srdivacky} 677204961Srdivacky 678204642Srdivacky//===----------------------------------------------------------------------===// 679204642Srdivacky// Call Calling Convention Implementation 680204642Srdivacky//===----------------------------------------------------------------------===// 681204642Srdivacky 682204642Srdivacky/// LowerCall - functions arguments are copied from virtual regs to 683204642Srdivacky/// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted. 684204642Srdivacky/// TODO: isVarArg, isTailCall. 685204642SrdivackySDValue MBlazeTargetLowering:: 686239462SdimLowerCall(TargetLowering::CallLoweringInfo &CLI, 687207618Srdivacky SmallVectorImpl<SDValue> &InVals) const { 688239462Sdim SelectionDAG &DAG = CLI.DAG; 689239462Sdim DebugLoc &dl = CLI.DL; 690239462Sdim SmallVector<ISD::OutputArg, 32> &Outs = CLI.Outs; 691239462Sdim SmallVector<SDValue, 32> &OutVals = CLI.OutVals; 692239462Sdim SmallVector<ISD::InputArg, 32> &Ins = CLI.Ins; 693239462Sdim SDValue Chain = CLI.Chain; 694239462Sdim SDValue Callee = CLI.Callee; 695239462Sdim bool &isTailCall = CLI.IsTailCall; 696239462Sdim CallingConv::ID CallConv = CLI.CallConv; 697239462Sdim bool isVarArg = CLI.IsVarArg; 698239462Sdim 699204961Srdivacky // MBlaze does not yet support tail call optimization 700204961Srdivacky isTailCall = false; 701204961Srdivacky 702218893Sdim // The MBlaze requires stack slots for arguments passed to var arg 703218893Sdim // functions even if they are passed in registers. 704218893Sdim bool needsRegArgSlots = isVarArg; 705218893Sdim 706204642Srdivacky MachineFunction &MF = DAG.getMachineFunction(); 707204642Srdivacky MachineFrameInfo *MFI = MF.getFrameInfo(); 708218893Sdim const TargetFrameLowering &TFI = *MF.getTarget().getFrameLowering(); 709204642Srdivacky 710204642Srdivacky // Analyze operands of the call, assigning locations to each operand. 711204642Srdivacky SmallVector<CCValAssign, 16> ArgLocs; 712223017Sdim CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), 713239462Sdim getTargetMachine(), ArgLocs, *DAG.getContext()); 714218893Sdim CCInfo.AnalyzeCallOperands(Outs, CC_MBlaze); 715204642Srdivacky 716204642Srdivacky // Get a count of how many bytes are to be pushed on the stack. 717204642Srdivacky unsigned NumBytes = CCInfo.getNextStackOffset(); 718218893Sdim 719218893Sdim // Variable argument function calls require a minimum of 24-bytes of stack 720218893Sdim if (isVarArg && NumBytes < 24) NumBytes = 24; 721218893Sdim 722204642Srdivacky Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumBytes, true)); 723204642Srdivacky 724204642Srdivacky SmallVector<std::pair<unsigned, SDValue>, 8> RegsToPass; 725204642Srdivacky SmallVector<SDValue, 8> MemOpChains; 726204642Srdivacky 727204642Srdivacky // Walk the register/memloc assignments, inserting copies/loads. 728204642Srdivacky for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { 729204642Srdivacky CCValAssign &VA = ArgLocs[i]; 730218893Sdim MVT RegVT = VA.getLocVT(); 731210299Sed SDValue Arg = OutVals[i]; 732204642Srdivacky 733204642Srdivacky // Promote the value if needed. 734204642Srdivacky switch (VA.getLocInfo()) { 735204642Srdivacky default: llvm_unreachable("Unknown loc info!"); 736204642Srdivacky case CCValAssign::Full: break; 737204642Srdivacky case CCValAssign::SExt: 738204642Srdivacky Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, RegVT, Arg); 739204642Srdivacky break; 740204642Srdivacky case CCValAssign::ZExt: 741204642Srdivacky Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, RegVT, Arg); 742204642Srdivacky break; 743204642Srdivacky case CCValAssign::AExt: 744204642Srdivacky Arg = DAG.getNode(ISD::ANY_EXTEND, dl, RegVT, Arg); 745204642Srdivacky break; 746204642Srdivacky } 747204642Srdivacky 748204642Srdivacky // Arguments that can be passed on register must be kept at 749204642Srdivacky // RegsToPass vector 750204642Srdivacky if (VA.isRegLoc()) { 751204642Srdivacky RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); 752204642Srdivacky } else { 753204642Srdivacky // Register can't get to this point... 754204642Srdivacky assert(VA.isMemLoc()); 755204642Srdivacky 756218893Sdim // Since we are alread passing values on the stack we don't 757218893Sdim // need to worry about creating additional slots for the 758218893Sdim // values passed via registers. 759218893Sdim needsRegArgSlots = false; 760218893Sdim 761204642Srdivacky // Create the frame index object for this incoming parameter 762218893Sdim unsigned ArgSize = VA.getValVT().getSizeInBits()/8; 763218893Sdim unsigned StackLoc = VA.getLocMemOffset() + 4; 764218893Sdim int FI = MFI->CreateFixedObject(ArgSize, StackLoc, true); 765204642Srdivacky 766204642Srdivacky SDValue PtrOff = DAG.getFrameIndex(FI,getPointerTy()); 767204642Srdivacky 768204642Srdivacky // emit ISD::STORE whichs stores the 769204642Srdivacky // parameter value to a stack Location 770218893Sdim MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, 771218893Sdim MachinePointerInfo(), 772204642Srdivacky false, false, 0)); 773204642Srdivacky } 774204642Srdivacky } 775204642Srdivacky 776218893Sdim // If we need to reserve stack space for the arguments passed via registers 777218893Sdim // then create a fixed stack object at the beginning of the stack. 778218893Sdim if (needsRegArgSlots && TFI.hasReservedCallFrame(MF)) 779218893Sdim MFI->CreateFixedObject(28,0,true); 780218893Sdim 781204642Srdivacky // Transform all store nodes into one single node because all store 782204642Srdivacky // nodes are independent of each other. 783204642Srdivacky if (!MemOpChains.empty()) 784204642Srdivacky Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, 785204642Srdivacky &MemOpChains[0], MemOpChains.size()); 786204642Srdivacky 787204642Srdivacky // Build a sequence of copy-to-reg nodes chained together with token 788204642Srdivacky // chain and flag operands which copy the outgoing args into registers. 789221345Sdim // The InFlag in necessary since all emitted instructions must be 790204642Srdivacky // stuck together. 791204642Srdivacky SDValue InFlag; 792204642Srdivacky for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { 793204642Srdivacky Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first, 794204642Srdivacky RegsToPass[i].second, InFlag); 795204642Srdivacky InFlag = Chain.getValue(1); 796204642Srdivacky } 797204642Srdivacky 798204642Srdivacky // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every 799204642Srdivacky // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol 800204642Srdivacky // node so that legalize doesn't hack it. 801204642Srdivacky if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) 802210299Sed Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, 803218893Sdim getPointerTy(), 0, 0); 804204642Srdivacky else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) 805204642Srdivacky Callee = DAG.getTargetExternalSymbol(S->getSymbol(), 806218893Sdim getPointerTy(), 0); 807204642Srdivacky 808204642Srdivacky // MBlazeJmpLink = #chain, #target_address, #opt_in_flags... 809204642Srdivacky // = Chain, Callee, Reg#1, Reg#2, ... 810204642Srdivacky // 811204642Srdivacky // Returns a chain & a flag for retval copy to use. 812218893Sdim SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); 813204642Srdivacky SmallVector<SDValue, 8> Ops; 814204642Srdivacky Ops.push_back(Chain); 815204642Srdivacky Ops.push_back(Callee); 816204642Srdivacky 817204642Srdivacky // Add argument registers to the end of the list so that they are 818204642Srdivacky // known live into the call. 819204642Srdivacky for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { 820204642Srdivacky Ops.push_back(DAG.getRegister(RegsToPass[i].first, 821204642Srdivacky RegsToPass[i].second.getValueType())); 822204642Srdivacky } 823204642Srdivacky 824204642Srdivacky if (InFlag.getNode()) 825204642Srdivacky Ops.push_back(InFlag); 826204642Srdivacky 827204642Srdivacky Chain = DAG.getNode(MBlazeISD::JmpLink, dl, NodeTys, &Ops[0], Ops.size()); 828204642Srdivacky InFlag = Chain.getValue(1); 829204642Srdivacky 830204642Srdivacky // Create the CALLSEQ_END node. 831204642Srdivacky Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumBytes, true), 832204642Srdivacky DAG.getIntPtrConstant(0, true), InFlag); 833204642Srdivacky if (!Ins.empty()) 834204642Srdivacky InFlag = Chain.getValue(1); 835204642Srdivacky 836204642Srdivacky // Handle result values, copying them out of physregs into vregs that we 837204642Srdivacky // return. 838204642Srdivacky return LowerCallResult(Chain, InFlag, CallConv, isVarArg, 839204642Srdivacky Ins, dl, DAG, InVals); 840204642Srdivacky} 841204642Srdivacky 842204642Srdivacky/// LowerCallResult - Lower the result values of a call into the 843204642Srdivacky/// appropriate copies out of appropriate physical registers. 844204642SrdivackySDValue MBlazeTargetLowering:: 845204642SrdivackyLowerCallResult(SDValue Chain, SDValue InFlag, CallingConv::ID CallConv, 846204642Srdivacky bool isVarArg, const SmallVectorImpl<ISD::InputArg> &Ins, 847204642Srdivacky DebugLoc dl, SelectionDAG &DAG, 848207618Srdivacky SmallVectorImpl<SDValue> &InVals) const { 849204642Srdivacky // Assign locations to each value returned by this call. 850204642Srdivacky SmallVector<CCValAssign, 16> RVLocs; 851223017Sdim CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), 852239462Sdim getTargetMachine(), RVLocs, *DAG.getContext()); 853204642Srdivacky 854204642Srdivacky CCInfo.AnalyzeCallResult(Ins, RetCC_MBlaze); 855204642Srdivacky 856204642Srdivacky // Copy all of the result registers out of their specified physreg. 857204642Srdivacky for (unsigned i = 0; i != RVLocs.size(); ++i) { 858204642Srdivacky Chain = DAG.getCopyFromReg(Chain, dl, RVLocs[i].getLocReg(), 859204642Srdivacky RVLocs[i].getValVT(), InFlag).getValue(1); 860204642Srdivacky InFlag = Chain.getValue(2); 861204642Srdivacky InVals.push_back(Chain.getValue(0)); 862218893Sdim } 863204642Srdivacky 864204642Srdivacky return Chain; 865204642Srdivacky} 866204642Srdivacky 867204642Srdivacky//===----------------------------------------------------------------------===// 868204642Srdivacky// Formal Arguments Calling Convention Implementation 869204642Srdivacky//===----------------------------------------------------------------------===// 870204642Srdivacky 871204642Srdivacky/// LowerFormalArguments - transform physical registers into 872204642Srdivacky/// virtual registers and generate load operations for 873204642Srdivacky/// arguments places on the stack. 874204642SrdivackySDValue MBlazeTargetLowering:: 875204642SrdivackyLowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, 876204642Srdivacky const SmallVectorImpl<ISD::InputArg> &Ins, 877204642Srdivacky DebugLoc dl, SelectionDAG &DAG, 878207618Srdivacky SmallVectorImpl<SDValue> &InVals) const { 879204642Srdivacky MachineFunction &MF = DAG.getMachineFunction(); 880204642Srdivacky MachineFrameInfo *MFI = MF.getFrameInfo(); 881204642Srdivacky MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>(); 882204642Srdivacky 883204642Srdivacky unsigned StackReg = MF.getTarget().getRegisterInfo()->getFrameRegister(MF); 884207618Srdivacky MBlazeFI->setVarArgsFrameIndex(0); 885204642Srdivacky 886204961Srdivacky // Used with vargs to acumulate store chains. 887204961Srdivacky std::vector<SDValue> OutChains; 888204961Srdivacky 889204961Srdivacky // Keep track of the last register used for arguments 890204961Srdivacky unsigned ArgRegEnd = 0; 891204961Srdivacky 892204642Srdivacky // Assign locations to all of the incoming arguments. 893204642Srdivacky SmallVector<CCValAssign, 16> ArgLocs; 894223017Sdim CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), 895239462Sdim getTargetMachine(), ArgLocs, *DAG.getContext()); 896204642Srdivacky 897218893Sdim CCInfo.AnalyzeFormalArguments(Ins, CC_MBlaze); 898204642Srdivacky SDValue StackPtr; 899204642Srdivacky 900204642Srdivacky for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { 901204642Srdivacky CCValAssign &VA = ArgLocs[i]; 902204642Srdivacky 903204642Srdivacky // Arguments stored on registers 904204642Srdivacky if (VA.isRegLoc()) { 905218893Sdim MVT RegVT = VA.getLocVT(); 906204961Srdivacky ArgRegEnd = VA.getLocReg(); 907234353Sdim const TargetRegisterClass *RC; 908204642Srdivacky 909204642Srdivacky if (RegVT == MVT::i32) 910239462Sdim RC = &MBlaze::GPRRegClass; 911204642Srdivacky else if (RegVT == MVT::f32) 912239462Sdim RC = &MBlaze::GPRRegClass; 913204642Srdivacky else 914204642Srdivacky llvm_unreachable("RegVT not supported by LowerFormalArguments"); 915204642Srdivacky 916204642Srdivacky // Transform the arguments stored on 917204642Srdivacky // physical registers into virtual ones 918219077Sdim unsigned Reg = MF.addLiveIn(ArgRegEnd, RC); 919204642Srdivacky SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, RegVT); 920204642Srdivacky 921204642Srdivacky // If this is an 8 or 16-bit value, it has been passed promoted 922204642Srdivacky // to 32 bits. Insert an assert[sz]ext to capture this, then 923204961Srdivacky // truncate to the right size. If if is a floating point value 924204961Srdivacky // then convert to the correct type. 925204642Srdivacky if (VA.getLocInfo() != CCValAssign::Full) { 926204642Srdivacky unsigned Opcode = 0; 927204642Srdivacky if (VA.getLocInfo() == CCValAssign::SExt) 928204642Srdivacky Opcode = ISD::AssertSext; 929204642Srdivacky else if (VA.getLocInfo() == CCValAssign::ZExt) 930204642Srdivacky Opcode = ISD::AssertZext; 931204642Srdivacky if (Opcode) 932204642Srdivacky ArgValue = DAG.getNode(Opcode, dl, RegVT, ArgValue, 933204642Srdivacky DAG.getValueType(VA.getValVT())); 934204642Srdivacky ArgValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), ArgValue); 935204642Srdivacky } 936204642Srdivacky 937204642Srdivacky InVals.push_back(ArgValue); 938204642Srdivacky } else { // VA.isRegLoc() 939204642Srdivacky // sanity check 940204642Srdivacky assert(VA.isMemLoc()); 941204642Srdivacky 942204961Srdivacky // The last argument is not a register 943204961Srdivacky ArgRegEnd = 0; 944204961Srdivacky 945204642Srdivacky // The stack pointer offset is relative to the caller stack frame. 946204642Srdivacky // Since the real stack size is unknown here, a negative SPOffset 947204642Srdivacky // is used so there's a way to adjust these offsets when the stack 948204642Srdivacky // size get known (on EliminateFrameIndex). A dummy SPOffset is 949204642Srdivacky // used instead of a direct negative address (which is recorded to 950204642Srdivacky // be used on emitPrologue) to avoid mis-calc of the first stack 951204642Srdivacky // offset on PEI::calculateFrameObjectOffsets. 952204642Srdivacky // Arguments are always 32-bit. 953204642Srdivacky unsigned ArgSize = VA.getLocVT().getSizeInBits()/8; 954218893Sdim unsigned StackLoc = VA.getLocMemOffset() + 4; 955210299Sed int FI = MFI->CreateFixedObject(ArgSize, 0, true); 956218893Sdim MBlazeFI->recordLoadArgsFI(FI, -StackLoc); 957218893Sdim MBlazeFI->recordLiveIn(FI); 958204642Srdivacky 959204642Srdivacky // Create load nodes to retrieve arguments from the stack 960204642Srdivacky SDValue FIN = DAG.getFrameIndex(FI, getPointerTy()); 961218893Sdim InVals.push_back(DAG.getLoad(VA.getValVT(), dl, Chain, FIN, 962218893Sdim MachinePointerInfo::getFixedStack(FI), 963234353Sdim false, false, false, 0)); 964204642Srdivacky } 965204642Srdivacky } 966204642Srdivacky 967204961Srdivacky // To meet ABI, when VARARGS are passed on registers, the registers 968204961Srdivacky // must have their values written to the caller stack frame. If the last 969218893Sdim // argument was placed in the stack, there's no need to save any register. 970204961Srdivacky if ((isVarArg) && ArgRegEnd) { 971204961Srdivacky if (StackPtr.getNode() == 0) 972204961Srdivacky StackPtr = DAG.getRegister(StackReg, getPointerTy()); 973204961Srdivacky 974204961Srdivacky // The last register argument that must be saved is MBlaze::R10 975239462Sdim const TargetRegisterClass *RC = &MBlaze::GPRRegClass; 976204961Srdivacky 977226633Sdim unsigned Begin = getMBlazeRegisterNumbering(MBlaze::R5); 978226633Sdim unsigned Start = getMBlazeRegisterNumbering(ArgRegEnd+1); 979226633Sdim unsigned End = getMBlazeRegisterNumbering(MBlaze::R10); 980218893Sdim unsigned StackLoc = Start - Begin + 1; 981204961Srdivacky 982204961Srdivacky for (; Start <= End; ++Start, ++StackLoc) { 983226633Sdim unsigned Reg = getMBlazeRegisterFromNumbering(Start); 984219077Sdim unsigned LiveReg = MF.addLiveIn(Reg, RC); 985204961Srdivacky SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, LiveReg, MVT::i32); 986204961Srdivacky 987210299Sed int FI = MFI->CreateFixedObject(4, 0, true); 988218893Sdim MBlazeFI->recordStoreVarArgsFI(FI, -(StackLoc*4)); 989204961Srdivacky SDValue PtrOff = DAG.getFrameIndex(FI, getPointerTy()); 990218893Sdim OutChains.push_back(DAG.getStore(Chain, dl, ArgValue, PtrOff, 991218893Sdim MachinePointerInfo(), 992204961Srdivacky false, false, 0)); 993204961Srdivacky 994204961Srdivacky // Record the frame index of the first variable argument 995204961Srdivacky // which is a value necessary to VASTART. 996207618Srdivacky if (!MBlazeFI->getVarArgsFrameIndex()) 997207618Srdivacky MBlazeFI->setVarArgsFrameIndex(FI); 998204961Srdivacky } 999204961Srdivacky } 1000204961Srdivacky 1001218893Sdim // All stores are grouped in one node to allow the matching between 1002204961Srdivacky // the size of Ins and InVals. This only happens when on varg functions 1003204961Srdivacky if (!OutChains.empty()) { 1004204961Srdivacky OutChains.push_back(Chain); 1005204961Srdivacky Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, 1006204961Srdivacky &OutChains[0], OutChains.size()); 1007204961Srdivacky } 1008204961Srdivacky 1009204642Srdivacky return Chain; 1010204642Srdivacky} 1011204642Srdivacky 1012204642Srdivacky//===----------------------------------------------------------------------===// 1013204642Srdivacky// Return Value Calling Convention Implementation 1014204642Srdivacky//===----------------------------------------------------------------------===// 1015204642Srdivacky 1016204642SrdivackySDValue MBlazeTargetLowering:: 1017204642SrdivackyLowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, 1018204642Srdivacky const SmallVectorImpl<ISD::OutputArg> &Outs, 1019210299Sed const SmallVectorImpl<SDValue> &OutVals, 1020207618Srdivacky DebugLoc dl, SelectionDAG &DAG) const { 1021204642Srdivacky // CCValAssign - represent the assignment of 1022204642Srdivacky // the return value to a location 1023204642Srdivacky SmallVector<CCValAssign, 16> RVLocs; 1024204642Srdivacky 1025204642Srdivacky // CCState - Info about the registers and stack slot. 1026223017Sdim CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), 1027239462Sdim getTargetMachine(), RVLocs, *DAG.getContext()); 1028204642Srdivacky 1029204642Srdivacky // Analize return values. 1030204642Srdivacky CCInfo.AnalyzeReturn(Outs, RetCC_MBlaze); 1031204642Srdivacky 1032204642Srdivacky SDValue Flag; 1033249423Sdim SmallVector<SDValue, 4> RetOps(1, Chain); 1034204642Srdivacky 1035249423Sdim // If this function is using the interrupt_handler calling convention 1036249423Sdim // then use "rtid r14, 0" otherwise use "rtsd r15, 8" 1037249423Sdim unsigned Ret = (CallConv == CallingConv::MBLAZE_INTR) ? MBlazeISD::IRet 1038249423Sdim : MBlazeISD::Ret; 1039249423Sdim unsigned Reg = (CallConv == CallingConv::MBLAZE_INTR) ? MBlaze::R14 1040249423Sdim : MBlaze::R15; 1041249423Sdim RetOps.push_back(DAG.getRegister(Reg, MVT::i32)); 1042249423Sdim 1043249423Sdim 1044204642Srdivacky // Copy the result values into the output registers. 1045204642Srdivacky for (unsigned i = 0; i != RVLocs.size(); ++i) { 1046204642Srdivacky CCValAssign &VA = RVLocs[i]; 1047204642Srdivacky assert(VA.isRegLoc() && "Can only return in registers!"); 1048204642Srdivacky 1049204642Srdivacky Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), 1050210299Sed OutVals[i], Flag); 1051204642Srdivacky 1052204642Srdivacky // guarantee that all emitted copies are 1053204642Srdivacky // stuck together, avoiding something bad 1054204642Srdivacky Flag = Chain.getValue(1); 1055249423Sdim RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); 1056204642Srdivacky } 1057204642Srdivacky 1058249423Sdim RetOps[0] = Chain; // Update chain. 1059218893Sdim 1060249423Sdim // Add the flag if we have it. 1061204642Srdivacky if (Flag.getNode()) 1062249423Sdim RetOps.push_back(Flag); 1063218893Sdim 1064249423Sdim return DAG.getNode(Ret, dl, MVT::Other, &RetOps[0], RetOps.size()); 1065204642Srdivacky} 1066204642Srdivacky 1067204642Srdivacky//===----------------------------------------------------------------------===// 1068204642Srdivacky// MBlaze Inline Assembly Support 1069204642Srdivacky//===----------------------------------------------------------------------===// 1070204642Srdivacky 1071204642Srdivacky/// getConstraintType - Given a constraint letter, return the type of 1072204642Srdivacky/// constraint it is for this target. 1073204642SrdivackyMBlazeTargetLowering::ConstraintType MBlazeTargetLowering:: 1074204642SrdivackygetConstraintType(const std::string &Constraint) const 1075204642Srdivacky{ 1076204642Srdivacky // MBlaze specific constrainy 1077204642Srdivacky // 1078204642Srdivacky // 'd' : An address register. Equivalent to r. 1079204642Srdivacky // 'y' : Equivalent to r; retained for 1080204642Srdivacky // backwards compatibility. 1081204642Srdivacky // 'f' : Floating Point registers. 1082204642Srdivacky if (Constraint.size() == 1) { 1083204642Srdivacky switch (Constraint[0]) { 1084204642Srdivacky default : break; 1085204642Srdivacky case 'd': 1086204642Srdivacky case 'y': 1087204642Srdivacky case 'f': 1088204642Srdivacky return C_RegisterClass; 1089204642Srdivacky } 1090204642Srdivacky } 1091204642Srdivacky return TargetLowering::getConstraintType(Constraint); 1092204642Srdivacky} 1093204642Srdivacky 1094218893Sdim/// Examine constraint type and operand type and determine a weight value. 1095218893Sdim/// This object must already have been set up with the operand type 1096218893Sdim/// and the current alternative constraint selected. 1097218893SdimTargetLowering::ConstraintWeight 1098218893SdimMBlazeTargetLowering::getSingleConstraintMatchWeight( 1099218893Sdim AsmOperandInfo &info, const char *constraint) const { 1100218893Sdim ConstraintWeight weight = CW_Invalid; 1101218893Sdim Value *CallOperandVal = info.CallOperandVal; 1102218893Sdim // If we don't have a value, we can't do a match, 1103218893Sdim // but allow it at the lowest weight. 1104218893Sdim if (CallOperandVal == NULL) 1105218893Sdim return CW_Default; 1106226633Sdim Type *type = CallOperandVal->getType(); 1107218893Sdim // Look at the constraint type. 1108218893Sdim switch (*constraint) { 1109218893Sdim default: 1110218893Sdim weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint); 1111221345Sdim break; 1112218893Sdim case 'd': 1113218893Sdim case 'y': 1114218893Sdim if (type->isIntegerTy()) 1115218893Sdim weight = CW_Register; 1116218893Sdim break; 1117218893Sdim case 'f': 1118218893Sdim if (type->isFloatTy()) 1119218893Sdim weight = CW_Register; 1120218893Sdim break; 1121218893Sdim } 1122218893Sdim return weight; 1123218893Sdim} 1124218893Sdim 1125224145Sdim/// Given a register class constraint, like 'r', if this corresponds directly 1126224145Sdim/// to an LLVM register class, return a register of 0 and the register class 1127224145Sdim/// pointer. 1128204642Srdivackystd::pair<unsigned, const TargetRegisterClass*> MBlazeTargetLowering:: 1129204642SrdivackygetRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const { 1130204642Srdivacky if (Constraint.size() == 1) { 1131204642Srdivacky switch (Constraint[0]) { 1132204642Srdivacky case 'r': 1133239462Sdim return std::make_pair(0U, &MBlaze::GPRRegClass); 1134224145Sdim // TODO: These can't possibly be right, but match what was in 1135224145Sdim // getRegClassForInlineAsmConstraint. 1136224145Sdim case 'd': 1137224145Sdim case 'y': 1138204642Srdivacky case 'f': 1139204642Srdivacky if (VT == MVT::f32) 1140239462Sdim return std::make_pair(0U, &MBlaze::GPRRegClass); 1141204642Srdivacky } 1142204642Srdivacky } 1143204642Srdivacky return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT); 1144204642Srdivacky} 1145204642Srdivacky 1146204642Srdivackybool MBlazeTargetLowering:: 1147204642SrdivackyisOffsetFoldingLegal(const GlobalAddressSDNode *GA) const { 1148204642Srdivacky // The MBlaze target isn't yet aware of offsets. 1149204642Srdivacky return false; 1150204642Srdivacky} 1151204642Srdivacky 1152204642Srdivackybool MBlazeTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT) const { 1153204642Srdivacky return VT != MVT::f32; 1154204642Srdivacky} 1155