1239310Sdim//===-- MipsSEFrameLowering.cpp - Mips32/64 Frame 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 Mips32/64 implementation of TargetFrameLowering class.
11239310Sdim//
12239310Sdim//===----------------------------------------------------------------------===//
13239310Sdim
14239310Sdim#include "MipsSEFrameLowering.h"
15249423Sdim#include "MCTargetDesc/MipsBaseInfo.h"
16239310Sdim#include "MipsAnalyzeImmediate.h"
17249423Sdim#include "MipsMachineFunction.h"
18239310Sdim#include "MipsSEInstrInfo.h"
19239310Sdim#include "llvm/CodeGen/MachineFrameInfo.h"
20239310Sdim#include "llvm/CodeGen/MachineFunction.h"
21239310Sdim#include "llvm/CodeGen/MachineInstrBuilder.h"
22239310Sdim#include "llvm/CodeGen/MachineModuleInfo.h"
23239310Sdim#include "llvm/CodeGen/MachineRegisterInfo.h"
24243830Sdim#include "llvm/CodeGen/RegisterScavenging.h"
25249423Sdim#include "llvm/IR/DataLayout.h"
26249423Sdim#include "llvm/IR/Function.h"
27249423Sdim#include "llvm/Support/CommandLine.h"
28239310Sdim#include "llvm/Target/TargetOptions.h"
29239310Sdim
30239310Sdimusing namespace llvm;
31239310Sdim
32249423Sdimnamespace {
33249423Sdimtypedef MachineBasicBlock::iterator Iter;
34249423Sdim
35263508Sdimstatic std::pair<unsigned, unsigned> getMFHiLoOpc(unsigned Src) {
36263508Sdim  if (Mips::ACC64RegClass.contains(Src))
37263508Sdim    return std::make_pair((unsigned)Mips::PseudoMFHI,
38263508Sdim                          (unsigned)Mips::PseudoMFLO);
39263508Sdim
40263508Sdim  if (Mips::ACC64DSPRegClass.contains(Src))
41263508Sdim    return std::make_pair((unsigned)Mips::MFHI_DSP, (unsigned)Mips::MFLO_DSP);
42263508Sdim
43263508Sdim  if (Mips::ACC128RegClass.contains(Src))
44263508Sdim    return std::make_pair((unsigned)Mips::PseudoMFHI64,
45263508Sdim                          (unsigned)Mips::PseudoMFLO64);
46263508Sdim
47263508Sdim  return std::make_pair(0, 0);
48263508Sdim}
49263508Sdim
50251662Sdim/// Helper class to expand pseudos.
51251662Sdimclass ExpandPseudo {
52249423Sdimpublic:
53251662Sdim  ExpandPseudo(MachineFunction &MF);
54249423Sdim  bool expand();
55249423Sdim
56249423Sdimprivate:
57249423Sdim  bool expandInstr(MachineBasicBlock &MBB, Iter I);
58251662Sdim  void expandLoadCCond(MachineBasicBlock &MBB, Iter I);
59251662Sdim  void expandStoreCCond(MachineBasicBlock &MBB, Iter I);
60251662Sdim  void expandLoadACC(MachineBasicBlock &MBB, Iter I, unsigned RegSize);
61263508Sdim  void expandStoreACC(MachineBasicBlock &MBB, Iter I, unsigned MFHiOpc,
62263508Sdim                      unsigned MFLoOpc, unsigned RegSize);
63251662Sdim  bool expandCopy(MachineBasicBlock &MBB, Iter I);
64263508Sdim  bool expandCopyACC(MachineBasicBlock &MBB, Iter I, unsigned MFHiOpc,
65263508Sdim                     unsigned MFLoOpc);
66249423Sdim
67249423Sdim  MachineFunction &MF;
68249423Sdim  MachineRegisterInfo &MRI;
69249423Sdim};
70249423Sdim}
71249423Sdim
72251662SdimExpandPseudo::ExpandPseudo(MachineFunction &MF_)
73263508Sdim  : MF(MF_), MRI(MF.getRegInfo()) {}
74249423Sdim
75251662Sdimbool ExpandPseudo::expand() {
76249423Sdim  bool Expanded = false;
77249423Sdim
78249423Sdim  for (MachineFunction::iterator BB = MF.begin(), BBEnd = MF.end();
79249423Sdim       BB != BBEnd; ++BB)
80249423Sdim    for (Iter I = BB->begin(), End = BB->end(); I != End;)
81249423Sdim      Expanded |= expandInstr(*BB, I++);
82249423Sdim
83249423Sdim  return Expanded;
84249423Sdim}
85249423Sdim
86251662Sdimbool ExpandPseudo::expandInstr(MachineBasicBlock &MBB, Iter I) {
87249423Sdim  switch(I->getOpcode()) {
88251662Sdim  case Mips::LOAD_CCOND_DSP:
89251662Sdim    expandLoadCCond(MBB, I);
90251662Sdim    break;
91251662Sdim  case Mips::STORE_CCOND_DSP:
92251662Sdim    expandStoreCCond(MBB, I);
93251662Sdim    break;
94263508Sdim  case Mips::LOAD_ACC64:
95263508Sdim  case Mips::LOAD_ACC64DSP:
96251662Sdim    expandLoadACC(MBB, I, 4);
97249423Sdim    break;
98263508Sdim  case Mips::LOAD_ACC128:
99251662Sdim    expandLoadACC(MBB, I, 8);
100249423Sdim    break;
101263508Sdim  case Mips::STORE_ACC64:
102263508Sdim    expandStoreACC(MBB, I, Mips::PseudoMFHI, Mips::PseudoMFLO, 4);
103249423Sdim    break;
104263508Sdim  case Mips::STORE_ACC64DSP:
105263508Sdim    expandStoreACC(MBB, I, Mips::MFHI_DSP, Mips::MFLO_DSP, 4);
106249423Sdim    break;
107263508Sdim  case Mips::STORE_ACC128:
108263508Sdim    expandStoreACC(MBB, I, Mips::PseudoMFHI64, Mips::PseudoMFLO64, 8);
109263508Sdim    break;
110251662Sdim  case TargetOpcode::COPY:
111251662Sdim    if (!expandCopy(MBB, I))
112251662Sdim      return false;
113249423Sdim    break;
114249423Sdim  default:
115249423Sdim    return false;
116249423Sdim  }
117249423Sdim
118249423Sdim  MBB.erase(I);
119249423Sdim  return true;
120249423Sdim}
121249423Sdim
122251662Sdimvoid ExpandPseudo::expandLoadCCond(MachineBasicBlock &MBB, Iter I) {
123251662Sdim  //  load $vr, FI
124251662Sdim  //  copy ccond, $vr
125251662Sdim
126251662Sdim  assert(I->getOperand(0).isReg() && I->getOperand(1).isFI());
127251662Sdim
128263508Sdim  const MipsSEInstrInfo &TII =
129263508Sdim    *static_cast<const MipsSEInstrInfo*>(MF.getTarget().getInstrInfo());
130263508Sdim  const MipsRegisterInfo &RegInfo =
131263508Sdim    *static_cast<const MipsRegisterInfo*>(MF.getTarget().getRegisterInfo());
132263508Sdim
133251662Sdim  const TargetRegisterClass *RC = RegInfo.intRegClass(4);
134251662Sdim  unsigned VR = MRI.createVirtualRegister(RC);
135251662Sdim  unsigned Dst = I->getOperand(0).getReg(), FI = I->getOperand(1).getIndex();
136251662Sdim
137251662Sdim  TII.loadRegFromStack(MBB, I, VR, FI, RC, &RegInfo, 0);
138251662Sdim  BuildMI(MBB, I, I->getDebugLoc(), TII.get(TargetOpcode::COPY), Dst)
139251662Sdim    .addReg(VR, RegState::Kill);
140251662Sdim}
141251662Sdim
142251662Sdimvoid ExpandPseudo::expandStoreCCond(MachineBasicBlock &MBB, Iter I) {
143251662Sdim  //  copy $vr, ccond
144251662Sdim  //  store $vr, FI
145251662Sdim
146251662Sdim  assert(I->getOperand(0).isReg() && I->getOperand(1).isFI());
147251662Sdim
148263508Sdim  const MipsSEInstrInfo &TII =
149263508Sdim    *static_cast<const MipsSEInstrInfo*>(MF.getTarget().getInstrInfo());
150263508Sdim  const MipsRegisterInfo &RegInfo =
151263508Sdim    *static_cast<const MipsRegisterInfo*>(MF.getTarget().getRegisterInfo());
152263508Sdim
153251662Sdim  const TargetRegisterClass *RC = RegInfo.intRegClass(4);
154251662Sdim  unsigned VR = MRI.createVirtualRegister(RC);
155251662Sdim  unsigned Src = I->getOperand(0).getReg(), FI = I->getOperand(1).getIndex();
156251662Sdim
157251662Sdim  BuildMI(MBB, I, I->getDebugLoc(), TII.get(TargetOpcode::COPY), VR)
158251662Sdim    .addReg(Src, getKillRegState(I->getOperand(0).isKill()));
159251662Sdim  TII.storeRegToStack(MBB, I, VR, true, FI, RC, &RegInfo, 0);
160251662Sdim}
161251662Sdim
162251662Sdimvoid ExpandPseudo::expandLoadACC(MachineBasicBlock &MBB, Iter I,
163249423Sdim                                 unsigned RegSize) {
164249423Sdim  //  load $vr0, FI
165249423Sdim  //  copy lo, $vr0
166249423Sdim  //  load $vr1, FI + 4
167249423Sdim  //  copy hi, $vr1
168249423Sdim
169249423Sdim  assert(I->getOperand(0).isReg() && I->getOperand(1).isFI());
170249423Sdim
171263508Sdim  const MipsSEInstrInfo &TII =
172263508Sdim    *static_cast<const MipsSEInstrInfo*>(MF.getTarget().getInstrInfo());
173263508Sdim  const MipsRegisterInfo &RegInfo =
174263508Sdim    *static_cast<const MipsRegisterInfo*>(MF.getTarget().getRegisterInfo());
175263508Sdim
176249423Sdim  const TargetRegisterClass *RC = RegInfo.intRegClass(RegSize);
177249423Sdim  unsigned VR0 = MRI.createVirtualRegister(RC);
178249423Sdim  unsigned VR1 = MRI.createVirtualRegister(RC);
179249423Sdim  unsigned Dst = I->getOperand(0).getReg(), FI = I->getOperand(1).getIndex();
180249423Sdim  unsigned Lo = RegInfo.getSubReg(Dst, Mips::sub_lo);
181249423Sdim  unsigned Hi = RegInfo.getSubReg(Dst, Mips::sub_hi);
182249423Sdim  DebugLoc DL = I->getDebugLoc();
183249423Sdim  const MCInstrDesc &Desc = TII.get(TargetOpcode::COPY);
184249423Sdim
185249423Sdim  TII.loadRegFromStack(MBB, I, VR0, FI, RC, &RegInfo, 0);
186249423Sdim  BuildMI(MBB, I, DL, Desc, Lo).addReg(VR0, RegState::Kill);
187249423Sdim  TII.loadRegFromStack(MBB, I, VR1, FI, RC, &RegInfo, RegSize);
188249423Sdim  BuildMI(MBB, I, DL, Desc, Hi).addReg(VR1, RegState::Kill);
189249423Sdim}
190249423Sdim
191251662Sdimvoid ExpandPseudo::expandStoreACC(MachineBasicBlock &MBB, Iter I,
192263508Sdim                                  unsigned MFHiOpc, unsigned MFLoOpc,
193249423Sdim                                  unsigned RegSize) {
194263508Sdim  //  mflo $vr0, src
195249423Sdim  //  store $vr0, FI
196263508Sdim  //  mfhi $vr1, src
197249423Sdim  //  store $vr1, FI + 4
198249423Sdim
199249423Sdim  assert(I->getOperand(0).isReg() && I->getOperand(1).isFI());
200249423Sdim
201263508Sdim  const MipsSEInstrInfo &TII =
202263508Sdim    *static_cast<const MipsSEInstrInfo*>(MF.getTarget().getInstrInfo());
203263508Sdim  const MipsRegisterInfo &RegInfo =
204263508Sdim    *static_cast<const MipsRegisterInfo*>(MF.getTarget().getRegisterInfo());
205263508Sdim
206249423Sdim  const TargetRegisterClass *RC = RegInfo.intRegClass(RegSize);
207249423Sdim  unsigned VR0 = MRI.createVirtualRegister(RC);
208249423Sdim  unsigned VR1 = MRI.createVirtualRegister(RC);
209249423Sdim  unsigned Src = I->getOperand(0).getReg(), FI = I->getOperand(1).getIndex();
210249423Sdim  unsigned SrcKill = getKillRegState(I->getOperand(0).isKill());
211249423Sdim  DebugLoc DL = I->getDebugLoc();
212249423Sdim
213263508Sdim  BuildMI(MBB, I, DL, TII.get(MFLoOpc), VR0).addReg(Src);
214249423Sdim  TII.storeRegToStack(MBB, I, VR0, true, FI, RC, &RegInfo, 0);
215263508Sdim  BuildMI(MBB, I, DL, TII.get(MFHiOpc), VR1).addReg(Src, SrcKill);
216249423Sdim  TII.storeRegToStack(MBB, I, VR1, true, FI, RC, &RegInfo, RegSize);
217249423Sdim}
218249423Sdim
219251662Sdimbool ExpandPseudo::expandCopy(MachineBasicBlock &MBB, Iter I) {
220263508Sdim  unsigned Src = I->getOperand(1).getReg();
221263508Sdim  std::pair<unsigned, unsigned> Opcodes = getMFHiLoOpc(Src);
222251662Sdim
223263508Sdim  if (!Opcodes.first)
224263508Sdim    return false;
225251662Sdim
226263508Sdim  return expandCopyACC(MBB, I, Opcodes.first, Opcodes.second);
227251662Sdim}
228251662Sdim
229263508Sdimbool ExpandPseudo::expandCopyACC(MachineBasicBlock &MBB, Iter I,
230263508Sdim                                 unsigned MFHiOpc, unsigned MFLoOpc) {
231263508Sdim  //  mflo $vr0, src
232249423Sdim  //  copy dst_lo, $vr0
233263508Sdim  //  mfhi $vr1, src
234249423Sdim  //  copy dst_hi, $vr1
235249423Sdim
236263508Sdim  const MipsSEInstrInfo &TII =
237263508Sdim    *static_cast<const MipsSEInstrInfo*>(MF.getTarget().getInstrInfo());
238263508Sdim  const MipsRegisterInfo &RegInfo =
239263508Sdim    *static_cast<const MipsRegisterInfo*>(MF.getTarget().getRegisterInfo());
240263508Sdim
241263508Sdim  unsigned Dst = I->getOperand(0).getReg(), Src = I->getOperand(1).getReg();
242263508Sdim  unsigned VRegSize = RegInfo.getMinimalPhysRegClass(Dst)->getSize() / 2;
243263508Sdim  const TargetRegisterClass *RC = RegInfo.intRegClass(VRegSize);
244249423Sdim  unsigned VR0 = MRI.createVirtualRegister(RC);
245249423Sdim  unsigned VR1 = MRI.createVirtualRegister(RC);
246249423Sdim  unsigned SrcKill = getKillRegState(I->getOperand(1).isKill());
247249423Sdim  unsigned DstLo = RegInfo.getSubReg(Dst, Mips::sub_lo);
248249423Sdim  unsigned DstHi = RegInfo.getSubReg(Dst, Mips::sub_hi);
249249423Sdim  DebugLoc DL = I->getDebugLoc();
250249423Sdim
251263508Sdim  BuildMI(MBB, I, DL, TII.get(MFLoOpc), VR0).addReg(Src);
252249423Sdim  BuildMI(MBB, I, DL, TII.get(TargetOpcode::COPY), DstLo)
253249423Sdim    .addReg(VR0, RegState::Kill);
254263508Sdim  BuildMI(MBB, I, DL, TII.get(MFHiOpc), VR1).addReg(Src, SrcKill);
255249423Sdim  BuildMI(MBB, I, DL, TII.get(TargetOpcode::COPY), DstHi)
256249423Sdim    .addReg(VR1, RegState::Kill);
257251662Sdim  return true;
258249423Sdim}
259249423Sdim
260249423Sdimunsigned MipsSEFrameLowering::ehDataReg(unsigned I) const {
261249423Sdim  static const unsigned EhDataReg[] = {
262249423Sdim    Mips::A0, Mips::A1, Mips::A2, Mips::A3
263249423Sdim  };
264249423Sdim  static const unsigned EhDataReg64[] = {
265249423Sdim    Mips::A0_64, Mips::A1_64, Mips::A2_64, Mips::A3_64
266249423Sdim  };
267249423Sdim
268249423Sdim  return STI.isABI_N64() ? EhDataReg64[I] : EhDataReg[I];
269249423Sdim}
270249423Sdim
271239310Sdimvoid MipsSEFrameLowering::emitPrologue(MachineFunction &MF) const {
272239310Sdim  MachineBasicBlock &MBB   = MF.front();
273239310Sdim  MachineFrameInfo *MFI    = MF.getFrameInfo();
274249423Sdim  MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
275263508Sdim
276239310Sdim  const MipsSEInstrInfo &TII =
277239310Sdim    *static_cast<const MipsSEInstrInfo*>(MF.getTarget().getInstrInfo());
278263508Sdim  const MipsRegisterInfo &RegInfo =
279263508Sdim    *static_cast<const MipsRegisterInfo*>(MF.getTarget().getRegisterInfo());
280263508Sdim
281239310Sdim  MachineBasicBlock::iterator MBBI = MBB.begin();
282239310Sdim  DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
283239310Sdim  unsigned SP = STI.isABI_N64() ? Mips::SP_64 : Mips::SP;
284239310Sdim  unsigned FP = STI.isABI_N64() ? Mips::FP_64 : Mips::FP;
285239310Sdim  unsigned ZERO = STI.isABI_N64() ? Mips::ZERO_64 : Mips::ZERO;
286239310Sdim  unsigned ADDu = STI.isABI_N64() ? Mips::DADDu : Mips::ADDu;
287239310Sdim
288239310Sdim  // First, compute final stack size.
289239310Sdim  uint64_t StackSize = MFI->getStackSize();
290239310Sdim
291239310Sdim  // No need to allocate space on the stack.
292239310Sdim  if (StackSize == 0 && !MFI->adjustsStack()) return;
293239310Sdim
294239310Sdim  MachineModuleInfo &MMI = MF.getMMI();
295263508Sdim  const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo();
296239310Sdim  MachineLocation DstML, SrcML;
297239310Sdim
298239310Sdim  // Adjust stack.
299239310Sdim  TII.adjustStackPtr(SP, -StackSize, MBB, MBBI);
300239310Sdim
301239310Sdim  // emit ".cfi_def_cfa_offset StackSize"
302239310Sdim  MCSymbol *AdjustSPLabel = MMI.getContext().CreateTempSymbol();
303239310Sdim  BuildMI(MBB, MBBI, dl,
304239310Sdim          TII.get(TargetOpcode::PROLOG_LABEL)).addSym(AdjustSPLabel);
305263508Sdim  MMI.addFrameInst(
306263508Sdim      MCCFIInstruction::createDefCfaOffset(AdjustSPLabel, -StackSize));
307239310Sdim
308239310Sdim  const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
309239310Sdim
310239310Sdim  if (CSI.size()) {
311239310Sdim    // Find the instruction past the last instruction that saves a callee-saved
312239310Sdim    // register to the stack.
313239310Sdim    for (unsigned i = 0; i < CSI.size(); ++i)
314239310Sdim      ++MBBI;
315239310Sdim
316239310Sdim    // Iterate over list of callee-saved registers and emit .cfi_offset
317239310Sdim    // directives.
318239310Sdim    MCSymbol *CSLabel = MMI.getContext().CreateTempSymbol();
319239310Sdim    BuildMI(MBB, MBBI, dl,
320239310Sdim            TII.get(TargetOpcode::PROLOG_LABEL)).addSym(CSLabel);
321239310Sdim
322239310Sdim    for (std::vector<CalleeSavedInfo>::const_iterator I = CSI.begin(),
323239310Sdim           E = CSI.end(); I != E; ++I) {
324239310Sdim      int64_t Offset = MFI->getObjectOffset(I->getFrameIdx());
325239310Sdim      unsigned Reg = I->getReg();
326239310Sdim
327239310Sdim      // If Reg is a double precision register, emit two cfa_offsets,
328239310Sdim      // one for each of the paired single precision registers.
329239310Sdim      if (Mips::AFGR64RegClass.contains(Reg)) {
330263508Sdim        unsigned Reg0 =
331263508Sdim            MRI->getDwarfRegNum(RegInfo.getSubReg(Reg, Mips::sub_lo), true);
332263508Sdim        unsigned Reg1 =
333263508Sdim            MRI->getDwarfRegNum(RegInfo.getSubReg(Reg, Mips::sub_hi), true);
334239310Sdim
335239310Sdim        if (!STI.isLittle())
336263508Sdim          std::swap(Reg0, Reg1);
337239310Sdim
338263508Sdim        MMI.addFrameInst(
339263508Sdim            MCCFIInstruction::createOffset(CSLabel, Reg0, Offset));
340263508Sdim        MMI.addFrameInst(
341263508Sdim            MCCFIInstruction::createOffset(CSLabel, Reg1, Offset + 4));
342239310Sdim      } else {
343263508Sdim        // Reg is either in GPR32 or FGR32.
344263508Sdim        MMI.addFrameInst(MCCFIInstruction::createOffset(
345263508Sdim            CSLabel, MRI->getDwarfRegNum(Reg, 1), Offset));
346239310Sdim      }
347239310Sdim    }
348239310Sdim  }
349239310Sdim
350249423Sdim  if (MipsFI->callsEhReturn()) {
351249423Sdim    const TargetRegisterClass *RC = STI.isABI_N64() ?
352263508Sdim        &Mips::GPR64RegClass : &Mips::GPR32RegClass;
353249423Sdim
354249423Sdim    // Insert instructions that spill eh data registers.
355249423Sdim    for (int I = 0; I < 4; ++I) {
356249423Sdim      if (!MBB.isLiveIn(ehDataReg(I)))
357249423Sdim        MBB.addLiveIn(ehDataReg(I));
358249423Sdim      TII.storeRegToStackSlot(MBB, MBBI, ehDataReg(I), false,
359263508Sdim                              MipsFI->getEhDataRegFI(I), RC, &RegInfo);
360249423Sdim    }
361249423Sdim
362249423Sdim    // Emit .cfi_offset directives for eh data registers.
363249423Sdim    MCSymbol *CSLabel2 = MMI.getContext().CreateTempSymbol();
364249423Sdim    BuildMI(MBB, MBBI, dl,
365249423Sdim            TII.get(TargetOpcode::PROLOG_LABEL)).addSym(CSLabel2);
366249423Sdim    for (int I = 0; I < 4; ++I) {
367249423Sdim      int64_t Offset = MFI->getObjectOffset(MipsFI->getEhDataRegFI(I));
368263508Sdim      unsigned Reg = MRI->getDwarfRegNum(ehDataReg(I), true);
369263508Sdim      MMI.addFrameInst(MCCFIInstruction::createOffset(CSLabel2, Reg, Offset));
370249423Sdim    }
371249423Sdim  }
372249423Sdim
373239310Sdim  // if framepointer enabled, set it to point to the stack pointer.
374239310Sdim  if (hasFP(MF)) {
375239310Sdim    // Insert instruction "move $fp, $sp" at this location.
376239310Sdim    BuildMI(MBB, MBBI, dl, TII.get(ADDu), FP).addReg(SP).addReg(ZERO);
377239310Sdim
378239310Sdim    // emit ".cfi_def_cfa_register $fp"
379239310Sdim    MCSymbol *SetFPLabel = MMI.getContext().CreateTempSymbol();
380239310Sdim    BuildMI(MBB, MBBI, dl,
381239310Sdim            TII.get(TargetOpcode::PROLOG_LABEL)).addSym(SetFPLabel);
382263508Sdim    MMI.addFrameInst(MCCFIInstruction::createDefCfaRegister(
383263508Sdim        SetFPLabel, MRI->getDwarfRegNum(FP, true)));
384239310Sdim  }
385239310Sdim}
386239310Sdim
387239310Sdimvoid MipsSEFrameLowering::emitEpilogue(MachineFunction &MF,
388239310Sdim                                       MachineBasicBlock &MBB) const {
389239310Sdim  MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
390239310Sdim  MachineFrameInfo *MFI            = MF.getFrameInfo();
391249423Sdim  MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
392263508Sdim
393239310Sdim  const MipsSEInstrInfo &TII =
394239310Sdim    *static_cast<const MipsSEInstrInfo*>(MF.getTarget().getInstrInfo());
395263508Sdim  const MipsRegisterInfo &RegInfo =
396263508Sdim    *static_cast<const MipsRegisterInfo*>(MF.getTarget().getRegisterInfo());
397263508Sdim
398239310Sdim  DebugLoc dl = MBBI->getDebugLoc();
399239310Sdim  unsigned SP = STI.isABI_N64() ? Mips::SP_64 : Mips::SP;
400239310Sdim  unsigned FP = STI.isABI_N64() ? Mips::FP_64 : Mips::FP;
401239310Sdim  unsigned ZERO = STI.isABI_N64() ? Mips::ZERO_64 : Mips::ZERO;
402239310Sdim  unsigned ADDu = STI.isABI_N64() ? Mips::DADDu : Mips::ADDu;
403239310Sdim
404239310Sdim  // if framepointer enabled, restore the stack pointer.
405239310Sdim  if (hasFP(MF)) {
406239310Sdim    // Find the first instruction that restores a callee-saved register.
407239310Sdim    MachineBasicBlock::iterator I = MBBI;
408239310Sdim
409239310Sdim    for (unsigned i = 0; i < MFI->getCalleeSavedInfo().size(); ++i)
410239310Sdim      --I;
411239310Sdim
412239310Sdim    // Insert instruction "move $sp, $fp" at this location.
413239310Sdim    BuildMI(MBB, I, dl, TII.get(ADDu), SP).addReg(FP).addReg(ZERO);
414239310Sdim  }
415239310Sdim
416249423Sdim  if (MipsFI->callsEhReturn()) {
417249423Sdim    const TargetRegisterClass *RC = STI.isABI_N64() ?
418263508Sdim        &Mips::GPR64RegClass : &Mips::GPR32RegClass;
419249423Sdim
420249423Sdim    // Find first instruction that restores a callee-saved register.
421249423Sdim    MachineBasicBlock::iterator I = MBBI;
422249423Sdim    for (unsigned i = 0; i < MFI->getCalleeSavedInfo().size(); ++i)
423249423Sdim      --I;
424249423Sdim
425249423Sdim    // Insert instructions that restore eh data registers.
426249423Sdim    for (int J = 0; J < 4; ++J) {
427249423Sdim      TII.loadRegFromStackSlot(MBB, I, ehDataReg(J), MipsFI->getEhDataRegFI(J),
428263508Sdim                               RC, &RegInfo);
429249423Sdim    }
430249423Sdim  }
431249423Sdim
432239310Sdim  // Get the number of bytes from FrameInfo
433239310Sdim  uint64_t StackSize = MFI->getStackSize();
434239310Sdim
435239310Sdim  if (!StackSize)
436239310Sdim    return;
437239310Sdim
438239310Sdim  // Adjust stack.
439239310Sdim  TII.adjustStackPtr(SP, StackSize, MBB, MBBI);
440239310Sdim}
441239310Sdim
442239310Sdimbool MipsSEFrameLowering::
443239310SdimspillCalleeSavedRegisters(MachineBasicBlock &MBB,
444239310Sdim                          MachineBasicBlock::iterator MI,
445239310Sdim                          const std::vector<CalleeSavedInfo> &CSI,
446239310Sdim                          const TargetRegisterInfo *TRI) const {
447239310Sdim  MachineFunction *MF = MBB.getParent();
448239310Sdim  MachineBasicBlock *EntryBlock = MF->begin();
449239310Sdim  const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo();
450239310Sdim
451239310Sdim  for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
452239310Sdim    // Add the callee-saved register as live-in. Do not add if the register is
453239310Sdim    // RA and return address is taken, because it has already been added in
454239310Sdim    // method MipsTargetLowering::LowerRETURNADDR.
455239310Sdim    // It's killed at the spill, unless the register is RA and return address
456239310Sdim    // is taken.
457239310Sdim    unsigned Reg = CSI[i].getReg();
458239310Sdim    bool IsRAAndRetAddrIsTaken = (Reg == Mips::RA || Reg == Mips::RA_64)
459239310Sdim        && MF->getFrameInfo()->isReturnAddressTaken();
460239310Sdim    if (!IsRAAndRetAddrIsTaken)
461239310Sdim      EntryBlock->addLiveIn(Reg);
462239310Sdim
463239310Sdim    // Insert the spill to the stack frame.
464239310Sdim    bool IsKill = !IsRAAndRetAddrIsTaken;
465239310Sdim    const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
466239310Sdim    TII.storeRegToStackSlot(*EntryBlock, MI, Reg, IsKill,
467239310Sdim                            CSI[i].getFrameIdx(), RC, TRI);
468239310Sdim  }
469239310Sdim
470239310Sdim  return true;
471239310Sdim}
472239310Sdim
473239310Sdimbool
474239310SdimMipsSEFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
475239310Sdim  const MachineFrameInfo *MFI = MF.getFrameInfo();
476239310Sdim
477239310Sdim  // Reserve call frame if the size of the maximum call frame fits into 16-bit
478239310Sdim  // immediate field and there are no variable sized objects on the stack.
479249423Sdim  // Make sure the second register scavenger spill slot can be accessed with one
480249423Sdim  // instruction.
481249423Sdim  return isInt<16>(MFI->getMaxCallFrameSize() + getStackAlignment()) &&
482249423Sdim    !MFI->hasVarSizedObjects();
483239310Sdim}
484239310Sdim
485249423Sdim// Eliminate ADJCALLSTACKDOWN, ADJCALLSTACKUP pseudo instructions
486239310Sdimvoid MipsSEFrameLowering::
487249423SdimeliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
488249423Sdim                              MachineBasicBlock::iterator I) const {
489249423Sdim  const MipsSEInstrInfo &TII =
490249423Sdim    *static_cast<const MipsSEInstrInfo*>(MF.getTarget().getInstrInfo());
491249423Sdim
492249423Sdim  if (!hasReservedCallFrame(MF)) {
493249423Sdim    int64_t Amount = I->getOperand(0).getImm();
494249423Sdim
495249423Sdim    if (I->getOpcode() == Mips::ADJCALLSTACKDOWN)
496249423Sdim      Amount = -Amount;
497249423Sdim
498249423Sdim    unsigned SP = STI.isABI_N64() ? Mips::SP_64 : Mips::SP;
499249423Sdim    TII.adjustStackPtr(SP, Amount, MBB, I);
500249423Sdim  }
501249423Sdim
502249423Sdim  MBB.erase(I);
503249423Sdim}
504249423Sdim
505249423Sdimvoid MipsSEFrameLowering::
506239310SdimprocessFunctionBeforeCalleeSavedScan(MachineFunction &MF,
507239310Sdim                                     RegScavenger *RS) const {
508239310Sdim  MachineRegisterInfo &MRI = MF.getRegInfo();
509249423Sdim  MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
510239310Sdim  unsigned FP = STI.isABI_N64() ? Mips::FP_64 : Mips::FP;
511239310Sdim
512239310Sdim  // Mark $fp as used if function has dedicated frame pointer.
513239310Sdim  if (hasFP(MF))
514239310Sdim    MRI.setPhysRegUsed(FP);
515243830Sdim
516249423Sdim  // Create spill slots for eh data registers if function calls eh_return.
517249423Sdim  if (MipsFI->callsEhReturn())
518249423Sdim    MipsFI->createEhDataRegsFI();
519249423Sdim
520249423Sdim  // Expand pseudo instructions which load, store or copy accumulators.
521249423Sdim  // Add an emergency spill slot if a pseudo was expanded.
522251662Sdim  if (ExpandPseudo(MF).expand()) {
523249423Sdim    // The spill slot should be half the size of the accumulator. If target is
524249423Sdim    // mips64, it should be 64-bit, otherwise it should be 32-bt.
525249423Sdim    const TargetRegisterClass *RC = STI.hasMips64() ?
526263508Sdim      &Mips::GPR64RegClass : &Mips::GPR32RegClass;
527249423Sdim    int FI = MF.getFrameInfo()->CreateStackObject(RC->getSize(),
528249423Sdim                                                  RC->getAlignment(), false);
529249423Sdim    RS->addScavengingFrameIndex(FI);
530249423Sdim  }
531249423Sdim
532243830Sdim  // Set scavenging frame index if necessary.
533243830Sdim  uint64_t MaxSPOffset = MF.getInfo<MipsFunctionInfo>()->getIncomingArgSize() +
534243830Sdim    estimateStackSize(MF);
535243830Sdim
536243830Sdim  if (isInt<16>(MaxSPOffset))
537243830Sdim    return;
538243830Sdim
539243830Sdim  const TargetRegisterClass *RC = STI.isABI_N64() ?
540263508Sdim    &Mips::GPR64RegClass : &Mips::GPR32RegClass;
541243830Sdim  int FI = MF.getFrameInfo()->CreateStackObject(RC->getSize(),
542243830Sdim                                                RC->getAlignment(), false);
543249423Sdim  RS->addScavengingFrameIndex(FI);
544239310Sdim}
545239310Sdim
546239310Sdimconst MipsFrameLowering *
547239310Sdimllvm::createMipsSEFrameLowering(const MipsSubtarget &ST) {
548239310Sdim  return new MipsSEFrameLowering(ST);
549239310Sdim}
550