Mips16InstrInfo.cpp revision 61b97b8c1721ba45e5c10ca307ceebe1efdf72a9
1//===-- Mips16InstrInfo.cpp - Mips16 Instruction Information --------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file contains the Mips16 implementation of the TargetInstrInfo class.
11//
12//===----------------------------------------------------------------------===//
13
14#include "Mips16InstrInfo.h"
15#include "InstPrinter/MipsInstPrinter.h"
16#include "MipsMachineFunction.h"
17#include "MipsTargetMachine.h"
18#include "llvm/ADT/STLExtras.h"
19#include "llvm/ADT/StringRef.h"
20#include "llvm/CodeGen/MachineInstrBuilder.h"
21#include "llvm/CodeGen/MachineRegisterInfo.h"
22#include "llvm/CodeGen/RegisterScavenging.h"
23#include "llvm/Support/CommandLine.h"
24#include "llvm/Support/ErrorHandling.h"
25#include "llvm/Support/TargetRegistry.h"
26
27using namespace llvm;
28
29static cl::opt<bool> NeverUseSaveRestore(
30  "mips16-never-use-save-restore",
31  cl::init(false),
32  cl::desc("For testing ability to adjust stack pointer "
33           "without save/restore instruction"),
34  cl::Hidden);
35
36
37Mips16InstrInfo::Mips16InstrInfo(MipsTargetMachine &tm)
38  : MipsInstrInfo(tm, Mips::BimmX16),
39    RI(*tm.getSubtargetImpl(), *this) {}
40
41const MipsRegisterInfo &Mips16InstrInfo::getRegisterInfo() const {
42  return RI;
43}
44
45/// isLoadFromStackSlot - If the specified machine instruction is a direct
46/// load from a stack slot, return the virtual or physical register number of
47/// the destination along with the FrameIndex of the loaded stack slot.  If
48/// not, return 0.  This predicate must return 0 if the instruction has
49/// any side effects other than loading from the stack slot.
50unsigned Mips16InstrInfo::
51isLoadFromStackSlot(const MachineInstr *MI, int &FrameIndex) const
52{
53  return 0;
54}
55
56/// isStoreToStackSlot - If the specified machine instruction is a direct
57/// store to a stack slot, return the virtual or physical register number of
58/// the source reg along with the FrameIndex of the loaded stack slot.  If
59/// not, return 0.  This predicate must return 0 if the instruction has
60/// any side effects other than storing to the stack slot.
61unsigned Mips16InstrInfo::
62isStoreToStackSlot(const MachineInstr *MI, int &FrameIndex) const
63{
64  return 0;
65}
66
67void Mips16InstrInfo::copyPhysReg(MachineBasicBlock &MBB,
68                                  MachineBasicBlock::iterator I, DebugLoc DL,
69                                  unsigned DestReg, unsigned SrcReg,
70                                  bool KillSrc) const {
71  unsigned Opc = 0;
72
73  if (Mips::CPU16RegsRegClass.contains(DestReg) &&
74      Mips::CPURegsRegClass.contains(SrcReg))
75    Opc = Mips::MoveR3216;
76  else if (Mips::CPURegsRegClass.contains(DestReg) &&
77           Mips::CPU16RegsRegClass.contains(SrcReg))
78    Opc = Mips::Move32R16;
79  else if ((SrcReg == Mips::HI) &&
80           (Mips::CPU16RegsRegClass.contains(DestReg)))
81    Opc = Mips::Mfhi16, SrcReg = 0;
82
83  else if ((SrcReg == Mips::LO) &&
84           (Mips::CPU16RegsRegClass.contains(DestReg)))
85    Opc = Mips::Mflo16, SrcReg = 0;
86
87
88  assert(Opc && "Cannot copy registers");
89
90  MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(Opc));
91
92  if (DestReg)
93    MIB.addReg(DestReg, RegState::Define);
94
95  if (SrcReg)
96    MIB.addReg(SrcReg, getKillRegState(KillSrc));
97}
98
99void Mips16InstrInfo::
100storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
101                    unsigned SrcReg, bool isKill, int FI,
102                    const TargetRegisterClass *RC,
103                    const TargetRegisterInfo *TRI) const {
104  DebugLoc DL;
105  if (I != MBB.end()) DL = I->getDebugLoc();
106  MachineMemOperand *MMO = GetMemOperand(MBB, FI, MachineMemOperand::MOStore);
107  unsigned Opc = 0;
108  if (Mips::CPU16RegsRegClass.hasSubClassEq(RC))
109    Opc = Mips::SwRxSpImmX16;
110  assert(Opc && "Register class not handled!");
111  BuildMI(MBB, I, DL, get(Opc)).addReg(SrcReg, getKillRegState(isKill))
112    .addFrameIndex(FI).addImm(0).addMemOperand(MMO);
113}
114
115void Mips16InstrInfo::
116loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
117                     unsigned DestReg, int FI,
118                     const TargetRegisterClass *RC,
119                     const TargetRegisterInfo *TRI) const {
120  DebugLoc DL;
121  if (I != MBB.end()) DL = I->getDebugLoc();
122  MachineMemOperand *MMO = GetMemOperand(MBB, FI, MachineMemOperand::MOLoad);
123  unsigned Opc = 0;
124
125  if (Mips::CPU16RegsRegClass.hasSubClassEq(RC))
126    Opc = Mips::LwRxSpImmX16;
127  assert(Opc && "Register class not handled!");
128  BuildMI(MBB, I, DL, get(Opc), DestReg).addFrameIndex(FI).addImm(0)
129    .addMemOperand(MMO);
130}
131
132bool Mips16InstrInfo::expandPostRAPseudo(MachineBasicBlock::iterator MI) const {
133  MachineBasicBlock &MBB = *MI->getParent();
134
135  switch(MI->getDesc().getOpcode()) {
136  default:
137    return false;
138  case Mips::RetRA16:
139    ExpandRetRA16(MBB, MI, Mips::JrcRa16);
140    break;
141  }
142
143  MBB.erase(MI);
144  return true;
145}
146
147/// GetOppositeBranchOpc - Return the inverse of the specified
148/// opcode, e.g. turning BEQ to BNE.
149unsigned Mips16InstrInfo::GetOppositeBranchOpc(unsigned Opc) const {
150  switch (Opc) {
151  default:  llvm_unreachable("Illegal opcode!");
152  case Mips::BeqzRxImmX16: return Mips::BnezRxImmX16;
153  case Mips::BnezRxImmX16: return Mips::BeqzRxImmX16;
154  case Mips::BteqzT8CmpX16: return Mips::BtnezT8CmpX16;
155  case Mips::BteqzT8SltX16: return Mips::BtnezT8SltX16;
156  case Mips::BteqzT8SltiX16: return Mips::BtnezT8SltiX16;
157  case Mips::BtnezX16: return Mips::BteqzX16;
158  case Mips::BtnezT8CmpiX16: return Mips::BteqzT8CmpiX16;
159  case Mips::BtnezT8SltuX16: return Mips::BteqzT8SltuX16;
160  case Mips::BtnezT8SltiuX16: return Mips::BteqzT8SltiuX16;
161  case Mips::BteqzX16: return Mips::BtnezX16;
162  case Mips::BteqzT8CmpiX16: return Mips::BtnezT8CmpiX16;
163  case Mips::BteqzT8SltuX16: return Mips::BtnezT8SltuX16;
164  case Mips::BteqzT8SltiuX16: return Mips::BtnezT8SltiuX16;
165  case Mips::BtnezT8CmpX16: return Mips::BteqzT8CmpX16;
166  case Mips::BtnezT8SltX16: return Mips::BteqzT8SltX16;
167  case Mips::BtnezT8SltiX16: return Mips::BteqzT8SltiX16;
168  }
169  assert(false && "Implement this function.");
170  return 0;
171}
172
173// Adjust SP by FrameSize bytes. Save RA, S0, S1
174void Mips16InstrInfo::makeFrame(unsigned SP, int64_t FrameSize,
175                    MachineBasicBlock &MBB,
176                    MachineBasicBlock::iterator I) const {
177  DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc();
178  if (!NeverUseSaveRestore) {
179    if (isUInt<11>(FrameSize))
180      BuildMI(MBB, I, DL, get(Mips::SaveRaF16)).addImm(FrameSize);
181    else {
182      int Base = 2040; // should create template function like isUInt that
183                       // returns largest possible n bit unsigned integer
184      int64_t Remainder = FrameSize - Base;
185      BuildMI(MBB, I, DL, get(Mips::SaveRaF16)). addImm(Base);
186      if (isInt<16>(-Remainder))
187        BuildMI(MBB, I, DL, get(Mips::AddiuSpImmX16)). addImm(-Remainder);
188      else
189        adjustStackPtrBig(SP, -Remainder, MBB, I, Mips::V0, Mips::V1);
190    }
191
192  }
193  else {
194    //
195    // sw ra, -4[sp]
196    // sw s1, -8[sp]
197    // sw s0, -12[sp]
198
199    MachineInstrBuilder MIB1 = BuildMI(MBB, I, DL, get(Mips::SwRxSpImmX16),
200                                       Mips::RA);
201    MIB1.addReg(Mips::SP);
202    MIB1.addImm(-4);
203    MachineInstrBuilder MIB2 = BuildMI(MBB, I, DL, get(Mips::SwRxSpImmX16),
204                                       Mips::S1);
205    MIB2.addReg(Mips::SP);
206    MIB2.addImm(-8);
207    MachineInstrBuilder MIB3 = BuildMI(MBB, I, DL, get(Mips::SwRxSpImmX16),
208                                       Mips::S0);
209    MIB3.addReg(Mips::SP);
210    MIB3.addImm(-12);
211    adjustStackPtrBig(SP, -FrameSize, MBB, I, Mips::V0, Mips::V1);
212  }
213}
214
215// Adjust SP by FrameSize bytes. Restore RA, S0, S1
216void Mips16InstrInfo::restoreFrame(unsigned SP, int64_t FrameSize,
217                                   MachineBasicBlock &MBB,
218                                   MachineBasicBlock::iterator I) const {
219  DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc();
220  if (!NeverUseSaveRestore) {
221    if (isUInt<11>(FrameSize))
222      BuildMI(MBB, I, DL, get(Mips::RestoreRaF16)).addImm(FrameSize);
223    else {
224      int Base = 2040; // should create template function like isUInt that
225                       // returns largest possible n bit unsigned integer
226      int64_t Remainder = FrameSize - Base;
227      if (isInt<16>(Remainder))
228        BuildMI(MBB, I, DL, get(Mips::AddiuSpImmX16)). addImm(Remainder);
229      else
230        adjustStackPtrBig(SP, Remainder, MBB, I, Mips::A0, Mips::A1);
231      BuildMI(MBB, I, DL, get(Mips::RestoreRaF16)). addImm(Base);
232    }
233  }
234  else {
235    adjustStackPtrBig(SP, FrameSize, MBB, I, Mips::A0, Mips::A1);
236    // lw ra, -4[sp]
237    // lw s1, -8[sp]
238    // lw s0, -12[sp]
239    MachineInstrBuilder MIB1 = BuildMI(MBB, I, DL, get(Mips::LwRxSpImmX16),
240                                       Mips::A0);
241    MIB1.addReg(Mips::SP);
242    MIB1.addImm(-4);
243    MachineInstrBuilder MIB0 = BuildMI(MBB, I, DL, get(Mips::Move32R16),
244                                       Mips::RA);
245     MIB0.addReg(Mips::A0);
246    MachineInstrBuilder MIB2 = BuildMI(MBB, I, DL, get(Mips::LwRxSpImmX16),
247                                       Mips::S1);
248    MIB2.addReg(Mips::SP);
249    MIB2.addImm(-8);
250    MachineInstrBuilder MIB3 = BuildMI(MBB, I, DL, get(Mips::LwRxSpImmX16),
251                                       Mips::S0);
252    MIB3.addReg(Mips::SP);
253    MIB3.addImm(-12);
254  }
255
256}
257
258// Adjust SP by Amount bytes where bytes can be up to 32bit number.
259// This can only be called at times that we know that there is at least one free
260// register.
261// This is clearly safe at prologue and epilogue.
262//
263void Mips16InstrInfo::adjustStackPtrBig(unsigned SP, int64_t Amount,
264                                        MachineBasicBlock &MBB,
265                                        MachineBasicBlock::iterator I,
266                                        unsigned Reg1, unsigned Reg2) const {
267  DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc();
268//  MachineRegisterInfo &RegInfo = MBB.getParent()->getRegInfo();
269//  unsigned Reg1 = RegInfo.createVirtualRegister(&Mips::CPU16RegsRegClass);
270//  unsigned Reg2 = RegInfo.createVirtualRegister(&Mips::CPU16RegsRegClass);
271  //
272  // li reg1, constant
273  // move reg2, sp
274  // add reg1, reg1, reg2
275  // move sp, reg1
276  //
277  //
278  MachineInstrBuilder MIB1 = BuildMI(MBB, I, DL, get(Mips::LwConstant32), Reg1);
279  MIB1.addImm(Amount);
280  MachineInstrBuilder MIB2 = BuildMI(MBB, I, DL, get(Mips::MoveR3216), Reg2);
281  MIB2.addReg(Mips::SP, RegState::Kill);
282  MachineInstrBuilder MIB3 = BuildMI(MBB, I, DL, get(Mips::AdduRxRyRz16), Reg1);
283  MIB3.addReg(Reg1);
284  MIB3.addReg(Reg2, RegState::Kill);
285  MachineInstrBuilder MIB4 = BuildMI(MBB, I, DL, get(Mips::Move32R16),
286                                                     Mips::SP);
287  MIB4.addReg(Reg1, RegState::Kill);
288}
289
290void Mips16InstrInfo::adjustStackPtrBigUnrestricted(unsigned SP, int64_t Amount,
291                    MachineBasicBlock &MBB,
292                    MachineBasicBlock::iterator I) const {
293   assert(false && "adjust stack pointer amount exceeded");
294}
295
296/// Adjust SP by Amount bytes.
297void Mips16InstrInfo::adjustStackPtr(unsigned SP, int64_t Amount,
298                                     MachineBasicBlock &MBB,
299                                     MachineBasicBlock::iterator I) const {
300  DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc();
301  if (isInt<16>(Amount))  // need to change to addiu sp, ....and isInt<16>
302    BuildMI(MBB, I, DL, get(Mips::AddiuSpImmX16)). addImm(Amount);
303  else
304    adjustStackPtrBigUnrestricted(SP, Amount, MBB, I);
305}
306
307/// This function generates the sequence of instructions needed to get the
308/// result of adding register REG and immediate IMM.
309unsigned
310Mips16InstrInfo::loadImmediate(unsigned FrameReg,
311                               int64_t Imm, MachineBasicBlock &MBB,
312                               MachineBasicBlock::iterator II, DebugLoc DL,
313                               unsigned &NewImm) const {
314  //
315  // given original instruction is:
316  // Instr rx, T[offset] where offset is too big.
317  //
318  // lo = offset & 0xFFFF
319  // hi = ((offset >> 16) + (lo >> 15)) & 0xFFFF;
320  //
321  // let T = temporary register
322  // li T, hi
323  // shl T, 16
324  // add T, Rx, T
325  //
326  RegScavenger rs;
327  int32_t lo = Imm & 0xFFFF;
328  int32_t hi = ((Imm >> 16) + (lo >> 15)) & 0xFFFF;
329  NewImm = lo;
330  unsigned Reg =0;
331  unsigned SpReg = 0;
332  rs.enterBasicBlock(&MBB);
333  rs.forward(II);
334  //
335  // we use T0 for the first register, if we need to save something away.
336  // we use T1 for the second register, if we need to save something away.
337  //
338  unsigned FirstRegSaved =0, SecondRegSaved=0;
339  unsigned FirstRegSavedTo = 0, SecondRegSavedTo = 0;
340
341  Reg = rs.FindUnusedReg(&Mips::CPU16RegsRegClass);
342  if (Reg == 0) {
343    FirstRegSaved = Reg = Mips::V0;
344    FirstRegSavedTo = Mips::T0;
345    copyPhysReg(MBB, II, DL, FirstRegSavedTo, FirstRegSaved, true);
346  }
347  else
348    rs.setUsed(Reg);
349  BuildMI(MBB, II, DL, get(Mips::LiRxImmX16), Reg).addImm(hi);
350  BuildMI(MBB, II, DL, get(Mips::SllX16), Reg).addReg(Reg).
351    addImm(16);
352  if (FrameReg == Mips::SP) {
353    SpReg = rs.FindUnusedReg(&Mips::CPU16RegsRegClass);
354    if (SpReg == 0) {
355      if (Reg != Mips::V1) {
356        SecondRegSaved = SpReg = Mips::V1;
357        SecondRegSavedTo = Mips::T1;
358      }
359      else {
360        SecondRegSaved = SpReg = Mips::V0;
361        SecondRegSavedTo = Mips::T0;
362      }
363      copyPhysReg(MBB, II, DL, SecondRegSavedTo, SecondRegSaved, true);
364    }
365    else
366      rs.setUsed(SpReg);
367
368    copyPhysReg(MBB, II, DL, SpReg, Mips::SP, false);
369    BuildMI(MBB, II, DL, get(Mips::  AdduRxRyRz16), Reg).addReg(SpReg)
370      .addReg(Reg);
371  }
372  else
373    BuildMI(MBB, II, DL, get(Mips::  AdduRxRyRz16), Reg).addReg(FrameReg)
374      .addReg(Reg, RegState::Kill);
375  if (FirstRegSaved || SecondRegSaved) {
376    II = llvm::next(II);
377    if (FirstRegSaved)
378      copyPhysReg(MBB, II, DL, FirstRegSaved, FirstRegSavedTo, true);
379    if (SecondRegSaved)
380      copyPhysReg(MBB, II, DL, SecondRegSaved, SecondRegSavedTo, true);
381  }
382  return Reg;
383}
384
385unsigned Mips16InstrInfo::GetAnalyzableBrOpc(unsigned Opc) const {
386  return (Opc == Mips::BeqzRxImmX16   || Opc == Mips::BimmX16  ||
387          Opc == Mips::BnezRxImmX16   || Opc == Mips::BteqzX16 ||
388          Opc == Mips::BteqzT8CmpX16  || Opc == Mips::BteqzT8CmpiX16 ||
389          Opc == Mips::BteqzT8SltX16  || Opc == Mips::BteqzT8SltuX16  ||
390          Opc == Mips::BteqzT8SltiX16 || Opc == Mips::BteqzT8SltiuX16 ||
391          Opc == Mips::BtnezX16       || Opc == Mips::BtnezT8CmpX16 ||
392          Opc == Mips::BtnezT8CmpiX16 || Opc == Mips::BtnezT8SltX16 ||
393          Opc == Mips::BtnezT8SltuX16 || Opc == Mips::BtnezT8SltiX16 ||
394          Opc == Mips::BtnezT8SltiuX16 ) ? Opc : 0;
395}
396
397void Mips16InstrInfo::ExpandRetRA16(MachineBasicBlock &MBB,
398                                  MachineBasicBlock::iterator I,
399                                  unsigned Opc) const {
400  BuildMI(MBB, I, I->getDebugLoc(), get(Opc));
401}
402
403const MipsInstrInfo *llvm::createMips16InstrInfo(MipsTargetMachine &TM) {
404  return new Mips16InstrInfo(TM);
405}
406