1f4a2713aSLionel Sambuc //===-- MipsSEInstrInfo.cpp - Mips32/64 Instruction Information -----------===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc //                     The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc // This file contains the Mips32/64 implementation of the TargetInstrInfo class.
11f4a2713aSLionel Sambuc //
12f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
13f4a2713aSLionel Sambuc 
14f4a2713aSLionel Sambuc #include "MipsSEInstrInfo.h"
15f4a2713aSLionel Sambuc #include "InstPrinter/MipsInstPrinter.h"
16f4a2713aSLionel Sambuc #include "MipsMachineFunction.h"
17f4a2713aSLionel Sambuc #include "MipsTargetMachine.h"
18f4a2713aSLionel Sambuc #include "llvm/ADT/STLExtras.h"
19f4a2713aSLionel Sambuc #include "llvm/CodeGen/MachineInstrBuilder.h"
20f4a2713aSLionel Sambuc #include "llvm/CodeGen/MachineRegisterInfo.h"
21f4a2713aSLionel Sambuc #include "llvm/Support/CommandLine.h"
22f4a2713aSLionel Sambuc #include "llvm/Support/ErrorHandling.h"
23f4a2713aSLionel Sambuc #include "llvm/Support/TargetRegistry.h"
24f4a2713aSLionel Sambuc 
25f4a2713aSLionel Sambuc using namespace llvm;
26f4a2713aSLionel Sambuc 
MipsSEInstrInfo(const MipsSubtarget & STI)27*0a6a1f1dSLionel Sambuc MipsSEInstrInfo::MipsSEInstrInfo(const MipsSubtarget &STI)
28*0a6a1f1dSLionel Sambuc     : MipsInstrInfo(STI, STI.getRelocationModel() == Reloc::PIC_ ? Mips::B
29*0a6a1f1dSLionel Sambuc                                                                  : Mips::J),
30*0a6a1f1dSLionel Sambuc       RI(STI) {}
31f4a2713aSLionel Sambuc 
getRegisterInfo() const32f4a2713aSLionel Sambuc const MipsRegisterInfo &MipsSEInstrInfo::getRegisterInfo() const {
33f4a2713aSLionel Sambuc   return RI;
34f4a2713aSLionel Sambuc }
35f4a2713aSLionel Sambuc 
36f4a2713aSLionel Sambuc /// isLoadFromStackSlot - If the specified machine instruction is a direct
37f4a2713aSLionel Sambuc /// load from a stack slot, return the virtual or physical register number of
38f4a2713aSLionel Sambuc /// the destination along with the FrameIndex of the loaded stack slot.  If
39f4a2713aSLionel Sambuc /// not, return 0.  This predicate must return 0 if the instruction has
40f4a2713aSLionel Sambuc /// any side effects other than loading from the stack slot.
isLoadFromStackSlot(const MachineInstr * MI,int & FrameIndex) const41*0a6a1f1dSLionel Sambuc unsigned MipsSEInstrInfo::isLoadFromStackSlot(const MachineInstr *MI,
42*0a6a1f1dSLionel Sambuc                                               int &FrameIndex) const {
43f4a2713aSLionel Sambuc   unsigned Opc = MI->getOpcode();
44f4a2713aSLionel Sambuc 
45f4a2713aSLionel Sambuc   if ((Opc == Mips::LW)   || (Opc == Mips::LD)   ||
46f4a2713aSLionel Sambuc       (Opc == Mips::LWC1) || (Opc == Mips::LDC1) || (Opc == Mips::LDC164)) {
47f4a2713aSLionel Sambuc     if ((MI->getOperand(1).isFI()) && // is a stack slot
48f4a2713aSLionel Sambuc         (MI->getOperand(2).isImm()) &&  // the imm is zero
49f4a2713aSLionel Sambuc         (isZeroImm(MI->getOperand(2)))) {
50f4a2713aSLionel Sambuc       FrameIndex = MI->getOperand(1).getIndex();
51f4a2713aSLionel Sambuc       return MI->getOperand(0).getReg();
52f4a2713aSLionel Sambuc     }
53f4a2713aSLionel Sambuc   }
54f4a2713aSLionel Sambuc 
55f4a2713aSLionel Sambuc   return 0;
56f4a2713aSLionel Sambuc }
57f4a2713aSLionel Sambuc 
58f4a2713aSLionel Sambuc /// isStoreToStackSlot - If the specified machine instruction is a direct
59f4a2713aSLionel Sambuc /// store to a stack slot, return the virtual or physical register number of
60f4a2713aSLionel Sambuc /// the source reg along with the FrameIndex of the loaded stack slot.  If
61f4a2713aSLionel Sambuc /// not, return 0.  This predicate must return 0 if the instruction has
62f4a2713aSLionel Sambuc /// any side effects other than storing to the stack slot.
isStoreToStackSlot(const MachineInstr * MI,int & FrameIndex) const63*0a6a1f1dSLionel Sambuc unsigned MipsSEInstrInfo::isStoreToStackSlot(const MachineInstr *MI,
64*0a6a1f1dSLionel Sambuc                                              int &FrameIndex) const {
65f4a2713aSLionel Sambuc   unsigned Opc = MI->getOpcode();
66f4a2713aSLionel Sambuc 
67f4a2713aSLionel Sambuc   if ((Opc == Mips::SW)   || (Opc == Mips::SD)   ||
68f4a2713aSLionel Sambuc       (Opc == Mips::SWC1) || (Opc == Mips::SDC1) || (Opc == Mips::SDC164)) {
69f4a2713aSLionel Sambuc     if ((MI->getOperand(1).isFI()) && // is a stack slot
70f4a2713aSLionel Sambuc         (MI->getOperand(2).isImm()) &&  // the imm is zero
71f4a2713aSLionel Sambuc         (isZeroImm(MI->getOperand(2)))) {
72f4a2713aSLionel Sambuc       FrameIndex = MI->getOperand(1).getIndex();
73f4a2713aSLionel Sambuc       return MI->getOperand(0).getReg();
74f4a2713aSLionel Sambuc     }
75f4a2713aSLionel Sambuc   }
76f4a2713aSLionel Sambuc   return 0;
77f4a2713aSLionel Sambuc }
78f4a2713aSLionel Sambuc 
copyPhysReg(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,DebugLoc DL,unsigned DestReg,unsigned SrcReg,bool KillSrc) const79f4a2713aSLionel Sambuc void MipsSEInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
80f4a2713aSLionel Sambuc                                   MachineBasicBlock::iterator I, DebugLoc DL,
81f4a2713aSLionel Sambuc                                   unsigned DestReg, unsigned SrcReg,
82f4a2713aSLionel Sambuc                                   bool KillSrc) const {
83f4a2713aSLionel Sambuc   unsigned Opc = 0, ZeroReg = 0;
84*0a6a1f1dSLionel Sambuc   bool isMicroMips = Subtarget.inMicroMipsMode();
85f4a2713aSLionel Sambuc 
86f4a2713aSLionel Sambuc   if (Mips::GPR32RegClass.contains(DestReg)) { // Copy to CPU Reg.
87*0a6a1f1dSLionel Sambuc     if (Mips::GPR32RegClass.contains(SrcReg)) {
88*0a6a1f1dSLionel Sambuc       if (isMicroMips)
89*0a6a1f1dSLionel Sambuc         Opc = Mips::MOVE16_MM;
90*0a6a1f1dSLionel Sambuc       else
91f4a2713aSLionel Sambuc         Opc = Mips::ADDu, ZeroReg = Mips::ZERO;
92*0a6a1f1dSLionel Sambuc     } else if (Mips::CCRRegClass.contains(SrcReg))
93f4a2713aSLionel Sambuc       Opc = Mips::CFC1;
94f4a2713aSLionel Sambuc     else if (Mips::FGR32RegClass.contains(SrcReg))
95f4a2713aSLionel Sambuc       Opc = Mips::MFC1;
96*0a6a1f1dSLionel Sambuc     else if (Mips::HI32RegClass.contains(SrcReg)) {
97*0a6a1f1dSLionel Sambuc       Opc = isMicroMips ? Mips::MFHI16_MM : Mips::MFHI;
98*0a6a1f1dSLionel Sambuc       SrcReg = 0;
99*0a6a1f1dSLionel Sambuc     } else if (Mips::LO32RegClass.contains(SrcReg)) {
100*0a6a1f1dSLionel Sambuc       Opc = isMicroMips ? Mips::MFLO16_MM : Mips::MFLO;
101*0a6a1f1dSLionel Sambuc       SrcReg = 0;
102*0a6a1f1dSLionel Sambuc     } else if (Mips::HI32DSPRegClass.contains(SrcReg))
103f4a2713aSLionel Sambuc       Opc = Mips::MFHI_DSP;
104f4a2713aSLionel Sambuc     else if (Mips::LO32DSPRegClass.contains(SrcReg))
105f4a2713aSLionel Sambuc       Opc = Mips::MFLO_DSP;
106f4a2713aSLionel Sambuc     else if (Mips::DSPCCRegClass.contains(SrcReg)) {
107f4a2713aSLionel Sambuc       BuildMI(MBB, I, DL, get(Mips::RDDSP), DestReg).addImm(1 << 4)
108f4a2713aSLionel Sambuc         .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
109f4a2713aSLionel Sambuc       return;
110f4a2713aSLionel Sambuc     }
111f4a2713aSLionel Sambuc     else if (Mips::MSACtrlRegClass.contains(SrcReg))
112f4a2713aSLionel Sambuc       Opc = Mips::CFCMSA;
113f4a2713aSLionel Sambuc   }
114f4a2713aSLionel Sambuc   else if (Mips::GPR32RegClass.contains(SrcReg)) { // Copy from CPU Reg.
115f4a2713aSLionel Sambuc     if (Mips::CCRRegClass.contains(DestReg))
116f4a2713aSLionel Sambuc       Opc = Mips::CTC1;
117f4a2713aSLionel Sambuc     else if (Mips::FGR32RegClass.contains(DestReg))
118f4a2713aSLionel Sambuc       Opc = Mips::MTC1;
119f4a2713aSLionel Sambuc     else if (Mips::HI32RegClass.contains(DestReg))
120f4a2713aSLionel Sambuc       Opc = Mips::MTHI, DestReg = 0;
121f4a2713aSLionel Sambuc     else if (Mips::LO32RegClass.contains(DestReg))
122f4a2713aSLionel Sambuc       Opc = Mips::MTLO, DestReg = 0;
123f4a2713aSLionel Sambuc     else if (Mips::HI32DSPRegClass.contains(DestReg))
124f4a2713aSLionel Sambuc       Opc = Mips::MTHI_DSP;
125f4a2713aSLionel Sambuc     else if (Mips::LO32DSPRegClass.contains(DestReg))
126f4a2713aSLionel Sambuc       Opc = Mips::MTLO_DSP;
127f4a2713aSLionel Sambuc     else if (Mips::DSPCCRegClass.contains(DestReg)) {
128f4a2713aSLionel Sambuc       BuildMI(MBB, I, DL, get(Mips::WRDSP))
129f4a2713aSLionel Sambuc         .addReg(SrcReg, getKillRegState(KillSrc)).addImm(1 << 4)
130f4a2713aSLionel Sambuc         .addReg(DestReg, RegState::ImplicitDefine);
131f4a2713aSLionel Sambuc       return;
132f4a2713aSLionel Sambuc     }
133f4a2713aSLionel Sambuc     else if (Mips::MSACtrlRegClass.contains(DestReg))
134f4a2713aSLionel Sambuc       Opc = Mips::CTCMSA;
135f4a2713aSLionel Sambuc   }
136f4a2713aSLionel Sambuc   else if (Mips::FGR32RegClass.contains(DestReg, SrcReg))
137f4a2713aSLionel Sambuc     Opc = Mips::FMOV_S;
138f4a2713aSLionel Sambuc   else if (Mips::AFGR64RegClass.contains(DestReg, SrcReg))
139f4a2713aSLionel Sambuc     Opc = Mips::FMOV_D32;
140f4a2713aSLionel Sambuc   else if (Mips::FGR64RegClass.contains(DestReg, SrcReg))
141f4a2713aSLionel Sambuc     Opc = Mips::FMOV_D64;
142f4a2713aSLionel Sambuc   else if (Mips::GPR64RegClass.contains(DestReg)) { // Copy to CPU64 Reg.
143f4a2713aSLionel Sambuc     if (Mips::GPR64RegClass.contains(SrcReg))
144f4a2713aSLionel Sambuc       Opc = Mips::DADDu, ZeroReg = Mips::ZERO_64;
145f4a2713aSLionel Sambuc     else if (Mips::HI64RegClass.contains(SrcReg))
146f4a2713aSLionel Sambuc       Opc = Mips::MFHI64, SrcReg = 0;
147f4a2713aSLionel Sambuc     else if (Mips::LO64RegClass.contains(SrcReg))
148f4a2713aSLionel Sambuc       Opc = Mips::MFLO64, SrcReg = 0;
149f4a2713aSLionel Sambuc     else if (Mips::FGR64RegClass.contains(SrcReg))
150f4a2713aSLionel Sambuc       Opc = Mips::DMFC1;
151f4a2713aSLionel Sambuc   }
152f4a2713aSLionel Sambuc   else if (Mips::GPR64RegClass.contains(SrcReg)) { // Copy from CPU64 Reg.
153f4a2713aSLionel Sambuc     if (Mips::HI64RegClass.contains(DestReg))
154f4a2713aSLionel Sambuc       Opc = Mips::MTHI64, DestReg = 0;
155f4a2713aSLionel Sambuc     else if (Mips::LO64RegClass.contains(DestReg))
156f4a2713aSLionel Sambuc       Opc = Mips::MTLO64, DestReg = 0;
157f4a2713aSLionel Sambuc     else if (Mips::FGR64RegClass.contains(DestReg))
158f4a2713aSLionel Sambuc       Opc = Mips::DMTC1;
159f4a2713aSLionel Sambuc   }
160f4a2713aSLionel Sambuc   else if (Mips::MSA128BRegClass.contains(DestReg)) { // Copy to MSA reg
161f4a2713aSLionel Sambuc     if (Mips::MSA128BRegClass.contains(SrcReg))
162f4a2713aSLionel Sambuc       Opc = Mips::MOVE_V;
163f4a2713aSLionel Sambuc   }
164f4a2713aSLionel Sambuc 
165f4a2713aSLionel Sambuc   assert(Opc && "Cannot copy registers");
166f4a2713aSLionel Sambuc 
167f4a2713aSLionel Sambuc   MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(Opc));
168f4a2713aSLionel Sambuc 
169f4a2713aSLionel Sambuc   if (DestReg)
170f4a2713aSLionel Sambuc     MIB.addReg(DestReg, RegState::Define);
171f4a2713aSLionel Sambuc 
172f4a2713aSLionel Sambuc   if (SrcReg)
173f4a2713aSLionel Sambuc     MIB.addReg(SrcReg, getKillRegState(KillSrc));
174f4a2713aSLionel Sambuc 
175f4a2713aSLionel Sambuc   if (ZeroReg)
176f4a2713aSLionel Sambuc     MIB.addReg(ZeroReg);
177f4a2713aSLionel Sambuc }
178f4a2713aSLionel Sambuc 
179f4a2713aSLionel Sambuc void MipsSEInstrInfo::
storeRegToStack(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,unsigned SrcReg,bool isKill,int FI,const TargetRegisterClass * RC,const TargetRegisterInfo * TRI,int64_t Offset) const180f4a2713aSLionel Sambuc storeRegToStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
181f4a2713aSLionel Sambuc                 unsigned SrcReg, bool isKill, int FI,
182f4a2713aSLionel Sambuc                 const TargetRegisterClass *RC, const TargetRegisterInfo *TRI,
183f4a2713aSLionel Sambuc                 int64_t Offset) const {
184f4a2713aSLionel Sambuc   DebugLoc DL;
185f4a2713aSLionel Sambuc   if (I != MBB.end()) DL = I->getDebugLoc();
186f4a2713aSLionel Sambuc   MachineMemOperand *MMO = GetMemOperand(MBB, FI, MachineMemOperand::MOStore);
187f4a2713aSLionel Sambuc 
188f4a2713aSLionel Sambuc   unsigned Opc = 0;
189f4a2713aSLionel Sambuc 
190f4a2713aSLionel Sambuc   if (Mips::GPR32RegClass.hasSubClassEq(RC))
191f4a2713aSLionel Sambuc     Opc = Mips::SW;
192f4a2713aSLionel Sambuc   else if (Mips::GPR64RegClass.hasSubClassEq(RC))
193f4a2713aSLionel Sambuc     Opc = Mips::SD;
194f4a2713aSLionel Sambuc   else if (Mips::ACC64RegClass.hasSubClassEq(RC))
195f4a2713aSLionel Sambuc     Opc = Mips::STORE_ACC64;
196f4a2713aSLionel Sambuc   else if (Mips::ACC64DSPRegClass.hasSubClassEq(RC))
197f4a2713aSLionel Sambuc     Opc = Mips::STORE_ACC64DSP;
198f4a2713aSLionel Sambuc   else if (Mips::ACC128RegClass.hasSubClassEq(RC))
199f4a2713aSLionel Sambuc     Opc = Mips::STORE_ACC128;
200f4a2713aSLionel Sambuc   else if (Mips::DSPCCRegClass.hasSubClassEq(RC))
201f4a2713aSLionel Sambuc     Opc = Mips::STORE_CCOND_DSP;
202f4a2713aSLionel Sambuc   else if (Mips::FGR32RegClass.hasSubClassEq(RC))
203f4a2713aSLionel Sambuc     Opc = Mips::SWC1;
204f4a2713aSLionel Sambuc   else if (Mips::AFGR64RegClass.hasSubClassEq(RC))
205f4a2713aSLionel Sambuc     Opc = Mips::SDC1;
206f4a2713aSLionel Sambuc   else if (Mips::FGR64RegClass.hasSubClassEq(RC))
207f4a2713aSLionel Sambuc     Opc = Mips::SDC164;
208f4a2713aSLionel Sambuc   else if (RC->hasType(MVT::v16i8))
209f4a2713aSLionel Sambuc     Opc = Mips::ST_B;
210f4a2713aSLionel Sambuc   else if (RC->hasType(MVT::v8i16) || RC->hasType(MVT::v8f16))
211f4a2713aSLionel Sambuc     Opc = Mips::ST_H;
212f4a2713aSLionel Sambuc   else if (RC->hasType(MVT::v4i32) || RC->hasType(MVT::v4f32))
213f4a2713aSLionel Sambuc     Opc = Mips::ST_W;
214f4a2713aSLionel Sambuc   else if (RC->hasType(MVT::v2i64) || RC->hasType(MVT::v2f64))
215f4a2713aSLionel Sambuc     Opc = Mips::ST_D;
216f4a2713aSLionel Sambuc 
217f4a2713aSLionel Sambuc   assert(Opc && "Register class not handled!");
218f4a2713aSLionel Sambuc   BuildMI(MBB, I, DL, get(Opc)).addReg(SrcReg, getKillRegState(isKill))
219f4a2713aSLionel Sambuc     .addFrameIndex(FI).addImm(Offset).addMemOperand(MMO);
220f4a2713aSLionel Sambuc }
221f4a2713aSLionel Sambuc 
222f4a2713aSLionel Sambuc void MipsSEInstrInfo::
loadRegFromStack(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,unsigned DestReg,int FI,const TargetRegisterClass * RC,const TargetRegisterInfo * TRI,int64_t Offset) const223f4a2713aSLionel Sambuc loadRegFromStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
224f4a2713aSLionel Sambuc                  unsigned DestReg, int FI, const TargetRegisterClass *RC,
225f4a2713aSLionel Sambuc                  const TargetRegisterInfo *TRI, int64_t Offset) const {
226f4a2713aSLionel Sambuc   DebugLoc DL;
227f4a2713aSLionel Sambuc   if (I != MBB.end()) DL = I->getDebugLoc();
228f4a2713aSLionel Sambuc   MachineMemOperand *MMO = GetMemOperand(MBB, FI, MachineMemOperand::MOLoad);
229f4a2713aSLionel Sambuc   unsigned Opc = 0;
230f4a2713aSLionel Sambuc 
231f4a2713aSLionel Sambuc   if (Mips::GPR32RegClass.hasSubClassEq(RC))
232f4a2713aSLionel Sambuc     Opc = Mips::LW;
233f4a2713aSLionel Sambuc   else if (Mips::GPR64RegClass.hasSubClassEq(RC))
234f4a2713aSLionel Sambuc     Opc = Mips::LD;
235f4a2713aSLionel Sambuc   else if (Mips::ACC64RegClass.hasSubClassEq(RC))
236f4a2713aSLionel Sambuc     Opc = Mips::LOAD_ACC64;
237f4a2713aSLionel Sambuc   else if (Mips::ACC64DSPRegClass.hasSubClassEq(RC))
238f4a2713aSLionel Sambuc     Opc = Mips::LOAD_ACC64DSP;
239f4a2713aSLionel Sambuc   else if (Mips::ACC128RegClass.hasSubClassEq(RC))
240f4a2713aSLionel Sambuc     Opc = Mips::LOAD_ACC128;
241f4a2713aSLionel Sambuc   else if (Mips::DSPCCRegClass.hasSubClassEq(RC))
242f4a2713aSLionel Sambuc     Opc = Mips::LOAD_CCOND_DSP;
243f4a2713aSLionel Sambuc   else if (Mips::FGR32RegClass.hasSubClassEq(RC))
244f4a2713aSLionel Sambuc     Opc = Mips::LWC1;
245f4a2713aSLionel Sambuc   else if (Mips::AFGR64RegClass.hasSubClassEq(RC))
246f4a2713aSLionel Sambuc     Opc = Mips::LDC1;
247f4a2713aSLionel Sambuc   else if (Mips::FGR64RegClass.hasSubClassEq(RC))
248f4a2713aSLionel Sambuc     Opc = Mips::LDC164;
249f4a2713aSLionel Sambuc   else if (RC->hasType(MVT::v16i8))
250f4a2713aSLionel Sambuc     Opc = Mips::LD_B;
251f4a2713aSLionel Sambuc   else if (RC->hasType(MVT::v8i16) || RC->hasType(MVT::v8f16))
252f4a2713aSLionel Sambuc     Opc = Mips::LD_H;
253f4a2713aSLionel Sambuc   else if (RC->hasType(MVT::v4i32) || RC->hasType(MVT::v4f32))
254f4a2713aSLionel Sambuc     Opc = Mips::LD_W;
255f4a2713aSLionel Sambuc   else if (RC->hasType(MVT::v2i64) || RC->hasType(MVT::v2f64))
256f4a2713aSLionel Sambuc     Opc = Mips::LD_D;
257f4a2713aSLionel Sambuc 
258f4a2713aSLionel Sambuc   assert(Opc && "Register class not handled!");
259f4a2713aSLionel Sambuc   BuildMI(MBB, I, DL, get(Opc), DestReg).addFrameIndex(FI).addImm(Offset)
260f4a2713aSLionel Sambuc     .addMemOperand(MMO);
261f4a2713aSLionel Sambuc }
262f4a2713aSLionel Sambuc 
expandPostRAPseudo(MachineBasicBlock::iterator MI) const263f4a2713aSLionel Sambuc bool MipsSEInstrInfo::expandPostRAPseudo(MachineBasicBlock::iterator MI) const {
264f4a2713aSLionel Sambuc   MachineBasicBlock &MBB = *MI->getParent();
265*0a6a1f1dSLionel Sambuc   bool isMicroMips = Subtarget.inMicroMipsMode();
266*0a6a1f1dSLionel Sambuc   unsigned Opc;
267f4a2713aSLionel Sambuc 
268f4a2713aSLionel Sambuc   switch(MI->getDesc().getOpcode()) {
269f4a2713aSLionel Sambuc   default:
270f4a2713aSLionel Sambuc     return false;
271f4a2713aSLionel Sambuc   case Mips::RetRA:
272*0a6a1f1dSLionel Sambuc     expandRetRA(MBB, MI);
273f4a2713aSLionel Sambuc     break;
274f4a2713aSLionel Sambuc   case Mips::PseudoMFHI:
275*0a6a1f1dSLionel Sambuc     Opc = isMicroMips ? Mips::MFHI16_MM : Mips::MFHI;
276*0a6a1f1dSLionel Sambuc     expandPseudoMFHiLo(MBB, MI, Opc);
277f4a2713aSLionel Sambuc     break;
278f4a2713aSLionel Sambuc   case Mips::PseudoMFLO:
279*0a6a1f1dSLionel Sambuc     Opc = isMicroMips ? Mips::MFLO16_MM : Mips::MFLO;
280*0a6a1f1dSLionel Sambuc     expandPseudoMFHiLo(MBB, MI, Opc);
281f4a2713aSLionel Sambuc     break;
282f4a2713aSLionel Sambuc   case Mips::PseudoMFHI64:
283f4a2713aSLionel Sambuc     expandPseudoMFHiLo(MBB, MI, Mips::MFHI64);
284f4a2713aSLionel Sambuc     break;
285f4a2713aSLionel Sambuc   case Mips::PseudoMFLO64:
286f4a2713aSLionel Sambuc     expandPseudoMFHiLo(MBB, MI, Mips::MFLO64);
287f4a2713aSLionel Sambuc     break;
288f4a2713aSLionel Sambuc   case Mips::PseudoMTLOHI:
289f4a2713aSLionel Sambuc     expandPseudoMTLoHi(MBB, MI, Mips::MTLO, Mips::MTHI, false);
290f4a2713aSLionel Sambuc     break;
291f4a2713aSLionel Sambuc   case Mips::PseudoMTLOHI64:
292f4a2713aSLionel Sambuc     expandPseudoMTLoHi(MBB, MI, Mips::MTLO64, Mips::MTHI64, false);
293f4a2713aSLionel Sambuc     break;
294f4a2713aSLionel Sambuc   case Mips::PseudoMTLOHI_DSP:
295f4a2713aSLionel Sambuc     expandPseudoMTLoHi(MBB, MI, Mips::MTLO_DSP, Mips::MTHI_DSP, true);
296f4a2713aSLionel Sambuc     break;
297f4a2713aSLionel Sambuc   case Mips::PseudoCVT_S_W:
298f4a2713aSLionel Sambuc     expandCvtFPInt(MBB, MI, Mips::CVT_S_W, Mips::MTC1, false);
299f4a2713aSLionel Sambuc     break;
300f4a2713aSLionel Sambuc   case Mips::PseudoCVT_D32_W:
301f4a2713aSLionel Sambuc     expandCvtFPInt(MBB, MI, Mips::CVT_D32_W, Mips::MTC1, false);
302f4a2713aSLionel Sambuc     break;
303f4a2713aSLionel Sambuc   case Mips::PseudoCVT_S_L:
304f4a2713aSLionel Sambuc     expandCvtFPInt(MBB, MI, Mips::CVT_S_L, Mips::DMTC1, true);
305f4a2713aSLionel Sambuc     break;
306f4a2713aSLionel Sambuc   case Mips::PseudoCVT_D64_W:
307f4a2713aSLionel Sambuc     expandCvtFPInt(MBB, MI, Mips::CVT_D64_W, Mips::MTC1, true);
308f4a2713aSLionel Sambuc     break;
309f4a2713aSLionel Sambuc   case Mips::PseudoCVT_D64_L:
310f4a2713aSLionel Sambuc     expandCvtFPInt(MBB, MI, Mips::CVT_D64_L, Mips::DMTC1, true);
311f4a2713aSLionel Sambuc     break;
312f4a2713aSLionel Sambuc   case Mips::BuildPairF64:
313f4a2713aSLionel Sambuc     expandBuildPairF64(MBB, MI, false);
314f4a2713aSLionel Sambuc     break;
315f4a2713aSLionel Sambuc   case Mips::BuildPairF64_64:
316f4a2713aSLionel Sambuc     expandBuildPairF64(MBB, MI, true);
317f4a2713aSLionel Sambuc     break;
318f4a2713aSLionel Sambuc   case Mips::ExtractElementF64:
319f4a2713aSLionel Sambuc     expandExtractElementF64(MBB, MI, false);
320f4a2713aSLionel Sambuc     break;
321f4a2713aSLionel Sambuc   case Mips::ExtractElementF64_64:
322f4a2713aSLionel Sambuc     expandExtractElementF64(MBB, MI, true);
323f4a2713aSLionel Sambuc     break;
324f4a2713aSLionel Sambuc   case Mips::MIPSeh_return32:
325f4a2713aSLionel Sambuc   case Mips::MIPSeh_return64:
326f4a2713aSLionel Sambuc     expandEhReturn(MBB, MI);
327f4a2713aSLionel Sambuc     break;
328f4a2713aSLionel Sambuc   }
329f4a2713aSLionel Sambuc 
330f4a2713aSLionel Sambuc   MBB.erase(MI);
331f4a2713aSLionel Sambuc   return true;
332f4a2713aSLionel Sambuc }
333f4a2713aSLionel Sambuc 
334f4a2713aSLionel Sambuc /// getOppositeBranchOpc - Return the inverse of the specified
335f4a2713aSLionel Sambuc /// opcode, e.g. turning BEQ to BNE.
getOppositeBranchOpc(unsigned Opc) const336f4a2713aSLionel Sambuc unsigned MipsSEInstrInfo::getOppositeBranchOpc(unsigned Opc) const {
337f4a2713aSLionel Sambuc   switch (Opc) {
338f4a2713aSLionel Sambuc   default:           llvm_unreachable("Illegal opcode!");
339f4a2713aSLionel Sambuc   case Mips::BEQ:    return Mips::BNE;
340f4a2713aSLionel Sambuc   case Mips::BNE:    return Mips::BEQ;
341f4a2713aSLionel Sambuc   case Mips::BGTZ:   return Mips::BLEZ;
342f4a2713aSLionel Sambuc   case Mips::BGEZ:   return Mips::BLTZ;
343f4a2713aSLionel Sambuc   case Mips::BLTZ:   return Mips::BGEZ;
344f4a2713aSLionel Sambuc   case Mips::BLEZ:   return Mips::BGTZ;
345f4a2713aSLionel Sambuc   case Mips::BEQ64:  return Mips::BNE64;
346f4a2713aSLionel Sambuc   case Mips::BNE64:  return Mips::BEQ64;
347f4a2713aSLionel Sambuc   case Mips::BGTZ64: return Mips::BLEZ64;
348f4a2713aSLionel Sambuc   case Mips::BGEZ64: return Mips::BLTZ64;
349f4a2713aSLionel Sambuc   case Mips::BLTZ64: return Mips::BGEZ64;
350f4a2713aSLionel Sambuc   case Mips::BLEZ64: return Mips::BGTZ64;
351f4a2713aSLionel Sambuc   case Mips::BC1T:   return Mips::BC1F;
352f4a2713aSLionel Sambuc   case Mips::BC1F:   return Mips::BC1T;
353*0a6a1f1dSLionel Sambuc   case Mips::BEQZC_MM: return Mips::BNEZC_MM;
354*0a6a1f1dSLionel Sambuc   case Mips::BNEZC_MM: return Mips::BEQZC_MM;
355f4a2713aSLionel Sambuc   }
356f4a2713aSLionel Sambuc }
357f4a2713aSLionel Sambuc 
358f4a2713aSLionel Sambuc /// Adjust SP by Amount bytes.
adjustStackPtr(unsigned SP,int64_t Amount,MachineBasicBlock & MBB,MachineBasicBlock::iterator I) const359f4a2713aSLionel Sambuc void MipsSEInstrInfo::adjustStackPtr(unsigned SP, int64_t Amount,
360f4a2713aSLionel Sambuc                                      MachineBasicBlock &MBB,
361f4a2713aSLionel Sambuc                                      MachineBasicBlock::iterator I) const {
362*0a6a1f1dSLionel Sambuc   const MipsSubtarget &STI = Subtarget;
363f4a2713aSLionel Sambuc   DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc();
364f4a2713aSLionel Sambuc   unsigned ADDu = STI.isABI_N64() ? Mips::DADDu : Mips::ADDu;
365f4a2713aSLionel Sambuc   unsigned ADDiu = STI.isABI_N64() ? Mips::DADDiu : Mips::ADDiu;
366f4a2713aSLionel Sambuc 
367*0a6a1f1dSLionel Sambuc   if (Amount == 0)
368*0a6a1f1dSLionel Sambuc     return;
369*0a6a1f1dSLionel Sambuc 
370f4a2713aSLionel Sambuc   if (isInt<16>(Amount))// addi sp, sp, amount
371f4a2713aSLionel Sambuc     BuildMI(MBB, I, DL, get(ADDiu), SP).addReg(SP).addImm(Amount);
372f4a2713aSLionel Sambuc   else { // Expand immediate that doesn't fit in 16-bit.
373*0a6a1f1dSLionel Sambuc     unsigned Reg = loadImmediate(Amount, MBB, I, DL, nullptr);
374f4a2713aSLionel Sambuc     BuildMI(MBB, I, DL, get(ADDu), SP).addReg(SP).addReg(Reg, RegState::Kill);
375f4a2713aSLionel Sambuc   }
376f4a2713aSLionel Sambuc }
377f4a2713aSLionel Sambuc 
378f4a2713aSLionel Sambuc /// This function generates the sequence of instructions needed to get the
379f4a2713aSLionel Sambuc /// result of adding register REG and immediate IMM.
380f4a2713aSLionel Sambuc unsigned
loadImmediate(int64_t Imm,MachineBasicBlock & MBB,MachineBasicBlock::iterator II,DebugLoc DL,unsigned * NewImm) const381f4a2713aSLionel Sambuc MipsSEInstrInfo::loadImmediate(int64_t Imm, MachineBasicBlock &MBB,
382f4a2713aSLionel Sambuc                                MachineBasicBlock::iterator II, DebugLoc DL,
383f4a2713aSLionel Sambuc                                unsigned *NewImm) const {
384f4a2713aSLionel Sambuc   MipsAnalyzeImmediate AnalyzeImm;
385*0a6a1f1dSLionel Sambuc   const MipsSubtarget &STI = Subtarget;
386f4a2713aSLionel Sambuc   MachineRegisterInfo &RegInfo = MBB.getParent()->getRegInfo();
387f4a2713aSLionel Sambuc   unsigned Size = STI.isABI_N64() ? 64 : 32;
388f4a2713aSLionel Sambuc   unsigned LUi = STI.isABI_N64() ? Mips::LUi64 : Mips::LUi;
389f4a2713aSLionel Sambuc   unsigned ZEROReg = STI.isABI_N64() ? Mips::ZERO_64 : Mips::ZERO;
390f4a2713aSLionel Sambuc   const TargetRegisterClass *RC = STI.isABI_N64() ?
391f4a2713aSLionel Sambuc     &Mips::GPR64RegClass : &Mips::GPR32RegClass;
392f4a2713aSLionel Sambuc   bool LastInstrIsADDiu = NewImm;
393f4a2713aSLionel Sambuc 
394f4a2713aSLionel Sambuc   const MipsAnalyzeImmediate::InstSeq &Seq =
395f4a2713aSLionel Sambuc     AnalyzeImm.Analyze(Imm, Size, LastInstrIsADDiu);
396f4a2713aSLionel Sambuc   MipsAnalyzeImmediate::InstSeq::const_iterator Inst = Seq.begin();
397f4a2713aSLionel Sambuc 
398f4a2713aSLionel Sambuc   assert(Seq.size() && (!LastInstrIsADDiu || (Seq.size() > 1)));
399f4a2713aSLionel Sambuc 
400f4a2713aSLionel Sambuc   // The first instruction can be a LUi, which is different from other
401f4a2713aSLionel Sambuc   // instructions (ADDiu, ORI and SLL) in that it does not have a register
402f4a2713aSLionel Sambuc   // operand.
403f4a2713aSLionel Sambuc   unsigned Reg = RegInfo.createVirtualRegister(RC);
404f4a2713aSLionel Sambuc 
405f4a2713aSLionel Sambuc   if (Inst->Opc == LUi)
406f4a2713aSLionel Sambuc     BuildMI(MBB, II, DL, get(LUi), Reg).addImm(SignExtend64<16>(Inst->ImmOpnd));
407f4a2713aSLionel Sambuc   else
408f4a2713aSLionel Sambuc     BuildMI(MBB, II, DL, get(Inst->Opc), Reg).addReg(ZEROReg)
409f4a2713aSLionel Sambuc       .addImm(SignExtend64<16>(Inst->ImmOpnd));
410f4a2713aSLionel Sambuc 
411f4a2713aSLionel Sambuc   // Build the remaining instructions in Seq.
412f4a2713aSLionel Sambuc   for (++Inst; Inst != Seq.end() - LastInstrIsADDiu; ++Inst)
413f4a2713aSLionel Sambuc     BuildMI(MBB, II, DL, get(Inst->Opc), Reg).addReg(Reg, RegState::Kill)
414f4a2713aSLionel Sambuc       .addImm(SignExtend64<16>(Inst->ImmOpnd));
415f4a2713aSLionel Sambuc 
416f4a2713aSLionel Sambuc   if (LastInstrIsADDiu)
417f4a2713aSLionel Sambuc     *NewImm = Inst->ImmOpnd;
418f4a2713aSLionel Sambuc 
419f4a2713aSLionel Sambuc   return Reg;
420f4a2713aSLionel Sambuc }
421f4a2713aSLionel Sambuc 
getAnalyzableBrOpc(unsigned Opc) const422f4a2713aSLionel Sambuc unsigned MipsSEInstrInfo::getAnalyzableBrOpc(unsigned Opc) const {
423f4a2713aSLionel Sambuc   return (Opc == Mips::BEQ    || Opc == Mips::BNE    || Opc == Mips::BGTZ   ||
424f4a2713aSLionel Sambuc           Opc == Mips::BGEZ   || Opc == Mips::BLTZ   || Opc == Mips::BLEZ   ||
425f4a2713aSLionel Sambuc           Opc == Mips::BEQ64  || Opc == Mips::BNE64  || Opc == Mips::BGTZ64 ||
426f4a2713aSLionel Sambuc           Opc == Mips::BGEZ64 || Opc == Mips::BLTZ64 || Opc == Mips::BLEZ64 ||
427f4a2713aSLionel Sambuc           Opc == Mips::BC1T   || Opc == Mips::BC1F   || Opc == Mips::B      ||
428*0a6a1f1dSLionel Sambuc           Opc == Mips::J || Opc == Mips::BEQZC_MM || Opc == Mips::BNEZC_MM) ?
429f4a2713aSLionel Sambuc          Opc : 0;
430f4a2713aSLionel Sambuc }
431f4a2713aSLionel Sambuc 
expandRetRA(MachineBasicBlock & MBB,MachineBasicBlock::iterator I) const432f4a2713aSLionel Sambuc void MipsSEInstrInfo::expandRetRA(MachineBasicBlock &MBB,
433*0a6a1f1dSLionel Sambuc                                   MachineBasicBlock::iterator I) const {
434*0a6a1f1dSLionel Sambuc   if (Subtarget.isGP64bit())
435*0a6a1f1dSLionel Sambuc     BuildMI(MBB, I, I->getDebugLoc(), get(Mips::PseudoReturn64))
436*0a6a1f1dSLionel Sambuc         .addReg(Mips::RA_64);
437*0a6a1f1dSLionel Sambuc   else
438*0a6a1f1dSLionel Sambuc     BuildMI(MBB, I, I->getDebugLoc(), get(Mips::PseudoReturn)).addReg(Mips::RA);
439f4a2713aSLionel Sambuc }
440f4a2713aSLionel Sambuc 
441f4a2713aSLionel Sambuc std::pair<bool, bool>
compareOpndSize(unsigned Opc,const MachineFunction & MF) const442f4a2713aSLionel Sambuc MipsSEInstrInfo::compareOpndSize(unsigned Opc,
443f4a2713aSLionel Sambuc                                  const MachineFunction &MF) const {
444f4a2713aSLionel Sambuc   const MCInstrDesc &Desc = get(Opc);
445f4a2713aSLionel Sambuc   assert(Desc.NumOperands == 2 && "Unary instruction expected.");
446f4a2713aSLionel Sambuc   const MipsRegisterInfo *RI = &getRegisterInfo();
447f4a2713aSLionel Sambuc   unsigned DstRegSize = getRegClass(Desc, 0, RI, MF)->getSize();
448f4a2713aSLionel Sambuc   unsigned SrcRegSize = getRegClass(Desc, 1, RI, MF)->getSize();
449f4a2713aSLionel Sambuc 
450f4a2713aSLionel Sambuc   return std::make_pair(DstRegSize > SrcRegSize, DstRegSize < SrcRegSize);
451f4a2713aSLionel Sambuc }
452f4a2713aSLionel Sambuc 
expandPseudoMFHiLo(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,unsigned NewOpc) const453f4a2713aSLionel Sambuc void MipsSEInstrInfo::expandPseudoMFHiLo(MachineBasicBlock &MBB,
454f4a2713aSLionel Sambuc                                          MachineBasicBlock::iterator I,
455f4a2713aSLionel Sambuc                                          unsigned NewOpc) const {
456f4a2713aSLionel Sambuc   BuildMI(MBB, I, I->getDebugLoc(), get(NewOpc), I->getOperand(0).getReg());
457f4a2713aSLionel Sambuc }
458f4a2713aSLionel Sambuc 
expandPseudoMTLoHi(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,unsigned LoOpc,unsigned HiOpc,bool HasExplicitDef) const459f4a2713aSLionel Sambuc void MipsSEInstrInfo::expandPseudoMTLoHi(MachineBasicBlock &MBB,
460f4a2713aSLionel Sambuc                                          MachineBasicBlock::iterator I,
461f4a2713aSLionel Sambuc                                          unsigned LoOpc,
462f4a2713aSLionel Sambuc                                          unsigned HiOpc,
463f4a2713aSLionel Sambuc                                          bool HasExplicitDef) const {
464f4a2713aSLionel Sambuc   // Expand
465f4a2713aSLionel Sambuc   //  lo_hi pseudomtlohi $gpr0, $gpr1
466f4a2713aSLionel Sambuc   // to these two instructions:
467f4a2713aSLionel Sambuc   //  mtlo $gpr0
468f4a2713aSLionel Sambuc   //  mthi $gpr1
469f4a2713aSLionel Sambuc 
470f4a2713aSLionel Sambuc   DebugLoc DL = I->getDebugLoc();
471f4a2713aSLionel Sambuc   const MachineOperand &SrcLo = I->getOperand(1), &SrcHi = I->getOperand(2);
472f4a2713aSLionel Sambuc   MachineInstrBuilder LoInst = BuildMI(MBB, I, DL, get(LoOpc));
473f4a2713aSLionel Sambuc   MachineInstrBuilder HiInst = BuildMI(MBB, I, DL, get(HiOpc));
474f4a2713aSLionel Sambuc   LoInst.addReg(SrcLo.getReg(), getKillRegState(SrcLo.isKill()));
475f4a2713aSLionel Sambuc   HiInst.addReg(SrcHi.getReg(), getKillRegState(SrcHi.isKill()));
476f4a2713aSLionel Sambuc 
477f4a2713aSLionel Sambuc   // Add lo/hi registers if the mtlo/hi instructions created have explicit
478f4a2713aSLionel Sambuc   // def registers.
479f4a2713aSLionel Sambuc   if (HasExplicitDef) {
480f4a2713aSLionel Sambuc     unsigned DstReg = I->getOperand(0).getReg();
481f4a2713aSLionel Sambuc     unsigned DstLo = getRegisterInfo().getSubReg(DstReg, Mips::sub_lo);
482f4a2713aSLionel Sambuc     unsigned DstHi = getRegisterInfo().getSubReg(DstReg, Mips::sub_hi);
483f4a2713aSLionel Sambuc     LoInst.addReg(DstLo, RegState::Define);
484f4a2713aSLionel Sambuc     HiInst.addReg(DstHi, RegState::Define);
485f4a2713aSLionel Sambuc   }
486f4a2713aSLionel Sambuc }
487f4a2713aSLionel Sambuc 
expandCvtFPInt(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,unsigned CvtOpc,unsigned MovOpc,bool IsI64) const488f4a2713aSLionel Sambuc void MipsSEInstrInfo::expandCvtFPInt(MachineBasicBlock &MBB,
489f4a2713aSLionel Sambuc                                      MachineBasicBlock::iterator I,
490f4a2713aSLionel Sambuc                                      unsigned CvtOpc, unsigned MovOpc,
491f4a2713aSLionel Sambuc                                      bool IsI64) const {
492f4a2713aSLionel Sambuc   const MCInstrDesc &CvtDesc = get(CvtOpc), &MovDesc = get(MovOpc);
493f4a2713aSLionel Sambuc   const MachineOperand &Dst = I->getOperand(0), &Src = I->getOperand(1);
494f4a2713aSLionel Sambuc   unsigned DstReg = Dst.getReg(), SrcReg = Src.getReg(), TmpReg = DstReg;
495f4a2713aSLionel Sambuc   unsigned KillSrc =  getKillRegState(Src.isKill());
496f4a2713aSLionel Sambuc   DebugLoc DL = I->getDebugLoc();
497f4a2713aSLionel Sambuc   bool DstIsLarger, SrcIsLarger;
498f4a2713aSLionel Sambuc 
499*0a6a1f1dSLionel Sambuc   std::tie(DstIsLarger, SrcIsLarger) =
500*0a6a1f1dSLionel Sambuc       compareOpndSize(CvtOpc, *MBB.getParent());
501f4a2713aSLionel Sambuc 
502f4a2713aSLionel Sambuc   if (DstIsLarger)
503f4a2713aSLionel Sambuc     TmpReg = getRegisterInfo().getSubReg(DstReg, Mips::sub_lo);
504f4a2713aSLionel Sambuc 
505f4a2713aSLionel Sambuc   if (SrcIsLarger)
506f4a2713aSLionel Sambuc     DstReg = getRegisterInfo().getSubReg(DstReg, Mips::sub_lo);
507f4a2713aSLionel Sambuc 
508f4a2713aSLionel Sambuc   BuildMI(MBB, I, DL, MovDesc, TmpReg).addReg(SrcReg, KillSrc);
509f4a2713aSLionel Sambuc   BuildMI(MBB, I, DL, CvtDesc, DstReg).addReg(TmpReg, RegState::Kill);
510f4a2713aSLionel Sambuc }
511f4a2713aSLionel Sambuc 
expandExtractElementF64(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,bool FP64) const512f4a2713aSLionel Sambuc void MipsSEInstrInfo::expandExtractElementF64(MachineBasicBlock &MBB,
513f4a2713aSLionel Sambuc                                               MachineBasicBlock::iterator I,
514f4a2713aSLionel Sambuc                                               bool FP64) const {
515f4a2713aSLionel Sambuc   unsigned DstReg = I->getOperand(0).getReg();
516f4a2713aSLionel Sambuc   unsigned SrcReg = I->getOperand(1).getReg();
517f4a2713aSLionel Sambuc   unsigned N = I->getOperand(2).getImm();
518f4a2713aSLionel Sambuc   DebugLoc dl = I->getDebugLoc();
519f4a2713aSLionel Sambuc 
520f4a2713aSLionel Sambuc   assert(N < 2 && "Invalid immediate");
521f4a2713aSLionel Sambuc   unsigned SubIdx = N ? Mips::sub_hi : Mips::sub_lo;
522f4a2713aSLionel Sambuc   unsigned SubReg = getRegisterInfo().getSubReg(SrcReg, SubIdx);
523f4a2713aSLionel Sambuc 
524*0a6a1f1dSLionel Sambuc   // FPXX on MIPS-II or MIPS32r1 should have been handled with a spill/reload
525*0a6a1f1dSLionel Sambuc   // in MipsSEFrameLowering.cpp.
526*0a6a1f1dSLionel Sambuc   assert(!(Subtarget.isABI_FPXX() && !Subtarget.hasMips32r2()));
527*0a6a1f1dSLionel Sambuc 
528*0a6a1f1dSLionel Sambuc   // FP64A (FP64 with nooddspreg) should have been handled with a spill/reload
529*0a6a1f1dSLionel Sambuc   // in MipsSEFrameLowering.cpp.
530*0a6a1f1dSLionel Sambuc   assert(!(Subtarget.isFP64bit() && !Subtarget.useOddSPReg()));
531*0a6a1f1dSLionel Sambuc 
532*0a6a1f1dSLionel Sambuc   if (SubIdx == Mips::sub_hi && Subtarget.hasMTHC1()) {
533*0a6a1f1dSLionel Sambuc     // FIXME: Strictly speaking MFHC1 only reads the top 32-bits however, we
534*0a6a1f1dSLionel Sambuc     //        claim to read the whole 64-bits as part of a white lie used to
535*0a6a1f1dSLionel Sambuc     //        temporarily work around a widespread bug in the -mfp64 support.
536*0a6a1f1dSLionel Sambuc     //        The problem is that none of the 32-bit fpu ops mention the fact
537*0a6a1f1dSLionel Sambuc     //        that they clobber the upper 32-bits of the 64-bit FPR. Fixing that
538*0a6a1f1dSLionel Sambuc     //        requires a major overhaul of the FPU implementation which can't
539*0a6a1f1dSLionel Sambuc     //        be done right now due to time constraints.
540*0a6a1f1dSLionel Sambuc     //        MFHC1 is one of two instructions that are affected since they are
541*0a6a1f1dSLionel Sambuc     //        the only instructions that don't read the lower 32-bits.
542*0a6a1f1dSLionel Sambuc     //        We therefore pretend that it reads the bottom 32-bits to
543*0a6a1f1dSLionel Sambuc     //        artificially create a dependency and prevent the scheduler
544*0a6a1f1dSLionel Sambuc     //        changing the behaviour of the code.
545*0a6a1f1dSLionel Sambuc     BuildMI(MBB, I, dl, get(FP64 ? Mips::MFHC1_D64 : Mips::MFHC1_D32), DstReg)
546*0a6a1f1dSLionel Sambuc         .addReg(SrcReg);
547*0a6a1f1dSLionel Sambuc   } else
548f4a2713aSLionel Sambuc     BuildMI(MBB, I, dl, get(Mips::MFC1), DstReg).addReg(SubReg);
549f4a2713aSLionel Sambuc }
550f4a2713aSLionel Sambuc 
expandBuildPairF64(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,bool FP64) const551f4a2713aSLionel Sambuc void MipsSEInstrInfo::expandBuildPairF64(MachineBasicBlock &MBB,
552f4a2713aSLionel Sambuc                                          MachineBasicBlock::iterator I,
553f4a2713aSLionel Sambuc                                          bool FP64) const {
554f4a2713aSLionel Sambuc   unsigned DstReg = I->getOperand(0).getReg();
555f4a2713aSLionel Sambuc   unsigned LoReg = I->getOperand(1).getReg(), HiReg = I->getOperand(2).getReg();
556f4a2713aSLionel Sambuc   const MCInstrDesc& Mtc1Tdd = get(Mips::MTC1);
557f4a2713aSLionel Sambuc   DebugLoc dl = I->getDebugLoc();
558f4a2713aSLionel Sambuc   const TargetRegisterInfo &TRI = getRegisterInfo();
559f4a2713aSLionel Sambuc 
560*0a6a1f1dSLionel Sambuc   // When mthc1 is available, use:
561f4a2713aSLionel Sambuc   //   mtc1 Lo, $fp
562f4a2713aSLionel Sambuc   //   mthc1 Hi, $fp
563*0a6a1f1dSLionel Sambuc   //
564*0a6a1f1dSLionel Sambuc   // Otherwise, for O32 FPXX ABI:
565*0a6a1f1dSLionel Sambuc   //   spill + reload via ldc1
566*0a6a1f1dSLionel Sambuc   // This case is handled by the frame lowering code.
567*0a6a1f1dSLionel Sambuc   //
568*0a6a1f1dSLionel Sambuc   // Otherwise, for FP32:
569*0a6a1f1dSLionel Sambuc   //   mtc1 Lo, $fp
570*0a6a1f1dSLionel Sambuc   //   mtc1 Hi, $fp + 1
571*0a6a1f1dSLionel Sambuc   //
572*0a6a1f1dSLionel Sambuc   // The case where dmtc1 is available doesn't need to be handled here
573*0a6a1f1dSLionel Sambuc   // because it never creates a BuildPairF64 node.
574*0a6a1f1dSLionel Sambuc 
575*0a6a1f1dSLionel Sambuc   // FPXX on MIPS-II or MIPS32r1 should have been handled with a spill/reload
576*0a6a1f1dSLionel Sambuc   // in MipsSEFrameLowering.cpp.
577*0a6a1f1dSLionel Sambuc   assert(!(Subtarget.isABI_FPXX() && !Subtarget.hasMips32r2()));
578*0a6a1f1dSLionel Sambuc 
579*0a6a1f1dSLionel Sambuc   // FP64A (FP64 with nooddspreg) should have been handled with a spill/reload
580*0a6a1f1dSLionel Sambuc   // in MipsSEFrameLowering.cpp.
581*0a6a1f1dSLionel Sambuc   assert(!(Subtarget.isFP64bit() && !Subtarget.useOddSPReg()));
582f4a2713aSLionel Sambuc 
583f4a2713aSLionel Sambuc   BuildMI(MBB, I, dl, Mtc1Tdd, TRI.getSubReg(DstReg, Mips::sub_lo))
584f4a2713aSLionel Sambuc     .addReg(LoReg);
585f4a2713aSLionel Sambuc 
586*0a6a1f1dSLionel Sambuc   if (Subtarget.hasMTHC1()) {
587*0a6a1f1dSLionel Sambuc     // FIXME: The .addReg(DstReg) is a white lie used to temporarily work
588*0a6a1f1dSLionel Sambuc     //        around a widespread bug in the -mfp64 support.
589*0a6a1f1dSLionel Sambuc     //        The problem is that none of the 32-bit fpu ops mention the fact
590*0a6a1f1dSLionel Sambuc     //        that they clobber the upper 32-bits of the 64-bit FPR. Fixing that
591*0a6a1f1dSLionel Sambuc     //        requires a major overhaul of the FPU implementation which can't
592*0a6a1f1dSLionel Sambuc     //        be done right now due to time constraints.
593*0a6a1f1dSLionel Sambuc     //        MTHC1 is one of two instructions that are affected since they are
594*0a6a1f1dSLionel Sambuc     //        the only instructions that don't read the lower 32-bits.
595*0a6a1f1dSLionel Sambuc     //        We therefore pretend that it reads the bottom 32-bits to
596*0a6a1f1dSLionel Sambuc     //        artificially create a dependency and prevent the scheduler
597*0a6a1f1dSLionel Sambuc     //        changing the behaviour of the code.
598*0a6a1f1dSLionel Sambuc     BuildMI(MBB, I, dl, get(FP64 ? Mips::MTHC1_D64 : Mips::MTHC1_D32), DstReg)
599*0a6a1f1dSLionel Sambuc         .addReg(DstReg)
600f4a2713aSLionel Sambuc         .addReg(HiReg);
601*0a6a1f1dSLionel Sambuc   } else if (Subtarget.isABI_FPXX())
602*0a6a1f1dSLionel Sambuc     llvm_unreachable("BuildPairF64 not expanded in frame lowering code!");
603f4a2713aSLionel Sambuc   else
604f4a2713aSLionel Sambuc     BuildMI(MBB, I, dl, Mtc1Tdd, TRI.getSubReg(DstReg, Mips::sub_hi))
605f4a2713aSLionel Sambuc       .addReg(HiReg);
606f4a2713aSLionel Sambuc }
607f4a2713aSLionel Sambuc 
expandEhReturn(MachineBasicBlock & MBB,MachineBasicBlock::iterator I) const608f4a2713aSLionel Sambuc void MipsSEInstrInfo::expandEhReturn(MachineBasicBlock &MBB,
609f4a2713aSLionel Sambuc                                      MachineBasicBlock::iterator I) const {
610f4a2713aSLionel Sambuc   // This pseudo instruction is generated as part of the lowering of
611f4a2713aSLionel Sambuc   // ISD::EH_RETURN. We convert it to a stack increment by OffsetReg, and
612f4a2713aSLionel Sambuc   // indirect jump to TargetReg
613*0a6a1f1dSLionel Sambuc   unsigned ADDU = Subtarget.isABI_N64() ? Mips::DADDu : Mips::ADDu;
614*0a6a1f1dSLionel Sambuc   unsigned SP = Subtarget.isGP64bit() ? Mips::SP_64 : Mips::SP;
615*0a6a1f1dSLionel Sambuc   unsigned RA = Subtarget.isGP64bit() ? Mips::RA_64 : Mips::RA;
616*0a6a1f1dSLionel Sambuc   unsigned T9 = Subtarget.isGP64bit() ? Mips::T9_64 : Mips::T9;
617*0a6a1f1dSLionel Sambuc   unsigned ZERO = Subtarget.isGP64bit() ? Mips::ZERO_64 : Mips::ZERO;
618f4a2713aSLionel Sambuc   unsigned OffsetReg = I->getOperand(0).getReg();
619f4a2713aSLionel Sambuc   unsigned TargetReg = I->getOperand(1).getReg();
620f4a2713aSLionel Sambuc 
621f4a2713aSLionel Sambuc   // addu $ra, $v0, $zero
622f4a2713aSLionel Sambuc   // addu $sp, $sp, $v1
623*0a6a1f1dSLionel Sambuc   // jr   $ra (via RetRA)
624*0a6a1f1dSLionel Sambuc   const TargetMachine &TM = MBB.getParent()->getTarget();
625f4a2713aSLionel Sambuc   if (TM.getRelocationModel() == Reloc::PIC_)
626*0a6a1f1dSLionel Sambuc     BuildMI(MBB, I, I->getDebugLoc(), get(ADDU), T9)
627*0a6a1f1dSLionel Sambuc         .addReg(TargetReg)
628*0a6a1f1dSLionel Sambuc         .addReg(ZERO);
629*0a6a1f1dSLionel Sambuc   BuildMI(MBB, I, I->getDebugLoc(), get(ADDU), RA)
630*0a6a1f1dSLionel Sambuc       .addReg(TargetReg)
631*0a6a1f1dSLionel Sambuc       .addReg(ZERO);
632*0a6a1f1dSLionel Sambuc   BuildMI(MBB, I, I->getDebugLoc(), get(ADDU), SP).addReg(SP).addReg(OffsetReg);
633*0a6a1f1dSLionel Sambuc   expandRetRA(MBB, I);
634f4a2713aSLionel Sambuc }
635f4a2713aSLionel Sambuc 
createMipsSEInstrInfo(const MipsSubtarget & STI)636*0a6a1f1dSLionel Sambuc const MipsInstrInfo *llvm::createMipsSEInstrInfo(const MipsSubtarget &STI) {
637*0a6a1f1dSLionel Sambuc   return new MipsSEInstrInfo(STI);
638f4a2713aSLionel Sambuc }
639