Mips16InstrInfo.cpp revision 2de893210b0d4178edb4e3f2a965d57e97410341
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        BuildAddiuSpImm(MBB, I, -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        BuildAddiuSpImm(MBB, I, 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  if (isInt<16>(Amount))  // need to change to addiu sp, ....and isInt<16>
301    BuildAddiuSpImm(MBB, I, Amount);
302  else
303    adjustStackPtrBigUnrestricted(SP, Amount, MBB, I);
304}
305
306/// This function generates the sequence of instructions needed to get the
307/// result of adding register REG and immediate IMM.
308unsigned
309Mips16InstrInfo::loadImmediate(unsigned FrameReg,
310                               int64_t Imm, MachineBasicBlock &MBB,
311                               MachineBasicBlock::iterator II, DebugLoc DL,
312                               unsigned &NewImm) const {
313  //
314  // given original instruction is:
315  // Instr rx, T[offset] where offset is too big.
316  //
317  // lo = offset & 0xFFFF
318  // hi = ((offset >> 16) + (lo >> 15)) & 0xFFFF;
319  //
320  // let T = temporary register
321  // li T, hi
322  // shl T, 16
323  // add T, Rx, T
324  //
325  RegScavenger rs;
326  int32_t lo = Imm & 0xFFFF;
327  int32_t hi = ((Imm >> 16) + (lo >> 15)) & 0xFFFF;
328  NewImm = lo;
329  unsigned Reg =0;
330  unsigned SpReg = 0;
331  rs.enterBasicBlock(&MBB);
332  rs.forward(II);
333  //
334  // we use T0 for the first register, if we need to save something away.
335  // we use T1 for the second register, if we need to save something away.
336  //
337  unsigned FirstRegSaved =0, SecondRegSaved=0;
338  unsigned FirstRegSavedTo = 0, SecondRegSavedTo = 0;
339
340  Reg = rs.FindUnusedReg(&Mips::CPU16RegsRegClass);
341  if (Reg == 0) {
342    FirstRegSaved = Reg = Mips::V0;
343    FirstRegSavedTo = Mips::T0;
344    copyPhysReg(MBB, II, DL, FirstRegSavedTo, FirstRegSaved, true);
345  }
346  else
347    rs.setUsed(Reg);
348  BuildMI(MBB, II, DL, get(Mips::LiRxImmX16), Reg).addImm(hi);
349  BuildMI(MBB, II, DL, get(Mips::SllX16), Reg).addReg(Reg).
350    addImm(16);
351  if (FrameReg == Mips::SP) {
352    SpReg = rs.FindUnusedReg(&Mips::CPU16RegsRegClass);
353    if (SpReg == 0) {
354      if (Reg != Mips::V1) {
355        SecondRegSaved = SpReg = Mips::V1;
356        SecondRegSavedTo = Mips::T1;
357      }
358      else {
359        SecondRegSaved = SpReg = Mips::V0;
360        SecondRegSavedTo = Mips::T0;
361      }
362      copyPhysReg(MBB, II, DL, SecondRegSavedTo, SecondRegSaved, true);
363    }
364    else
365      rs.setUsed(SpReg);
366
367    copyPhysReg(MBB, II, DL, SpReg, Mips::SP, false);
368    BuildMI(MBB, II, DL, get(Mips::  AdduRxRyRz16), Reg).addReg(SpReg)
369      .addReg(Reg);
370  }
371  else
372    BuildMI(MBB, II, DL, get(Mips::  AdduRxRyRz16), Reg).addReg(FrameReg)
373      .addReg(Reg, RegState::Kill);
374  if (FirstRegSaved || SecondRegSaved) {
375    II = llvm::next(II);
376    if (FirstRegSaved)
377      copyPhysReg(MBB, II, DL, FirstRegSaved, FirstRegSavedTo, true);
378    if (SecondRegSaved)
379      copyPhysReg(MBB, II, DL, SecondRegSaved, SecondRegSavedTo, true);
380  }
381  return Reg;
382}
383
384unsigned Mips16InstrInfo::GetAnalyzableBrOpc(unsigned Opc) const {
385  return (Opc == Mips::BeqzRxImmX16   || Opc == Mips::BimmX16  ||
386          Opc == Mips::BnezRxImmX16   || Opc == Mips::BteqzX16 ||
387          Opc == Mips::BteqzT8CmpX16  || Opc == Mips::BteqzT8CmpiX16 ||
388          Opc == Mips::BteqzT8SltX16  || Opc == Mips::BteqzT8SltuX16  ||
389          Opc == Mips::BteqzT8SltiX16 || Opc == Mips::BteqzT8SltiuX16 ||
390          Opc == Mips::BtnezX16       || Opc == Mips::BtnezT8CmpX16 ||
391          Opc == Mips::BtnezT8CmpiX16 || Opc == Mips::BtnezT8SltX16 ||
392          Opc == Mips::BtnezT8SltuX16 || Opc == Mips::BtnezT8SltiX16 ||
393          Opc == Mips::BtnezT8SltiuX16 ) ? Opc : 0;
394}
395
396void Mips16InstrInfo::ExpandRetRA16(MachineBasicBlock &MBB,
397                                  MachineBasicBlock::iterator I,
398                                  unsigned Opc) const {
399  BuildMI(MBB, I, I->getDebugLoc(), get(Opc));
400}
401
402const MCInstrDesc &Mips16InstrInfo::AddiuSpImm(int64_t Imm) const {
403  if (validSpImm8(Imm))
404    return get(Mips::AddiuSpImm16);
405  else
406    return get(Mips::AddiuSpImmX16);
407}
408
409void Mips16InstrInfo::BuildAddiuSpImm
410  (MachineBasicBlock &MBB, MachineBasicBlock::iterator I, int64_t Imm) const {
411  DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc();
412  BuildMI(MBB, I, DL, AddiuSpImm(Imm)).addImm(Imm);
413}
414
415const MipsInstrInfo *llvm::createMips16InstrInfo(MipsTargetMachine &TM) {
416  return new Mips16InstrInfo(TM);
417}
418