1239310Sdim//===-- Mips16InstrInfo.cpp - Mips16 Instruction Information --------------===//
2239310Sdim//
3239310Sdim//                     The LLVM Compiler Infrastructure
4239310Sdim//
5239310Sdim// This file is distributed under the University of Illinois Open Source
6239310Sdim// License. See LICENSE.TXT for details.
7239310Sdim//
8239310Sdim//===----------------------------------------------------------------------===//
9239310Sdim//
10239310Sdim// This file contains the Mips16 implementation of the TargetInstrInfo class.
11239310Sdim//
12239310Sdim//===----------------------------------------------------------------------===//
13239310Sdim#include "Mips16InstrInfo.h"
14249423Sdim#include "InstPrinter/MipsInstPrinter.h"
15249423Sdim#include "MipsMachineFunction.h"
16239310Sdim#include "MipsTargetMachine.h"
17249423Sdim#include "llvm/ADT/STLExtras.h"
18249423Sdim#include "llvm/ADT/StringRef.h"
19239310Sdim#include "llvm/CodeGen/MachineInstrBuilder.h"
20239310Sdim#include "llvm/CodeGen/MachineRegisterInfo.h"
21249423Sdim#include "llvm/CodeGen/RegisterScavenging.h"
22263508Sdim#include "llvm/MC/MCAsmInfo.h"
23249423Sdim#include "llvm/Support/CommandLine.h"
24249423Sdim#include "llvm/Support/Debug.h"
25239310Sdim#include "llvm/Support/ErrorHandling.h"
26239310Sdim#include "llvm/Support/TargetRegistry.h"
27263508Sdim#include <cctype>
28239310Sdim
29239310Sdimusing namespace llvm;
30239310Sdim
31249423Sdimstatic cl::opt<bool> NeverUseSaveRestore(
32249423Sdim  "mips16-never-use-save-restore",
33249423Sdim  cl::init(false),
34249423Sdim  cl::desc("For testing ability to adjust stack pointer "
35249423Sdim           "without save/restore instruction"),
36249423Sdim  cl::Hidden);
37249423Sdim
38249423Sdim
39239310SdimMips16InstrInfo::Mips16InstrInfo(MipsTargetMachine &tm)
40263508Sdim  : MipsInstrInfo(tm, Mips::Bimm16),
41263508Sdim    RI(*tm.getSubtargetImpl()) {}
42239310Sdim
43239310Sdimconst MipsRegisterInfo &Mips16InstrInfo::getRegisterInfo() const {
44239310Sdim  return RI;
45239310Sdim}
46239310Sdim
47239310Sdim/// isLoadFromStackSlot - If the specified machine instruction is a direct
48239310Sdim/// load from a stack slot, return the virtual or physical register number of
49239310Sdim/// the destination along with the FrameIndex of the loaded stack slot.  If
50239310Sdim/// not, return 0.  This predicate must return 0 if the instruction has
51239310Sdim/// any side effects other than loading from the stack slot.
52239310Sdimunsigned Mips16InstrInfo::
53239310SdimisLoadFromStackSlot(const MachineInstr *MI, int &FrameIndex) const
54239310Sdim{
55239310Sdim  return 0;
56239310Sdim}
57239310Sdim
58239310Sdim/// isStoreToStackSlot - If the specified machine instruction is a direct
59239310Sdim/// store to a stack slot, return the virtual or physical register number of
60239310Sdim/// the source reg along with the FrameIndex of the loaded stack slot.  If
61239310Sdim/// not, return 0.  This predicate must return 0 if the instruction has
62239310Sdim/// any side effects other than storing to the stack slot.
63239310Sdimunsigned Mips16InstrInfo::
64239310SdimisStoreToStackSlot(const MachineInstr *MI, int &FrameIndex) const
65239310Sdim{
66239310Sdim  return 0;
67239310Sdim}
68239310Sdim
69239310Sdimvoid Mips16InstrInfo::copyPhysReg(MachineBasicBlock &MBB,
70239310Sdim                                  MachineBasicBlock::iterator I, DebugLoc DL,
71239310Sdim                                  unsigned DestReg, unsigned SrcReg,
72239310Sdim                                  bool KillSrc) const {
73243830Sdim  unsigned Opc = 0;
74239310Sdim
75243830Sdim  if (Mips::CPU16RegsRegClass.contains(DestReg) &&
76263508Sdim      Mips::GPR32RegClass.contains(SrcReg))
77243830Sdim    Opc = Mips::MoveR3216;
78263508Sdim  else if (Mips::GPR32RegClass.contains(DestReg) &&
79243830Sdim           Mips::CPU16RegsRegClass.contains(SrcReg))
80243830Sdim    Opc = Mips::Move32R16;
81263508Sdim  else if ((SrcReg == Mips::HI0) &&
82243830Sdim           (Mips::CPU16RegsRegClass.contains(DestReg)))
83243830Sdim    Opc = Mips::Mfhi16, SrcReg = 0;
84239310Sdim
85263508Sdim  else if ((SrcReg == Mips::LO0) &&
86243830Sdim           (Mips::CPU16RegsRegClass.contains(DestReg)))
87243830Sdim    Opc = Mips::Mflo16, SrcReg = 0;
88243830Sdim
89243830Sdim
90239310Sdim  assert(Opc && "Cannot copy registers");
91239310Sdim
92239310Sdim  MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(Opc));
93239310Sdim
94239310Sdim  if (DestReg)
95239310Sdim    MIB.addReg(DestReg, RegState::Define);
96239310Sdim
97239310Sdim  if (SrcReg)
98239310Sdim    MIB.addReg(SrcReg, getKillRegState(KillSrc));
99239310Sdim}
100239310Sdim
101239310Sdimvoid Mips16InstrInfo::
102249423SdimstoreRegToStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
103249423Sdim                unsigned SrcReg, bool isKill, int FI,
104249423Sdim                const TargetRegisterClass *RC, const TargetRegisterInfo *TRI,
105249423Sdim                int64_t Offset) const {
106243830Sdim  DebugLoc DL;
107243830Sdim  if (I != MBB.end()) DL = I->getDebugLoc();
108243830Sdim  MachineMemOperand *MMO = GetMemOperand(MBB, FI, MachineMemOperand::MOStore);
109243830Sdim  unsigned Opc = 0;
110243830Sdim  if (Mips::CPU16RegsRegClass.hasSubClassEq(RC))
111243830Sdim    Opc = Mips::SwRxSpImmX16;
112243830Sdim  assert(Opc && "Register class not handled!");
113263508Sdim  BuildMI(MBB, I, DL, get(Opc)).addReg(SrcReg, getKillRegState(isKill)).
114263508Sdim      addFrameIndex(FI).addImm(Offset)
115263508Sdim      .addMemOperand(MMO);
116239310Sdim}
117239310Sdim
118239310Sdimvoid Mips16InstrInfo::
119249423SdimloadRegFromStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
120249423Sdim                 unsigned DestReg, int FI, const TargetRegisterClass *RC,
121249423Sdim                 const TargetRegisterInfo *TRI, int64_t Offset) const {
122243830Sdim  DebugLoc DL;
123243830Sdim  if (I != MBB.end()) DL = I->getDebugLoc();
124243830Sdim  MachineMemOperand *MMO = GetMemOperand(MBB, FI, MachineMemOperand::MOLoad);
125243830Sdim  unsigned Opc = 0;
126243830Sdim
127243830Sdim  if (Mips::CPU16RegsRegClass.hasSubClassEq(RC))
128243830Sdim    Opc = Mips::LwRxSpImmX16;
129243830Sdim  assert(Opc && "Register class not handled!");
130249423Sdim  BuildMI(MBB, I, DL, get(Opc), DestReg).addFrameIndex(FI).addImm(Offset)
131243830Sdim    .addMemOperand(MMO);
132239310Sdim}
133239310Sdim
134239310Sdimbool Mips16InstrInfo::expandPostRAPseudo(MachineBasicBlock::iterator MI) const {
135239310Sdim  MachineBasicBlock &MBB = *MI->getParent();
136239310Sdim  switch(MI->getDesc().getOpcode()) {
137239310Sdim  default:
138239310Sdim    return false;
139239310Sdim  case Mips::RetRA16:
140243830Sdim    ExpandRetRA16(MBB, MI, Mips::JrcRa16);
141239310Sdim    break;
142239310Sdim  }
143239310Sdim
144239310Sdim  MBB.erase(MI);
145239310Sdim  return true;
146239310Sdim}
147239310Sdim
148239310Sdim/// GetOppositeBranchOpc - Return the inverse of the specified
149239310Sdim/// opcode, e.g. turning BEQ to BNE.
150263508Sdimunsigned Mips16InstrInfo::getOppositeBranchOpc(unsigned Opc) const {
151243830Sdim  switch (Opc) {
152243830Sdim  default:  llvm_unreachable("Illegal opcode!");
153243830Sdim  case Mips::BeqzRxImmX16: return Mips::BnezRxImmX16;
154243830Sdim  case Mips::BnezRxImmX16: return Mips::BeqzRxImmX16;
155263508Sdim  case Mips::BeqzRxImm16: return Mips::BnezRxImm16;
156263508Sdim  case Mips::BnezRxImm16: return Mips::BeqzRxImm16;
157243830Sdim  case Mips::BteqzT8CmpX16: return Mips::BtnezT8CmpX16;
158243830Sdim  case Mips::BteqzT8SltX16: return Mips::BtnezT8SltX16;
159243830Sdim  case Mips::BteqzT8SltiX16: return Mips::BtnezT8SltiX16;
160263508Sdim  case Mips::Btnez16: return Mips::Bteqz16;
161243830Sdim  case Mips::BtnezX16: return Mips::BteqzX16;
162243830Sdim  case Mips::BtnezT8CmpiX16: return Mips::BteqzT8CmpiX16;
163243830Sdim  case Mips::BtnezT8SltuX16: return Mips::BteqzT8SltuX16;
164243830Sdim  case Mips::BtnezT8SltiuX16: return Mips::BteqzT8SltiuX16;
165263508Sdim  case Mips::Bteqz16: return Mips::Btnez16;
166243830Sdim  case Mips::BteqzX16: return Mips::BtnezX16;
167243830Sdim  case Mips::BteqzT8CmpiX16: return Mips::BtnezT8CmpiX16;
168243830Sdim  case Mips::BteqzT8SltuX16: return Mips::BtnezT8SltuX16;
169243830Sdim  case Mips::BteqzT8SltiuX16: return Mips::BtnezT8SltiuX16;
170243830Sdim  case Mips::BtnezT8CmpX16: return Mips::BteqzT8CmpX16;
171243830Sdim  case Mips::BtnezT8SltX16: return Mips::BteqzT8SltX16;
172243830Sdim  case Mips::BtnezT8SltiX16: return Mips::BteqzT8SltiX16;
173243830Sdim  }
174239310Sdim  assert(false && "Implement this function.");
175239310Sdim  return 0;
176239310Sdim}
177239310Sdim
178249423Sdim// Adjust SP by FrameSize bytes. Save RA, S0, S1
179249423Sdimvoid Mips16InstrInfo::makeFrame(unsigned SP, int64_t FrameSize,
180249423Sdim                    MachineBasicBlock &MBB,
181249423Sdim                    MachineBasicBlock::iterator I) const {
182249423Sdim  DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc();
183249423Sdim  if (!NeverUseSaveRestore) {
184249423Sdim    if (isUInt<11>(FrameSize))
185249423Sdim      BuildMI(MBB, I, DL, get(Mips::SaveRaF16)).addImm(FrameSize);
186249423Sdim    else {
187249423Sdim      int Base = 2040; // should create template function like isUInt that
188249423Sdim                       // returns largest possible n bit unsigned integer
189249423Sdim      int64_t Remainder = FrameSize - Base;
190249423Sdim      BuildMI(MBB, I, DL, get(Mips::SaveRaF16)). addImm(Base);
191249423Sdim      if (isInt<16>(-Remainder))
192249423Sdim        BuildAddiuSpImm(MBB, I, -Remainder);
193249423Sdim      else
194249423Sdim        adjustStackPtrBig(SP, -Remainder, MBB, I, Mips::V0, Mips::V1);
195249423Sdim    }
196249423Sdim
197249423Sdim  }
198249423Sdim  else {
199249423Sdim    //
200249423Sdim    // sw ra, -4[sp]
201249423Sdim    // sw s1, -8[sp]
202249423Sdim    // sw s0, -12[sp]
203249423Sdim
204249423Sdim    MachineInstrBuilder MIB1 = BuildMI(MBB, I, DL, get(Mips::SwRxSpImmX16),
205249423Sdim                                       Mips::RA);
206249423Sdim    MIB1.addReg(Mips::SP);
207249423Sdim    MIB1.addImm(-4);
208249423Sdim    MachineInstrBuilder MIB2 = BuildMI(MBB, I, DL, get(Mips::SwRxSpImmX16),
209249423Sdim                                       Mips::S1);
210249423Sdim    MIB2.addReg(Mips::SP);
211249423Sdim    MIB2.addImm(-8);
212249423Sdim    MachineInstrBuilder MIB3 = BuildMI(MBB, I, DL, get(Mips::SwRxSpImmX16),
213249423Sdim                                       Mips::S0);
214249423Sdim    MIB3.addReg(Mips::SP);
215249423Sdim    MIB3.addImm(-12);
216249423Sdim    adjustStackPtrBig(SP, -FrameSize, MBB, I, Mips::V0, Mips::V1);
217249423Sdim  }
218249423Sdim}
219249423Sdim
220249423Sdim// Adjust SP by FrameSize bytes. Restore RA, S0, S1
221249423Sdimvoid Mips16InstrInfo::restoreFrame(unsigned SP, int64_t FrameSize,
222249423Sdim                                   MachineBasicBlock &MBB,
223249423Sdim                                   MachineBasicBlock::iterator I) const {
224249423Sdim  DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc();
225249423Sdim  if (!NeverUseSaveRestore) {
226249423Sdim    if (isUInt<11>(FrameSize))
227249423Sdim      BuildMI(MBB, I, DL, get(Mips::RestoreRaF16)).addImm(FrameSize);
228249423Sdim    else {
229249423Sdim      int Base = 2040; // should create template function like isUInt that
230249423Sdim                       // returns largest possible n bit unsigned integer
231249423Sdim      int64_t Remainder = FrameSize - Base;
232249423Sdim      if (isInt<16>(Remainder))
233249423Sdim        BuildAddiuSpImm(MBB, I, Remainder);
234249423Sdim      else
235249423Sdim        adjustStackPtrBig(SP, Remainder, MBB, I, Mips::A0, Mips::A1);
236249423Sdim      BuildMI(MBB, I, DL, get(Mips::RestoreRaF16)). addImm(Base);
237249423Sdim    }
238249423Sdim  }
239249423Sdim  else {
240249423Sdim    adjustStackPtrBig(SP, FrameSize, MBB, I, Mips::A0, Mips::A1);
241249423Sdim    // lw ra, -4[sp]
242249423Sdim    // lw s1, -8[sp]
243249423Sdim    // lw s0, -12[sp]
244249423Sdim    MachineInstrBuilder MIB1 = BuildMI(MBB, I, DL, get(Mips::LwRxSpImmX16),
245249423Sdim                                       Mips::A0);
246249423Sdim    MIB1.addReg(Mips::SP);
247249423Sdim    MIB1.addImm(-4);
248249423Sdim    MachineInstrBuilder MIB0 = BuildMI(MBB, I, DL, get(Mips::Move32R16),
249249423Sdim                                       Mips::RA);
250249423Sdim     MIB0.addReg(Mips::A0);
251249423Sdim    MachineInstrBuilder MIB2 = BuildMI(MBB, I, DL, get(Mips::LwRxSpImmX16),
252249423Sdim                                       Mips::S1);
253249423Sdim    MIB2.addReg(Mips::SP);
254249423Sdim    MIB2.addImm(-8);
255249423Sdim    MachineInstrBuilder MIB3 = BuildMI(MBB, I, DL, get(Mips::LwRxSpImmX16),
256249423Sdim                                       Mips::S0);
257249423Sdim    MIB3.addReg(Mips::SP);
258249423Sdim    MIB3.addImm(-12);
259249423Sdim  }
260249423Sdim
261249423Sdim}
262249423Sdim
263249423Sdim// Adjust SP by Amount bytes where bytes can be up to 32bit number.
264249423Sdim// This can only be called at times that we know that there is at least one free
265249423Sdim// register.
266249423Sdim// This is clearly safe at prologue and epilogue.
267249423Sdim//
268249423Sdimvoid Mips16InstrInfo::adjustStackPtrBig(unsigned SP, int64_t Amount,
269249423Sdim                                        MachineBasicBlock &MBB,
270249423Sdim                                        MachineBasicBlock::iterator I,
271249423Sdim                                        unsigned Reg1, unsigned Reg2) const {
272249423Sdim  DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc();
273249423Sdim//  MachineRegisterInfo &RegInfo = MBB.getParent()->getRegInfo();
274249423Sdim//  unsigned Reg1 = RegInfo.createVirtualRegister(&Mips::CPU16RegsRegClass);
275249423Sdim//  unsigned Reg2 = RegInfo.createVirtualRegister(&Mips::CPU16RegsRegClass);
276249423Sdim  //
277249423Sdim  // li reg1, constant
278249423Sdim  // move reg2, sp
279249423Sdim  // add reg1, reg1, reg2
280249423Sdim  // move sp, reg1
281249423Sdim  //
282249423Sdim  //
283249423Sdim  MachineInstrBuilder MIB1 = BuildMI(MBB, I, DL, get(Mips::LwConstant32), Reg1);
284249423Sdim  MIB1.addImm(Amount);
285249423Sdim  MachineInstrBuilder MIB2 = BuildMI(MBB, I, DL, get(Mips::MoveR3216), Reg2);
286249423Sdim  MIB2.addReg(Mips::SP, RegState::Kill);
287249423Sdim  MachineInstrBuilder MIB3 = BuildMI(MBB, I, DL, get(Mips::AdduRxRyRz16), Reg1);
288249423Sdim  MIB3.addReg(Reg1);
289249423Sdim  MIB3.addReg(Reg2, RegState::Kill);
290249423Sdim  MachineInstrBuilder MIB4 = BuildMI(MBB, I, DL, get(Mips::Move32R16),
291249423Sdim                                                     Mips::SP);
292249423Sdim  MIB4.addReg(Reg1, RegState::Kill);
293249423Sdim}
294249423Sdim
295249423Sdimvoid Mips16InstrInfo::adjustStackPtrBigUnrestricted(unsigned SP, int64_t Amount,
296249423Sdim                    MachineBasicBlock &MBB,
297249423Sdim                    MachineBasicBlock::iterator I) const {
298249423Sdim   assert(false && "adjust stack pointer amount exceeded");
299249423Sdim}
300249423Sdim
301243830Sdim/// Adjust SP by Amount bytes.
302243830Sdimvoid Mips16InstrInfo::adjustStackPtr(unsigned SP, int64_t Amount,
303243830Sdim                                     MachineBasicBlock &MBB,
304243830Sdim                                     MachineBasicBlock::iterator I) const {
305249423Sdim  if (isInt<16>(Amount))  // need to change to addiu sp, ....and isInt<16>
306249423Sdim    BuildAddiuSpImm(MBB, I, Amount);
307249423Sdim  else
308249423Sdim    adjustStackPtrBigUnrestricted(SP, Amount, MBB, I);
309249423Sdim}
310249423Sdim
311249423Sdim/// This function generates the sequence of instructions needed to get the
312249423Sdim/// result of adding register REG and immediate IMM.
313249423Sdimunsigned
314249423SdimMips16InstrInfo::loadImmediate(unsigned FrameReg,
315249423Sdim                               int64_t Imm, MachineBasicBlock &MBB,
316249423Sdim                               MachineBasicBlock::iterator II, DebugLoc DL,
317249423Sdim                               unsigned &NewImm) const {
318249423Sdim  //
319249423Sdim  // given original instruction is:
320249423Sdim  // Instr rx, T[offset] where offset is too big.
321249423Sdim  //
322249423Sdim  // lo = offset & 0xFFFF
323249423Sdim  // hi = ((offset >> 16) + (lo >> 15)) & 0xFFFF;
324249423Sdim  //
325249423Sdim  // let T = temporary register
326249423Sdim  // li T, hi
327249423Sdim  // shl T, 16
328249423Sdim  // add T, Rx, T
329249423Sdim  //
330249423Sdim  RegScavenger rs;
331249423Sdim  int32_t lo = Imm & 0xFFFF;
332249423Sdim  NewImm = lo;
333263508Sdim  int Reg =0;
334263508Sdim  int SpReg = 0;
335263508Sdim
336249423Sdim  rs.enterBasicBlock(&MBB);
337249423Sdim  rs.forward(II);
338249423Sdim  //
339263508Sdim  // We need to know which registers can be used, in the case where there
340263508Sdim  // are not enough free registers. We exclude all registers that
341263508Sdim  // are used in the instruction that we are helping.
342263508Sdim  //  // Consider all allocatable registers in the register class initially
343263508Sdim  BitVector Candidates =
344263508Sdim      RI.getAllocatableSet
345263508Sdim      (*II->getParent()->getParent(), &Mips::CPU16RegsRegClass);
346263508Sdim  // Exclude all the registers being used by the instruction.
347263508Sdim  for (unsigned i = 0, e = II->getNumOperands(); i != e; ++i) {
348263508Sdim    MachineOperand &MO = II->getOperand(i);
349263508Sdim    if (MO.isReg() && MO.getReg() != 0 && !MO.isDef() &&
350263508Sdim        !TargetRegisterInfo::isVirtualRegister(MO.getReg()))
351263508Sdim      Candidates.reset(MO.getReg());
352263508Sdim  }
353263508Sdim  //
354263508Sdim  // If the same register was used and defined in an instruction, then
355263508Sdim  // it will not be in the list of candidates.
356263508Sdim  //
357263508Sdim  // we need to analyze the instruction that we are helping.
358263508Sdim  // we need to know if it defines register x but register x is not
359263508Sdim  // present as an operand of the instruction. this tells
360263508Sdim  // whether the register is live before the instruction. if it's not
361263508Sdim  // then we don't need to save it in case there are no free registers.
362263508Sdim  //
363263508Sdim  int DefReg = 0;
364263508Sdim  for (unsigned i = 0, e = II->getNumOperands(); i != e; ++i) {
365263508Sdim    MachineOperand &MO = II->getOperand(i);
366263508Sdim    if (MO.isReg() && MO.isDef()) {
367263508Sdim      DefReg = MO.getReg();
368263508Sdim      break;
369263508Sdim    }
370263508Sdim  }
371263508Sdim  //
372263508Sdim  BitVector Available = rs.getRegsAvailable(&Mips::CPU16RegsRegClass);
373263508Sdim
374263508Sdim  Available &= Candidates;
375263508Sdim  //
376249423Sdim  // we use T0 for the first register, if we need to save something away.
377249423Sdim  // we use T1 for the second register, if we need to save something away.
378249423Sdim  //
379249423Sdim  unsigned FirstRegSaved =0, SecondRegSaved=0;
380249423Sdim  unsigned FirstRegSavedTo = 0, SecondRegSavedTo = 0;
381249423Sdim
382263508Sdim
383263508Sdim  Reg = Available.find_first();
384263508Sdim
385263508Sdim  if (Reg == -1) {
386263508Sdim    Reg = Candidates.find_first();
387263508Sdim    Candidates.reset(Reg);
388263508Sdim    if (DefReg != Reg) {
389263508Sdim      FirstRegSaved = Reg;
390263508Sdim      FirstRegSavedTo = Mips::T0;
391263508Sdim      copyPhysReg(MBB, II, DL, FirstRegSavedTo, FirstRegSaved, true);
392263508Sdim    }
393243830Sdim  }
394243830Sdim  else
395263508Sdim    Available.reset(Reg);
396263508Sdim  BuildMI(MBB, II, DL, get(Mips::LwConstant32), Reg).addImm(Imm);
397263508Sdim  NewImm = 0;
398249423Sdim  if (FrameReg == Mips::SP) {
399263508Sdim    SpReg = Available.find_first();
400263508Sdim    if (SpReg == -1) {
401263508Sdim      SpReg = Candidates.find_first();
402263508Sdim      // Candidates.reset(SpReg); // not really needed
403263508Sdim      if (DefReg!= SpReg) {
404263508Sdim        SecondRegSaved = SpReg;
405249423Sdim        SecondRegSavedTo = Mips::T1;
406249423Sdim      }
407263508Sdim      if (SecondRegSaved)
408263508Sdim        copyPhysReg(MBB, II, DL, SecondRegSavedTo, SecondRegSaved, true);
409249423Sdim    }
410263508Sdim   else
411263508Sdim     Available.reset(SpReg);
412249423Sdim    copyPhysReg(MBB, II, DL, SpReg, Mips::SP, false);
413263508Sdim    BuildMI(MBB, II, DL, get(Mips::  AdduRxRyRz16), Reg).addReg(SpReg, RegState::Kill)
414249423Sdim      .addReg(Reg);
415249423Sdim  }
416249423Sdim  else
417249423Sdim    BuildMI(MBB, II, DL, get(Mips::  AdduRxRyRz16), Reg).addReg(FrameReg)
418249423Sdim      .addReg(Reg, RegState::Kill);
419249423Sdim  if (FirstRegSaved || SecondRegSaved) {
420249423Sdim    II = llvm::next(II);
421249423Sdim    if (FirstRegSaved)
422249423Sdim      copyPhysReg(MBB, II, DL, FirstRegSaved, FirstRegSavedTo, true);
423249423Sdim    if (SecondRegSaved)
424249423Sdim      copyPhysReg(MBB, II, DL, SecondRegSaved, SecondRegSavedTo, true);
425249423Sdim  }
426249423Sdim  return Reg;
427243830Sdim}
428243830Sdim
429263508Sdim/// This function generates the sequence of instructions needed to get the
430263508Sdim/// result of adding register REG and immediate IMM.
431263508Sdimunsigned
432263508SdimMips16InstrInfo::basicLoadImmediate(
433263508Sdim  unsigned FrameReg,
434263508Sdim  int64_t Imm, MachineBasicBlock &MBB,
435263508Sdim  MachineBasicBlock::iterator II, DebugLoc DL,
436263508Sdim  unsigned &NewImm) const {
437263508Sdim  const TargetRegisterClass *RC = &Mips::CPU16RegsRegClass;
438263508Sdim  MachineRegisterInfo &RegInfo = MBB.getParent()->getRegInfo();
439263508Sdim  unsigned Reg = RegInfo.createVirtualRegister(RC);
440263508Sdim  BuildMI(MBB, II, DL, get(Mips::LwConstant32), Reg).addImm(Imm);
441263508Sdim  NewImm = 0;
442263508Sdim  return Reg;
443263508Sdim}
444263508Sdim
445263508Sdimunsigned Mips16InstrInfo::getAnalyzableBrOpc(unsigned Opc) const {
446243830Sdim  return (Opc == Mips::BeqzRxImmX16   || Opc == Mips::BimmX16  ||
447263508Sdim          Opc == Mips::Bimm16  ||
448263508Sdim          Opc == Mips::Bteqz16        || Opc == Mips::Btnez16 ||
449263508Sdim          Opc == Mips::BeqzRxImm16    || Opc == Mips::BnezRxImm16   ||
450243830Sdim          Opc == Mips::BnezRxImmX16   || Opc == Mips::BteqzX16 ||
451243830Sdim          Opc == Mips::BteqzT8CmpX16  || Opc == Mips::BteqzT8CmpiX16 ||
452243830Sdim          Opc == Mips::BteqzT8SltX16  || Opc == Mips::BteqzT8SltuX16  ||
453243830Sdim          Opc == Mips::BteqzT8SltiX16 || Opc == Mips::BteqzT8SltiuX16 ||
454243830Sdim          Opc == Mips::BtnezX16       || Opc == Mips::BtnezT8CmpX16 ||
455243830Sdim          Opc == Mips::BtnezT8CmpiX16 || Opc == Mips::BtnezT8SltX16 ||
456243830Sdim          Opc == Mips::BtnezT8SltuX16 || Opc == Mips::BtnezT8SltiX16 ||
457243830Sdim          Opc == Mips::BtnezT8SltiuX16 ) ? Opc : 0;
458239310Sdim}
459239310Sdim
460239310Sdimvoid Mips16InstrInfo::ExpandRetRA16(MachineBasicBlock &MBB,
461239310Sdim                                  MachineBasicBlock::iterator I,
462239310Sdim                                  unsigned Opc) const {
463239310Sdim  BuildMI(MBB, I, I->getDebugLoc(), get(Opc));
464239310Sdim}
465239310Sdim
466249423Sdim
467249423Sdimconst MCInstrDesc &Mips16InstrInfo::AddiuSpImm(int64_t Imm) const {
468249423Sdim  if (validSpImm8(Imm))
469249423Sdim    return get(Mips::AddiuSpImm16);
470249423Sdim  else
471249423Sdim    return get(Mips::AddiuSpImmX16);
472249423Sdim}
473249423Sdim
474249423Sdimvoid Mips16InstrInfo::BuildAddiuSpImm
475249423Sdim  (MachineBasicBlock &MBB, MachineBasicBlock::iterator I, int64_t Imm) const {
476249423Sdim  DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc();
477249423Sdim  BuildMI(MBB, I, DL, AddiuSpImm(Imm)).addImm(Imm);
478249423Sdim}
479249423Sdim
480239310Sdimconst MipsInstrInfo *llvm::createMips16InstrInfo(MipsTargetMachine &TM) {
481239310Sdim  return new Mips16InstrInfo(TM);
482239310Sdim}
483263508Sdim
484263508Sdimbool Mips16InstrInfo::validImmediate(unsigned Opcode, unsigned Reg,
485263508Sdim                                     int64_t Amount) {
486263508Sdim  switch (Opcode) {
487263508Sdim  case Mips::LbRxRyOffMemX16:
488263508Sdim  case Mips::LbuRxRyOffMemX16:
489263508Sdim  case Mips::LhRxRyOffMemX16:
490263508Sdim  case Mips::LhuRxRyOffMemX16:
491263508Sdim  case Mips::SbRxRyOffMemX16:
492263508Sdim  case Mips::ShRxRyOffMemX16:
493263508Sdim  case Mips::LwRxRyOffMemX16:
494263508Sdim  case Mips::SwRxRyOffMemX16:
495263508Sdim  case Mips::SwRxSpImmX16:
496263508Sdim  case Mips::LwRxSpImmX16:
497263508Sdim    return isInt<16>(Amount);
498263508Sdim  case Mips::AddiuRxRyOffMemX16:
499263508Sdim    if ((Reg == Mips::PC) || (Reg == Mips::SP))
500263508Sdim      return isInt<16>(Amount);
501263508Sdim    return isInt<15>(Amount);
502263508Sdim  }
503263508Sdim  llvm_unreachable("unexpected Opcode in validImmediate");
504263508Sdim}
505263508Sdim
506263508Sdim/// Measure the specified inline asm to determine an approximation of its
507263508Sdim/// length.
508263508Sdim/// Comments (which run till the next SeparatorString or newline) do not
509263508Sdim/// count as an instruction.
510263508Sdim/// Any other non-whitespace text is considered an instruction, with
511263508Sdim/// multiple instructions separated by SeparatorString or newlines.
512263508Sdim/// Variable-length instructions are not handled here; this function
513263508Sdim/// may be overloaded in the target code to do that.
514263508Sdim/// We implement the special case of the .space directive taking only an
515263508Sdim/// integer argument, which is the size in bytes. This is used for creating
516263508Sdim/// inline code spacing for testing purposes using inline assembly.
517263508Sdim///
518263508Sdimunsigned Mips16InstrInfo::getInlineAsmLength(const char *Str,
519263508Sdim                                             const MCAsmInfo &MAI) const {
520263508Sdim
521263508Sdim
522263508Sdim  // Count the number of instructions in the asm.
523263508Sdim  bool atInsnStart = true;
524263508Sdim  unsigned Length = 0;
525263508Sdim  for (; *Str; ++Str) {
526263508Sdim    if (*Str == '\n' || strncmp(Str, MAI.getSeparatorString(),
527263508Sdim                                strlen(MAI.getSeparatorString())) == 0)
528263508Sdim      atInsnStart = true;
529263508Sdim    if (atInsnStart && !std::isspace(static_cast<unsigned char>(*Str))) {
530263508Sdim      if (strncmp(Str, ".space", 6)==0) {
531263508Sdim        char *EStr; int Sz;
532263508Sdim        Sz = strtol(Str+6, &EStr, 10);
533263508Sdim        while (isspace(*EStr)) ++EStr;
534263508Sdim        if (*EStr=='\0') {
535263508Sdim          DEBUG(dbgs() << "parsed .space " << Sz << '\n');
536263508Sdim          return Sz;
537263508Sdim        }
538263508Sdim      }
539263508Sdim      Length += MAI.getMaxInstLength();
540263508Sdim      atInsnStart = false;
541263508Sdim    }
542263508Sdim    if (atInsnStart && strncmp(Str, MAI.getCommentString(),
543263508Sdim                               strlen(MAI.getCommentString())) == 0)
544263508Sdim      atInsnStart = false;
545263508Sdim  }
546263508Sdim
547263508Sdim  return Length;
548263508Sdim}
549