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