1139825Simp//===-- Mips16ISelLowering.h - Mips16 DAG Lowering Interface ----*- C++ -*-===// 249076Swpaul// 349076Swpaul// The LLVM Compiler Infrastructure 449076Swpaul// 549076Swpaul// This file is distributed under the University of Illinois Open Source 649076Swpaul// License. See LICENSE.TXT for details. 749076Swpaul// 849076Swpaul//===----------------------------------------------------------------------===// 949076Swpaul// 1049076Swpaul// Subclass of MipsTargetLowering specialized for mips16. 1149076Swpaul// 1249076Swpaul//===----------------------------------------------------------------------===// 1349076Swpaul#define DEBUG_TYPE "mips-lower" 1449076Swpaul#include "Mips16ISelLowering.h" 1549076Swpaul#include "MipsRegisterInfo.h" 1649076Swpaul#include "MipsTargetMachine.h" 1749076Swpaul#include "MCTargetDesc/MipsBaseInfo.h" 1849076Swpaul#include "llvm/CodeGen/MachineInstrBuilder.h" 1949076Swpaul#include "llvm/Support/CommandLine.h" 2049076Swpaul#include "llvm/Target/TargetInstrInfo.h" 2149076Swpaul 2249076Swpaulusing namespace llvm; 2349076Swpaul 2449076Swpaulstatic cl::opt<bool> DontExpandCondPseudos16( 2549076Swpaul "mips16-dont-expand-cond-pseudo", 2649076Swpaul cl::init(false), 2749076Swpaul cl::desc("Dont expand conditional move related " 2849076Swpaul "pseudos for Mips 16"), 2949076Swpaul cl::Hidden); 3049076Swpaul 3149076Swpaulnamespace { 3250477Speterstruct Mips16Libcall { 3349076Swpaul RTLIB::Libcall Libcall; 3449076Swpaul const char *Name; 3549076Swpaul 3649076Swpaul bool operator<(const Mips16Libcall &RHS) const { 3749076Swpaul return std::strcmp(Name, RHS.Name) < 0; 3849076Swpaul } 3949076Swpaul}; 4049076Swpaul 4149076Swpaulstruct Mips16IntrinsicHelperType{ 4249076Swpaul const char* Name; 4349076Swpaul const char* Helper; 4449076Swpaul 4549076Swpaul bool operator<(const Mips16IntrinsicHelperType &RHS) const { 4649076Swpaul return std::strcmp(Name, RHS.Name) < 0; 4749076Swpaul } 4849076Swpaul bool operator==(const Mips16IntrinsicHelperType &RHS) const { 4949076Swpaul return std::strcmp(Name, RHS.Name) == 0; 5049076Swpaul } 5149076Swpaul}; 5249076Swpaul} 5349076Swpaul 5449076Swpaul// Libcalls for which no helper is generated. Sorted by name for binary search. 5549076Swpaulstatic const Mips16Libcall HardFloatLibCalls[] = { 5649076Swpaul { RTLIB::ADD_F64, "__mips16_adddf3" }, 5749076Swpaul { RTLIB::ADD_F32, "__mips16_addsf3" }, 5849076Swpaul { RTLIB::DIV_F64, "__mips16_divdf3" }, 5949076Swpaul { RTLIB::DIV_F32, "__mips16_divsf3" }, 6049076Swpaul { RTLIB::OEQ_F64, "__mips16_eqdf2" }, 6149076Swpaul { RTLIB::OEQ_F32, "__mips16_eqsf2" }, 6249076Swpaul { RTLIB::FPEXT_F32_F64, "__mips16_extendsfdf2" }, 6353468Swpaul { RTLIB::FPTOSINT_F64_I32, "__mips16_fix_truncdfsi" }, 6453468Swpaul { RTLIB::FPTOSINT_F32_I32, "__mips16_fix_truncsfsi" }, 6553468Swpaul { RTLIB::SINTTOFP_I32_F64, "__mips16_floatsidf" }, 6649076Swpaul { RTLIB::SINTTOFP_I32_F32, "__mips16_floatsisf" }, 6749076Swpaul { RTLIB::UINTTOFP_I32_F64, "__mips16_floatunsidf" }, 6849076Swpaul { RTLIB::UINTTOFP_I32_F32, "__mips16_floatunsisf" }, 6949076Swpaul { RTLIB::OGE_F64, "__mips16_gedf2" }, 7053468Swpaul { RTLIB::OGE_F32, "__mips16_gesf2" }, 7153468Swpaul { RTLIB::OGT_F64, "__mips16_gtdf2" }, 7249076Swpaul { RTLIB::OGT_F32, "__mips16_gtsf2" }, 7349076Swpaul { RTLIB::OLE_F64, "__mips16_ledf2" }, 7449076Swpaul { RTLIB::OLE_F32, "__mips16_lesf2" }, 7549076Swpaul { RTLIB::OLT_F64, "__mips16_ltdf2" }, 7649076Swpaul { RTLIB::OLT_F32, "__mips16_ltsf2" }, 7749076Swpaul { RTLIB::MUL_F64, "__mips16_muldf3" }, 7849076Swpaul { RTLIB::MUL_F32, "__mips16_mulsf3" }, 7949076Swpaul { RTLIB::UNE_F64, "__mips16_nedf2" }, 8049076Swpaul { RTLIB::UNE_F32, "__mips16_nesf2" }, 8149076Swpaul { RTLIB::UNKNOWN_LIBCALL, "__mips16_ret_dc" }, // No associated libcall. 8249076Swpaul { RTLIB::UNKNOWN_LIBCALL, "__mips16_ret_df" }, // No associated libcall. 8349076Swpaul { RTLIB::UNKNOWN_LIBCALL, "__mips16_ret_sc" }, // No associated libcall. 8449076Swpaul { RTLIB::UNKNOWN_LIBCALL, "__mips16_ret_sf" }, // No associated libcall. 8549076Swpaul { RTLIB::SUB_F64, "__mips16_subdf3" }, 8649076Swpaul { RTLIB::SUB_F32, "__mips16_subsf3" }, 8749076Swpaul { RTLIB::FPROUND_F64_F32, "__mips16_truncdfsf2" }, 8849076Swpaul { RTLIB::UO_F64, "__mips16_unorddf2" }, 8949076Swpaul { RTLIB::UO_F32, "__mips16_unordsf2" } 9049076Swpaul}; 9149076Swpaul 9249076Swpaulstatic const Mips16IntrinsicHelperType Mips16IntrinsicHelper[] = { 9349076Swpaul {"__fixunsdfsi", "__mips16_call_stub_2" }, 9449076Swpaul {"ceil", "__mips16_call_stub_df_2"}, 9549076Swpaul {"ceilf", "__mips16_call_stub_sf_1"}, 9649076Swpaul {"copysign", "__mips16_call_stub_df_10"}, 9749076Swpaul {"copysignf", "__mips16_call_stub_sf_5"}, 9849076Swpaul {"cos", "__mips16_call_stub_df_2"}, 9949076Swpaul {"cosf", "__mips16_call_stub_sf_1"}, 10049076Swpaul {"exp2", "__mips16_call_stub_df_2"}, 10149076Swpaul {"exp2f", "__mips16_call_stub_sf_1"}, 10249076Swpaul {"floor", "__mips16_call_stub_df_2"}, 10349076Swpaul {"floorf", "__mips16_call_stub_sf_1"}, 10449076Swpaul {"log2", "__mips16_call_stub_df_2"}, 10549076Swpaul {"log2f", "__mips16_call_stub_sf_1"}, 10649076Swpaul {"nearbyint", "__mips16_call_stub_df_2"}, 10749076Swpaul {"nearbyintf", "__mips16_call_stub_sf_1"}, 10849076Swpaul {"rint", "__mips16_call_stub_df_2"}, 10949076Swpaul {"rintf", "__mips16_call_stub_sf_1"}, 11049076Swpaul {"sin", "__mips16_call_stub_df_2"}, 11149076Swpaul {"sinf", "__mips16_call_stub_sf_1"}, 11249076Swpaul {"sqrt", "__mips16_call_stub_df_2"}, 11349076Swpaul {"sqrtf", "__mips16_call_stub_sf_1"}, 11449076Swpaul {"trunc", "__mips16_call_stub_df_2"}, 11549076Swpaul {"truncf", "__mips16_call_stub_sf_1"}, 11649076Swpaul}; 11749076Swpaul 11849076SwpaulMips16TargetLowering::Mips16TargetLowering(MipsTargetMachine &TM) 11949076Swpaul : MipsTargetLowering(TM) { 12049076Swpaul // 12149076Swpaul // set up as if mips32 and then revert so we can test the mechanism 12249076Swpaul // for switching 12349076Swpaul addRegisterClass(MVT::i32, &Mips::GPR32RegClass); 12449076Swpaul addRegisterClass(MVT::f32, &Mips::FGR32RegClass); 12549076Swpaul computeRegisterProperties(); 12649076Swpaul clearRegisterClasses(); 12749076Swpaul 12849076Swpaul // Set up the register classes 12949076Swpaul addRegisterClass(MVT::i32, &Mips::CPU16RegsRegClass); 13049076Swpaul 13149076Swpaul if (Subtarget->inMips16HardFloat()) 13249076Swpaul setMips16HardFloatLibCalls(); 13349076Swpaul 13449076Swpaul setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Expand); 13549076Swpaul setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i32, Expand); 13649076Swpaul setOperationAction(ISD::ATOMIC_SWAP, MVT::i32, Expand); 13749076Swpaul setOperationAction(ISD::ATOMIC_LOAD_ADD, MVT::i32, Expand); 13849076Swpaul setOperationAction(ISD::ATOMIC_LOAD_SUB, MVT::i32, Expand); 13949076Swpaul setOperationAction(ISD::ATOMIC_LOAD_AND, MVT::i32, Expand); 14049076Swpaul setOperationAction(ISD::ATOMIC_LOAD_OR, MVT::i32, Expand); 14149076Swpaul setOperationAction(ISD::ATOMIC_LOAD_XOR, MVT::i32, Expand); 14249076Swpaul setOperationAction(ISD::ATOMIC_LOAD_NAND, MVT::i32, Expand); 14349076Swpaul setOperationAction(ISD::ATOMIC_LOAD_MIN, MVT::i32, Expand); 14449076Swpaul setOperationAction(ISD::ATOMIC_LOAD_MAX, MVT::i32, Expand); 14549076Swpaul setOperationAction(ISD::ATOMIC_LOAD_UMIN, MVT::i32, Expand); 14649076Swpaul setOperationAction(ISD::ATOMIC_LOAD_UMAX, MVT::i32, Expand); 14749076Swpaul 14849076Swpaul setOperationAction(ISD::ROTR, MVT::i32, Expand); 14949076Swpaul setOperationAction(ISD::ROTR, MVT::i64, Expand); 15049076Swpaul setOperationAction(ISD::BSWAP, MVT::i32, Expand); 15149076Swpaul setOperationAction(ISD::BSWAP, MVT::i64, Expand); 15249076Swpaul 15349076Swpaul computeRegisterProperties(); 15449076Swpaul} 15549076Swpaul 15649076Swpaulconst MipsTargetLowering * 15749076Swpaulllvm::createMips16TargetLowering(MipsTargetMachine &TM) { 15849076Swpaul return new Mips16TargetLowering(TM); 15949076Swpaul} 16049076Swpaul 16149076Swpaulbool 16249076SwpaulMips16TargetLowering::allowsUnalignedMemoryAccesses(EVT VT, bool *Fast) const { 16349076Swpaul return false; 16449076Swpaul} 16549076Swpaul 16649076SwpaulMachineBasicBlock * 16749076SwpaulMips16TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, 16849076Swpaul MachineBasicBlock *BB) const { 16949076Swpaul switch (MI->getOpcode()) { 17049076Swpaul default: 17149076Swpaul return MipsTargetLowering::EmitInstrWithCustomInserter(MI, BB); 17249076Swpaul case Mips::SelBeqZ: 17349076Swpaul return emitSel16(Mips::BeqzRxImm16, MI, BB); 17449076Swpaul case Mips::SelBneZ: 17549076Swpaul return emitSel16(Mips::BnezRxImm16, MI, BB); 17649076Swpaul case Mips::SelTBteqZCmpi: 17749076Swpaul return emitSeliT16(Mips::Bteqz16, Mips::CmpiRxImmX16, MI, BB); 17849076Swpaul case Mips::SelTBteqZSlti: 17949076Swpaul return emitSeliT16(Mips::Bteqz16, Mips::SltiRxImmX16, MI, BB); 18049076Swpaul case Mips::SelTBteqZSltiu: 18149076Swpaul return emitSeliT16(Mips::Bteqz16, Mips::SltiuRxImmX16, MI, BB); 18249076Swpaul case Mips::SelTBtneZCmpi: 18349076Swpaul return emitSeliT16(Mips::Btnez16, Mips::CmpiRxImmX16, MI, BB); 18449076Swpaul case Mips::SelTBtneZSlti: 18549076Swpaul return emitSeliT16(Mips::Btnez16, Mips::SltiRxImmX16, MI, BB); 18649076Swpaul case Mips::SelTBtneZSltiu: 18749076Swpaul return emitSeliT16(Mips::Btnez16, Mips::SltiuRxImmX16, MI, BB); 18849076Swpaul case Mips::SelTBteqZCmp: 18949076Swpaul return emitSelT16(Mips::Bteqz16, Mips::CmpRxRy16, MI, BB); 19049076Swpaul case Mips::SelTBteqZSlt: 19149076Swpaul return emitSelT16(Mips::Bteqz16, Mips::SltRxRy16, MI, BB); 19249076Swpaul case Mips::SelTBteqZSltu: 19349076Swpaul return emitSelT16(Mips::Bteqz16, Mips::SltuRxRy16, MI, BB); 19449076Swpaul case Mips::SelTBtneZCmp: 19549076Swpaul return emitSelT16(Mips::Btnez16, Mips::CmpRxRy16, MI, BB); 19649076Swpaul case Mips::SelTBtneZSlt: 19749076Swpaul return emitSelT16(Mips::Btnez16, Mips::SltRxRy16, MI, BB); 19849076Swpaul case Mips::SelTBtneZSltu: 199175526Syongari return emitSelT16(Mips::Btnez16, Mips::SltuRxRy16, MI, BB); 20049076Swpaul case Mips::BteqzT8CmpX16: 20149076Swpaul return emitFEXT_T8I816_ins(Mips::Bteqz16, Mips::CmpRxRy16, MI, BB); 20249076Swpaul case Mips::BteqzT8SltX16: 20349076Swpaul return emitFEXT_T8I816_ins(Mips::Bteqz16, Mips::SltRxRy16, MI, BB); 20449076Swpaul case Mips::BteqzT8SltuX16: 205175526Syongari // TBD: figure out a way to get this or remove the instruction 20649076Swpaul // altogether. 20749076Swpaul return emitFEXT_T8I816_ins(Mips::Bteqz16, Mips::SltuRxRy16, MI, BB); 20849076Swpaul case Mips::BtnezT8CmpX16: 20949076Swpaul return emitFEXT_T8I816_ins(Mips::Btnez16, Mips::CmpRxRy16, MI, BB); 21049076Swpaul case Mips::BtnezT8SltX16: 21149076Swpaul return emitFEXT_T8I816_ins(Mips::Btnez16, Mips::SltRxRy16, MI, BB); 21249076Swpaul case Mips::BtnezT8SltuX16: 21349076Swpaul // TBD: figure out a way to get this or remove the instruction 21449076Swpaul // altogether. 215175526Syongari return emitFEXT_T8I816_ins(Mips::Btnez16, Mips::SltuRxRy16, MI, BB); 21649076Swpaul case Mips::BteqzT8CmpiX16: return emitFEXT_T8I8I16_ins( 21749076Swpaul Mips::Bteqz16, Mips::CmpiRxImm16, Mips::CmpiRxImmX16, false, MI, BB); 21849076Swpaul case Mips::BteqzT8SltiX16: return emitFEXT_T8I8I16_ins( 21949076Swpaul Mips::Bteqz16, Mips::SltiRxImm16, Mips::SltiRxImmX16, true, MI, BB); 22049076Swpaul case Mips::BteqzT8SltiuX16: return emitFEXT_T8I8I16_ins( 22149076Swpaul Mips::Bteqz16, Mips::SltiuRxImm16, Mips::SltiuRxImmX16, false, MI, BB); 22249076Swpaul case Mips::BtnezT8CmpiX16: return emitFEXT_T8I8I16_ins( 22349076Swpaul Mips::Btnez16, Mips::CmpiRxImm16, Mips::CmpiRxImmX16, false, MI, BB); 22449076Swpaul case Mips::BtnezT8SltiX16: return emitFEXT_T8I8I16_ins( 22549076Swpaul Mips::Btnez16, Mips::SltiRxImm16, Mips::SltiRxImmX16, true, MI, BB); 22649076Swpaul case Mips::BtnezT8SltiuX16: return emitFEXT_T8I8I16_ins( 22749076Swpaul Mips::Btnez16, Mips::SltiuRxImm16, Mips::SltiuRxImmX16, false, MI, BB); 22849076Swpaul break; 22949076Swpaul case Mips::SltCCRxRy16: 23049076Swpaul return emitFEXT_CCRX16_ins(Mips::SltRxRy16, MI, BB); 23149076Swpaul break; 23249076Swpaul case Mips::SltiCCRxImmX16: 23349076Swpaul return emitFEXT_CCRXI16_ins 23449076Swpaul (Mips::SltiRxImm16, Mips::SltiRxImmX16, MI, BB); 23549076Swpaul case Mips::SltiuCCRxImmX16: 23649076Swpaul return emitFEXT_CCRXI16_ins 23749076Swpaul (Mips::SltiuRxImm16, Mips::SltiuRxImmX16, MI, BB); 23849076Swpaul case Mips::SltuCCRxRy16: 23949076Swpaul return emitFEXT_CCRX16_ins 24049076Swpaul (Mips::SltuRxRy16, MI, BB); 24149076Swpaul } 24249076Swpaul} 24349076Swpaul 24449076Swpaulbool Mips16TargetLowering:: 24549076SwpaulisEligibleForTailCallOptimization(const MipsCC &MipsCCInfo, 24649076Swpaul unsigned NextStackOffset, 24749076Swpaul const MipsFunctionInfo& FI) const { 24849076Swpaul // No tail call optimization for mips16. 24949076Swpaul return false; 25049076Swpaul} 25149076Swpaul 252175526Syongarivoid Mips16TargetLowering::setMips16HardFloatLibCalls() { 253175526Syongari for (unsigned I = 0; I != array_lengthof(HardFloatLibCalls); ++I) { 254175526Syongari assert((I == 0 || HardFloatLibCalls[I - 1] < HardFloatLibCalls[I]) && 255175526Syongari "Array not sorted!"); 256175526Syongari if (HardFloatLibCalls[I].Libcall != RTLIB::UNKNOWN_LIBCALL) 25749076Swpaul setLibcallName(HardFloatLibCalls[I].Libcall, HardFloatLibCalls[I].Name); 25849076Swpaul } 25949076Swpaul 26049076Swpaul setLibcallName(RTLIB::O_F64, "__mips16_unorddf2"); 26149076Swpaul setLibcallName(RTLIB::O_F32, "__mips16_unordsf2"); 26249076Swpaul} 26349076Swpaul 26449076Swpaul// 26549076Swpaul// The Mips16 hard float is a crazy quilt inherited from gcc. I have a much 26649076Swpaul// cleaner way to do all of this but it will have to wait until the traditional 26749076Swpaul// gcc mechanism is completed. 26849076Swpaul// 26949076Swpaul// For Pic, in order for Mips16 code to call Mips32 code which according the abi 27049076Swpaul// have either arguments or returned values placed in floating point registers, 27149076Swpaul// we use a set of helper functions. (This includes functions which return type 27249076Swpaul// complex which on Mips are returned in a pair of floating point registers). 27349076Swpaul// 27449076Swpaul// This is an encoding that we inherited from gcc. 27549076Swpaul// In Mips traditional O32, N32 ABI, floating point numbers are passed in 27649076Swpaul// floating point argument registers 1,2 only when the first and optionally 27749076Swpaul// the second arguments are float (sf) or double (df). 27849076Swpaul// For Mips16 we are only concerned with the situations where floating point 27949076Swpaul// arguments are being passed in floating point registers by the ABI, because 28049076Swpaul// Mips16 mode code cannot execute floating point instructions to load those 28149076Swpaul// values and hence helper functions are needed. 28249076Swpaul// The possibilities are (), (sf), (sf, sf), (sf, df), (df), (df, sf), (df, df) 28349076Swpaul// the helper function suffixs for these are: 28449076Swpaul// 0, 1, 5, 9, 2, 6, 10 28549076Swpaul// this suffix can then be calculated as follows: 28649076Swpaul// for a given argument Arg: 28749076Swpaul// Arg1x, Arg2x = 1 : Arg is sf 28849076Swpaul// 2 : Arg is df 28949076Swpaul// 0: Arg is neither sf or df 29049076Swpaul// So this stub is the string for number Arg1x + Arg2x*4. 29149076Swpaul// However not all numbers between 0 and 10 are possible, we check anyway and 29249076Swpaul// assert if the impossible exists. 29349076Swpaul// 29449076Swpaul 29549076Swpaulunsigned int Mips16TargetLowering::getMips16HelperFunctionStubNumber 29649076Swpaul (ArgListTy &Args) const { 29749076Swpaul unsigned int resultNum = 0; 29849076Swpaul if (Args.size() >= 1) { 29949076Swpaul Type *t = Args[0].Ty; 30049076Swpaul if (t->isFloatTy()) { 30149076Swpaul resultNum = 1; 30249076Swpaul } 30349076Swpaul else if (t->isDoubleTy()) { 30449076Swpaul resultNum = 2; 30549076Swpaul } 30649076Swpaul } 30749076Swpaul if (resultNum) { 30849076Swpaul if (Args.size() >=2) { 30949076Swpaul Type *t = Args[1].Ty; 31049076Swpaul if (t->isFloatTy()) { 31149076Swpaul resultNum += 4; 31249076Swpaul } 31349076Swpaul else if (t->isDoubleTy()) { 31449076Swpaul resultNum += 8; 31549076Swpaul } 31649076Swpaul } 31749076Swpaul } 31849076Swpaul return resultNum; 31949076Swpaul} 32049076Swpaul 32149076Swpaul// 32249076Swpaul// prefixs are attached to stub numbers depending on the return type . 32349076Swpaul// return type: float sf_ 32449076Swpaul// double df_ 32549076Swpaul// single complex sc_ 32649076Swpaul// double complext dc_ 32749076Swpaul// others NO PREFIX 32849076Swpaul// 32949076Swpaul// 33049076Swpaul// The full name of a helper function is__mips16_call_stub + 33149076Swpaul// return type dependent prefix + stub number 33249076Swpaul// 33349076Swpaul// 33449076Swpaul// This is something that probably should be in a different source file and 33549076Swpaul// perhaps done differently but my main purpose is to not waste runtime 33649076Swpaul// on something that we can enumerate in the source. Another possibility is 33749076Swpaul// to have a python script to generate these mapping tables. This will do 33849076Swpaul// for now. There are a whole series of helper function mapping arrays, one 33949076Swpaul// for each return type class as outlined above. There there are 11 possible 34049076Swpaul// entries. Ones with 0 are ones which should never be selected 34149076Swpaul// 34249076Swpaul// All the arrays are similar except for ones which return neither 34349076Swpaul// sf, df, sc, dc, in which only care about ones which have sf or df as a 34449076Swpaul// first parameter. 34549076Swpaul// 34649076Swpaul#define P_ "__mips16_call_stub_" 34749076Swpaul#define MAX_STUB_NUMBER 10 34849076Swpaul#define T1 P "1", P "2", 0, 0, P "5", P "6", 0, 0, P "9", P "10" 34949076Swpaul#define T P "0" , T1 35049076Swpaul#define P P_ 35149076Swpaulstatic char const * vMips16Helper[MAX_STUB_NUMBER+1] = 35249076Swpaul {0, T1 }; 35349076Swpaul#undef P 35449076Swpaul#define P P_ "sf_" 355232203Skevlostatic char const * sfMips16Helper[MAX_STUB_NUMBER+1] = 35649076Swpaul { T }; 35781737Swpaul#undef P 358175526Syongari#define P P_ "df_" 359175526Syongaristatic char const * dfMips16Helper[MAX_STUB_NUMBER+1] = 36049076Swpaul { T }; 36149076Swpaul#undef P 36249076Swpaul#define P P_ "sc_" 36349076Swpaulstatic char const * scMips16Helper[MAX_STUB_NUMBER+1] = 36449076Swpaul { T }; 36549076Swpaul#undef P 36649076Swpaul#define P P_ "dc_" 36749076Swpaulstatic char const * dcMips16Helper[MAX_STUB_NUMBER+1] = 36849076Swpaul { T }; 36949076Swpaul#undef P 370175526Syongari#undef P_ 371175526Syongari 372175526Syongari 37349076Swpaulconst char* Mips16TargetLowering:: 37449076Swpaul getMips16HelperFunction 37549076Swpaul (Type* RetTy, ArgListTy &Args, bool &needHelper) const { 37649076Swpaul const unsigned int stubNum = getMips16HelperFunctionStubNumber(Args); 37749076Swpaul#ifndef NDEBUG 37849076Swpaul const unsigned int maxStubNum = 10; 37949076Swpaul assert(stubNum <= maxStubNum); 38049076Swpaul const bool validStubNum[maxStubNum+1] = 38149076Swpaul {true, true, true, false, false, true, true, false, false, true, true}; 38249076Swpaul assert(validStubNum[stubNum]); 38349076Swpaul#endif 38449076Swpaul const char *result; 38549076Swpaul if (RetTy->isFloatTy()) { 38649076Swpaul result = sfMips16Helper[stubNum]; 38749076Swpaul } 38849076Swpaul else if (RetTy ->isDoubleTy()) { 38949076Swpaul result = dfMips16Helper[stubNum]; 39049076Swpaul } 39149076Swpaul else if (RetTy->isStructTy()) { 39249076Swpaul // check if it's complex 39349076Swpaul if (RetTy->getNumContainedTypes() == 2) { 39449076Swpaul if ((RetTy->getContainedType(0)->isFloatTy()) && 39549076Swpaul (RetTy->getContainedType(1)->isFloatTy())) { 39649076Swpaul result = scMips16Helper[stubNum]; 39749076Swpaul } 39849076Swpaul else if ((RetTy->getContainedType(0)->isDoubleTy()) && 39949076Swpaul (RetTy->getContainedType(1)->isDoubleTy())) { 40049076Swpaul result = dcMips16Helper[stubNum]; 40149076Swpaul } 40249076Swpaul else { 40349076Swpaul llvm_unreachable("Uncovered condition"); 40449076Swpaul } 40549076Swpaul } 40649076Swpaul else { 40749076Swpaul llvm_unreachable("Uncovered condition"); 40849076Swpaul } 40949076Swpaul } 41049076Swpaul else { 41149076Swpaul if (stubNum == 0) { 41249076Swpaul needHelper = false; 41349076Swpaul return ""; 41449076Swpaul } 41549076Swpaul result = vMips16Helper[stubNum]; 41649076Swpaul } 41749076Swpaul needHelper = true; 41849076Swpaul return result; 41949076Swpaul} 42049076Swpaul 42149076Swpaulvoid Mips16TargetLowering:: 42249076SwpaulgetOpndList(SmallVectorImpl<SDValue> &Ops, 42349076Swpaul std::deque< std::pair<unsigned, SDValue> > &RegsToPass, 42449076Swpaul bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage, 42549076Swpaul CallLoweringInfo &CLI, SDValue Callee, SDValue Chain) const { 42649076Swpaul SelectionDAG &DAG = CLI.DAG; 42749076Swpaul MachineFunction &MF = DAG.getMachineFunction(); 42849076Swpaul MipsFunctionInfo *FuncInfo = MF.getInfo<MipsFunctionInfo>(); 42949076Swpaul const char* Mips16HelperFunction = 0; 43049076Swpaul bool NeedMips16Helper = false; 43149076Swpaul 43249076Swpaul if (getTargetMachine().Options.UseSoftFloat && 43349076Swpaul Subtarget->inMips16HardFloat()) { 43449076Swpaul // 43549076Swpaul // currently we don't have symbols tagged with the mips16 or mips32 43649076Swpaul // qualifier so we will assume that we don't know what kind it is. 43749076Swpaul // and generate the helper 43849076Swpaul // 43949076Swpaul bool LookupHelper = true; 44049076Swpaul if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(CLI.Callee)) { 44149076Swpaul Mips16Libcall Find = { RTLIB::UNKNOWN_LIBCALL, S->getSymbol() }; 44249076Swpaul 44349076Swpaul if (std::binary_search(HardFloatLibCalls, array_endof(HardFloatLibCalls), 44449076Swpaul Find)) 44549076Swpaul LookupHelper = false; 44649076Swpaul else { 44749076Swpaul Mips16IntrinsicHelperType IntrinsicFind = {S->getSymbol(), ""}; 44849076Swpaul // one more look at list of intrinsics 44949076Swpaul if (std::binary_search(Mips16IntrinsicHelper, 45049076Swpaul array_endof(Mips16IntrinsicHelper), 45149076Swpaul IntrinsicFind)) { 45249076Swpaul const Mips16IntrinsicHelperType *h =(std::find(Mips16IntrinsicHelper, 45349076Swpaul array_endof(Mips16IntrinsicHelper), 45449076Swpaul IntrinsicFind)); 45549076Swpaul Mips16HelperFunction = h->Helper; 45649076Swpaul NeedMips16Helper = true; 45749076Swpaul LookupHelper = false; 45849076Swpaul } 45949076Swpaul 46049076Swpaul } 46149076Swpaul } else if (GlobalAddressSDNode *G = 462175526Syongari dyn_cast<GlobalAddressSDNode>(CLI.Callee)) { 463175526Syongari Mips16Libcall Find = { RTLIB::UNKNOWN_LIBCALL, 46449076Swpaul G->getGlobal()->getName().data() }; 46549076Swpaul 46649076Swpaul if (std::binary_search(HardFloatLibCalls, array_endof(HardFloatLibCalls), 46749076Swpaul Find)) 46849076Swpaul LookupHelper = false; 46949076Swpaul } 47049076Swpaul if (LookupHelper) Mips16HelperFunction = 47149076Swpaul getMips16HelperFunction(CLI.RetTy, CLI.Args, NeedMips16Helper); 47249076Swpaul 47349076Swpaul } 47449076Swpaul 47549076Swpaul SDValue JumpTarget = Callee; 47649076Swpaul 47749076Swpaul // T9 should contain the address of the callee function if 47849076Swpaul // -reloction-model=pic or it is an indirect call. 47949076Swpaul if (IsPICCall || !GlobalOrExternal) { 48049076Swpaul unsigned V0Reg = Mips::V0; 48149076Swpaul if (NeedMips16Helper) { 48249076Swpaul RegsToPass.push_front(std::make_pair(V0Reg, Callee)); 48349076Swpaul JumpTarget = DAG.getExternalSymbol(Mips16HelperFunction, getPointerTy()); 48449076Swpaul ExternalSymbolSDNode *S = cast<ExternalSymbolSDNode>(JumpTarget); 48549076Swpaul JumpTarget = getAddrGlobal(S, JumpTarget.getValueType(), DAG, 48649076Swpaul MipsII::MO_GOT, Chain, 48749076Swpaul FuncInfo->callPtrInfo(S->getSymbol())); 48849076Swpaul } else 48949076Swpaul RegsToPass.push_front(std::make_pair((unsigned)Mips::T9, Callee)); 49049076Swpaul } 49149076Swpaul 49249076Swpaul Ops.push_back(JumpTarget); 49349076Swpaul 49449076Swpaul MipsTargetLowering::getOpndList(Ops, RegsToPass, IsPICCall, GlobalOrExternal, 49549076Swpaul InternalLinkage, CLI, Callee, Chain); 49649076Swpaul} 49749076Swpaul 49849076SwpaulMachineBasicBlock *Mips16TargetLowering:: 49949076SwpaulemitSel16(unsigned Opc, MachineInstr *MI, MachineBasicBlock *BB) const { 50049076Swpaul if (DontExpandCondPseudos16) 50149076Swpaul return BB; 50249076Swpaul const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); 50349076Swpaul DebugLoc DL = MI->getDebugLoc(); 50449076Swpaul // To "insert" a SELECT_CC instruction, we actually have to insert the 50549076Swpaul // diamond control-flow pattern. The incoming instruction knows the 50649076Swpaul // destination vreg to set, the condition code register to branch on, the 50749076Swpaul // true/false values to select between, and a branch opcode to use. 50849076Swpaul const BasicBlock *LLVM_BB = BB->getBasicBlock(); 50949076Swpaul MachineFunction::iterator It = BB; 51049076Swpaul ++It; 51149076Swpaul 51249076Swpaul // thisMBB: 51349076Swpaul // ... 51449076Swpaul // TrueVal = ... 51549076Swpaul // setcc r1, r2, r3 51649076Swpaul // bNE r1, r0, copy1MBB 51749076Swpaul // fallthrough --> copy0MBB 51849076Swpaul MachineBasicBlock *thisMBB = BB; 51949076Swpaul MachineFunction *F = BB->getParent(); 52049076Swpaul MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB); 52149076Swpaul MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB); 52249076Swpaul F->insert(It, copy0MBB); 52349076Swpaul F->insert(It, sinkMBB); 52449076Swpaul 52549076Swpaul // Transfer the remainder of BB and its successor edges to sinkMBB. 52649076Swpaul sinkMBB->splice(sinkMBB->begin(), BB, 52749076Swpaul llvm::next(MachineBasicBlock::iterator(MI)), 52849076Swpaul BB->end()); 52949076Swpaul sinkMBB->transferSuccessorsAndUpdatePHIs(BB); 53049076Swpaul 53149076Swpaul // Next, add the true and fallthrough blocks as its successors. 53249076Swpaul BB->addSuccessor(copy0MBB); 53349076Swpaul BB->addSuccessor(sinkMBB); 53449076Swpaul 53549076Swpaul BuildMI(BB, DL, TII->get(Opc)).addReg(MI->getOperand(3).getReg()) 53649076Swpaul .addMBB(sinkMBB); 53749076Swpaul 53849076Swpaul // copy0MBB: 53949076Swpaul // %FalseValue = ... 54049076Swpaul // # fallthrough to sinkMBB 54149076Swpaul BB = copy0MBB; 54249076Swpaul 54349076Swpaul // Update machine-CFG edges 54449076Swpaul BB->addSuccessor(sinkMBB); 54549076Swpaul 54649076Swpaul // sinkMBB: 54749076Swpaul // %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copy0MBB ] 54849076Swpaul // ... 54949076Swpaul BB = sinkMBB; 55049076Swpaul 55149076Swpaul BuildMI(*BB, BB->begin(), DL, 55249076Swpaul TII->get(Mips::PHI), MI->getOperand(0).getReg()) 55349076Swpaul .addReg(MI->getOperand(1).getReg()).addMBB(thisMBB) 55449076Swpaul .addReg(MI->getOperand(2).getReg()).addMBB(copy0MBB); 55549076Swpaul 55649076Swpaul MI->eraseFromParent(); // The pseudo instruction is gone now. 55749076Swpaul return BB; 55849076Swpaul} 55949076Swpaul 56049076SwpaulMachineBasicBlock *Mips16TargetLowering::emitSelT16 56149076Swpaul (unsigned Opc1, unsigned Opc2, 56249076Swpaul MachineInstr *MI, MachineBasicBlock *BB) const { 56349076Swpaul if (DontExpandCondPseudos16) 56449076Swpaul return BB; 56549076Swpaul const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); 56649076Swpaul DebugLoc DL = MI->getDebugLoc(); 56749076Swpaul // To "insert" a SELECT_CC instruction, we actually have to insert the 56849076Swpaul // diamond control-flow pattern. The incoming instruction knows the 56949076Swpaul // destination vreg to set, the condition code register to branch on, the 57049076Swpaul // true/false values to select between, and a branch opcode to use. 57149076Swpaul const BasicBlock *LLVM_BB = BB->getBasicBlock(); 57249076Swpaul MachineFunction::iterator It = BB; 57349076Swpaul ++It; 57449076Swpaul 57549076Swpaul // thisMBB: 57649076Swpaul // ... 57749076Swpaul // TrueVal = ... 578175526Syongari // setcc r1, r2, r3 579175526Syongari // bNE r1, r0, copy1MBB 58049076Swpaul // fallthrough --> copy0MBB 58149076Swpaul MachineBasicBlock *thisMBB = BB; 58249076Swpaul MachineFunction *F = BB->getParent(); 58349076Swpaul MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB); 58449076Swpaul MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB); 58549076Swpaul F->insert(It, copy0MBB); 58649076Swpaul F->insert(It, sinkMBB); 58749076Swpaul 58849076Swpaul // Transfer the remainder of BB and its successor edges to sinkMBB. 58949076Swpaul sinkMBB->splice(sinkMBB->begin(), BB, 59049076Swpaul llvm::next(MachineBasicBlock::iterator(MI)), 59149076Swpaul BB->end()); 59249076Swpaul sinkMBB->transferSuccessorsAndUpdatePHIs(BB); 59349076Swpaul 59449076Swpaul // Next, add the true and fallthrough blocks as its successors. 59549076Swpaul BB->addSuccessor(copy0MBB); 59649076Swpaul BB->addSuccessor(sinkMBB); 59749076Swpaul 59849076Swpaul BuildMI(BB, DL, TII->get(Opc2)).addReg(MI->getOperand(3).getReg()) 59949076Swpaul .addReg(MI->getOperand(4).getReg()); 60049076Swpaul BuildMI(BB, DL, TII->get(Opc1)).addMBB(sinkMBB); 60149076Swpaul 60249076Swpaul // copy0MBB: 60349076Swpaul // %FalseValue = ... 60449076Swpaul // # fallthrough to sinkMBB 60549076Swpaul BB = copy0MBB; 60649076Swpaul 60749076Swpaul // Update machine-CFG edges 60849076Swpaul BB->addSuccessor(sinkMBB); 60949076Swpaul 61049076Swpaul // sinkMBB: 61149076Swpaul // %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copy0MBB ] 61249076Swpaul // ... 61349076Swpaul BB = sinkMBB; 61449076Swpaul 61549076Swpaul BuildMI(*BB, BB->begin(), DL, 61649076Swpaul TII->get(Mips::PHI), MI->getOperand(0).getReg()) 61749076Swpaul .addReg(MI->getOperand(1).getReg()).addMBB(thisMBB) 61849076Swpaul .addReg(MI->getOperand(2).getReg()).addMBB(copy0MBB); 61949076Swpaul 62049076Swpaul MI->eraseFromParent(); // The pseudo instruction is gone now. 62149076Swpaul return BB; 62249076Swpaul 62349076Swpaul} 624175526Syongari 625175526SyongariMachineBasicBlock *Mips16TargetLowering::emitSeliT16 62649076Swpaul (unsigned Opc1, unsigned Opc2, 62754161Swpaul MachineInstr *MI, MachineBasicBlock *BB) const { 62854161Swpaul if (DontExpandCondPseudos16) 62954161Swpaul return BB; 63054161Swpaul const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); 63154161Swpaul DebugLoc DL = MI->getDebugLoc(); 63254161Swpaul // To "insert" a SELECT_CC instruction, we actually have to insert the 63354161Swpaul // diamond control-flow pattern. The incoming instruction knows the 63454161Swpaul // destination vreg to set, the condition code register to branch on, the 63549076Swpaul // true/false values to select between, and a branch opcode to use. 63649076Swpaul const BasicBlock *LLVM_BB = BB->getBasicBlock(); 63749076Swpaul MachineFunction::iterator It = BB; 63849076Swpaul ++It; 63949076Swpaul 64049076Swpaul // thisMBB: 64149076Swpaul // ... 64249076Swpaul // TrueVal = ... 64349076Swpaul // setcc r1, r2, r3 64449076Swpaul // bNE r1, r0, copy1MBB 64549076Swpaul // fallthrough --> copy0MBB 64649076Swpaul MachineBasicBlock *thisMBB = BB; 64749076Swpaul MachineFunction *F = BB->getParent(); 64849076Swpaul MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB); 64949076Swpaul MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB); 65049076Swpaul F->insert(It, copy0MBB); 65149076Swpaul F->insert(It, sinkMBB); 65249076Swpaul 65349076Swpaul // Transfer the remainder of BB and its successor edges to sinkMBB. 65449076Swpaul sinkMBB->splice(sinkMBB->begin(), BB, 65549076Swpaul llvm::next(MachineBasicBlock::iterator(MI)), 656175526Syongari BB->end()); 657175526Syongari sinkMBB->transferSuccessorsAndUpdatePHIs(BB); 658175526Syongari 659175526Syongari // Next, add the true and fallthrough blocks as its successors. 660175526Syongari BB->addSuccessor(copy0MBB); 661175526Syongari BB->addSuccessor(sinkMBB); 662175526Syongari 663175526Syongari BuildMI(BB, DL, TII->get(Opc2)).addReg(MI->getOperand(3).getReg()) 664175526Syongari .addImm(MI->getOperand(4).getImm()); 665175526Syongari BuildMI(BB, DL, TII->get(Opc1)).addMBB(sinkMBB); 666175526Syongari 667175526Syongari // copy0MBB: 668175526Syongari // %FalseValue = ... 669175526Syongari // # fallthrough to sinkMBB 670175526Syongari BB = copy0MBB; 671175526Syongari 672175526Syongari // Update machine-CFG edges 673175526Syongari BB->addSuccessor(sinkMBB); 674175526Syongari 675175526Syongari // sinkMBB: 676175526Syongari // %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copy0MBB ] 677175526Syongari // ... 678175526Syongari BB = sinkMBB; 679175526Syongari 680175526Syongari BuildMI(*BB, BB->begin(), DL, 681175526Syongari TII->get(Mips::PHI), MI->getOperand(0).getReg()) 682175526Syongari .addReg(MI->getOperand(1).getReg()).addMBB(thisMBB) 683175526Syongari .addReg(MI->getOperand(2).getReg()).addMBB(copy0MBB); 684175526Syongari 685175526Syongari MI->eraseFromParent(); // The pseudo instruction is gone now. 686175526Syongari return BB; 687175526Syongari 688175526Syongari} 689175526Syongari 69049076SwpaulMachineBasicBlock 69149076Swpaul *Mips16TargetLowering::emitFEXT_T8I816_ins(unsigned BtOpc, unsigned CmpOpc, 69249076Swpaul MachineInstr *MI, 693175526Syongari MachineBasicBlock *BB) const { 694175526Syongari if (DontExpandCondPseudos16) 69549076Swpaul return BB; 696175526Syongari const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); 697175526Syongari unsigned regX = MI->getOperand(0).getReg(); 69849076Swpaul unsigned regY = MI->getOperand(1).getReg(); 69949076Swpaul MachineBasicBlock *target = MI->getOperand(2).getMBB(); 70049076Swpaul BuildMI(*BB, MI, MI->getDebugLoc(), TII->get(CmpOpc)).addReg(regX) 701175526Syongari .addReg(regY); 702175526Syongari BuildMI(*BB, MI, MI->getDebugLoc(), TII->get(BtOpc)).addMBB(target); 70349076Swpaul MI->eraseFromParent(); // The pseudo instruction is gone now. 70449076Swpaul return BB; 70549076Swpaul} 70649076Swpaul 70749076SwpaulMachineBasicBlock *Mips16TargetLowering::emitFEXT_T8I8I16_ins( 70849076Swpaul unsigned BtOpc, unsigned CmpiOpc, unsigned CmpiXOpc, bool ImmSigned, 70949076Swpaul MachineInstr *MI, MachineBasicBlock *BB) const { 71049076Swpaul if (DontExpandCondPseudos16) 71149076Swpaul return BB; 71249076Swpaul const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); 71349076Swpaul unsigned regX = MI->getOperand(0).getReg(); 71449076Swpaul int64_t imm = MI->getOperand(1).getImm(); 71549076Swpaul MachineBasicBlock *target = MI->getOperand(2).getMBB(); 71649076Swpaul unsigned CmpOpc; 717175526Syongari if (isUInt<8>(imm)) 71849076Swpaul CmpOpc = CmpiOpc; 71949076Swpaul else if ((!ImmSigned && isUInt<16>(imm)) || 720175526Syongari (ImmSigned && isInt<16>(imm))) 721175526Syongari CmpOpc = CmpiXOpc; 722175526Syongari else 72349076Swpaul llvm_unreachable("immediate field not usable"); 72449076Swpaul BuildMI(*BB, MI, MI->getDebugLoc(), TII->get(CmpOpc)).addReg(regX) 72549076Swpaul .addImm(imm); 726175526Syongari BuildMI(*BB, MI, MI->getDebugLoc(), TII->get(BtOpc)).addMBB(target); 72749076Swpaul MI->eraseFromParent(); // The pseudo instruction is gone now. 72849076Swpaul return BB; 729175526Syongari} 73049076Swpaul 73149076Swpaulstatic unsigned Mips16WhichOp8uOr16simm 73249076Swpaul (unsigned shortOp, unsigned longOp, int64_t Imm) { 73349076Swpaul if (isUInt<8>(Imm)) 73449076Swpaul return shortOp; 73549076Swpaul else if (isInt<16>(Imm)) 736175526Syongari return longOp; 737175526Syongari else 738175526Syongari llvm_unreachable("immediate field not usable"); 739175526Syongari} 740175526Syongari 74149076SwpaulMachineBasicBlock *Mips16TargetLowering::emitFEXT_CCRX16_ins( 74249076Swpaul unsigned SltOpc, 74349076Swpaul MachineInstr *MI, MachineBasicBlock *BB) const { 74449076Swpaul if (DontExpandCondPseudos16) 74549076Swpaul return BB; 74649076Swpaul const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); 74749076Swpaul unsigned CC = MI->getOperand(0).getReg(); 748175526Syongari unsigned regX = MI->getOperand(1).getReg(); 749175526Syongari unsigned regY = MI->getOperand(2).getReg(); 750175526Syongari BuildMI(*BB, MI, MI->getDebugLoc(), 751175526Syongari TII->get(SltOpc)).addReg(regX).addReg(regY); 75249076Swpaul BuildMI(*BB, MI, MI->getDebugLoc(), 75349076Swpaul TII->get(Mips::MoveR3216), CC).addReg(Mips::T8); 75449076Swpaul MI->eraseFromParent(); // The pseudo instruction is gone now. 75549076Swpaul return BB; 75649076Swpaul} 75749076Swpaul 75849076SwpaulMachineBasicBlock *Mips16TargetLowering::emitFEXT_CCRXI16_ins( 759175526Syongari unsigned SltiOpc, unsigned SltiXOpc, 760175526Syongari MachineInstr *MI, MachineBasicBlock *BB )const { 761175526Syongari if (DontExpandCondPseudos16) 76249076Swpaul return BB; 76349076Swpaul const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); 76449076Swpaul unsigned CC = MI->getOperand(0).getReg(); 76549076Swpaul unsigned regX = MI->getOperand(1).getReg(); 76649076Swpaul int64_t Imm = MI->getOperand(2).getImm(); 76749076Swpaul unsigned SltOpc = Mips16WhichOp8uOr16simm(SltiOpc, SltiXOpc, Imm); 76849076Swpaul BuildMI(*BB, MI, MI->getDebugLoc(), 769175526Syongari TII->get(SltOpc)).addReg(regX).addImm(Imm); 770175526Syongari BuildMI(*BB, MI, MI->getDebugLoc(), 771175526Syongari TII->get(Mips::MoveR3216), CC).addReg(Mips::T8); 772175526Syongari MI->eraseFromParent(); // The pseudo instruction is gone now. 773175526Syongari return BB; 774175526Syongari 77549076Swpaul} 77649076Swpaul