xref: /aosp_15_r20/external/llvm/lib/Target/Mips/MipsSEFrameLowering.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===-- MipsSEFrameLowering.cpp - Mips32/64 Frame Information -------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This file contains the Mips32/64 implementation of TargetFrameLowering class.
11*9880d681SAndroid Build Coastguard Worker //
12*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
13*9880d681SAndroid Build Coastguard Worker 
14*9880d681SAndroid Build Coastguard Worker #include "MipsSEFrameLowering.h"
15*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/MipsBaseInfo.h"
16*9880d681SAndroid Build Coastguard Worker #include "MipsMachineFunction.h"
17*9880d681SAndroid Build Coastguard Worker #include "MipsSEInstrInfo.h"
18*9880d681SAndroid Build Coastguard Worker #include "MipsSubtarget.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/StringSwitch.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFrameInfo.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFunction.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineInstrBuilder.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineModuleInfo.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineRegisterInfo.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/RegisterScavenging.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/DataLayout.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Function.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetOptions.h"
29*9880d681SAndroid Build Coastguard Worker 
30*9880d681SAndroid Build Coastguard Worker using namespace llvm;
31*9880d681SAndroid Build Coastguard Worker 
32*9880d681SAndroid Build Coastguard Worker namespace {
33*9880d681SAndroid Build Coastguard Worker typedef MachineBasicBlock::iterator Iter;
34*9880d681SAndroid Build Coastguard Worker 
getMFHiLoOpc(unsigned Src)35*9880d681SAndroid Build Coastguard Worker static std::pair<unsigned, unsigned> getMFHiLoOpc(unsigned Src) {
36*9880d681SAndroid Build Coastguard Worker   if (Mips::ACC64RegClass.contains(Src))
37*9880d681SAndroid Build Coastguard Worker     return std::make_pair((unsigned)Mips::PseudoMFHI,
38*9880d681SAndroid Build Coastguard Worker                           (unsigned)Mips::PseudoMFLO);
39*9880d681SAndroid Build Coastguard Worker 
40*9880d681SAndroid Build Coastguard Worker   if (Mips::ACC64DSPRegClass.contains(Src))
41*9880d681SAndroid Build Coastguard Worker     return std::make_pair((unsigned)Mips::MFHI_DSP, (unsigned)Mips::MFLO_DSP);
42*9880d681SAndroid Build Coastguard Worker 
43*9880d681SAndroid Build Coastguard Worker   if (Mips::ACC128RegClass.contains(Src))
44*9880d681SAndroid Build Coastguard Worker     return std::make_pair((unsigned)Mips::PseudoMFHI64,
45*9880d681SAndroid Build Coastguard Worker                           (unsigned)Mips::PseudoMFLO64);
46*9880d681SAndroid Build Coastguard Worker 
47*9880d681SAndroid Build Coastguard Worker   return std::make_pair(0, 0);
48*9880d681SAndroid Build Coastguard Worker }
49*9880d681SAndroid Build Coastguard Worker 
50*9880d681SAndroid Build Coastguard Worker /// Helper class to expand pseudos.
51*9880d681SAndroid Build Coastguard Worker class ExpandPseudo {
52*9880d681SAndroid Build Coastguard Worker public:
53*9880d681SAndroid Build Coastguard Worker   ExpandPseudo(MachineFunction &MF);
54*9880d681SAndroid Build Coastguard Worker   bool expand();
55*9880d681SAndroid Build Coastguard Worker 
56*9880d681SAndroid Build Coastguard Worker private:
57*9880d681SAndroid Build Coastguard Worker   bool expandInstr(MachineBasicBlock &MBB, Iter I);
58*9880d681SAndroid Build Coastguard Worker   void expandLoadCCond(MachineBasicBlock &MBB, Iter I);
59*9880d681SAndroid Build Coastguard Worker   void expandStoreCCond(MachineBasicBlock &MBB, Iter I);
60*9880d681SAndroid Build Coastguard Worker   void expandLoadACC(MachineBasicBlock &MBB, Iter I, unsigned RegSize);
61*9880d681SAndroid Build Coastguard Worker   void expandStoreACC(MachineBasicBlock &MBB, Iter I, unsigned MFHiOpc,
62*9880d681SAndroid Build Coastguard Worker                       unsigned MFLoOpc, unsigned RegSize);
63*9880d681SAndroid Build Coastguard Worker   bool expandCopy(MachineBasicBlock &MBB, Iter I);
64*9880d681SAndroid Build Coastguard Worker   bool expandCopyACC(MachineBasicBlock &MBB, Iter I, unsigned MFHiOpc,
65*9880d681SAndroid Build Coastguard Worker                      unsigned MFLoOpc);
66*9880d681SAndroid Build Coastguard Worker   bool expandBuildPairF64(MachineBasicBlock &MBB,
67*9880d681SAndroid Build Coastguard Worker                           MachineBasicBlock::iterator I, bool FP64) const;
68*9880d681SAndroid Build Coastguard Worker   bool expandExtractElementF64(MachineBasicBlock &MBB,
69*9880d681SAndroid Build Coastguard Worker                                MachineBasicBlock::iterator I, bool FP64) const;
70*9880d681SAndroid Build Coastguard Worker 
71*9880d681SAndroid Build Coastguard Worker   MachineFunction &MF;
72*9880d681SAndroid Build Coastguard Worker   MachineRegisterInfo &MRI;
73*9880d681SAndroid Build Coastguard Worker   const MipsSubtarget &Subtarget;
74*9880d681SAndroid Build Coastguard Worker   const MipsSEInstrInfo &TII;
75*9880d681SAndroid Build Coastguard Worker   const MipsRegisterInfo &RegInfo;
76*9880d681SAndroid Build Coastguard Worker };
77*9880d681SAndroid Build Coastguard Worker }
78*9880d681SAndroid Build Coastguard Worker 
ExpandPseudo(MachineFunction & MF_)79*9880d681SAndroid Build Coastguard Worker ExpandPseudo::ExpandPseudo(MachineFunction &MF_)
80*9880d681SAndroid Build Coastguard Worker     : MF(MF_), MRI(MF.getRegInfo()),
81*9880d681SAndroid Build Coastguard Worker       Subtarget(static_cast<const MipsSubtarget &>(MF.getSubtarget())),
82*9880d681SAndroid Build Coastguard Worker       TII(*static_cast<const MipsSEInstrInfo *>(Subtarget.getInstrInfo())),
83*9880d681SAndroid Build Coastguard Worker       RegInfo(*Subtarget.getRegisterInfo()) {}
84*9880d681SAndroid Build Coastguard Worker 
expand()85*9880d681SAndroid Build Coastguard Worker bool ExpandPseudo::expand() {
86*9880d681SAndroid Build Coastguard Worker   bool Expanded = false;
87*9880d681SAndroid Build Coastguard Worker 
88*9880d681SAndroid Build Coastguard Worker   for (auto &MBB : MF) {
89*9880d681SAndroid Build Coastguard Worker     for (Iter I = MBB.begin(), End = MBB.end(); I != End;)
90*9880d681SAndroid Build Coastguard Worker       Expanded |= expandInstr(MBB, I++);
91*9880d681SAndroid Build Coastguard Worker   }
92*9880d681SAndroid Build Coastguard Worker 
93*9880d681SAndroid Build Coastguard Worker   return Expanded;
94*9880d681SAndroid Build Coastguard Worker }
95*9880d681SAndroid Build Coastguard Worker 
expandInstr(MachineBasicBlock & MBB,Iter I)96*9880d681SAndroid Build Coastguard Worker bool ExpandPseudo::expandInstr(MachineBasicBlock &MBB, Iter I) {
97*9880d681SAndroid Build Coastguard Worker   switch(I->getOpcode()) {
98*9880d681SAndroid Build Coastguard Worker   case Mips::LOAD_CCOND_DSP:
99*9880d681SAndroid Build Coastguard Worker     expandLoadCCond(MBB, I);
100*9880d681SAndroid Build Coastguard Worker     break;
101*9880d681SAndroid Build Coastguard Worker   case Mips::STORE_CCOND_DSP:
102*9880d681SAndroid Build Coastguard Worker     expandStoreCCond(MBB, I);
103*9880d681SAndroid Build Coastguard Worker     break;
104*9880d681SAndroid Build Coastguard Worker   case Mips::LOAD_ACC64:
105*9880d681SAndroid Build Coastguard Worker   case Mips::LOAD_ACC64DSP:
106*9880d681SAndroid Build Coastguard Worker     expandLoadACC(MBB, I, 4);
107*9880d681SAndroid Build Coastguard Worker     break;
108*9880d681SAndroid Build Coastguard Worker   case Mips::LOAD_ACC128:
109*9880d681SAndroid Build Coastguard Worker     expandLoadACC(MBB, I, 8);
110*9880d681SAndroid Build Coastguard Worker     break;
111*9880d681SAndroid Build Coastguard Worker   case Mips::STORE_ACC64:
112*9880d681SAndroid Build Coastguard Worker     expandStoreACC(MBB, I, Mips::PseudoMFHI, Mips::PseudoMFLO, 4);
113*9880d681SAndroid Build Coastguard Worker     break;
114*9880d681SAndroid Build Coastguard Worker   case Mips::STORE_ACC64DSP:
115*9880d681SAndroid Build Coastguard Worker     expandStoreACC(MBB, I, Mips::MFHI_DSP, Mips::MFLO_DSP, 4);
116*9880d681SAndroid Build Coastguard Worker     break;
117*9880d681SAndroid Build Coastguard Worker   case Mips::STORE_ACC128:
118*9880d681SAndroid Build Coastguard Worker     expandStoreACC(MBB, I, Mips::PseudoMFHI64, Mips::PseudoMFLO64, 8);
119*9880d681SAndroid Build Coastguard Worker     break;
120*9880d681SAndroid Build Coastguard Worker   case Mips::BuildPairF64:
121*9880d681SAndroid Build Coastguard Worker     if (expandBuildPairF64(MBB, I, false))
122*9880d681SAndroid Build Coastguard Worker       MBB.erase(I);
123*9880d681SAndroid Build Coastguard Worker     return false;
124*9880d681SAndroid Build Coastguard Worker   case Mips::BuildPairF64_64:
125*9880d681SAndroid Build Coastguard Worker     if (expandBuildPairF64(MBB, I, true))
126*9880d681SAndroid Build Coastguard Worker       MBB.erase(I);
127*9880d681SAndroid Build Coastguard Worker     return false;
128*9880d681SAndroid Build Coastguard Worker   case Mips::ExtractElementF64:
129*9880d681SAndroid Build Coastguard Worker     if (expandExtractElementF64(MBB, I, false))
130*9880d681SAndroid Build Coastguard Worker       MBB.erase(I);
131*9880d681SAndroid Build Coastguard Worker     return false;
132*9880d681SAndroid Build Coastguard Worker   case Mips::ExtractElementF64_64:
133*9880d681SAndroid Build Coastguard Worker     if (expandExtractElementF64(MBB, I, true))
134*9880d681SAndroid Build Coastguard Worker       MBB.erase(I);
135*9880d681SAndroid Build Coastguard Worker     return false;
136*9880d681SAndroid Build Coastguard Worker   case TargetOpcode::COPY:
137*9880d681SAndroid Build Coastguard Worker     if (!expandCopy(MBB, I))
138*9880d681SAndroid Build Coastguard Worker       return false;
139*9880d681SAndroid Build Coastguard Worker     break;
140*9880d681SAndroid Build Coastguard Worker   default:
141*9880d681SAndroid Build Coastguard Worker     return false;
142*9880d681SAndroid Build Coastguard Worker   }
143*9880d681SAndroid Build Coastguard Worker 
144*9880d681SAndroid Build Coastguard Worker   MBB.erase(I);
145*9880d681SAndroid Build Coastguard Worker   return true;
146*9880d681SAndroid Build Coastguard Worker }
147*9880d681SAndroid Build Coastguard Worker 
expandLoadCCond(MachineBasicBlock & MBB,Iter I)148*9880d681SAndroid Build Coastguard Worker void ExpandPseudo::expandLoadCCond(MachineBasicBlock &MBB, Iter I) {
149*9880d681SAndroid Build Coastguard Worker   //  load $vr, FI
150*9880d681SAndroid Build Coastguard Worker   //  copy ccond, $vr
151*9880d681SAndroid Build Coastguard Worker 
152*9880d681SAndroid Build Coastguard Worker   assert(I->getOperand(0).isReg() && I->getOperand(1).isFI());
153*9880d681SAndroid Build Coastguard Worker 
154*9880d681SAndroid Build Coastguard Worker   const TargetRegisterClass *RC = RegInfo.intRegClass(4);
155*9880d681SAndroid Build Coastguard Worker   unsigned VR = MRI.createVirtualRegister(RC);
156*9880d681SAndroid Build Coastguard Worker   unsigned Dst = I->getOperand(0).getReg(), FI = I->getOperand(1).getIndex();
157*9880d681SAndroid Build Coastguard Worker 
158*9880d681SAndroid Build Coastguard Worker   TII.loadRegFromStack(MBB, I, VR, FI, RC, &RegInfo, 0);
159*9880d681SAndroid Build Coastguard Worker   BuildMI(MBB, I, I->getDebugLoc(), TII.get(TargetOpcode::COPY), Dst)
160*9880d681SAndroid Build Coastguard Worker     .addReg(VR, RegState::Kill);
161*9880d681SAndroid Build Coastguard Worker }
162*9880d681SAndroid Build Coastguard Worker 
expandStoreCCond(MachineBasicBlock & MBB,Iter I)163*9880d681SAndroid Build Coastguard Worker void ExpandPseudo::expandStoreCCond(MachineBasicBlock &MBB, Iter I) {
164*9880d681SAndroid Build Coastguard Worker   //  copy $vr, ccond
165*9880d681SAndroid Build Coastguard Worker   //  store $vr, FI
166*9880d681SAndroid Build Coastguard Worker 
167*9880d681SAndroid Build Coastguard Worker   assert(I->getOperand(0).isReg() && I->getOperand(1).isFI());
168*9880d681SAndroid Build Coastguard Worker 
169*9880d681SAndroid Build Coastguard Worker   const TargetRegisterClass *RC = RegInfo.intRegClass(4);
170*9880d681SAndroid Build Coastguard Worker   unsigned VR = MRI.createVirtualRegister(RC);
171*9880d681SAndroid Build Coastguard Worker   unsigned Src = I->getOperand(0).getReg(), FI = I->getOperand(1).getIndex();
172*9880d681SAndroid Build Coastguard Worker 
173*9880d681SAndroid Build Coastguard Worker   BuildMI(MBB, I, I->getDebugLoc(), TII.get(TargetOpcode::COPY), VR)
174*9880d681SAndroid Build Coastguard Worker     .addReg(Src, getKillRegState(I->getOperand(0).isKill()));
175*9880d681SAndroid Build Coastguard Worker   TII.storeRegToStack(MBB, I, VR, true, FI, RC, &RegInfo, 0);
176*9880d681SAndroid Build Coastguard Worker }
177*9880d681SAndroid Build Coastguard Worker 
expandLoadACC(MachineBasicBlock & MBB,Iter I,unsigned RegSize)178*9880d681SAndroid Build Coastguard Worker void ExpandPseudo::expandLoadACC(MachineBasicBlock &MBB, Iter I,
179*9880d681SAndroid Build Coastguard Worker                                  unsigned RegSize) {
180*9880d681SAndroid Build Coastguard Worker   //  load $vr0, FI
181*9880d681SAndroid Build Coastguard Worker   //  copy lo, $vr0
182*9880d681SAndroid Build Coastguard Worker   //  load $vr1, FI + 4
183*9880d681SAndroid Build Coastguard Worker   //  copy hi, $vr1
184*9880d681SAndroid Build Coastguard Worker 
185*9880d681SAndroid Build Coastguard Worker   assert(I->getOperand(0).isReg() && I->getOperand(1).isFI());
186*9880d681SAndroid Build Coastguard Worker 
187*9880d681SAndroid Build Coastguard Worker   const TargetRegisterClass *RC = RegInfo.intRegClass(RegSize);
188*9880d681SAndroid Build Coastguard Worker   unsigned VR0 = MRI.createVirtualRegister(RC);
189*9880d681SAndroid Build Coastguard Worker   unsigned VR1 = MRI.createVirtualRegister(RC);
190*9880d681SAndroid Build Coastguard Worker   unsigned Dst = I->getOperand(0).getReg(), FI = I->getOperand(1).getIndex();
191*9880d681SAndroid Build Coastguard Worker   unsigned Lo = RegInfo.getSubReg(Dst, Mips::sub_lo);
192*9880d681SAndroid Build Coastguard Worker   unsigned Hi = RegInfo.getSubReg(Dst, Mips::sub_hi);
193*9880d681SAndroid Build Coastguard Worker   DebugLoc DL = I->getDebugLoc();
194*9880d681SAndroid Build Coastguard Worker   const MCInstrDesc &Desc = TII.get(TargetOpcode::COPY);
195*9880d681SAndroid Build Coastguard Worker 
196*9880d681SAndroid Build Coastguard Worker   TII.loadRegFromStack(MBB, I, VR0, FI, RC, &RegInfo, 0);
197*9880d681SAndroid Build Coastguard Worker   BuildMI(MBB, I, DL, Desc, Lo).addReg(VR0, RegState::Kill);
198*9880d681SAndroid Build Coastguard Worker   TII.loadRegFromStack(MBB, I, VR1, FI, RC, &RegInfo, RegSize);
199*9880d681SAndroid Build Coastguard Worker   BuildMI(MBB, I, DL, Desc, Hi).addReg(VR1, RegState::Kill);
200*9880d681SAndroid Build Coastguard Worker }
201*9880d681SAndroid Build Coastguard Worker 
expandStoreACC(MachineBasicBlock & MBB,Iter I,unsigned MFHiOpc,unsigned MFLoOpc,unsigned RegSize)202*9880d681SAndroid Build Coastguard Worker void ExpandPseudo::expandStoreACC(MachineBasicBlock &MBB, Iter I,
203*9880d681SAndroid Build Coastguard Worker                                   unsigned MFHiOpc, unsigned MFLoOpc,
204*9880d681SAndroid Build Coastguard Worker                                   unsigned RegSize) {
205*9880d681SAndroid Build Coastguard Worker   //  mflo $vr0, src
206*9880d681SAndroid Build Coastguard Worker   //  store $vr0, FI
207*9880d681SAndroid Build Coastguard Worker   //  mfhi $vr1, src
208*9880d681SAndroid Build Coastguard Worker   //  store $vr1, FI + 4
209*9880d681SAndroid Build Coastguard Worker 
210*9880d681SAndroid Build Coastguard Worker   assert(I->getOperand(0).isReg() && I->getOperand(1).isFI());
211*9880d681SAndroid Build Coastguard Worker 
212*9880d681SAndroid Build Coastguard Worker   const TargetRegisterClass *RC = RegInfo.intRegClass(RegSize);
213*9880d681SAndroid Build Coastguard Worker   unsigned VR0 = MRI.createVirtualRegister(RC);
214*9880d681SAndroid Build Coastguard Worker   unsigned VR1 = MRI.createVirtualRegister(RC);
215*9880d681SAndroid Build Coastguard Worker   unsigned Src = I->getOperand(0).getReg(), FI = I->getOperand(1).getIndex();
216*9880d681SAndroid Build Coastguard Worker   unsigned SrcKill = getKillRegState(I->getOperand(0).isKill());
217*9880d681SAndroid Build Coastguard Worker   DebugLoc DL = I->getDebugLoc();
218*9880d681SAndroid Build Coastguard Worker 
219*9880d681SAndroid Build Coastguard Worker   BuildMI(MBB, I, DL, TII.get(MFLoOpc), VR0).addReg(Src);
220*9880d681SAndroid Build Coastguard Worker   TII.storeRegToStack(MBB, I, VR0, true, FI, RC, &RegInfo, 0);
221*9880d681SAndroid Build Coastguard Worker   BuildMI(MBB, I, DL, TII.get(MFHiOpc), VR1).addReg(Src, SrcKill);
222*9880d681SAndroid Build Coastguard Worker   TII.storeRegToStack(MBB, I, VR1, true, FI, RC, &RegInfo, RegSize);
223*9880d681SAndroid Build Coastguard Worker }
224*9880d681SAndroid Build Coastguard Worker 
expandCopy(MachineBasicBlock & MBB,Iter I)225*9880d681SAndroid Build Coastguard Worker bool ExpandPseudo::expandCopy(MachineBasicBlock &MBB, Iter I) {
226*9880d681SAndroid Build Coastguard Worker   unsigned Src = I->getOperand(1).getReg();
227*9880d681SAndroid Build Coastguard Worker   std::pair<unsigned, unsigned> Opcodes = getMFHiLoOpc(Src);
228*9880d681SAndroid Build Coastguard Worker 
229*9880d681SAndroid Build Coastguard Worker   if (!Opcodes.first)
230*9880d681SAndroid Build Coastguard Worker     return false;
231*9880d681SAndroid Build Coastguard Worker 
232*9880d681SAndroid Build Coastguard Worker   return expandCopyACC(MBB, I, Opcodes.first, Opcodes.second);
233*9880d681SAndroid Build Coastguard Worker }
234*9880d681SAndroid Build Coastguard Worker 
expandCopyACC(MachineBasicBlock & MBB,Iter I,unsigned MFHiOpc,unsigned MFLoOpc)235*9880d681SAndroid Build Coastguard Worker bool ExpandPseudo::expandCopyACC(MachineBasicBlock &MBB, Iter I,
236*9880d681SAndroid Build Coastguard Worker                                  unsigned MFHiOpc, unsigned MFLoOpc) {
237*9880d681SAndroid Build Coastguard Worker   //  mflo $vr0, src
238*9880d681SAndroid Build Coastguard Worker   //  copy dst_lo, $vr0
239*9880d681SAndroid Build Coastguard Worker   //  mfhi $vr1, src
240*9880d681SAndroid Build Coastguard Worker   //  copy dst_hi, $vr1
241*9880d681SAndroid Build Coastguard Worker 
242*9880d681SAndroid Build Coastguard Worker   unsigned Dst = I->getOperand(0).getReg(), Src = I->getOperand(1).getReg();
243*9880d681SAndroid Build Coastguard Worker   unsigned VRegSize = RegInfo.getMinimalPhysRegClass(Dst)->getSize() / 2;
244*9880d681SAndroid Build Coastguard Worker   const TargetRegisterClass *RC = RegInfo.intRegClass(VRegSize);
245*9880d681SAndroid Build Coastguard Worker   unsigned VR0 = MRI.createVirtualRegister(RC);
246*9880d681SAndroid Build Coastguard Worker   unsigned VR1 = MRI.createVirtualRegister(RC);
247*9880d681SAndroid Build Coastguard Worker   unsigned SrcKill = getKillRegState(I->getOperand(1).isKill());
248*9880d681SAndroid Build Coastguard Worker   unsigned DstLo = RegInfo.getSubReg(Dst, Mips::sub_lo);
249*9880d681SAndroid Build Coastguard Worker   unsigned DstHi = RegInfo.getSubReg(Dst, Mips::sub_hi);
250*9880d681SAndroid Build Coastguard Worker   DebugLoc DL = I->getDebugLoc();
251*9880d681SAndroid Build Coastguard Worker 
252*9880d681SAndroid Build Coastguard Worker   BuildMI(MBB, I, DL, TII.get(MFLoOpc), VR0).addReg(Src);
253*9880d681SAndroid Build Coastguard Worker   BuildMI(MBB, I, DL, TII.get(TargetOpcode::COPY), DstLo)
254*9880d681SAndroid Build Coastguard Worker     .addReg(VR0, RegState::Kill);
255*9880d681SAndroid Build Coastguard Worker   BuildMI(MBB, I, DL, TII.get(MFHiOpc), VR1).addReg(Src, SrcKill);
256*9880d681SAndroid Build Coastguard Worker   BuildMI(MBB, I, DL, TII.get(TargetOpcode::COPY), DstHi)
257*9880d681SAndroid Build Coastguard Worker     .addReg(VR1, RegState::Kill);
258*9880d681SAndroid Build Coastguard Worker   return true;
259*9880d681SAndroid Build Coastguard Worker }
260*9880d681SAndroid Build Coastguard Worker 
261*9880d681SAndroid Build Coastguard Worker /// This method expands the same instruction that MipsSEInstrInfo::
262*9880d681SAndroid Build Coastguard Worker /// expandBuildPairF64 does, for the case when ABI is fpxx and mthc1 is not
263*9880d681SAndroid Build Coastguard Worker /// available and the case where the ABI is FP64A. It is implemented here
264*9880d681SAndroid Build Coastguard Worker /// because frame indexes are eliminated before MipsSEInstrInfo::
265*9880d681SAndroid Build Coastguard Worker /// expandBuildPairF64 is called.
expandBuildPairF64(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,bool FP64) const266*9880d681SAndroid Build Coastguard Worker bool ExpandPseudo::expandBuildPairF64(MachineBasicBlock &MBB,
267*9880d681SAndroid Build Coastguard Worker                                       MachineBasicBlock::iterator I,
268*9880d681SAndroid Build Coastguard Worker                                       bool FP64) const {
269*9880d681SAndroid Build Coastguard Worker   // For fpxx and when mthc1 is not available, use:
270*9880d681SAndroid Build Coastguard Worker   //   spill + reload via ldc1
271*9880d681SAndroid Build Coastguard Worker   //
272*9880d681SAndroid Build Coastguard Worker   // The case where dmtc1 is available doesn't need to be handled here
273*9880d681SAndroid Build Coastguard Worker   // because it never creates a BuildPairF64 node.
274*9880d681SAndroid Build Coastguard Worker   //
275*9880d681SAndroid Build Coastguard Worker   // The FP64A ABI (fp64 with nooddspreg) must also use a spill/reload sequence
276*9880d681SAndroid Build Coastguard Worker   // for odd-numbered double precision values (because the lower 32-bits is
277*9880d681SAndroid Build Coastguard Worker   // transferred with mtc1 which is redirected to the upper half of the even
278*9880d681SAndroid Build Coastguard Worker   // register). Unfortunately, we have to make this decision before register
279*9880d681SAndroid Build Coastguard Worker   // allocation so for now we use a spill/reload sequence for all
280*9880d681SAndroid Build Coastguard Worker   // double-precision values in regardless of being an odd/even register.
281*9880d681SAndroid Build Coastguard Worker   if ((Subtarget.isABI_FPXX() && !Subtarget.hasMTHC1()) ||
282*9880d681SAndroid Build Coastguard Worker       (FP64 && !Subtarget.useOddSPReg())) {
283*9880d681SAndroid Build Coastguard Worker     unsigned DstReg = I->getOperand(0).getReg();
284*9880d681SAndroid Build Coastguard Worker     unsigned LoReg = I->getOperand(1).getReg();
285*9880d681SAndroid Build Coastguard Worker     unsigned HiReg = I->getOperand(2).getReg();
286*9880d681SAndroid Build Coastguard Worker 
287*9880d681SAndroid Build Coastguard Worker     // It should be impossible to have FGR64 on MIPS-II or MIPS32r1 (which are
288*9880d681SAndroid Build Coastguard Worker     // the cases where mthc1 is not available). 64-bit architectures and
289*9880d681SAndroid Build Coastguard Worker     // MIPS32r2 or later can use FGR64 though.
290*9880d681SAndroid Build Coastguard Worker     assert(Subtarget.isGP64bit() || Subtarget.hasMTHC1() ||
291*9880d681SAndroid Build Coastguard Worker            !Subtarget.isFP64bit());
292*9880d681SAndroid Build Coastguard Worker 
293*9880d681SAndroid Build Coastguard Worker     const TargetRegisterClass *RC = &Mips::GPR32RegClass;
294*9880d681SAndroid Build Coastguard Worker     const TargetRegisterClass *RC2 =
295*9880d681SAndroid Build Coastguard Worker         FP64 ? &Mips::FGR64RegClass : &Mips::AFGR64RegClass;
296*9880d681SAndroid Build Coastguard Worker 
297*9880d681SAndroid Build Coastguard Worker     // We re-use the same spill slot each time so that the stack frame doesn't
298*9880d681SAndroid Build Coastguard Worker     // grow too much in functions with a large number of moves.
299*9880d681SAndroid Build Coastguard Worker     int FI = MF.getInfo<MipsFunctionInfo>()->getMoveF64ViaSpillFI(RC2);
300*9880d681SAndroid Build Coastguard Worker     if (!Subtarget.isLittle())
301*9880d681SAndroid Build Coastguard Worker       std::swap(LoReg, HiReg);
302*9880d681SAndroid Build Coastguard Worker     TII.storeRegToStack(MBB, I, LoReg, I->getOperand(1).isKill(), FI, RC,
303*9880d681SAndroid Build Coastguard Worker                         &RegInfo, 0);
304*9880d681SAndroid Build Coastguard Worker     TII.storeRegToStack(MBB, I, HiReg, I->getOperand(2).isKill(), FI, RC,
305*9880d681SAndroid Build Coastguard Worker                         &RegInfo, 4);
306*9880d681SAndroid Build Coastguard Worker     TII.loadRegFromStack(MBB, I, DstReg, FI, RC2, &RegInfo, 0);
307*9880d681SAndroid Build Coastguard Worker     return true;
308*9880d681SAndroid Build Coastguard Worker   }
309*9880d681SAndroid Build Coastguard Worker 
310*9880d681SAndroid Build Coastguard Worker   return false;
311*9880d681SAndroid Build Coastguard Worker }
312*9880d681SAndroid Build Coastguard Worker 
313*9880d681SAndroid Build Coastguard Worker /// This method expands the same instruction that MipsSEInstrInfo::
314*9880d681SAndroid Build Coastguard Worker /// expandExtractElementF64 does, for the case when ABI is fpxx and mfhc1 is not
315*9880d681SAndroid Build Coastguard Worker /// available and the case where the ABI is FP64A. It is implemented here
316*9880d681SAndroid Build Coastguard Worker /// because frame indexes are eliminated before MipsSEInstrInfo::
317*9880d681SAndroid Build Coastguard Worker /// expandExtractElementF64 is called.
expandExtractElementF64(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,bool FP64) const318*9880d681SAndroid Build Coastguard Worker bool ExpandPseudo::expandExtractElementF64(MachineBasicBlock &MBB,
319*9880d681SAndroid Build Coastguard Worker                                            MachineBasicBlock::iterator I,
320*9880d681SAndroid Build Coastguard Worker                                            bool FP64) const {
321*9880d681SAndroid Build Coastguard Worker   const MachineOperand &Op1 = I->getOperand(1);
322*9880d681SAndroid Build Coastguard Worker   const MachineOperand &Op2 = I->getOperand(2);
323*9880d681SAndroid Build Coastguard Worker 
324*9880d681SAndroid Build Coastguard Worker   if ((Op1.isReg() && Op1.isUndef()) || (Op2.isReg() && Op2.isUndef())) {
325*9880d681SAndroid Build Coastguard Worker     unsigned DstReg = I->getOperand(0).getReg();
326*9880d681SAndroid Build Coastguard Worker     BuildMI(MBB, I, I->getDebugLoc(), TII.get(Mips::IMPLICIT_DEF), DstReg);
327*9880d681SAndroid Build Coastguard Worker     return true;
328*9880d681SAndroid Build Coastguard Worker   }
329*9880d681SAndroid Build Coastguard Worker 
330*9880d681SAndroid Build Coastguard Worker   // For fpxx and when mfhc1 is not available, use:
331*9880d681SAndroid Build Coastguard Worker   //   spill + reload via ldc1
332*9880d681SAndroid Build Coastguard Worker   //
333*9880d681SAndroid Build Coastguard Worker   // The case where dmfc1 is available doesn't need to be handled here
334*9880d681SAndroid Build Coastguard Worker   // because it never creates a ExtractElementF64 node.
335*9880d681SAndroid Build Coastguard Worker   //
336*9880d681SAndroid Build Coastguard Worker   // The FP64A ABI (fp64 with nooddspreg) must also use a spill/reload sequence
337*9880d681SAndroid Build Coastguard Worker   // for odd-numbered double precision values (because the lower 32-bits is
338*9880d681SAndroid Build Coastguard Worker   // transferred with mfc1 which is redirected to the upper half of the even
339*9880d681SAndroid Build Coastguard Worker   // register). Unfortunately, we have to make this decision before register
340*9880d681SAndroid Build Coastguard Worker   // allocation so for now we use a spill/reload sequence for all
341*9880d681SAndroid Build Coastguard Worker   // double-precision values in regardless of being an odd/even register.
342*9880d681SAndroid Build Coastguard Worker 
343*9880d681SAndroid Build Coastguard Worker   if ((Subtarget.isABI_FPXX() && !Subtarget.hasMTHC1()) ||
344*9880d681SAndroid Build Coastguard Worker       (FP64 && !Subtarget.useOddSPReg())) {
345*9880d681SAndroid Build Coastguard Worker     unsigned DstReg = I->getOperand(0).getReg();
346*9880d681SAndroid Build Coastguard Worker     unsigned SrcReg = Op1.getReg();
347*9880d681SAndroid Build Coastguard Worker     unsigned N = Op2.getImm();
348*9880d681SAndroid Build Coastguard Worker     int64_t Offset = 4 * (Subtarget.isLittle() ? N : (1 - N));
349*9880d681SAndroid Build Coastguard Worker 
350*9880d681SAndroid Build Coastguard Worker     // It should be impossible to have FGR64 on MIPS-II or MIPS32r1 (which are
351*9880d681SAndroid Build Coastguard Worker     // the cases where mfhc1 is not available). 64-bit architectures and
352*9880d681SAndroid Build Coastguard Worker     // MIPS32r2 or later can use FGR64 though.
353*9880d681SAndroid Build Coastguard Worker     assert(Subtarget.isGP64bit() || Subtarget.hasMTHC1() ||
354*9880d681SAndroid Build Coastguard Worker            !Subtarget.isFP64bit());
355*9880d681SAndroid Build Coastguard Worker 
356*9880d681SAndroid Build Coastguard Worker     const TargetRegisterClass *RC =
357*9880d681SAndroid Build Coastguard Worker         FP64 ? &Mips::FGR64RegClass : &Mips::AFGR64RegClass;
358*9880d681SAndroid Build Coastguard Worker     const TargetRegisterClass *RC2 = &Mips::GPR32RegClass;
359*9880d681SAndroid Build Coastguard Worker 
360*9880d681SAndroid Build Coastguard Worker     // We re-use the same spill slot each time so that the stack frame doesn't
361*9880d681SAndroid Build Coastguard Worker     // grow too much in functions with a large number of moves.
362*9880d681SAndroid Build Coastguard Worker     int FI = MF.getInfo<MipsFunctionInfo>()->getMoveF64ViaSpillFI(RC);
363*9880d681SAndroid Build Coastguard Worker     TII.storeRegToStack(MBB, I, SrcReg, Op1.isKill(), FI, RC, &RegInfo, 0);
364*9880d681SAndroid Build Coastguard Worker     TII.loadRegFromStack(MBB, I, DstReg, FI, RC2, &RegInfo, Offset);
365*9880d681SAndroid Build Coastguard Worker     return true;
366*9880d681SAndroid Build Coastguard Worker   }
367*9880d681SAndroid Build Coastguard Worker 
368*9880d681SAndroid Build Coastguard Worker   return false;
369*9880d681SAndroid Build Coastguard Worker }
370*9880d681SAndroid Build Coastguard Worker 
MipsSEFrameLowering(const MipsSubtarget & STI)371*9880d681SAndroid Build Coastguard Worker MipsSEFrameLowering::MipsSEFrameLowering(const MipsSubtarget &STI)
372*9880d681SAndroid Build Coastguard Worker     : MipsFrameLowering(STI, STI.stackAlignment()) {}
373*9880d681SAndroid Build Coastguard Worker 
emitPrologue(MachineFunction & MF,MachineBasicBlock & MBB) const374*9880d681SAndroid Build Coastguard Worker void MipsSEFrameLowering::emitPrologue(MachineFunction &MF,
375*9880d681SAndroid Build Coastguard Worker                                        MachineBasicBlock &MBB) const {
376*9880d681SAndroid Build Coastguard Worker   assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");
377*9880d681SAndroid Build Coastguard Worker   MachineFrameInfo *MFI    = MF.getFrameInfo();
378*9880d681SAndroid Build Coastguard Worker   MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
379*9880d681SAndroid Build Coastguard Worker 
380*9880d681SAndroid Build Coastguard Worker   const MipsSEInstrInfo &TII =
381*9880d681SAndroid Build Coastguard Worker       *static_cast<const MipsSEInstrInfo *>(STI.getInstrInfo());
382*9880d681SAndroid Build Coastguard Worker   const MipsRegisterInfo &RegInfo =
383*9880d681SAndroid Build Coastguard Worker       *static_cast<const MipsRegisterInfo *>(STI.getRegisterInfo());
384*9880d681SAndroid Build Coastguard Worker 
385*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock::iterator MBBI = MBB.begin();
386*9880d681SAndroid Build Coastguard Worker   DebugLoc dl;
387*9880d681SAndroid Build Coastguard Worker   MipsABIInfo ABI = STI.getABI();
388*9880d681SAndroid Build Coastguard Worker   unsigned SP = ABI.GetStackPtr();
389*9880d681SAndroid Build Coastguard Worker   unsigned FP = ABI.GetFramePtr();
390*9880d681SAndroid Build Coastguard Worker   unsigned ZERO = ABI.GetNullPtr();
391*9880d681SAndroid Build Coastguard Worker   unsigned MOVE = ABI.GetGPRMoveOp();
392*9880d681SAndroid Build Coastguard Worker   unsigned ADDiu = ABI.GetPtrAddiuOp();
393*9880d681SAndroid Build Coastguard Worker   unsigned AND = ABI.IsN64() ? Mips::AND64 : Mips::AND;
394*9880d681SAndroid Build Coastguard Worker 
395*9880d681SAndroid Build Coastguard Worker   const TargetRegisterClass *RC = ABI.ArePtrs64bit() ?
396*9880d681SAndroid Build Coastguard Worker         &Mips::GPR64RegClass : &Mips::GPR32RegClass;
397*9880d681SAndroid Build Coastguard Worker 
398*9880d681SAndroid Build Coastguard Worker   // First, compute final stack size.
399*9880d681SAndroid Build Coastguard Worker   uint64_t StackSize = MFI->getStackSize();
400*9880d681SAndroid Build Coastguard Worker 
401*9880d681SAndroid Build Coastguard Worker   // No need to allocate space on the stack.
402*9880d681SAndroid Build Coastguard Worker   if (StackSize == 0 && !MFI->adjustsStack()) return;
403*9880d681SAndroid Build Coastguard Worker 
404*9880d681SAndroid Build Coastguard Worker   MachineModuleInfo &MMI = MF.getMMI();
405*9880d681SAndroid Build Coastguard Worker   const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo();
406*9880d681SAndroid Build Coastguard Worker   MachineLocation DstML, SrcML;
407*9880d681SAndroid Build Coastguard Worker 
408*9880d681SAndroid Build Coastguard Worker   // Adjust stack.
409*9880d681SAndroid Build Coastguard Worker   TII.adjustStackPtr(SP, -StackSize, MBB, MBBI);
410*9880d681SAndroid Build Coastguard Worker 
411*9880d681SAndroid Build Coastguard Worker   // emit ".cfi_def_cfa_offset StackSize"
412*9880d681SAndroid Build Coastguard Worker   unsigned CFIIndex = MMI.addFrameInst(
413*9880d681SAndroid Build Coastguard Worker       MCCFIInstruction::createDefCfaOffset(nullptr, -StackSize));
414*9880d681SAndroid Build Coastguard Worker   BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
415*9880d681SAndroid Build Coastguard Worker       .addCFIIndex(CFIIndex);
416*9880d681SAndroid Build Coastguard Worker 
417*9880d681SAndroid Build Coastguard Worker   if (MF.getFunction()->hasFnAttribute("interrupt"))
418*9880d681SAndroid Build Coastguard Worker     emitInterruptPrologueStub(MF, MBB);
419*9880d681SAndroid Build Coastguard Worker 
420*9880d681SAndroid Build Coastguard Worker   const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
421*9880d681SAndroid Build Coastguard Worker 
422*9880d681SAndroid Build Coastguard Worker   if (CSI.size()) {
423*9880d681SAndroid Build Coastguard Worker     // Find the instruction past the last instruction that saves a callee-saved
424*9880d681SAndroid Build Coastguard Worker     // register to the stack.
425*9880d681SAndroid Build Coastguard Worker     for (unsigned i = 0; i < CSI.size(); ++i)
426*9880d681SAndroid Build Coastguard Worker       ++MBBI;
427*9880d681SAndroid Build Coastguard Worker 
428*9880d681SAndroid Build Coastguard Worker     // Iterate over list of callee-saved registers and emit .cfi_offset
429*9880d681SAndroid Build Coastguard Worker     // directives.
430*9880d681SAndroid Build Coastguard Worker     for (std::vector<CalleeSavedInfo>::const_iterator I = CSI.begin(),
431*9880d681SAndroid Build Coastguard Worker            E = CSI.end(); I != E; ++I) {
432*9880d681SAndroid Build Coastguard Worker       int64_t Offset = MFI->getObjectOffset(I->getFrameIdx());
433*9880d681SAndroid Build Coastguard Worker       unsigned Reg = I->getReg();
434*9880d681SAndroid Build Coastguard Worker 
435*9880d681SAndroid Build Coastguard Worker       // If Reg is a double precision register, emit two cfa_offsets,
436*9880d681SAndroid Build Coastguard Worker       // one for each of the paired single precision registers.
437*9880d681SAndroid Build Coastguard Worker       if (Mips::AFGR64RegClass.contains(Reg)) {
438*9880d681SAndroid Build Coastguard Worker         unsigned Reg0 =
439*9880d681SAndroid Build Coastguard Worker             MRI->getDwarfRegNum(RegInfo.getSubReg(Reg, Mips::sub_lo), true);
440*9880d681SAndroid Build Coastguard Worker         unsigned Reg1 =
441*9880d681SAndroid Build Coastguard Worker             MRI->getDwarfRegNum(RegInfo.getSubReg(Reg, Mips::sub_hi), true);
442*9880d681SAndroid Build Coastguard Worker 
443*9880d681SAndroid Build Coastguard Worker         if (!STI.isLittle())
444*9880d681SAndroid Build Coastguard Worker           std::swap(Reg0, Reg1);
445*9880d681SAndroid Build Coastguard Worker 
446*9880d681SAndroid Build Coastguard Worker         unsigned CFIIndex = MMI.addFrameInst(
447*9880d681SAndroid Build Coastguard Worker             MCCFIInstruction::createOffset(nullptr, Reg0, Offset));
448*9880d681SAndroid Build Coastguard Worker         BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
449*9880d681SAndroid Build Coastguard Worker             .addCFIIndex(CFIIndex);
450*9880d681SAndroid Build Coastguard Worker 
451*9880d681SAndroid Build Coastguard Worker         CFIIndex = MMI.addFrameInst(
452*9880d681SAndroid Build Coastguard Worker             MCCFIInstruction::createOffset(nullptr, Reg1, Offset + 4));
453*9880d681SAndroid Build Coastguard Worker         BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
454*9880d681SAndroid Build Coastguard Worker             .addCFIIndex(CFIIndex);
455*9880d681SAndroid Build Coastguard Worker       } else if (Mips::FGR64RegClass.contains(Reg)) {
456*9880d681SAndroid Build Coastguard Worker         unsigned Reg0 = MRI->getDwarfRegNum(Reg, true);
457*9880d681SAndroid Build Coastguard Worker         unsigned Reg1 = MRI->getDwarfRegNum(Reg, true) + 1;
458*9880d681SAndroid Build Coastguard Worker 
459*9880d681SAndroid Build Coastguard Worker         if (!STI.isLittle())
460*9880d681SAndroid Build Coastguard Worker           std::swap(Reg0, Reg1);
461*9880d681SAndroid Build Coastguard Worker 
462*9880d681SAndroid Build Coastguard Worker         unsigned CFIIndex = MMI.addFrameInst(
463*9880d681SAndroid Build Coastguard Worker           MCCFIInstruction::createOffset(nullptr, Reg0, Offset));
464*9880d681SAndroid Build Coastguard Worker         BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
465*9880d681SAndroid Build Coastguard Worker             .addCFIIndex(CFIIndex);
466*9880d681SAndroid Build Coastguard Worker 
467*9880d681SAndroid Build Coastguard Worker         CFIIndex = MMI.addFrameInst(
468*9880d681SAndroid Build Coastguard Worker           MCCFIInstruction::createOffset(nullptr, Reg1, Offset + 4));
469*9880d681SAndroid Build Coastguard Worker         BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
470*9880d681SAndroid Build Coastguard Worker             .addCFIIndex(CFIIndex);
471*9880d681SAndroid Build Coastguard Worker       } else {
472*9880d681SAndroid Build Coastguard Worker         // Reg is either in GPR32 or FGR32.
473*9880d681SAndroid Build Coastguard Worker         unsigned CFIIndex = MMI.addFrameInst(MCCFIInstruction::createOffset(
474*9880d681SAndroid Build Coastguard Worker             nullptr, MRI->getDwarfRegNum(Reg, 1), Offset));
475*9880d681SAndroid Build Coastguard Worker         BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
476*9880d681SAndroid Build Coastguard Worker             .addCFIIndex(CFIIndex);
477*9880d681SAndroid Build Coastguard Worker       }
478*9880d681SAndroid Build Coastguard Worker     }
479*9880d681SAndroid Build Coastguard Worker   }
480*9880d681SAndroid Build Coastguard Worker 
481*9880d681SAndroid Build Coastguard Worker   if (MipsFI->callsEhReturn()) {
482*9880d681SAndroid Build Coastguard Worker     // Insert instructions that spill eh data registers.
483*9880d681SAndroid Build Coastguard Worker     for (int I = 0; I < 4; ++I) {
484*9880d681SAndroid Build Coastguard Worker       if (!MBB.isLiveIn(ABI.GetEhDataReg(I)))
485*9880d681SAndroid Build Coastguard Worker         MBB.addLiveIn(ABI.GetEhDataReg(I));
486*9880d681SAndroid Build Coastguard Worker       TII.storeRegToStackSlot(MBB, MBBI, ABI.GetEhDataReg(I), false,
487*9880d681SAndroid Build Coastguard Worker                               MipsFI->getEhDataRegFI(I), RC, &RegInfo);
488*9880d681SAndroid Build Coastguard Worker     }
489*9880d681SAndroid Build Coastguard Worker 
490*9880d681SAndroid Build Coastguard Worker     // Emit .cfi_offset directives for eh data registers.
491*9880d681SAndroid Build Coastguard Worker     for (int I = 0; I < 4; ++I) {
492*9880d681SAndroid Build Coastguard Worker       int64_t Offset = MFI->getObjectOffset(MipsFI->getEhDataRegFI(I));
493*9880d681SAndroid Build Coastguard Worker       unsigned Reg = MRI->getDwarfRegNum(ABI.GetEhDataReg(I), true);
494*9880d681SAndroid Build Coastguard Worker       unsigned CFIIndex = MMI.addFrameInst(
495*9880d681SAndroid Build Coastguard Worker           MCCFIInstruction::createOffset(nullptr, Reg, Offset));
496*9880d681SAndroid Build Coastguard Worker       BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
497*9880d681SAndroid Build Coastguard Worker           .addCFIIndex(CFIIndex);
498*9880d681SAndroid Build Coastguard Worker     }
499*9880d681SAndroid Build Coastguard Worker   }
500*9880d681SAndroid Build Coastguard Worker 
501*9880d681SAndroid Build Coastguard Worker   // if framepointer enabled, set it to point to the stack pointer.
502*9880d681SAndroid Build Coastguard Worker   if (hasFP(MF)) {
503*9880d681SAndroid Build Coastguard Worker     // Insert instruction "move $fp, $sp" at this location.
504*9880d681SAndroid Build Coastguard Worker     BuildMI(MBB, MBBI, dl, TII.get(MOVE), FP).addReg(SP).addReg(ZERO)
505*9880d681SAndroid Build Coastguard Worker       .setMIFlag(MachineInstr::FrameSetup);
506*9880d681SAndroid Build Coastguard Worker 
507*9880d681SAndroid Build Coastguard Worker     // emit ".cfi_def_cfa_register $fp"
508*9880d681SAndroid Build Coastguard Worker     unsigned CFIIndex = MMI.addFrameInst(MCCFIInstruction::createDefCfaRegister(
509*9880d681SAndroid Build Coastguard Worker         nullptr, MRI->getDwarfRegNum(FP, true)));
510*9880d681SAndroid Build Coastguard Worker     BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
511*9880d681SAndroid Build Coastguard Worker         .addCFIIndex(CFIIndex);
512*9880d681SAndroid Build Coastguard Worker 
513*9880d681SAndroid Build Coastguard Worker     if (RegInfo.needsStackRealignment(MF)) {
514*9880d681SAndroid Build Coastguard Worker       // addiu $Reg, $zero, -MaxAlignment
515*9880d681SAndroid Build Coastguard Worker       // andi $sp, $sp, $Reg
516*9880d681SAndroid Build Coastguard Worker       unsigned VR = MF.getRegInfo().createVirtualRegister(RC);
517*9880d681SAndroid Build Coastguard Worker       assert(isInt<16>(MFI->getMaxAlignment()) &&
518*9880d681SAndroid Build Coastguard Worker              "Function's alignment size requirement is not supported.");
519*9880d681SAndroid Build Coastguard Worker       int MaxAlign = -(int)MFI->getMaxAlignment();
520*9880d681SAndroid Build Coastguard Worker 
521*9880d681SAndroid Build Coastguard Worker       BuildMI(MBB, MBBI, dl, TII.get(ADDiu), VR).addReg(ZERO) .addImm(MaxAlign);
522*9880d681SAndroid Build Coastguard Worker       BuildMI(MBB, MBBI, dl, TII.get(AND), SP).addReg(SP).addReg(VR);
523*9880d681SAndroid Build Coastguard Worker 
524*9880d681SAndroid Build Coastguard Worker       if (hasBP(MF)) {
525*9880d681SAndroid Build Coastguard Worker         // move $s7, $sp
526*9880d681SAndroid Build Coastguard Worker         unsigned BP = STI.isABI_N64() ? Mips::S7_64 : Mips::S7;
527*9880d681SAndroid Build Coastguard Worker         BuildMI(MBB, MBBI, dl, TII.get(MOVE), BP)
528*9880d681SAndroid Build Coastguard Worker           .addReg(SP)
529*9880d681SAndroid Build Coastguard Worker           .addReg(ZERO);
530*9880d681SAndroid Build Coastguard Worker       }
531*9880d681SAndroid Build Coastguard Worker     }
532*9880d681SAndroid Build Coastguard Worker   }
533*9880d681SAndroid Build Coastguard Worker }
534*9880d681SAndroid Build Coastguard Worker 
emitInterruptPrologueStub(MachineFunction & MF,MachineBasicBlock & MBB) const535*9880d681SAndroid Build Coastguard Worker void MipsSEFrameLowering::emitInterruptPrologueStub(
536*9880d681SAndroid Build Coastguard Worker     MachineFunction &MF, MachineBasicBlock &MBB) const {
537*9880d681SAndroid Build Coastguard Worker 
538*9880d681SAndroid Build Coastguard Worker   MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
539*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock::iterator MBBI = MBB.begin();
540*9880d681SAndroid Build Coastguard Worker   DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
541*9880d681SAndroid Build Coastguard Worker 
542*9880d681SAndroid Build Coastguard Worker   // Report an error the target doesn't support Mips32r2 or later.
543*9880d681SAndroid Build Coastguard Worker   // The epilogue relies on the use of the "ehb" to clear execution
544*9880d681SAndroid Build Coastguard Worker   // hazards. Pre R2 Mips relies on an implementation defined number
545*9880d681SAndroid Build Coastguard Worker   // of "ssnop"s to clear the execution hazard. Support for ssnop hazard
546*9880d681SAndroid Build Coastguard Worker   // clearing is not provided so reject that configuration.
547*9880d681SAndroid Build Coastguard Worker   if (!STI.hasMips32r2())
548*9880d681SAndroid Build Coastguard Worker     report_fatal_error(
549*9880d681SAndroid Build Coastguard Worker         "\"interrupt\" attribute is not supported on pre-MIPS32R2 or "
550*9880d681SAndroid Build Coastguard Worker         "MIPS16 targets.");
551*9880d681SAndroid Build Coastguard Worker 
552*9880d681SAndroid Build Coastguard Worker   // The GP register contains the "user" value, so we cannot perform
553*9880d681SAndroid Build Coastguard Worker   // any gp relative loads until we restore the "kernel" or "system" gp
554*9880d681SAndroid Build Coastguard Worker   // value. Until support is written we shall only accept the static
555*9880d681SAndroid Build Coastguard Worker   // relocation model.
556*9880d681SAndroid Build Coastguard Worker   if ((STI.getRelocationModel() != Reloc::Static))
557*9880d681SAndroid Build Coastguard Worker     report_fatal_error("\"interrupt\" attribute is only supported for the "
558*9880d681SAndroid Build Coastguard Worker                        "static relocation model on MIPS at the present time.");
559*9880d681SAndroid Build Coastguard Worker 
560*9880d681SAndroid Build Coastguard Worker   if (!STI.isABI_O32() || STI.hasMips64())
561*9880d681SAndroid Build Coastguard Worker     report_fatal_error("\"interrupt\" attribute is only supported for the "
562*9880d681SAndroid Build Coastguard Worker                        "O32 ABI on MIPS32R2+ at the present time.");
563*9880d681SAndroid Build Coastguard Worker 
564*9880d681SAndroid Build Coastguard Worker   // Perform ISR handling like GCC
565*9880d681SAndroid Build Coastguard Worker   StringRef IntKind =
566*9880d681SAndroid Build Coastguard Worker       MF.getFunction()->getFnAttribute("interrupt").getValueAsString();
567*9880d681SAndroid Build Coastguard Worker   const TargetRegisterClass *PtrRC = &Mips::GPR32RegClass;
568*9880d681SAndroid Build Coastguard Worker 
569*9880d681SAndroid Build Coastguard Worker   // EIC interrupt handling needs to read the Cause register to disable
570*9880d681SAndroid Build Coastguard Worker   // interrupts.
571*9880d681SAndroid Build Coastguard Worker   if (IntKind == "eic") {
572*9880d681SAndroid Build Coastguard Worker     // Coprocessor registers are always live per se.
573*9880d681SAndroid Build Coastguard Worker     MBB.addLiveIn(Mips::COP013);
574*9880d681SAndroid Build Coastguard Worker     BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::MFC0), Mips::K0)
575*9880d681SAndroid Build Coastguard Worker         .addReg(Mips::COP013)
576*9880d681SAndroid Build Coastguard Worker         .addImm(0)
577*9880d681SAndroid Build Coastguard Worker         .setMIFlag(MachineInstr::FrameSetup);
578*9880d681SAndroid Build Coastguard Worker 
579*9880d681SAndroid Build Coastguard Worker     BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::EXT), Mips::K0)
580*9880d681SAndroid Build Coastguard Worker         .addReg(Mips::K0)
581*9880d681SAndroid Build Coastguard Worker         .addImm(10)
582*9880d681SAndroid Build Coastguard Worker         .addImm(6)
583*9880d681SAndroid Build Coastguard Worker         .setMIFlag(MachineInstr::FrameSetup);
584*9880d681SAndroid Build Coastguard Worker   }
585*9880d681SAndroid Build Coastguard Worker 
586*9880d681SAndroid Build Coastguard Worker   // Fetch and spill EPC
587*9880d681SAndroid Build Coastguard Worker   MBB.addLiveIn(Mips::COP014);
588*9880d681SAndroid Build Coastguard Worker   BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::MFC0), Mips::K1)
589*9880d681SAndroid Build Coastguard Worker       .addReg(Mips::COP014)
590*9880d681SAndroid Build Coastguard Worker       .addImm(0)
591*9880d681SAndroid Build Coastguard Worker       .setMIFlag(MachineInstr::FrameSetup);
592*9880d681SAndroid Build Coastguard Worker 
593*9880d681SAndroid Build Coastguard Worker   STI.getInstrInfo()->storeRegToStack(MBB, MBBI, Mips::K1, false,
594*9880d681SAndroid Build Coastguard Worker                                       MipsFI->getISRRegFI(0), PtrRC,
595*9880d681SAndroid Build Coastguard Worker                                       STI.getRegisterInfo(), 0);
596*9880d681SAndroid Build Coastguard Worker 
597*9880d681SAndroid Build Coastguard Worker   // Fetch and Spill Status
598*9880d681SAndroid Build Coastguard Worker   MBB.addLiveIn(Mips::COP012);
599*9880d681SAndroid Build Coastguard Worker   BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::MFC0), Mips::K1)
600*9880d681SAndroid Build Coastguard Worker       .addReg(Mips::COP012)
601*9880d681SAndroid Build Coastguard Worker       .addImm(0)
602*9880d681SAndroid Build Coastguard Worker       .setMIFlag(MachineInstr::FrameSetup);
603*9880d681SAndroid Build Coastguard Worker 
604*9880d681SAndroid Build Coastguard Worker   STI.getInstrInfo()->storeRegToStack(MBB, MBBI, Mips::K1, false,
605*9880d681SAndroid Build Coastguard Worker                                       MipsFI->getISRRegFI(1), PtrRC,
606*9880d681SAndroid Build Coastguard Worker                                       STI.getRegisterInfo(), 0);
607*9880d681SAndroid Build Coastguard Worker 
608*9880d681SAndroid Build Coastguard Worker   // Build the configuration for disabling lower priority interrupts. Non EIC
609*9880d681SAndroid Build Coastguard Worker   // interrupts need to be masked off with zero, EIC from the Cause register.
610*9880d681SAndroid Build Coastguard Worker   unsigned InsPosition = 8;
611*9880d681SAndroid Build Coastguard Worker   unsigned InsSize = 0;
612*9880d681SAndroid Build Coastguard Worker   unsigned SrcReg = Mips::ZERO;
613*9880d681SAndroid Build Coastguard Worker 
614*9880d681SAndroid Build Coastguard Worker   // If the interrupt we're tied to is the EIC, switch the source for the
615*9880d681SAndroid Build Coastguard Worker   // masking off interrupts to the cause register.
616*9880d681SAndroid Build Coastguard Worker   if (IntKind == "eic") {
617*9880d681SAndroid Build Coastguard Worker     SrcReg = Mips::K0;
618*9880d681SAndroid Build Coastguard Worker     InsPosition = 10;
619*9880d681SAndroid Build Coastguard Worker     InsSize = 6;
620*9880d681SAndroid Build Coastguard Worker   } else
621*9880d681SAndroid Build Coastguard Worker     InsSize = StringSwitch<unsigned>(IntKind)
622*9880d681SAndroid Build Coastguard Worker                   .Case("sw0", 1)
623*9880d681SAndroid Build Coastguard Worker                   .Case("sw1", 2)
624*9880d681SAndroid Build Coastguard Worker                   .Case("hw0", 3)
625*9880d681SAndroid Build Coastguard Worker                   .Case("hw1", 4)
626*9880d681SAndroid Build Coastguard Worker                   .Case("hw2", 5)
627*9880d681SAndroid Build Coastguard Worker                   .Case("hw3", 6)
628*9880d681SAndroid Build Coastguard Worker                   .Case("hw4", 7)
629*9880d681SAndroid Build Coastguard Worker                   .Case("hw5", 8)
630*9880d681SAndroid Build Coastguard Worker                   .Default(0);
631*9880d681SAndroid Build Coastguard Worker   assert(InsSize != 0 && "Unknown interrupt type!");
632*9880d681SAndroid Build Coastguard Worker 
633*9880d681SAndroid Build Coastguard Worker   BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::INS), Mips::K1)
634*9880d681SAndroid Build Coastguard Worker       .addReg(SrcReg)
635*9880d681SAndroid Build Coastguard Worker       .addImm(InsPosition)
636*9880d681SAndroid Build Coastguard Worker       .addImm(InsSize)
637*9880d681SAndroid Build Coastguard Worker       .addReg(Mips::K1)
638*9880d681SAndroid Build Coastguard Worker       .setMIFlag(MachineInstr::FrameSetup);
639*9880d681SAndroid Build Coastguard Worker 
640*9880d681SAndroid Build Coastguard Worker   // Mask off KSU, ERL, EXL
641*9880d681SAndroid Build Coastguard Worker   BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::INS), Mips::K1)
642*9880d681SAndroid Build Coastguard Worker       .addReg(Mips::ZERO)
643*9880d681SAndroid Build Coastguard Worker       .addImm(1)
644*9880d681SAndroid Build Coastguard Worker       .addImm(4)
645*9880d681SAndroid Build Coastguard Worker       .addReg(Mips::K1)
646*9880d681SAndroid Build Coastguard Worker       .setMIFlag(MachineInstr::FrameSetup);
647*9880d681SAndroid Build Coastguard Worker 
648*9880d681SAndroid Build Coastguard Worker   // Disable the FPU as we are not spilling those register sets.
649*9880d681SAndroid Build Coastguard Worker   if (!STI.useSoftFloat())
650*9880d681SAndroid Build Coastguard Worker     BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::INS), Mips::K1)
651*9880d681SAndroid Build Coastguard Worker         .addReg(Mips::ZERO)
652*9880d681SAndroid Build Coastguard Worker         .addImm(29)
653*9880d681SAndroid Build Coastguard Worker         .addImm(1)
654*9880d681SAndroid Build Coastguard Worker         .addReg(Mips::K1)
655*9880d681SAndroid Build Coastguard Worker         .setMIFlag(MachineInstr::FrameSetup);
656*9880d681SAndroid Build Coastguard Worker 
657*9880d681SAndroid Build Coastguard Worker   // Set the new status
658*9880d681SAndroid Build Coastguard Worker   BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::MTC0), Mips::COP012)
659*9880d681SAndroid Build Coastguard Worker       .addReg(Mips::K1)
660*9880d681SAndroid Build Coastguard Worker       .addImm(0)
661*9880d681SAndroid Build Coastguard Worker       .setMIFlag(MachineInstr::FrameSetup);
662*9880d681SAndroid Build Coastguard Worker }
663*9880d681SAndroid Build Coastguard Worker 
emitEpilogue(MachineFunction & MF,MachineBasicBlock & MBB) const664*9880d681SAndroid Build Coastguard Worker void MipsSEFrameLowering::emitEpilogue(MachineFunction &MF,
665*9880d681SAndroid Build Coastguard Worker                                        MachineBasicBlock &MBB) const {
666*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
667*9880d681SAndroid Build Coastguard Worker   MachineFrameInfo *MFI            = MF.getFrameInfo();
668*9880d681SAndroid Build Coastguard Worker   MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
669*9880d681SAndroid Build Coastguard Worker 
670*9880d681SAndroid Build Coastguard Worker   const MipsSEInstrInfo &TII =
671*9880d681SAndroid Build Coastguard Worker       *static_cast<const MipsSEInstrInfo *>(STI.getInstrInfo());
672*9880d681SAndroid Build Coastguard Worker   const MipsRegisterInfo &RegInfo =
673*9880d681SAndroid Build Coastguard Worker       *static_cast<const MipsRegisterInfo *>(STI.getRegisterInfo());
674*9880d681SAndroid Build Coastguard Worker 
675*9880d681SAndroid Build Coastguard Worker   DebugLoc DL = MBBI->getDebugLoc();
676*9880d681SAndroid Build Coastguard Worker   MipsABIInfo ABI = STI.getABI();
677*9880d681SAndroid Build Coastguard Worker   unsigned SP = ABI.GetStackPtr();
678*9880d681SAndroid Build Coastguard Worker   unsigned FP = ABI.GetFramePtr();
679*9880d681SAndroid Build Coastguard Worker   unsigned ZERO = ABI.GetNullPtr();
680*9880d681SAndroid Build Coastguard Worker   unsigned MOVE = ABI.GetGPRMoveOp();
681*9880d681SAndroid Build Coastguard Worker 
682*9880d681SAndroid Build Coastguard Worker   // if framepointer enabled, restore the stack pointer.
683*9880d681SAndroid Build Coastguard Worker   if (hasFP(MF)) {
684*9880d681SAndroid Build Coastguard Worker     // Find the first instruction that restores a callee-saved register.
685*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock::iterator I = MBBI;
686*9880d681SAndroid Build Coastguard Worker 
687*9880d681SAndroid Build Coastguard Worker     for (unsigned i = 0; i < MFI->getCalleeSavedInfo().size(); ++i)
688*9880d681SAndroid Build Coastguard Worker       --I;
689*9880d681SAndroid Build Coastguard Worker 
690*9880d681SAndroid Build Coastguard Worker     // Insert instruction "move $sp, $fp" at this location.
691*9880d681SAndroid Build Coastguard Worker     BuildMI(MBB, I, DL, TII.get(MOVE), SP).addReg(FP).addReg(ZERO);
692*9880d681SAndroid Build Coastguard Worker   }
693*9880d681SAndroid Build Coastguard Worker 
694*9880d681SAndroid Build Coastguard Worker   if (MipsFI->callsEhReturn()) {
695*9880d681SAndroid Build Coastguard Worker     const TargetRegisterClass *RC =
696*9880d681SAndroid Build Coastguard Worker         ABI.ArePtrs64bit() ? &Mips::GPR64RegClass : &Mips::GPR32RegClass;
697*9880d681SAndroid Build Coastguard Worker 
698*9880d681SAndroid Build Coastguard Worker     // Find first instruction that restores a callee-saved register.
699*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock::iterator I = MBBI;
700*9880d681SAndroid Build Coastguard Worker     for (unsigned i = 0; i < MFI->getCalleeSavedInfo().size(); ++i)
701*9880d681SAndroid Build Coastguard Worker       --I;
702*9880d681SAndroid Build Coastguard Worker 
703*9880d681SAndroid Build Coastguard Worker     // Insert instructions that restore eh data registers.
704*9880d681SAndroid Build Coastguard Worker     for (int J = 0; J < 4; ++J) {
705*9880d681SAndroid Build Coastguard Worker       TII.loadRegFromStackSlot(MBB, I, ABI.GetEhDataReg(J),
706*9880d681SAndroid Build Coastguard Worker                                MipsFI->getEhDataRegFI(J), RC, &RegInfo);
707*9880d681SAndroid Build Coastguard Worker     }
708*9880d681SAndroid Build Coastguard Worker   }
709*9880d681SAndroid Build Coastguard Worker 
710*9880d681SAndroid Build Coastguard Worker   if (MF.getFunction()->hasFnAttribute("interrupt"))
711*9880d681SAndroid Build Coastguard Worker     emitInterruptEpilogueStub(MF, MBB);
712*9880d681SAndroid Build Coastguard Worker 
713*9880d681SAndroid Build Coastguard Worker   // Get the number of bytes from FrameInfo
714*9880d681SAndroid Build Coastguard Worker   uint64_t StackSize = MFI->getStackSize();
715*9880d681SAndroid Build Coastguard Worker 
716*9880d681SAndroid Build Coastguard Worker   if (!StackSize)
717*9880d681SAndroid Build Coastguard Worker     return;
718*9880d681SAndroid Build Coastguard Worker 
719*9880d681SAndroid Build Coastguard Worker   // Adjust stack.
720*9880d681SAndroid Build Coastguard Worker   TII.adjustStackPtr(SP, StackSize, MBB, MBBI);
721*9880d681SAndroid Build Coastguard Worker }
722*9880d681SAndroid Build Coastguard Worker 
emitInterruptEpilogueStub(MachineFunction & MF,MachineBasicBlock & MBB) const723*9880d681SAndroid Build Coastguard Worker void MipsSEFrameLowering::emitInterruptEpilogueStub(
724*9880d681SAndroid Build Coastguard Worker     MachineFunction &MF, MachineBasicBlock &MBB) const {
725*9880d681SAndroid Build Coastguard Worker 
726*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
727*9880d681SAndroid Build Coastguard Worker   MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
728*9880d681SAndroid Build Coastguard Worker   DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
729*9880d681SAndroid Build Coastguard Worker 
730*9880d681SAndroid Build Coastguard Worker   // Perform ISR handling like GCC
731*9880d681SAndroid Build Coastguard Worker   const TargetRegisterClass *PtrRC = &Mips::GPR32RegClass;
732*9880d681SAndroid Build Coastguard Worker 
733*9880d681SAndroid Build Coastguard Worker   // Disable Interrupts.
734*9880d681SAndroid Build Coastguard Worker   BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::DI), Mips::ZERO);
735*9880d681SAndroid Build Coastguard Worker   BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::EHB));
736*9880d681SAndroid Build Coastguard Worker 
737*9880d681SAndroid Build Coastguard Worker   // Restore EPC
738*9880d681SAndroid Build Coastguard Worker   STI.getInstrInfo()->loadRegFromStackSlot(MBB, MBBI, Mips::K1,
739*9880d681SAndroid Build Coastguard Worker                                            MipsFI->getISRRegFI(0), PtrRC,
740*9880d681SAndroid Build Coastguard Worker                                            STI.getRegisterInfo());
741*9880d681SAndroid Build Coastguard Worker   BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::MTC0), Mips::COP014)
742*9880d681SAndroid Build Coastguard Worker       .addReg(Mips::K1)
743*9880d681SAndroid Build Coastguard Worker       .addImm(0);
744*9880d681SAndroid Build Coastguard Worker 
745*9880d681SAndroid Build Coastguard Worker   // Restore Status
746*9880d681SAndroid Build Coastguard Worker   STI.getInstrInfo()->loadRegFromStackSlot(MBB, MBBI, Mips::K1,
747*9880d681SAndroid Build Coastguard Worker                                            MipsFI->getISRRegFI(1), PtrRC,
748*9880d681SAndroid Build Coastguard Worker                                            STI.getRegisterInfo());
749*9880d681SAndroid Build Coastguard Worker   BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::MTC0), Mips::COP012)
750*9880d681SAndroid Build Coastguard Worker       .addReg(Mips::K1)
751*9880d681SAndroid Build Coastguard Worker       .addImm(0);
752*9880d681SAndroid Build Coastguard Worker }
753*9880d681SAndroid Build Coastguard Worker 
getFrameIndexReference(const MachineFunction & MF,int FI,unsigned & FrameReg) const754*9880d681SAndroid Build Coastguard Worker int MipsSEFrameLowering::getFrameIndexReference(const MachineFunction &MF,
755*9880d681SAndroid Build Coastguard Worker                                                 int FI,
756*9880d681SAndroid Build Coastguard Worker                                                 unsigned &FrameReg) const {
757*9880d681SAndroid Build Coastguard Worker   const MachineFrameInfo *MFI = MF.getFrameInfo();
758*9880d681SAndroid Build Coastguard Worker   MipsABIInfo ABI = STI.getABI();
759*9880d681SAndroid Build Coastguard Worker 
760*9880d681SAndroid Build Coastguard Worker   if (MFI->isFixedObjectIndex(FI))
761*9880d681SAndroid Build Coastguard Worker     FrameReg = hasFP(MF) ? ABI.GetFramePtr() : ABI.GetStackPtr();
762*9880d681SAndroid Build Coastguard Worker   else
763*9880d681SAndroid Build Coastguard Worker     FrameReg = hasBP(MF) ? ABI.GetBasePtr() : ABI.GetStackPtr();
764*9880d681SAndroid Build Coastguard Worker 
765*9880d681SAndroid Build Coastguard Worker   return MFI->getObjectOffset(FI) + MFI->getStackSize() -
766*9880d681SAndroid Build Coastguard Worker          getOffsetOfLocalArea() + MFI->getOffsetAdjustment();
767*9880d681SAndroid Build Coastguard Worker }
768*9880d681SAndroid Build Coastguard Worker 
769*9880d681SAndroid Build Coastguard Worker bool MipsSEFrameLowering::
spillCalleeSavedRegisters(MachineBasicBlock & MBB,MachineBasicBlock::iterator MI,const std::vector<CalleeSavedInfo> & CSI,const TargetRegisterInfo * TRI) const770*9880d681SAndroid Build Coastguard Worker spillCalleeSavedRegisters(MachineBasicBlock &MBB,
771*9880d681SAndroid Build Coastguard Worker                           MachineBasicBlock::iterator MI,
772*9880d681SAndroid Build Coastguard Worker                           const std::vector<CalleeSavedInfo> &CSI,
773*9880d681SAndroid Build Coastguard Worker                           const TargetRegisterInfo *TRI) const {
774*9880d681SAndroid Build Coastguard Worker   MachineFunction *MF = MBB.getParent();
775*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock *EntryBlock = &MF->front();
776*9880d681SAndroid Build Coastguard Worker   const TargetInstrInfo &TII = *STI.getInstrInfo();
777*9880d681SAndroid Build Coastguard Worker 
778*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
779*9880d681SAndroid Build Coastguard Worker     // Add the callee-saved register as live-in. Do not add if the register is
780*9880d681SAndroid Build Coastguard Worker     // RA and return address is taken, because it has already been added in
781*9880d681SAndroid Build Coastguard Worker     // method MipsTargetLowering::LowerRETURNADDR.
782*9880d681SAndroid Build Coastguard Worker     // It's killed at the spill, unless the register is RA and return address
783*9880d681SAndroid Build Coastguard Worker     // is taken.
784*9880d681SAndroid Build Coastguard Worker     unsigned Reg = CSI[i].getReg();
785*9880d681SAndroid Build Coastguard Worker     bool IsRAAndRetAddrIsTaken = (Reg == Mips::RA || Reg == Mips::RA_64)
786*9880d681SAndroid Build Coastguard Worker         && MF->getFrameInfo()->isReturnAddressTaken();
787*9880d681SAndroid Build Coastguard Worker     if (!IsRAAndRetAddrIsTaken)
788*9880d681SAndroid Build Coastguard Worker       EntryBlock->addLiveIn(Reg);
789*9880d681SAndroid Build Coastguard Worker 
790*9880d681SAndroid Build Coastguard Worker     // ISRs require HI/LO to be spilled into kernel registers to be then
791*9880d681SAndroid Build Coastguard Worker     // spilled to the stack frame.
792*9880d681SAndroid Build Coastguard Worker     bool IsLOHI = (Reg == Mips::LO0 || Reg == Mips::LO0_64 ||
793*9880d681SAndroid Build Coastguard Worker                    Reg == Mips::HI0 || Reg == Mips::HI0_64);
794*9880d681SAndroid Build Coastguard Worker     const Function *Func = MBB.getParent()->getFunction();
795*9880d681SAndroid Build Coastguard Worker     if (IsLOHI && Func->hasFnAttribute("interrupt")) {
796*9880d681SAndroid Build Coastguard Worker       DebugLoc DL = MI->getDebugLoc();
797*9880d681SAndroid Build Coastguard Worker 
798*9880d681SAndroid Build Coastguard Worker       unsigned Op = 0;
799*9880d681SAndroid Build Coastguard Worker       if (!STI.getABI().ArePtrs64bit()) {
800*9880d681SAndroid Build Coastguard Worker         Op = (Reg == Mips::HI0) ? Mips::MFHI : Mips::MFLO;
801*9880d681SAndroid Build Coastguard Worker         Reg = Mips::K0;
802*9880d681SAndroid Build Coastguard Worker       } else {
803*9880d681SAndroid Build Coastguard Worker         Op = (Reg == Mips::HI0) ? Mips::MFHI64 : Mips::MFLO64;
804*9880d681SAndroid Build Coastguard Worker         Reg = Mips::K0_64;
805*9880d681SAndroid Build Coastguard Worker       }
806*9880d681SAndroid Build Coastguard Worker       BuildMI(MBB, MI, DL, TII.get(Op), Mips::K0)
807*9880d681SAndroid Build Coastguard Worker           .setMIFlag(MachineInstr::FrameSetup);
808*9880d681SAndroid Build Coastguard Worker     }
809*9880d681SAndroid Build Coastguard Worker 
810*9880d681SAndroid Build Coastguard Worker     // Insert the spill to the stack frame.
811*9880d681SAndroid Build Coastguard Worker     bool IsKill = !IsRAAndRetAddrIsTaken;
812*9880d681SAndroid Build Coastguard Worker     const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
813*9880d681SAndroid Build Coastguard Worker     TII.storeRegToStackSlot(*EntryBlock, MI, Reg, IsKill,
814*9880d681SAndroid Build Coastguard Worker                             CSI[i].getFrameIdx(), RC, TRI);
815*9880d681SAndroid Build Coastguard Worker   }
816*9880d681SAndroid Build Coastguard Worker 
817*9880d681SAndroid Build Coastguard Worker   return true;
818*9880d681SAndroid Build Coastguard Worker }
819*9880d681SAndroid Build Coastguard Worker 
820*9880d681SAndroid Build Coastguard Worker bool
hasReservedCallFrame(const MachineFunction & MF) const821*9880d681SAndroid Build Coastguard Worker MipsSEFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
822*9880d681SAndroid Build Coastguard Worker   const MachineFrameInfo *MFI = MF.getFrameInfo();
823*9880d681SAndroid Build Coastguard Worker 
824*9880d681SAndroid Build Coastguard Worker   // Reserve call frame if the size of the maximum call frame fits into 16-bit
825*9880d681SAndroid Build Coastguard Worker   // immediate field and there are no variable sized objects on the stack.
826*9880d681SAndroid Build Coastguard Worker   // Make sure the second register scavenger spill slot can be accessed with one
827*9880d681SAndroid Build Coastguard Worker   // instruction.
828*9880d681SAndroid Build Coastguard Worker   return isInt<16>(MFI->getMaxCallFrameSize() + getStackAlignment()) &&
829*9880d681SAndroid Build Coastguard Worker     !MFI->hasVarSizedObjects();
830*9880d681SAndroid Build Coastguard Worker }
831*9880d681SAndroid Build Coastguard Worker 
832*9880d681SAndroid Build Coastguard Worker /// Mark \p Reg and all registers aliasing it in the bitset.
setAliasRegs(MachineFunction & MF,BitVector & SavedRegs,unsigned Reg)833*9880d681SAndroid Build Coastguard Worker static void setAliasRegs(MachineFunction &MF, BitVector &SavedRegs,
834*9880d681SAndroid Build Coastguard Worker                          unsigned Reg) {
835*9880d681SAndroid Build Coastguard Worker   const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
836*9880d681SAndroid Build Coastguard Worker   for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI)
837*9880d681SAndroid Build Coastguard Worker     SavedRegs.set(*AI);
838*9880d681SAndroid Build Coastguard Worker }
839*9880d681SAndroid Build Coastguard Worker 
determineCalleeSaves(MachineFunction & MF,BitVector & SavedRegs,RegScavenger * RS) const840*9880d681SAndroid Build Coastguard Worker void MipsSEFrameLowering::determineCalleeSaves(MachineFunction &MF,
841*9880d681SAndroid Build Coastguard Worker                                                BitVector &SavedRegs,
842*9880d681SAndroid Build Coastguard Worker                                                RegScavenger *RS) const {
843*9880d681SAndroid Build Coastguard Worker   TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
844*9880d681SAndroid Build Coastguard Worker   MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
845*9880d681SAndroid Build Coastguard Worker   MipsABIInfo ABI = STI.getABI();
846*9880d681SAndroid Build Coastguard Worker   unsigned FP = ABI.GetFramePtr();
847*9880d681SAndroid Build Coastguard Worker   unsigned BP = ABI.IsN64() ? Mips::S7_64 : Mips::S7;
848*9880d681SAndroid Build Coastguard Worker 
849*9880d681SAndroid Build Coastguard Worker   // Mark $fp as used if function has dedicated frame pointer.
850*9880d681SAndroid Build Coastguard Worker   if (hasFP(MF))
851*9880d681SAndroid Build Coastguard Worker     setAliasRegs(MF, SavedRegs, FP);
852*9880d681SAndroid Build Coastguard Worker   // Mark $s7 as used if function has dedicated base pointer.
853*9880d681SAndroid Build Coastguard Worker   if (hasBP(MF))
854*9880d681SAndroid Build Coastguard Worker     setAliasRegs(MF, SavedRegs, BP);
855*9880d681SAndroid Build Coastguard Worker 
856*9880d681SAndroid Build Coastguard Worker   // Create spill slots for eh data registers if function calls eh_return.
857*9880d681SAndroid Build Coastguard Worker   if (MipsFI->callsEhReturn())
858*9880d681SAndroid Build Coastguard Worker     MipsFI->createEhDataRegsFI();
859*9880d681SAndroid Build Coastguard Worker 
860*9880d681SAndroid Build Coastguard Worker   // Create spill slots for Coprocessor 0 registers if function is an ISR.
861*9880d681SAndroid Build Coastguard Worker   if (MipsFI->isISR())
862*9880d681SAndroid Build Coastguard Worker     MipsFI->createISRRegFI();
863*9880d681SAndroid Build Coastguard Worker 
864*9880d681SAndroid Build Coastguard Worker   // Expand pseudo instructions which load, store or copy accumulators.
865*9880d681SAndroid Build Coastguard Worker   // Add an emergency spill slot if a pseudo was expanded.
866*9880d681SAndroid Build Coastguard Worker   if (ExpandPseudo(MF).expand()) {
867*9880d681SAndroid Build Coastguard Worker     // The spill slot should be half the size of the accumulator. If target is
868*9880d681SAndroid Build Coastguard Worker     // mips64, it should be 64-bit, otherwise it should be 32-bt.
869*9880d681SAndroid Build Coastguard Worker     const TargetRegisterClass *RC = STI.hasMips64() ?
870*9880d681SAndroid Build Coastguard Worker       &Mips::GPR64RegClass : &Mips::GPR32RegClass;
871*9880d681SAndroid Build Coastguard Worker     int FI = MF.getFrameInfo()->CreateStackObject(RC->getSize(),
872*9880d681SAndroid Build Coastguard Worker                                                   RC->getAlignment(), false);
873*9880d681SAndroid Build Coastguard Worker     RS->addScavengingFrameIndex(FI);
874*9880d681SAndroid Build Coastguard Worker   }
875*9880d681SAndroid Build Coastguard Worker 
876*9880d681SAndroid Build Coastguard Worker   // Set scavenging frame index if necessary.
877*9880d681SAndroid Build Coastguard Worker   uint64_t MaxSPOffset = MF.getInfo<MipsFunctionInfo>()->getIncomingArgSize() +
878*9880d681SAndroid Build Coastguard Worker     estimateStackSize(MF);
879*9880d681SAndroid Build Coastguard Worker 
880*9880d681SAndroid Build Coastguard Worker   if (isInt<16>(MaxSPOffset))
881*9880d681SAndroid Build Coastguard Worker     return;
882*9880d681SAndroid Build Coastguard Worker 
883*9880d681SAndroid Build Coastguard Worker   const TargetRegisterClass *RC =
884*9880d681SAndroid Build Coastguard Worker       ABI.ArePtrs64bit() ? &Mips::GPR64RegClass : &Mips::GPR32RegClass;
885*9880d681SAndroid Build Coastguard Worker   int FI = MF.getFrameInfo()->CreateStackObject(RC->getSize(),
886*9880d681SAndroid Build Coastguard Worker                                                 RC->getAlignment(), false);
887*9880d681SAndroid Build Coastguard Worker   RS->addScavengingFrameIndex(FI);
888*9880d681SAndroid Build Coastguard Worker }
889*9880d681SAndroid Build Coastguard Worker 
890*9880d681SAndroid Build Coastguard Worker const MipsFrameLowering *
createMipsSEFrameLowering(const MipsSubtarget & ST)891*9880d681SAndroid Build Coastguard Worker llvm::createMipsSEFrameLowering(const MipsSubtarget &ST) {
892*9880d681SAndroid Build Coastguard Worker   return new MipsSEFrameLowering(ST);
893*9880d681SAndroid Build Coastguard Worker }
894