1249259Sdim//===-- Mips16ISelLowering.h - Mips16 DAG Lowering Interface ----*- C++ -*-===//
2249259Sdim//
3249259Sdim//                     The LLVM Compiler Infrastructure
4249259Sdim//
5249259Sdim// This file is distributed under the University of Illinois Open Source
6249259Sdim// License. See LICENSE.TXT for details.
7249259Sdim//
8249259Sdim//===----------------------------------------------------------------------===//
9249259Sdim//
10249259Sdim// Subclass of MipsTargetLowering specialized for mips16.
11249259Sdim//
12249259Sdim//===----------------------------------------------------------------------===//
13249259Sdim#define DEBUG_TYPE "mips-lower"
14249259Sdim#include "Mips16ISelLowering.h"
15249259Sdim#include "MipsRegisterInfo.h"
16263508Sdim#include "MipsTargetMachine.h"
17249259Sdim#include "MCTargetDesc/MipsBaseInfo.h"
18249259Sdim#include "llvm/CodeGen/MachineInstrBuilder.h"
19249259Sdim#include "llvm/Support/CommandLine.h"
20249259Sdim#include "llvm/Target/TargetInstrInfo.h"
21249259Sdim
22249259Sdimusing namespace llvm;
23249259Sdim
24249259Sdimstatic cl::opt<bool> DontExpandCondPseudos16(
25249259Sdim  "mips16-dont-expand-cond-pseudo",
26249259Sdim  cl::init(false),
27249259Sdim  cl::desc("Dont expand conditional move related "
28249259Sdim           "pseudos for Mips 16"),
29249259Sdim  cl::Hidden);
30249259Sdim
31249259Sdimnamespace {
32263508Sdimstruct Mips16Libcall {
33263508Sdim  RTLIB::Libcall Libcall;
34263508Sdim  const char *Name;
35263508Sdim
36263508Sdim  bool operator<(const Mips16Libcall &RHS) const {
37263508Sdim    return std::strcmp(Name, RHS.Name) < 0;
38263508Sdim  }
39263508Sdim};
40263508Sdim
41263508Sdimstruct Mips16IntrinsicHelperType{
42263508Sdim  const char* Name;
43263508Sdim  const char* Helper;
44263508Sdim
45263508Sdim  bool operator<(const Mips16IntrinsicHelperType &RHS) const {
46263508Sdim    return std::strcmp(Name, RHS.Name) < 0;
47263508Sdim  }
48263508Sdim  bool operator==(const Mips16IntrinsicHelperType &RHS) const {
49263508Sdim    return std::strcmp(Name, RHS.Name) == 0;
50263508Sdim  }
51263508Sdim};
52249259Sdim}
53249259Sdim
54263508Sdim// Libcalls for which no helper is generated. Sorted by name for binary search.
55263508Sdimstatic const Mips16Libcall HardFloatLibCalls[] = {
56263508Sdim  { RTLIB::ADD_F64, "__mips16_adddf3" },
57263508Sdim  { RTLIB::ADD_F32, "__mips16_addsf3" },
58263508Sdim  { RTLIB::DIV_F64, "__mips16_divdf3" },
59263508Sdim  { RTLIB::DIV_F32, "__mips16_divsf3" },
60263508Sdim  { RTLIB::OEQ_F64, "__mips16_eqdf2" },
61263508Sdim  { RTLIB::OEQ_F32, "__mips16_eqsf2" },
62263508Sdim  { RTLIB::FPEXT_F32_F64, "__mips16_extendsfdf2" },
63263508Sdim  { RTLIB::FPTOSINT_F64_I32, "__mips16_fix_truncdfsi" },
64263508Sdim  { RTLIB::FPTOSINT_F32_I32, "__mips16_fix_truncsfsi" },
65263508Sdim  { RTLIB::SINTTOFP_I32_F64, "__mips16_floatsidf" },
66263508Sdim  { RTLIB::SINTTOFP_I32_F32, "__mips16_floatsisf" },
67263508Sdim  { RTLIB::UINTTOFP_I32_F64, "__mips16_floatunsidf" },
68263508Sdim  { RTLIB::UINTTOFP_I32_F32, "__mips16_floatunsisf" },
69263508Sdim  { RTLIB::OGE_F64, "__mips16_gedf2" },
70263508Sdim  { RTLIB::OGE_F32, "__mips16_gesf2" },
71263508Sdim  { RTLIB::OGT_F64, "__mips16_gtdf2" },
72263508Sdim  { RTLIB::OGT_F32, "__mips16_gtsf2" },
73263508Sdim  { RTLIB::OLE_F64, "__mips16_ledf2" },
74263508Sdim  { RTLIB::OLE_F32, "__mips16_lesf2" },
75263508Sdim  { RTLIB::OLT_F64, "__mips16_ltdf2" },
76263508Sdim  { RTLIB::OLT_F32, "__mips16_ltsf2" },
77263508Sdim  { RTLIB::MUL_F64, "__mips16_muldf3" },
78263508Sdim  { RTLIB::MUL_F32, "__mips16_mulsf3" },
79263508Sdim  { RTLIB::UNE_F64, "__mips16_nedf2" },
80263508Sdim  { RTLIB::UNE_F32, "__mips16_nesf2" },
81263508Sdim  { RTLIB::UNKNOWN_LIBCALL, "__mips16_ret_dc" }, // No associated libcall.
82263508Sdim  { RTLIB::UNKNOWN_LIBCALL, "__mips16_ret_df" }, // No associated libcall.
83263508Sdim  { RTLIB::UNKNOWN_LIBCALL, "__mips16_ret_sc" }, // No associated libcall.
84263508Sdim  { RTLIB::UNKNOWN_LIBCALL, "__mips16_ret_sf" }, // No associated libcall.
85263508Sdim  { RTLIB::SUB_F64, "__mips16_subdf3" },
86263508Sdim  { RTLIB::SUB_F32, "__mips16_subsf3" },
87263508Sdim  { RTLIB::FPROUND_F64_F32, "__mips16_truncdfsf2" },
88263508Sdim  { RTLIB::UO_F64, "__mips16_unorddf2" },
89263508Sdim  { RTLIB::UO_F32, "__mips16_unordsf2" }
90263508Sdim};
91263508Sdim
92263508Sdimstatic const Mips16IntrinsicHelperType Mips16IntrinsicHelper[] = {
93263508Sdim  {"__fixunsdfsi", "__mips16_call_stub_2" },
94263508Sdim  {"ceil",  "__mips16_call_stub_df_2"},
95263508Sdim  {"ceilf", "__mips16_call_stub_sf_1"},
96263508Sdim  {"copysign",  "__mips16_call_stub_df_10"},
97263508Sdim  {"copysignf", "__mips16_call_stub_sf_5"},
98263508Sdim  {"cos",  "__mips16_call_stub_df_2"},
99263508Sdim  {"cosf", "__mips16_call_stub_sf_1"},
100263508Sdim  {"exp2",  "__mips16_call_stub_df_2"},
101263508Sdim  {"exp2f", "__mips16_call_stub_sf_1"},
102263508Sdim  {"floor",  "__mips16_call_stub_df_2"},
103263508Sdim  {"floorf", "__mips16_call_stub_sf_1"},
104263508Sdim  {"log2",  "__mips16_call_stub_df_2"},
105263508Sdim  {"log2f", "__mips16_call_stub_sf_1"},
106263508Sdim  {"nearbyint",  "__mips16_call_stub_df_2"},
107263508Sdim  {"nearbyintf", "__mips16_call_stub_sf_1"},
108263508Sdim  {"rint",  "__mips16_call_stub_df_2"},
109263508Sdim  {"rintf", "__mips16_call_stub_sf_1"},
110263508Sdim  {"sin",  "__mips16_call_stub_df_2"},
111263508Sdim  {"sinf", "__mips16_call_stub_sf_1"},
112263508Sdim  {"sqrt",  "__mips16_call_stub_df_2"},
113263508Sdim  {"sqrtf", "__mips16_call_stub_sf_1"},
114263508Sdim  {"trunc",  "__mips16_call_stub_df_2"},
115263508Sdim  {"truncf", "__mips16_call_stub_sf_1"},
116263508Sdim};
117263508Sdim
118249259SdimMips16TargetLowering::Mips16TargetLowering(MipsTargetMachine &TM)
119249259Sdim  : MipsTargetLowering(TM) {
120249259Sdim  //
121249259Sdim  // set up as if mips32 and then revert so we can test the mechanism
122249259Sdim  // for switching
123263508Sdim  addRegisterClass(MVT::i32, &Mips::GPR32RegClass);
124249259Sdim  addRegisterClass(MVT::f32, &Mips::FGR32RegClass);
125249259Sdim  computeRegisterProperties();
126249259Sdim  clearRegisterClasses();
127249259Sdim
128249259Sdim  // Set up the register classes
129249259Sdim  addRegisterClass(MVT::i32, &Mips::CPU16RegsRegClass);
130249259Sdim
131263508Sdim  if (Subtarget->inMips16HardFloat())
132249259Sdim    setMips16HardFloatLibCalls();
133249259Sdim
134249259Sdim  setOperationAction(ISD::ATOMIC_FENCE,       MVT::Other, Expand);
135249259Sdim  setOperationAction(ISD::ATOMIC_CMP_SWAP,    MVT::i32,   Expand);
136249259Sdim  setOperationAction(ISD::ATOMIC_SWAP,        MVT::i32,   Expand);
137249259Sdim  setOperationAction(ISD::ATOMIC_LOAD_ADD,    MVT::i32,   Expand);
138249259Sdim  setOperationAction(ISD::ATOMIC_LOAD_SUB,    MVT::i32,   Expand);
139249259Sdim  setOperationAction(ISD::ATOMIC_LOAD_AND,    MVT::i32,   Expand);
140249259Sdim  setOperationAction(ISD::ATOMIC_LOAD_OR,     MVT::i32,   Expand);
141249259Sdim  setOperationAction(ISD::ATOMIC_LOAD_XOR,    MVT::i32,   Expand);
142249259Sdim  setOperationAction(ISD::ATOMIC_LOAD_NAND,   MVT::i32,   Expand);
143249259Sdim  setOperationAction(ISD::ATOMIC_LOAD_MIN,    MVT::i32,   Expand);
144249259Sdim  setOperationAction(ISD::ATOMIC_LOAD_MAX,    MVT::i32,   Expand);
145249259Sdim  setOperationAction(ISD::ATOMIC_LOAD_UMIN,   MVT::i32,   Expand);
146249259Sdim  setOperationAction(ISD::ATOMIC_LOAD_UMAX,   MVT::i32,   Expand);
147249259Sdim
148263508Sdim  setOperationAction(ISD::ROTR, MVT::i32,  Expand);
149263508Sdim  setOperationAction(ISD::ROTR, MVT::i64,  Expand);
150263508Sdim  setOperationAction(ISD::BSWAP, MVT::i32, Expand);
151263508Sdim  setOperationAction(ISD::BSWAP, MVT::i64, Expand);
152263508Sdim
153249259Sdim  computeRegisterProperties();
154249259Sdim}
155249259Sdim
156249259Sdimconst MipsTargetLowering *
157249259Sdimllvm::createMips16TargetLowering(MipsTargetMachine &TM) {
158249259Sdim  return new Mips16TargetLowering(TM);
159249259Sdim}
160249259Sdim
161249259Sdimbool
162249259SdimMips16TargetLowering::allowsUnalignedMemoryAccesses(EVT VT, bool *Fast) const {
163249259Sdim  return false;
164249259Sdim}
165249259Sdim
166249259SdimMachineBasicBlock *
167249259SdimMips16TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
168249259Sdim                                                  MachineBasicBlock *BB) const {
169249259Sdim  switch (MI->getOpcode()) {
170249259Sdim  default:
171249259Sdim    return MipsTargetLowering::EmitInstrWithCustomInserter(MI, BB);
172249259Sdim  case Mips::SelBeqZ:
173249259Sdim    return emitSel16(Mips::BeqzRxImm16, MI, BB);
174249259Sdim  case Mips::SelBneZ:
175249259Sdim    return emitSel16(Mips::BnezRxImm16, MI, BB);
176249259Sdim  case Mips::SelTBteqZCmpi:
177263508Sdim    return emitSeliT16(Mips::Bteqz16, Mips::CmpiRxImmX16, MI, BB);
178249259Sdim  case Mips::SelTBteqZSlti:
179263508Sdim    return emitSeliT16(Mips::Bteqz16, Mips::SltiRxImmX16, MI, BB);
180249259Sdim  case Mips::SelTBteqZSltiu:
181263508Sdim    return emitSeliT16(Mips::Bteqz16, Mips::SltiuRxImmX16, MI, BB);
182249259Sdim  case Mips::SelTBtneZCmpi:
183263508Sdim    return emitSeliT16(Mips::Btnez16, Mips::CmpiRxImmX16, MI, BB);
184249259Sdim  case Mips::SelTBtneZSlti:
185263508Sdim    return emitSeliT16(Mips::Btnez16, Mips::SltiRxImmX16, MI, BB);
186249259Sdim  case Mips::SelTBtneZSltiu:
187263508Sdim    return emitSeliT16(Mips::Btnez16, Mips::SltiuRxImmX16, MI, BB);
188249259Sdim  case Mips::SelTBteqZCmp:
189263508Sdim    return emitSelT16(Mips::Bteqz16, Mips::CmpRxRy16, MI, BB);
190249259Sdim  case Mips::SelTBteqZSlt:
191263508Sdim    return emitSelT16(Mips::Bteqz16, Mips::SltRxRy16, MI, BB);
192249259Sdim  case Mips::SelTBteqZSltu:
193263508Sdim    return emitSelT16(Mips::Bteqz16, Mips::SltuRxRy16, MI, BB);
194249259Sdim  case Mips::SelTBtneZCmp:
195263508Sdim    return emitSelT16(Mips::Btnez16, Mips::CmpRxRy16, MI, BB);
196249259Sdim  case Mips::SelTBtneZSlt:
197263508Sdim    return emitSelT16(Mips::Btnez16, Mips::SltRxRy16, MI, BB);
198249259Sdim  case Mips::SelTBtneZSltu:
199263508Sdim    return emitSelT16(Mips::Btnez16, Mips::SltuRxRy16, MI, BB);
200249259Sdim  case Mips::BteqzT8CmpX16:
201263508Sdim    return emitFEXT_T8I816_ins(Mips::Bteqz16, Mips::CmpRxRy16, MI, BB);
202249259Sdim  case Mips::BteqzT8SltX16:
203263508Sdim    return emitFEXT_T8I816_ins(Mips::Bteqz16, Mips::SltRxRy16, MI, BB);
204249259Sdim  case Mips::BteqzT8SltuX16:
205249259Sdim    // TBD: figure out a way to get this or remove the instruction
206249259Sdim    // altogether.
207263508Sdim    return emitFEXT_T8I816_ins(Mips::Bteqz16, Mips::SltuRxRy16, MI, BB);
208249259Sdim  case Mips::BtnezT8CmpX16:
209263508Sdim    return emitFEXT_T8I816_ins(Mips::Btnez16, Mips::CmpRxRy16, MI, BB);
210249259Sdim  case Mips::BtnezT8SltX16:
211263508Sdim    return emitFEXT_T8I816_ins(Mips::Btnez16, Mips::SltRxRy16, MI, BB);
212249259Sdim  case Mips::BtnezT8SltuX16:
213249259Sdim    // TBD: figure out a way to get this or remove the instruction
214249259Sdim    // altogether.
215263508Sdim    return emitFEXT_T8I816_ins(Mips::Btnez16, Mips::SltuRxRy16, MI, BB);
216249259Sdim  case Mips::BteqzT8CmpiX16: return emitFEXT_T8I8I16_ins(
217263508Sdim    Mips::Bteqz16, Mips::CmpiRxImm16, Mips::CmpiRxImmX16, false, MI, BB);
218249259Sdim  case Mips::BteqzT8SltiX16: return emitFEXT_T8I8I16_ins(
219263508Sdim    Mips::Bteqz16, Mips::SltiRxImm16, Mips::SltiRxImmX16, true, MI, BB);
220249259Sdim  case Mips::BteqzT8SltiuX16: return emitFEXT_T8I8I16_ins(
221263508Sdim    Mips::Bteqz16, Mips::SltiuRxImm16, Mips::SltiuRxImmX16, false, MI, BB);
222249259Sdim  case Mips::BtnezT8CmpiX16: return emitFEXT_T8I8I16_ins(
223263508Sdim    Mips::Btnez16, Mips::CmpiRxImm16, Mips::CmpiRxImmX16, false, MI, BB);
224249259Sdim  case Mips::BtnezT8SltiX16: return emitFEXT_T8I8I16_ins(
225263508Sdim    Mips::Btnez16, Mips::SltiRxImm16, Mips::SltiRxImmX16, true, MI, BB);
226249259Sdim  case Mips::BtnezT8SltiuX16: return emitFEXT_T8I8I16_ins(
227263508Sdim    Mips::Btnez16, Mips::SltiuRxImm16, Mips::SltiuRxImmX16, false, MI, BB);
228249259Sdim    break;
229249259Sdim  case Mips::SltCCRxRy16:
230249259Sdim    return emitFEXT_CCRX16_ins(Mips::SltRxRy16, MI, BB);
231249259Sdim    break;
232249259Sdim  case Mips::SltiCCRxImmX16:
233249259Sdim    return emitFEXT_CCRXI16_ins
234249259Sdim      (Mips::SltiRxImm16, Mips::SltiRxImmX16, MI, BB);
235249259Sdim  case Mips::SltiuCCRxImmX16:
236249259Sdim    return emitFEXT_CCRXI16_ins
237249259Sdim      (Mips::SltiuRxImm16, Mips::SltiuRxImmX16, MI, BB);
238249259Sdim  case Mips::SltuCCRxRy16:
239249259Sdim    return emitFEXT_CCRX16_ins
240249259Sdim      (Mips::SltuRxRy16, MI, BB);
241249259Sdim  }
242249259Sdim}
243249259Sdim
244249259Sdimbool Mips16TargetLowering::
245249259SdimisEligibleForTailCallOptimization(const MipsCC &MipsCCInfo,
246249259Sdim                                  unsigned NextStackOffset,
247249259Sdim                                  const MipsFunctionInfo& FI) const {
248249259Sdim  // No tail call optimization for mips16.
249249259Sdim  return false;
250249259Sdim}
251249259Sdim
252263508Sdimvoid Mips16TargetLowering::setMips16HardFloatLibCalls() {
253263508Sdim  for (unsigned I = 0; I != array_lengthof(HardFloatLibCalls); ++I) {
254263508Sdim    assert((I == 0 || HardFloatLibCalls[I - 1] < HardFloatLibCalls[I]) &&
255263508Sdim           "Array not sorted!");
256263508Sdim    if (HardFloatLibCalls[I].Libcall != RTLIB::UNKNOWN_LIBCALL)
257263508Sdim      setLibcallName(HardFloatLibCalls[I].Libcall, HardFloatLibCalls[I].Name);
258263508Sdim  }
259249259Sdim
260263508Sdim  setLibcallName(RTLIB::O_F64, "__mips16_unorddf2");
261263508Sdim  setLibcallName(RTLIB::O_F32, "__mips16_unordsf2");
262249259Sdim}
263249259Sdim
264249259Sdim//
265249259Sdim// The Mips16 hard float is a crazy quilt inherited from gcc. I have a much
266249259Sdim// cleaner way to do all of this but it will have to wait until the traditional
267249259Sdim// gcc mechanism is completed.
268249259Sdim//
269249259Sdim// For Pic, in order for Mips16 code to call Mips32 code which according the abi
270249259Sdim// have either arguments or returned values placed in floating point registers,
271249259Sdim// we use a set of helper functions. (This includes functions which return type
272249259Sdim//  complex which on Mips are returned in a pair of floating point registers).
273249259Sdim//
274249259Sdim// This is an encoding that we inherited from gcc.
275249259Sdim// In Mips traditional O32, N32 ABI, floating point numbers are passed in
276249259Sdim// floating point argument registers 1,2 only when the first and optionally
277249259Sdim// the second arguments are float (sf) or double (df).
278249259Sdim// For Mips16 we are only concerned with the situations where floating point
279249259Sdim// arguments are being passed in floating point registers by the ABI, because
280249259Sdim// Mips16 mode code cannot execute floating point instructions to load those
281249259Sdim// values and hence helper functions are needed.
282249259Sdim// The possibilities are (), (sf), (sf, sf), (sf, df), (df), (df, sf), (df, df)
283249259Sdim// the helper function suffixs for these are:
284249259Sdim//                        0,  1,    5,        9,         2,   6,        10
285249259Sdim// this suffix can then be calculated as follows:
286249259Sdim// for a given argument Arg:
287249259Sdim//     Arg1x, Arg2x = 1 :  Arg is sf
288249259Sdim//                    2 :  Arg is df
289249259Sdim//                    0:   Arg is neither sf or df
290249259Sdim// So this stub is the string for number Arg1x + Arg2x*4.
291249259Sdim// However not all numbers between 0 and 10 are possible, we check anyway and
292249259Sdim// assert if the impossible exists.
293249259Sdim//
294249259Sdim
295249259Sdimunsigned int Mips16TargetLowering::getMips16HelperFunctionStubNumber
296249259Sdim  (ArgListTy &Args) const {
297249259Sdim  unsigned int resultNum = 0;
298249259Sdim  if (Args.size() >= 1) {
299249259Sdim    Type *t = Args[0].Ty;
300249259Sdim    if (t->isFloatTy()) {
301249259Sdim      resultNum = 1;
302249259Sdim    }
303249259Sdim    else if (t->isDoubleTy()) {
304249259Sdim      resultNum = 2;
305249259Sdim    }
306249259Sdim  }
307249259Sdim  if (resultNum) {
308249259Sdim    if (Args.size() >=2) {
309249259Sdim      Type *t = Args[1].Ty;
310249259Sdim      if (t->isFloatTy()) {
311249259Sdim        resultNum += 4;
312249259Sdim      }
313249259Sdim      else if (t->isDoubleTy()) {
314249259Sdim        resultNum += 8;
315249259Sdim      }
316249259Sdim    }
317249259Sdim  }
318249259Sdim  return resultNum;
319249259Sdim}
320249259Sdim
321249259Sdim//
322249259Sdim// prefixs are attached to stub numbers depending on the return type .
323249259Sdim// return type: float  sf_
324249259Sdim//              double df_
325249259Sdim//              single complex sc_
326249259Sdim//              double complext dc_
327249259Sdim//              others  NO PREFIX
328249259Sdim//
329249259Sdim//
330249259Sdim// The full name of a helper function is__mips16_call_stub +
331249259Sdim//    return type dependent prefix + stub number
332249259Sdim//
333249259Sdim//
334249259Sdim// This is something that probably should be in a different source file and
335249259Sdim// perhaps done differently but my main purpose is to not waste runtime
336249259Sdim// on something that we can enumerate in the source. Another possibility is
337249259Sdim// to have a python script to generate these mapping tables. This will do
338249259Sdim// for now. There are a whole series of helper function mapping arrays, one
339249259Sdim// for each return type class as outlined above. There there are 11 possible
340249259Sdim//  entries. Ones with 0 are ones which should never be selected
341249259Sdim//
342249259Sdim// All the arrays are similar except for ones which return neither
343249259Sdim// sf, df, sc, dc, in which only care about ones which have sf or df as a
344249259Sdim// first parameter.
345249259Sdim//
346249259Sdim#define P_ "__mips16_call_stub_"
347249259Sdim#define MAX_STUB_NUMBER 10
348249259Sdim#define T1 P "1", P "2", 0, 0, P "5", P "6", 0, 0, P "9", P "10"
349249259Sdim#define T P "0" , T1
350249259Sdim#define P P_
351249259Sdimstatic char const * vMips16Helper[MAX_STUB_NUMBER+1] =
352249259Sdim  {0, T1 };
353249259Sdim#undef P
354249259Sdim#define P P_ "sf_"
355249259Sdimstatic char const * sfMips16Helper[MAX_STUB_NUMBER+1] =
356249259Sdim  { T };
357249259Sdim#undef P
358249259Sdim#define P P_ "df_"
359249259Sdimstatic char const * dfMips16Helper[MAX_STUB_NUMBER+1] =
360249259Sdim  { T };
361249259Sdim#undef P
362249259Sdim#define P P_ "sc_"
363249259Sdimstatic char const * scMips16Helper[MAX_STUB_NUMBER+1] =
364249259Sdim  { T };
365249259Sdim#undef P
366249259Sdim#define P P_ "dc_"
367249259Sdimstatic char const * dcMips16Helper[MAX_STUB_NUMBER+1] =
368249259Sdim  { T };
369249259Sdim#undef P
370249259Sdim#undef P_
371249259Sdim
372249259Sdim
373249259Sdimconst char* Mips16TargetLowering::
374249259Sdim  getMips16HelperFunction
375249259Sdim    (Type* RetTy, ArgListTy &Args, bool &needHelper) const {
376249259Sdim  const unsigned int stubNum = getMips16HelperFunctionStubNumber(Args);
377249259Sdim#ifndef NDEBUG
378249259Sdim  const unsigned int maxStubNum = 10;
379249259Sdim  assert(stubNum <= maxStubNum);
380249259Sdim  const bool validStubNum[maxStubNum+1] =
381249259Sdim    {true, true, true, false, false, true, true, false, false, true, true};
382249259Sdim  assert(validStubNum[stubNum]);
383249259Sdim#endif
384249259Sdim  const char *result;
385249259Sdim  if (RetTy->isFloatTy()) {
386249259Sdim    result = sfMips16Helper[stubNum];
387249259Sdim  }
388249259Sdim  else if (RetTy ->isDoubleTy()) {
389249259Sdim    result = dfMips16Helper[stubNum];
390249259Sdim  }
391249259Sdim  else if (RetTy->isStructTy()) {
392249259Sdim    // check if it's complex
393249259Sdim    if (RetTy->getNumContainedTypes() == 2) {
394249259Sdim      if ((RetTy->getContainedType(0)->isFloatTy()) &&
395249259Sdim          (RetTy->getContainedType(1)->isFloatTy())) {
396249259Sdim        result = scMips16Helper[stubNum];
397249259Sdim      }
398249259Sdim      else if ((RetTy->getContainedType(0)->isDoubleTy()) &&
399249259Sdim               (RetTy->getContainedType(1)->isDoubleTy())) {
400249259Sdim        result = dcMips16Helper[stubNum];
401249259Sdim      }
402249259Sdim      else {
403249259Sdim        llvm_unreachable("Uncovered condition");
404249259Sdim      }
405249259Sdim    }
406249259Sdim    else {
407249259Sdim      llvm_unreachable("Uncovered condition");
408249259Sdim    }
409249259Sdim  }
410249259Sdim  else {
411249259Sdim    if (stubNum == 0) {
412249259Sdim      needHelper = false;
413249259Sdim      return "";
414249259Sdim    }
415249259Sdim    result = vMips16Helper[stubNum];
416249259Sdim  }
417249259Sdim  needHelper = true;
418249259Sdim  return result;
419249259Sdim}
420249259Sdim
421249259Sdimvoid Mips16TargetLowering::
422249259SdimgetOpndList(SmallVectorImpl<SDValue> &Ops,
423249259Sdim            std::deque< std::pair<unsigned, SDValue> > &RegsToPass,
424249259Sdim            bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage,
425249259Sdim            CallLoweringInfo &CLI, SDValue Callee, SDValue Chain) const {
426249259Sdim  SelectionDAG &DAG = CLI.DAG;
427263508Sdim  MachineFunction &MF = DAG.getMachineFunction();
428263508Sdim  MipsFunctionInfo *FuncInfo = MF.getInfo<MipsFunctionInfo>();
429249259Sdim  const char* Mips16HelperFunction = 0;
430249259Sdim  bool NeedMips16Helper = false;
431249259Sdim
432263508Sdim  if (getTargetMachine().Options.UseSoftFloat &&
433263508Sdim      Subtarget->inMips16HardFloat()) {
434249259Sdim    //
435249259Sdim    // currently we don't have symbols tagged with the mips16 or mips32
436249259Sdim    // qualifier so we will assume that we don't know what kind it is.
437249259Sdim    // and generate the helper
438249259Sdim    //
439249259Sdim    bool LookupHelper = true;
440249259Sdim    if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(CLI.Callee)) {
441263508Sdim      Mips16Libcall Find = { RTLIB::UNKNOWN_LIBCALL, S->getSymbol() };
442263508Sdim
443263508Sdim      if (std::binary_search(HardFloatLibCalls, array_endof(HardFloatLibCalls),
444263508Sdim                             Find))
445249259Sdim        LookupHelper = false;
446263508Sdim      else {
447263508Sdim        Mips16IntrinsicHelperType IntrinsicFind = {S->getSymbol(), ""};
448263508Sdim        // one more look at list of intrinsics
449263508Sdim        if (std::binary_search(Mips16IntrinsicHelper,
450263508Sdim            array_endof(Mips16IntrinsicHelper),
451263508Sdim                                     IntrinsicFind)) {
452263508Sdim          const Mips16IntrinsicHelperType *h =(std::find(Mips16IntrinsicHelper,
453263508Sdim              array_endof(Mips16IntrinsicHelper),
454263508Sdim                                       IntrinsicFind));
455263508Sdim          Mips16HelperFunction = h->Helper;
456263508Sdim          NeedMips16Helper = true;
457263508Sdim          LookupHelper = false;
458263508Sdim        }
459263508Sdim
460249259Sdim      }
461263508Sdim    } else if (GlobalAddressSDNode *G =
462263508Sdim                   dyn_cast<GlobalAddressSDNode>(CLI.Callee)) {
463263508Sdim      Mips16Libcall Find = { RTLIB::UNKNOWN_LIBCALL,
464263508Sdim                             G->getGlobal()->getName().data() };
465263508Sdim
466263508Sdim      if (std::binary_search(HardFloatLibCalls, array_endof(HardFloatLibCalls),
467263508Sdim                             Find))
468263508Sdim        LookupHelper = false;
469249259Sdim    }
470249259Sdim    if (LookupHelper) Mips16HelperFunction =
471249259Sdim      getMips16HelperFunction(CLI.RetTy, CLI.Args, NeedMips16Helper);
472249259Sdim
473249259Sdim  }
474249259Sdim
475249259Sdim  SDValue JumpTarget = Callee;
476249259Sdim
477249259Sdim  // T9 should contain the address of the callee function if
478249259Sdim  // -reloction-model=pic or it is an indirect call.
479249259Sdim  if (IsPICCall || !GlobalOrExternal) {
480249259Sdim    unsigned V0Reg = Mips::V0;
481249259Sdim    if (NeedMips16Helper) {
482249259Sdim      RegsToPass.push_front(std::make_pair(V0Reg, Callee));
483249259Sdim      JumpTarget = DAG.getExternalSymbol(Mips16HelperFunction, getPointerTy());
484263508Sdim      ExternalSymbolSDNode *S = cast<ExternalSymbolSDNode>(JumpTarget);
485263508Sdim      JumpTarget = getAddrGlobal(S, JumpTarget.getValueType(), DAG,
486263508Sdim                                 MipsII::MO_GOT, Chain,
487263508Sdim                                 FuncInfo->callPtrInfo(S->getSymbol()));
488249259Sdim    } else
489249259Sdim      RegsToPass.push_front(std::make_pair((unsigned)Mips::T9, Callee));
490249259Sdim  }
491249259Sdim
492249259Sdim  Ops.push_back(JumpTarget);
493249259Sdim
494249259Sdim  MipsTargetLowering::getOpndList(Ops, RegsToPass, IsPICCall, GlobalOrExternal,
495249259Sdim                                  InternalLinkage, CLI, Callee, Chain);
496249259Sdim}
497249259Sdim
498249259SdimMachineBasicBlock *Mips16TargetLowering::
499249259SdimemitSel16(unsigned Opc, MachineInstr *MI, MachineBasicBlock *BB) const {
500249259Sdim  if (DontExpandCondPseudos16)
501249259Sdim    return BB;
502249259Sdim  const TargetInstrInfo *TII = getTargetMachine().getInstrInfo();
503249259Sdim  DebugLoc DL = MI->getDebugLoc();
504249259Sdim  // To "insert" a SELECT_CC instruction, we actually have to insert the
505249259Sdim  // diamond control-flow pattern.  The incoming instruction knows the
506249259Sdim  // destination vreg to set, the condition code register to branch on, the
507249259Sdim  // true/false values to select between, and a branch opcode to use.
508249259Sdim  const BasicBlock *LLVM_BB = BB->getBasicBlock();
509249259Sdim  MachineFunction::iterator It = BB;
510249259Sdim  ++It;
511249259Sdim
512249259Sdim  //  thisMBB:
513249259Sdim  //  ...
514249259Sdim  //   TrueVal = ...
515249259Sdim  //   setcc r1, r2, r3
516249259Sdim  //   bNE   r1, r0, copy1MBB
517249259Sdim  //   fallthrough --> copy0MBB
518249259Sdim  MachineBasicBlock *thisMBB  = BB;
519249259Sdim  MachineFunction *F = BB->getParent();
520249259Sdim  MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB);
521249259Sdim  MachineBasicBlock *sinkMBB  = F->CreateMachineBasicBlock(LLVM_BB);
522249259Sdim  F->insert(It, copy0MBB);
523249259Sdim  F->insert(It, sinkMBB);
524249259Sdim
525249259Sdim  // Transfer the remainder of BB and its successor edges to sinkMBB.
526249259Sdim  sinkMBB->splice(sinkMBB->begin(), BB,
527249259Sdim                  llvm::next(MachineBasicBlock::iterator(MI)),
528249259Sdim                  BB->end());
529249259Sdim  sinkMBB->transferSuccessorsAndUpdatePHIs(BB);
530249259Sdim
531249259Sdim  // Next, add the true and fallthrough blocks as its successors.
532249259Sdim  BB->addSuccessor(copy0MBB);
533249259Sdim  BB->addSuccessor(sinkMBB);
534249259Sdim
535249259Sdim  BuildMI(BB, DL, TII->get(Opc)).addReg(MI->getOperand(3).getReg())
536249259Sdim    .addMBB(sinkMBB);
537249259Sdim
538249259Sdim  //  copy0MBB:
539249259Sdim  //   %FalseValue = ...
540249259Sdim  //   # fallthrough to sinkMBB
541249259Sdim  BB = copy0MBB;
542249259Sdim
543249259Sdim  // Update machine-CFG edges
544249259Sdim  BB->addSuccessor(sinkMBB);
545249259Sdim
546249259Sdim  //  sinkMBB:
547249259Sdim  //   %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copy0MBB ]
548249259Sdim  //  ...
549249259Sdim  BB = sinkMBB;
550249259Sdim
551249259Sdim  BuildMI(*BB, BB->begin(), DL,
552249259Sdim          TII->get(Mips::PHI), MI->getOperand(0).getReg())
553249259Sdim    .addReg(MI->getOperand(1).getReg()).addMBB(thisMBB)
554249259Sdim    .addReg(MI->getOperand(2).getReg()).addMBB(copy0MBB);
555249259Sdim
556249259Sdim  MI->eraseFromParent();   // The pseudo instruction is gone now.
557249259Sdim  return BB;
558249259Sdim}
559249259Sdim
560249259SdimMachineBasicBlock *Mips16TargetLowering::emitSelT16
561249259Sdim  (unsigned Opc1, unsigned Opc2,
562249259Sdim   MachineInstr *MI, MachineBasicBlock *BB) const {
563249259Sdim  if (DontExpandCondPseudos16)
564249259Sdim    return BB;
565249259Sdim  const TargetInstrInfo *TII = getTargetMachine().getInstrInfo();
566249259Sdim  DebugLoc DL = MI->getDebugLoc();
567249259Sdim  // To "insert" a SELECT_CC instruction, we actually have to insert the
568249259Sdim  // diamond control-flow pattern.  The incoming instruction knows the
569249259Sdim  // destination vreg to set, the condition code register to branch on, the
570249259Sdim  // true/false values to select between, and a branch opcode to use.
571249259Sdim  const BasicBlock *LLVM_BB = BB->getBasicBlock();
572249259Sdim  MachineFunction::iterator It = BB;
573249259Sdim  ++It;
574249259Sdim
575249259Sdim  //  thisMBB:
576249259Sdim  //  ...
577249259Sdim  //   TrueVal = ...
578249259Sdim  //   setcc r1, r2, r3
579249259Sdim  //   bNE   r1, r0, copy1MBB
580249259Sdim  //   fallthrough --> copy0MBB
581249259Sdim  MachineBasicBlock *thisMBB  = BB;
582249259Sdim  MachineFunction *F = BB->getParent();
583249259Sdim  MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB);
584249259Sdim  MachineBasicBlock *sinkMBB  = F->CreateMachineBasicBlock(LLVM_BB);
585249259Sdim  F->insert(It, copy0MBB);
586249259Sdim  F->insert(It, sinkMBB);
587249259Sdim
588249259Sdim  // Transfer the remainder of BB and its successor edges to sinkMBB.
589249259Sdim  sinkMBB->splice(sinkMBB->begin(), BB,
590249259Sdim                  llvm::next(MachineBasicBlock::iterator(MI)),
591249259Sdim                  BB->end());
592249259Sdim  sinkMBB->transferSuccessorsAndUpdatePHIs(BB);
593249259Sdim
594249259Sdim  // Next, add the true and fallthrough blocks as its successors.
595249259Sdim  BB->addSuccessor(copy0MBB);
596249259Sdim  BB->addSuccessor(sinkMBB);
597249259Sdim
598249259Sdim  BuildMI(BB, DL, TII->get(Opc2)).addReg(MI->getOperand(3).getReg())
599249259Sdim    .addReg(MI->getOperand(4).getReg());
600249259Sdim  BuildMI(BB, DL, TII->get(Opc1)).addMBB(sinkMBB);
601249259Sdim
602249259Sdim  //  copy0MBB:
603249259Sdim  //   %FalseValue = ...
604249259Sdim  //   # fallthrough to sinkMBB
605249259Sdim  BB = copy0MBB;
606249259Sdim
607249259Sdim  // Update machine-CFG edges
608249259Sdim  BB->addSuccessor(sinkMBB);
609249259Sdim
610249259Sdim  //  sinkMBB:
611249259Sdim  //   %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copy0MBB ]
612249259Sdim  //  ...
613249259Sdim  BB = sinkMBB;
614249259Sdim
615249259Sdim  BuildMI(*BB, BB->begin(), DL,
616249259Sdim          TII->get(Mips::PHI), MI->getOperand(0).getReg())
617249259Sdim    .addReg(MI->getOperand(1).getReg()).addMBB(thisMBB)
618249259Sdim    .addReg(MI->getOperand(2).getReg()).addMBB(copy0MBB);
619249259Sdim
620249259Sdim  MI->eraseFromParent();   // The pseudo instruction is gone now.
621249259Sdim  return BB;
622249259Sdim
623249259Sdim}
624249259Sdim
625249259SdimMachineBasicBlock *Mips16TargetLowering::emitSeliT16
626249259Sdim  (unsigned Opc1, unsigned Opc2,
627249259Sdim   MachineInstr *MI, MachineBasicBlock *BB) const {
628249259Sdim  if (DontExpandCondPseudos16)
629249259Sdim    return BB;
630249259Sdim  const TargetInstrInfo *TII = getTargetMachine().getInstrInfo();
631249259Sdim  DebugLoc DL = MI->getDebugLoc();
632249259Sdim  // To "insert" a SELECT_CC instruction, we actually have to insert the
633249259Sdim  // diamond control-flow pattern.  The incoming instruction knows the
634249259Sdim  // destination vreg to set, the condition code register to branch on, the
635249259Sdim  // true/false values to select between, and a branch opcode to use.
636249259Sdim  const BasicBlock *LLVM_BB = BB->getBasicBlock();
637249259Sdim  MachineFunction::iterator It = BB;
638249259Sdim  ++It;
639249259Sdim
640249259Sdim  //  thisMBB:
641249259Sdim  //  ...
642249259Sdim  //   TrueVal = ...
643249259Sdim  //   setcc r1, r2, r3
644249259Sdim  //   bNE   r1, r0, copy1MBB
645249259Sdim  //   fallthrough --> copy0MBB
646249259Sdim  MachineBasicBlock *thisMBB  = BB;
647249259Sdim  MachineFunction *F = BB->getParent();
648249259Sdim  MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB);
649249259Sdim  MachineBasicBlock *sinkMBB  = F->CreateMachineBasicBlock(LLVM_BB);
650249259Sdim  F->insert(It, copy0MBB);
651249259Sdim  F->insert(It, sinkMBB);
652249259Sdim
653249259Sdim  // Transfer the remainder of BB and its successor edges to sinkMBB.
654249259Sdim  sinkMBB->splice(sinkMBB->begin(), BB,
655249259Sdim                  llvm::next(MachineBasicBlock::iterator(MI)),
656249259Sdim                  BB->end());
657249259Sdim  sinkMBB->transferSuccessorsAndUpdatePHIs(BB);
658249259Sdim
659249259Sdim  // Next, add the true and fallthrough blocks as its successors.
660249259Sdim  BB->addSuccessor(copy0MBB);
661249259Sdim  BB->addSuccessor(sinkMBB);
662249259Sdim
663249259Sdim  BuildMI(BB, DL, TII->get(Opc2)).addReg(MI->getOperand(3).getReg())
664249259Sdim    .addImm(MI->getOperand(4).getImm());
665249259Sdim  BuildMI(BB, DL, TII->get(Opc1)).addMBB(sinkMBB);
666249259Sdim
667249259Sdim  //  copy0MBB:
668249259Sdim  //   %FalseValue = ...
669249259Sdim  //   # fallthrough to sinkMBB
670249259Sdim  BB = copy0MBB;
671249259Sdim
672249259Sdim  // Update machine-CFG edges
673249259Sdim  BB->addSuccessor(sinkMBB);
674249259Sdim
675249259Sdim  //  sinkMBB:
676249259Sdim  //   %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copy0MBB ]
677249259Sdim  //  ...
678249259Sdim  BB = sinkMBB;
679249259Sdim
680249259Sdim  BuildMI(*BB, BB->begin(), DL,
681249259Sdim          TII->get(Mips::PHI), MI->getOperand(0).getReg())
682249259Sdim    .addReg(MI->getOperand(1).getReg()).addMBB(thisMBB)
683249259Sdim    .addReg(MI->getOperand(2).getReg()).addMBB(copy0MBB);
684249259Sdim
685249259Sdim  MI->eraseFromParent();   // The pseudo instruction is gone now.
686249259Sdim  return BB;
687249259Sdim
688249259Sdim}
689249259Sdim
690249259SdimMachineBasicBlock
691249259Sdim  *Mips16TargetLowering::emitFEXT_T8I816_ins(unsigned BtOpc, unsigned CmpOpc,
692249259Sdim                                             MachineInstr *MI,
693249259Sdim                                             MachineBasicBlock *BB) const {
694249259Sdim  if (DontExpandCondPseudos16)
695249259Sdim    return BB;
696249259Sdim  const TargetInstrInfo *TII = getTargetMachine().getInstrInfo();
697249259Sdim  unsigned regX = MI->getOperand(0).getReg();
698249259Sdim  unsigned regY = MI->getOperand(1).getReg();
699249259Sdim  MachineBasicBlock *target = MI->getOperand(2).getMBB();
700251662Sdim  BuildMI(*BB, MI, MI->getDebugLoc(), TII->get(CmpOpc)).addReg(regX)
701251662Sdim    .addReg(regY);
702249259Sdim  BuildMI(*BB, MI, MI->getDebugLoc(), TII->get(BtOpc)).addMBB(target);
703249259Sdim  MI->eraseFromParent();   // The pseudo instruction is gone now.
704249259Sdim  return BB;
705249259Sdim}
706249259Sdim
707249259SdimMachineBasicBlock *Mips16TargetLowering::emitFEXT_T8I8I16_ins(
708263508Sdim  unsigned BtOpc, unsigned CmpiOpc, unsigned CmpiXOpc, bool ImmSigned,
709249259Sdim  MachineInstr *MI,  MachineBasicBlock *BB) const {
710249259Sdim  if (DontExpandCondPseudos16)
711249259Sdim    return BB;
712249259Sdim  const TargetInstrInfo *TII = getTargetMachine().getInstrInfo();
713249259Sdim  unsigned regX = MI->getOperand(0).getReg();
714249259Sdim  int64_t imm = MI->getOperand(1).getImm();
715249259Sdim  MachineBasicBlock *target = MI->getOperand(2).getMBB();
716249259Sdim  unsigned CmpOpc;
717249259Sdim  if (isUInt<8>(imm))
718249259Sdim    CmpOpc = CmpiOpc;
719263508Sdim  else if ((!ImmSigned && isUInt<16>(imm)) ||
720263508Sdim           (ImmSigned && isInt<16>(imm)))
721249259Sdim    CmpOpc = CmpiXOpc;
722249259Sdim  else
723249259Sdim    llvm_unreachable("immediate field not usable");
724251662Sdim  BuildMI(*BB, MI, MI->getDebugLoc(), TII->get(CmpOpc)).addReg(regX)
725251662Sdim    .addImm(imm);
726249259Sdim  BuildMI(*BB, MI, MI->getDebugLoc(), TII->get(BtOpc)).addMBB(target);
727249259Sdim  MI->eraseFromParent();   // The pseudo instruction is gone now.
728249259Sdim  return BB;
729249259Sdim}
730249259Sdim
731249259Sdimstatic unsigned Mips16WhichOp8uOr16simm
732249259Sdim  (unsigned shortOp, unsigned longOp, int64_t Imm) {
733249259Sdim  if (isUInt<8>(Imm))
734249259Sdim    return shortOp;
735249259Sdim  else if (isInt<16>(Imm))
736249259Sdim    return longOp;
737249259Sdim  else
738249259Sdim    llvm_unreachable("immediate field not usable");
739249259Sdim}
740249259Sdim
741249259SdimMachineBasicBlock *Mips16TargetLowering::emitFEXT_CCRX16_ins(
742249259Sdim  unsigned SltOpc,
743249259Sdim  MachineInstr *MI,  MachineBasicBlock *BB) const {
744249259Sdim  if (DontExpandCondPseudos16)
745249259Sdim    return BB;
746249259Sdim  const TargetInstrInfo *TII = getTargetMachine().getInstrInfo();
747249259Sdim  unsigned CC = MI->getOperand(0).getReg();
748249259Sdim  unsigned regX = MI->getOperand(1).getReg();
749249259Sdim  unsigned regY = MI->getOperand(2).getReg();
750249259Sdim  BuildMI(*BB, MI, MI->getDebugLoc(),
751249259Sdim		  TII->get(SltOpc)).addReg(regX).addReg(regY);
752249259Sdim  BuildMI(*BB, MI, MI->getDebugLoc(),
753249259Sdim          TII->get(Mips::MoveR3216), CC).addReg(Mips::T8);
754249259Sdim  MI->eraseFromParent();   // The pseudo instruction is gone now.
755249259Sdim  return BB;
756249259Sdim}
757249259Sdim
758249259SdimMachineBasicBlock *Mips16TargetLowering::emitFEXT_CCRXI16_ins(
759249259Sdim  unsigned SltiOpc, unsigned SltiXOpc,
760249259Sdim  MachineInstr *MI,  MachineBasicBlock *BB )const {
761249259Sdim  if (DontExpandCondPseudos16)
762249259Sdim    return BB;
763249259Sdim  const TargetInstrInfo *TII = getTargetMachine().getInstrInfo();
764249259Sdim  unsigned CC = MI->getOperand(0).getReg();
765249259Sdim  unsigned regX = MI->getOperand(1).getReg();
766249259Sdim  int64_t Imm = MI->getOperand(2).getImm();
767249259Sdim  unsigned SltOpc = Mips16WhichOp8uOr16simm(SltiOpc, SltiXOpc, Imm);
768249259Sdim  BuildMI(*BB, MI, MI->getDebugLoc(),
769249259Sdim          TII->get(SltOpc)).addReg(regX).addImm(Imm);
770249259Sdim  BuildMI(*BB, MI, MI->getDebugLoc(),
771249259Sdim          TII->get(Mips::MoveR3216), CC).addReg(Mips::T8);
772249259Sdim  MI->eraseFromParent();   // The pseudo instruction is gone now.
773249259Sdim  return BB;
774249259Sdim
775249259Sdim}
776