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