xref: /minix3/external/bsd/llvm/dist/llvm/lib/Target/Sparc/SparcInstrInfo.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1f4a2713aSLionel Sambuc //===-- SparcInstrInfo.cpp - Sparc 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 Sparc implementation of the TargetInstrInfo class.
11f4a2713aSLionel Sambuc //
12f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
13f4a2713aSLionel Sambuc 
14f4a2713aSLionel Sambuc #include "SparcInstrInfo.h"
15f4a2713aSLionel Sambuc #include "Sparc.h"
16f4a2713aSLionel Sambuc #include "SparcMachineFunctionInfo.h"
17f4a2713aSLionel Sambuc #include "SparcSubtarget.h"
18f4a2713aSLionel Sambuc #include "llvm/ADT/STLExtras.h"
19f4a2713aSLionel Sambuc #include "llvm/ADT/SmallVector.h"
20f4a2713aSLionel Sambuc #include "llvm/CodeGen/MachineFrameInfo.h"
21f4a2713aSLionel Sambuc #include "llvm/CodeGen/MachineInstrBuilder.h"
22f4a2713aSLionel Sambuc #include "llvm/CodeGen/MachineMemOperand.h"
23f4a2713aSLionel Sambuc #include "llvm/CodeGen/MachineRegisterInfo.h"
24f4a2713aSLionel Sambuc #include "llvm/Support/ErrorHandling.h"
25f4a2713aSLionel Sambuc #include "llvm/Support/TargetRegistry.h"
26f4a2713aSLionel Sambuc 
27f4a2713aSLionel Sambuc using namespace llvm;
28f4a2713aSLionel Sambuc 
29*0a6a1f1dSLionel Sambuc #define GET_INSTRINFO_CTOR_DTOR
30*0a6a1f1dSLionel Sambuc #include "SparcGenInstrInfo.inc"
31f4a2713aSLionel Sambuc 
32f4a2713aSLionel Sambuc // Pin the vtable to this file.
anchor()33f4a2713aSLionel Sambuc void SparcInstrInfo::anchor() {}
34f4a2713aSLionel Sambuc 
SparcInstrInfo(SparcSubtarget & ST)35f4a2713aSLionel Sambuc SparcInstrInfo::SparcInstrInfo(SparcSubtarget &ST)
36f4a2713aSLionel Sambuc   : SparcGenInstrInfo(SP::ADJCALLSTACKDOWN, SP::ADJCALLSTACKUP),
37f4a2713aSLionel Sambuc     RI(ST), Subtarget(ST) {
38f4a2713aSLionel Sambuc }
39f4a2713aSLionel Sambuc 
40f4a2713aSLionel Sambuc /// isLoadFromStackSlot - If the specified machine instruction is a direct
41f4a2713aSLionel Sambuc /// load from a stack slot, return the virtual or physical register number of
42f4a2713aSLionel Sambuc /// the destination along with the FrameIndex of the loaded stack slot.  If
43f4a2713aSLionel Sambuc /// not, return 0.  This predicate must return 0 if the instruction has
44f4a2713aSLionel Sambuc /// any side effects other than loading from the stack slot.
isLoadFromStackSlot(const MachineInstr * MI,int & FrameIndex) const45f4a2713aSLionel Sambuc unsigned SparcInstrInfo::isLoadFromStackSlot(const MachineInstr *MI,
46f4a2713aSLionel Sambuc                                              int &FrameIndex) const {
47f4a2713aSLionel Sambuc   if (MI->getOpcode() == SP::LDri ||
48f4a2713aSLionel Sambuc       MI->getOpcode() == SP::LDXri ||
49f4a2713aSLionel Sambuc       MI->getOpcode() == SP::LDFri ||
50f4a2713aSLionel Sambuc       MI->getOpcode() == SP::LDDFri ||
51f4a2713aSLionel Sambuc       MI->getOpcode() == SP::LDQFri) {
52f4a2713aSLionel Sambuc     if (MI->getOperand(1).isFI() && MI->getOperand(2).isImm() &&
53f4a2713aSLionel Sambuc         MI->getOperand(2).getImm() == 0) {
54f4a2713aSLionel Sambuc       FrameIndex = MI->getOperand(1).getIndex();
55f4a2713aSLionel Sambuc       return MI->getOperand(0).getReg();
56f4a2713aSLionel Sambuc     }
57f4a2713aSLionel Sambuc   }
58f4a2713aSLionel Sambuc   return 0;
59f4a2713aSLionel Sambuc }
60f4a2713aSLionel Sambuc 
61f4a2713aSLionel Sambuc /// isStoreToStackSlot - If the specified machine instruction is a direct
62f4a2713aSLionel Sambuc /// store to a stack slot, return the virtual or physical register number of
63f4a2713aSLionel Sambuc /// the source reg along with the FrameIndex of the loaded stack slot.  If
64f4a2713aSLionel Sambuc /// not, return 0.  This predicate must return 0 if the instruction has
65f4a2713aSLionel Sambuc /// any side effects other than storing to the stack slot.
isStoreToStackSlot(const MachineInstr * MI,int & FrameIndex) const66f4a2713aSLionel Sambuc unsigned SparcInstrInfo::isStoreToStackSlot(const MachineInstr *MI,
67f4a2713aSLionel Sambuc                                             int &FrameIndex) const {
68f4a2713aSLionel Sambuc   if (MI->getOpcode() == SP::STri ||
69f4a2713aSLionel Sambuc       MI->getOpcode() == SP::STXri ||
70f4a2713aSLionel Sambuc       MI->getOpcode() == SP::STFri ||
71f4a2713aSLionel Sambuc       MI->getOpcode() == SP::STDFri ||
72f4a2713aSLionel Sambuc       MI->getOpcode() == SP::STQFri) {
73f4a2713aSLionel Sambuc     if (MI->getOperand(0).isFI() && MI->getOperand(1).isImm() &&
74f4a2713aSLionel Sambuc         MI->getOperand(1).getImm() == 0) {
75f4a2713aSLionel Sambuc       FrameIndex = MI->getOperand(0).getIndex();
76f4a2713aSLionel Sambuc       return MI->getOperand(2).getReg();
77f4a2713aSLionel Sambuc     }
78f4a2713aSLionel Sambuc   }
79f4a2713aSLionel Sambuc   return 0;
80f4a2713aSLionel Sambuc }
81f4a2713aSLionel Sambuc 
IsIntegerCC(unsigned CC)82f4a2713aSLionel Sambuc static bool IsIntegerCC(unsigned CC)
83f4a2713aSLionel Sambuc {
84f4a2713aSLionel Sambuc   return  (CC <= SPCC::ICC_VC);
85f4a2713aSLionel Sambuc }
86f4a2713aSLionel Sambuc 
87f4a2713aSLionel Sambuc 
GetOppositeBranchCondition(SPCC::CondCodes CC)88f4a2713aSLionel Sambuc static SPCC::CondCodes GetOppositeBranchCondition(SPCC::CondCodes CC)
89f4a2713aSLionel Sambuc {
90f4a2713aSLionel Sambuc   switch(CC) {
91*0a6a1f1dSLionel Sambuc   case SPCC::ICC_A:    return SPCC::ICC_N;
92*0a6a1f1dSLionel Sambuc   case SPCC::ICC_N:    return SPCC::ICC_A;
93f4a2713aSLionel Sambuc   case SPCC::ICC_NE:   return SPCC::ICC_E;
94f4a2713aSLionel Sambuc   case SPCC::ICC_E:    return SPCC::ICC_NE;
95f4a2713aSLionel Sambuc   case SPCC::ICC_G:    return SPCC::ICC_LE;
96f4a2713aSLionel Sambuc   case SPCC::ICC_LE:   return SPCC::ICC_G;
97f4a2713aSLionel Sambuc   case SPCC::ICC_GE:   return SPCC::ICC_L;
98f4a2713aSLionel Sambuc   case SPCC::ICC_L:    return SPCC::ICC_GE;
99f4a2713aSLionel Sambuc   case SPCC::ICC_GU:   return SPCC::ICC_LEU;
100f4a2713aSLionel Sambuc   case SPCC::ICC_LEU:  return SPCC::ICC_GU;
101f4a2713aSLionel Sambuc   case SPCC::ICC_CC:   return SPCC::ICC_CS;
102f4a2713aSLionel Sambuc   case SPCC::ICC_CS:   return SPCC::ICC_CC;
103f4a2713aSLionel Sambuc   case SPCC::ICC_POS:  return SPCC::ICC_NEG;
104f4a2713aSLionel Sambuc   case SPCC::ICC_NEG:  return SPCC::ICC_POS;
105f4a2713aSLionel Sambuc   case SPCC::ICC_VC:   return SPCC::ICC_VS;
106f4a2713aSLionel Sambuc   case SPCC::ICC_VS:   return SPCC::ICC_VC;
107f4a2713aSLionel Sambuc 
108*0a6a1f1dSLionel Sambuc   case SPCC::FCC_A:    return SPCC::FCC_N;
109*0a6a1f1dSLionel Sambuc   case SPCC::FCC_N:    return SPCC::FCC_A;
110f4a2713aSLionel Sambuc   case SPCC::FCC_U:    return SPCC::FCC_O;
111f4a2713aSLionel Sambuc   case SPCC::FCC_O:    return SPCC::FCC_U;
112f4a2713aSLionel Sambuc   case SPCC::FCC_G:    return SPCC::FCC_ULE;
113f4a2713aSLionel Sambuc   case SPCC::FCC_LE:   return SPCC::FCC_UG;
114f4a2713aSLionel Sambuc   case SPCC::FCC_UG:   return SPCC::FCC_LE;
115f4a2713aSLionel Sambuc   case SPCC::FCC_ULE:  return SPCC::FCC_G;
116f4a2713aSLionel Sambuc   case SPCC::FCC_L:    return SPCC::FCC_UGE;
117f4a2713aSLionel Sambuc   case SPCC::FCC_GE:   return SPCC::FCC_UL;
118f4a2713aSLionel Sambuc   case SPCC::FCC_UL:   return SPCC::FCC_GE;
119f4a2713aSLionel Sambuc   case SPCC::FCC_UGE:  return SPCC::FCC_L;
120f4a2713aSLionel Sambuc   case SPCC::FCC_LG:   return SPCC::FCC_UE;
121f4a2713aSLionel Sambuc   case SPCC::FCC_UE:   return SPCC::FCC_LG;
122f4a2713aSLionel Sambuc   case SPCC::FCC_NE:   return SPCC::FCC_E;
123f4a2713aSLionel Sambuc   case SPCC::FCC_E:    return SPCC::FCC_NE;
124f4a2713aSLionel Sambuc   }
125f4a2713aSLionel Sambuc   llvm_unreachable("Invalid cond code");
126f4a2713aSLionel Sambuc }
127f4a2713aSLionel Sambuc 
AnalyzeBranch(MachineBasicBlock & MBB,MachineBasicBlock * & TBB,MachineBasicBlock * & FBB,SmallVectorImpl<MachineOperand> & Cond,bool AllowModify) const128f4a2713aSLionel Sambuc bool SparcInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,
129f4a2713aSLionel Sambuc                                    MachineBasicBlock *&TBB,
130f4a2713aSLionel Sambuc                                    MachineBasicBlock *&FBB,
131f4a2713aSLionel Sambuc                                    SmallVectorImpl<MachineOperand> &Cond,
132f4a2713aSLionel Sambuc                                    bool AllowModify) const
133f4a2713aSLionel Sambuc {
134f4a2713aSLionel Sambuc 
135f4a2713aSLionel Sambuc   MachineBasicBlock::iterator I = MBB.end();
136f4a2713aSLionel Sambuc   MachineBasicBlock::iterator UnCondBrIter = MBB.end();
137f4a2713aSLionel Sambuc   while (I != MBB.begin()) {
138f4a2713aSLionel Sambuc     --I;
139f4a2713aSLionel Sambuc 
140f4a2713aSLionel Sambuc     if (I->isDebugValue())
141f4a2713aSLionel Sambuc       continue;
142f4a2713aSLionel Sambuc 
143f4a2713aSLionel Sambuc     // When we see a non-terminator, we are done.
144f4a2713aSLionel Sambuc     if (!isUnpredicatedTerminator(I))
145f4a2713aSLionel Sambuc       break;
146f4a2713aSLionel Sambuc 
147f4a2713aSLionel Sambuc     // Terminator is not a branch.
148f4a2713aSLionel Sambuc     if (!I->isBranch())
149f4a2713aSLionel Sambuc       return true;
150f4a2713aSLionel Sambuc 
151f4a2713aSLionel Sambuc     // Handle Unconditional branches.
152f4a2713aSLionel Sambuc     if (I->getOpcode() == SP::BA) {
153f4a2713aSLionel Sambuc       UnCondBrIter = I;
154f4a2713aSLionel Sambuc 
155f4a2713aSLionel Sambuc       if (!AllowModify) {
156f4a2713aSLionel Sambuc         TBB = I->getOperand(0).getMBB();
157f4a2713aSLionel Sambuc         continue;
158f4a2713aSLionel Sambuc       }
159f4a2713aSLionel Sambuc 
160*0a6a1f1dSLionel Sambuc       while (std::next(I) != MBB.end())
161*0a6a1f1dSLionel Sambuc         std::next(I)->eraseFromParent();
162f4a2713aSLionel Sambuc 
163f4a2713aSLionel Sambuc       Cond.clear();
164*0a6a1f1dSLionel Sambuc       FBB = nullptr;
165f4a2713aSLionel Sambuc 
166f4a2713aSLionel Sambuc       if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) {
167*0a6a1f1dSLionel Sambuc         TBB = nullptr;
168f4a2713aSLionel Sambuc         I->eraseFromParent();
169f4a2713aSLionel Sambuc         I = MBB.end();
170f4a2713aSLionel Sambuc         UnCondBrIter = MBB.end();
171f4a2713aSLionel Sambuc         continue;
172f4a2713aSLionel Sambuc       }
173f4a2713aSLionel Sambuc 
174f4a2713aSLionel Sambuc       TBB = I->getOperand(0).getMBB();
175f4a2713aSLionel Sambuc       continue;
176f4a2713aSLionel Sambuc     }
177f4a2713aSLionel Sambuc 
178f4a2713aSLionel Sambuc     unsigned Opcode = I->getOpcode();
179f4a2713aSLionel Sambuc     if (Opcode != SP::BCOND && Opcode != SP::FBCOND)
180f4a2713aSLionel Sambuc       return true; // Unknown Opcode.
181f4a2713aSLionel Sambuc 
182f4a2713aSLionel Sambuc     SPCC::CondCodes BranchCode = (SPCC::CondCodes)I->getOperand(1).getImm();
183f4a2713aSLionel Sambuc 
184f4a2713aSLionel Sambuc     if (Cond.empty()) {
185f4a2713aSLionel Sambuc       MachineBasicBlock *TargetBB = I->getOperand(0).getMBB();
186f4a2713aSLionel Sambuc       if (AllowModify && UnCondBrIter != MBB.end() &&
187f4a2713aSLionel Sambuc           MBB.isLayoutSuccessor(TargetBB)) {
188f4a2713aSLionel Sambuc 
189f4a2713aSLionel Sambuc         // Transform the code
190f4a2713aSLionel Sambuc         //
191f4a2713aSLionel Sambuc         //    brCC L1
192f4a2713aSLionel Sambuc         //    ba L2
193f4a2713aSLionel Sambuc         // L1:
194f4a2713aSLionel Sambuc         //    ..
195f4a2713aSLionel Sambuc         // L2:
196f4a2713aSLionel Sambuc         //
197f4a2713aSLionel Sambuc         // into
198f4a2713aSLionel Sambuc         //
199f4a2713aSLionel Sambuc         //   brnCC L2
200f4a2713aSLionel Sambuc         // L1:
201f4a2713aSLionel Sambuc         //   ...
202f4a2713aSLionel Sambuc         // L2:
203f4a2713aSLionel Sambuc         //
204f4a2713aSLionel Sambuc         BranchCode = GetOppositeBranchCondition(BranchCode);
205f4a2713aSLionel Sambuc         MachineBasicBlock::iterator OldInst = I;
206f4a2713aSLionel Sambuc         BuildMI(MBB, UnCondBrIter, MBB.findDebugLoc(I), get(Opcode))
207f4a2713aSLionel Sambuc           .addMBB(UnCondBrIter->getOperand(0).getMBB()).addImm(BranchCode);
208f4a2713aSLionel Sambuc         BuildMI(MBB, UnCondBrIter, MBB.findDebugLoc(I), get(SP::BA))
209f4a2713aSLionel Sambuc           .addMBB(TargetBB);
210f4a2713aSLionel Sambuc 
211f4a2713aSLionel Sambuc         OldInst->eraseFromParent();
212f4a2713aSLionel Sambuc         UnCondBrIter->eraseFromParent();
213f4a2713aSLionel Sambuc 
214f4a2713aSLionel Sambuc         UnCondBrIter = MBB.end();
215f4a2713aSLionel Sambuc         I = MBB.end();
216f4a2713aSLionel Sambuc         continue;
217f4a2713aSLionel Sambuc       }
218f4a2713aSLionel Sambuc       FBB = TBB;
219f4a2713aSLionel Sambuc       TBB = I->getOperand(0).getMBB();
220f4a2713aSLionel Sambuc       Cond.push_back(MachineOperand::CreateImm(BranchCode));
221f4a2713aSLionel Sambuc       continue;
222f4a2713aSLionel Sambuc     }
223f4a2713aSLionel Sambuc     // FIXME: Handle subsequent conditional branches.
224f4a2713aSLionel Sambuc     // For now, we can't handle multiple conditional branches.
225f4a2713aSLionel Sambuc     return true;
226f4a2713aSLionel Sambuc   }
227f4a2713aSLionel Sambuc   return false;
228f4a2713aSLionel Sambuc }
229f4a2713aSLionel Sambuc 
230f4a2713aSLionel Sambuc unsigned
InsertBranch(MachineBasicBlock & MBB,MachineBasicBlock * TBB,MachineBasicBlock * FBB,const SmallVectorImpl<MachineOperand> & Cond,DebugLoc DL) const231f4a2713aSLionel Sambuc SparcInstrInfo::InsertBranch(MachineBasicBlock &MBB,MachineBasicBlock *TBB,
232f4a2713aSLionel Sambuc                              MachineBasicBlock *FBB,
233f4a2713aSLionel Sambuc                              const SmallVectorImpl<MachineOperand> &Cond,
234f4a2713aSLionel Sambuc                              DebugLoc DL) const {
235f4a2713aSLionel Sambuc   assert(TBB && "InsertBranch must not be told to insert a fallthrough");
236f4a2713aSLionel Sambuc   assert((Cond.size() == 1 || Cond.size() == 0) &&
237f4a2713aSLionel Sambuc          "Sparc branch conditions should have one component!");
238f4a2713aSLionel Sambuc 
239f4a2713aSLionel Sambuc   if (Cond.empty()) {
240f4a2713aSLionel Sambuc     assert(!FBB && "Unconditional branch with multiple successors!");
241f4a2713aSLionel Sambuc     BuildMI(&MBB, DL, get(SP::BA)).addMBB(TBB);
242f4a2713aSLionel Sambuc     return 1;
243f4a2713aSLionel Sambuc   }
244f4a2713aSLionel Sambuc 
245f4a2713aSLionel Sambuc   // Conditional branch
246f4a2713aSLionel Sambuc   unsigned CC = Cond[0].getImm();
247f4a2713aSLionel Sambuc 
248f4a2713aSLionel Sambuc   if (IsIntegerCC(CC))
249f4a2713aSLionel Sambuc     BuildMI(&MBB, DL, get(SP::BCOND)).addMBB(TBB).addImm(CC);
250f4a2713aSLionel Sambuc   else
251f4a2713aSLionel Sambuc     BuildMI(&MBB, DL, get(SP::FBCOND)).addMBB(TBB).addImm(CC);
252f4a2713aSLionel Sambuc   if (!FBB)
253f4a2713aSLionel Sambuc     return 1;
254f4a2713aSLionel Sambuc 
255f4a2713aSLionel Sambuc   BuildMI(&MBB, DL, get(SP::BA)).addMBB(FBB);
256f4a2713aSLionel Sambuc   return 2;
257f4a2713aSLionel Sambuc }
258f4a2713aSLionel Sambuc 
RemoveBranch(MachineBasicBlock & MBB) const259f4a2713aSLionel Sambuc unsigned SparcInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const
260f4a2713aSLionel Sambuc {
261f4a2713aSLionel Sambuc   MachineBasicBlock::iterator I = MBB.end();
262f4a2713aSLionel Sambuc   unsigned Count = 0;
263f4a2713aSLionel Sambuc   while (I != MBB.begin()) {
264f4a2713aSLionel Sambuc     --I;
265f4a2713aSLionel Sambuc 
266f4a2713aSLionel Sambuc     if (I->isDebugValue())
267f4a2713aSLionel Sambuc       continue;
268f4a2713aSLionel Sambuc 
269f4a2713aSLionel Sambuc     if (I->getOpcode() != SP::BA
270f4a2713aSLionel Sambuc         && I->getOpcode() != SP::BCOND
271f4a2713aSLionel Sambuc         && I->getOpcode() != SP::FBCOND)
272f4a2713aSLionel Sambuc       break; // Not a branch
273f4a2713aSLionel Sambuc 
274f4a2713aSLionel Sambuc     I->eraseFromParent();
275f4a2713aSLionel Sambuc     I = MBB.end();
276f4a2713aSLionel Sambuc     ++Count;
277f4a2713aSLionel Sambuc   }
278f4a2713aSLionel Sambuc   return Count;
279f4a2713aSLionel Sambuc }
280f4a2713aSLionel Sambuc 
copyPhysReg(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,DebugLoc DL,unsigned DestReg,unsigned SrcReg,bool KillSrc) const281f4a2713aSLionel Sambuc void SparcInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
282f4a2713aSLionel Sambuc                                  MachineBasicBlock::iterator I, DebugLoc DL,
283f4a2713aSLionel Sambuc                                  unsigned DestReg, unsigned SrcReg,
284f4a2713aSLionel Sambuc                                  bool KillSrc) const {
285f4a2713aSLionel Sambuc   unsigned numSubRegs = 0;
286f4a2713aSLionel Sambuc   unsigned movOpc     = 0;
287*0a6a1f1dSLionel Sambuc   const unsigned *subRegIdx = nullptr;
288f4a2713aSLionel Sambuc 
289f4a2713aSLionel Sambuc   const unsigned DFP_FP_SubRegsIdx[]  = { SP::sub_even, SP::sub_odd };
290f4a2713aSLionel Sambuc   const unsigned QFP_DFP_SubRegsIdx[] = { SP::sub_even64, SP::sub_odd64 };
291f4a2713aSLionel Sambuc   const unsigned QFP_FP_SubRegsIdx[]  = { SP::sub_even, SP::sub_odd,
292f4a2713aSLionel Sambuc                                           SP::sub_odd64_then_sub_even,
293f4a2713aSLionel Sambuc                                           SP::sub_odd64_then_sub_odd };
294f4a2713aSLionel Sambuc 
295f4a2713aSLionel Sambuc   if (SP::IntRegsRegClass.contains(DestReg, SrcReg))
296f4a2713aSLionel Sambuc     BuildMI(MBB, I, DL, get(SP::ORrr), DestReg).addReg(SP::G0)
297f4a2713aSLionel Sambuc       .addReg(SrcReg, getKillRegState(KillSrc));
298f4a2713aSLionel Sambuc   else if (SP::FPRegsRegClass.contains(DestReg, SrcReg))
299f4a2713aSLionel Sambuc     BuildMI(MBB, I, DL, get(SP::FMOVS), DestReg)
300f4a2713aSLionel Sambuc       .addReg(SrcReg, getKillRegState(KillSrc));
301f4a2713aSLionel Sambuc   else if (SP::DFPRegsRegClass.contains(DestReg, SrcReg)) {
302f4a2713aSLionel Sambuc     if (Subtarget.isV9()) {
303f4a2713aSLionel Sambuc       BuildMI(MBB, I, DL, get(SP::FMOVD), DestReg)
304f4a2713aSLionel Sambuc         .addReg(SrcReg, getKillRegState(KillSrc));
305f4a2713aSLionel Sambuc     } else {
306f4a2713aSLionel Sambuc       // Use two FMOVS instructions.
307f4a2713aSLionel Sambuc       subRegIdx  = DFP_FP_SubRegsIdx;
308f4a2713aSLionel Sambuc       numSubRegs = 2;
309f4a2713aSLionel Sambuc       movOpc     = SP::FMOVS;
310f4a2713aSLionel Sambuc     }
311f4a2713aSLionel Sambuc   } else if (SP::QFPRegsRegClass.contains(DestReg, SrcReg)) {
312f4a2713aSLionel Sambuc     if (Subtarget.isV9()) {
313f4a2713aSLionel Sambuc       if (Subtarget.hasHardQuad()) {
314f4a2713aSLionel Sambuc         BuildMI(MBB, I, DL, get(SP::FMOVQ), DestReg)
315f4a2713aSLionel Sambuc           .addReg(SrcReg, getKillRegState(KillSrc));
316f4a2713aSLionel Sambuc       } else {
317f4a2713aSLionel Sambuc         // Use two FMOVD instructions.
318f4a2713aSLionel Sambuc         subRegIdx  = QFP_DFP_SubRegsIdx;
319f4a2713aSLionel Sambuc         numSubRegs = 2;
320f4a2713aSLionel Sambuc         movOpc     = SP::FMOVD;
321f4a2713aSLionel Sambuc       }
322f4a2713aSLionel Sambuc     } else {
323f4a2713aSLionel Sambuc       // Use four FMOVS instructions.
324f4a2713aSLionel Sambuc       subRegIdx  = QFP_FP_SubRegsIdx;
325f4a2713aSLionel Sambuc       numSubRegs = 4;
326f4a2713aSLionel Sambuc       movOpc     = SP::FMOVS;
327f4a2713aSLionel Sambuc     }
328f4a2713aSLionel Sambuc   } else
329f4a2713aSLionel Sambuc     llvm_unreachable("Impossible reg-to-reg copy");
330f4a2713aSLionel Sambuc 
331*0a6a1f1dSLionel Sambuc   if (numSubRegs == 0 || subRegIdx == nullptr || movOpc == 0)
332f4a2713aSLionel Sambuc     return;
333f4a2713aSLionel Sambuc 
334f4a2713aSLionel Sambuc   const TargetRegisterInfo *TRI = &getRegisterInfo();
335*0a6a1f1dSLionel Sambuc   MachineInstr *MovMI = nullptr;
336f4a2713aSLionel Sambuc 
337f4a2713aSLionel Sambuc   for (unsigned i = 0; i != numSubRegs; ++i) {
338f4a2713aSLionel Sambuc     unsigned Dst = TRI->getSubReg(DestReg, subRegIdx[i]);
339f4a2713aSLionel Sambuc     unsigned Src = TRI->getSubReg(SrcReg,  subRegIdx[i]);
340f4a2713aSLionel Sambuc     assert(Dst && Src && "Bad sub-register");
341f4a2713aSLionel Sambuc 
342f4a2713aSLionel Sambuc     MovMI = BuildMI(MBB, I, DL, get(movOpc), Dst).addReg(Src);
343f4a2713aSLionel Sambuc   }
344f4a2713aSLionel Sambuc   // Add implicit super-register defs and kills to the last MovMI.
345f4a2713aSLionel Sambuc   MovMI->addRegisterDefined(DestReg, TRI);
346f4a2713aSLionel Sambuc   if (KillSrc)
347f4a2713aSLionel Sambuc     MovMI->addRegisterKilled(SrcReg, TRI);
348f4a2713aSLionel Sambuc }
349f4a2713aSLionel Sambuc 
350f4a2713aSLionel Sambuc void SparcInstrInfo::
storeRegToStackSlot(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,unsigned SrcReg,bool isKill,int FI,const TargetRegisterClass * RC,const TargetRegisterInfo * TRI) const351f4a2713aSLionel Sambuc storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
352f4a2713aSLionel Sambuc                     unsigned SrcReg, bool isKill, int FI,
353f4a2713aSLionel Sambuc                     const TargetRegisterClass *RC,
354f4a2713aSLionel Sambuc                     const TargetRegisterInfo *TRI) const {
355f4a2713aSLionel Sambuc   DebugLoc DL;
356f4a2713aSLionel Sambuc   if (I != MBB.end()) DL = I->getDebugLoc();
357f4a2713aSLionel Sambuc 
358f4a2713aSLionel Sambuc   MachineFunction *MF = MBB.getParent();
359f4a2713aSLionel Sambuc   const MachineFrameInfo &MFI = *MF->getFrameInfo();
360f4a2713aSLionel Sambuc   MachineMemOperand *MMO =
361f4a2713aSLionel Sambuc     MF->getMachineMemOperand(MachinePointerInfo::getFixedStack(FI),
362f4a2713aSLionel Sambuc                              MachineMemOperand::MOStore,
363f4a2713aSLionel Sambuc                              MFI.getObjectSize(FI),
364f4a2713aSLionel Sambuc                              MFI.getObjectAlignment(FI));
365f4a2713aSLionel Sambuc 
366f4a2713aSLionel Sambuc   // On the order of operands here: think "[FrameIdx + 0] = SrcReg".
367f4a2713aSLionel Sambuc  if (RC == &SP::I64RegsRegClass)
368f4a2713aSLionel Sambuc     BuildMI(MBB, I, DL, get(SP::STXri)).addFrameIndex(FI).addImm(0)
369f4a2713aSLionel Sambuc       .addReg(SrcReg, getKillRegState(isKill)).addMemOperand(MMO);
370f4a2713aSLionel Sambuc   else if (RC == &SP::IntRegsRegClass)
371f4a2713aSLionel Sambuc     BuildMI(MBB, I, DL, get(SP::STri)).addFrameIndex(FI).addImm(0)
372f4a2713aSLionel Sambuc       .addReg(SrcReg, getKillRegState(isKill)).addMemOperand(MMO);
373f4a2713aSLionel Sambuc   else if (RC == &SP::FPRegsRegClass)
374f4a2713aSLionel Sambuc     BuildMI(MBB, I, DL, get(SP::STFri)).addFrameIndex(FI).addImm(0)
375f4a2713aSLionel Sambuc       .addReg(SrcReg,  getKillRegState(isKill)).addMemOperand(MMO);
376f4a2713aSLionel Sambuc   else if (SP::DFPRegsRegClass.hasSubClassEq(RC))
377f4a2713aSLionel Sambuc     BuildMI(MBB, I, DL, get(SP::STDFri)).addFrameIndex(FI).addImm(0)
378f4a2713aSLionel Sambuc       .addReg(SrcReg,  getKillRegState(isKill)).addMemOperand(MMO);
379f4a2713aSLionel Sambuc   else if (SP::QFPRegsRegClass.hasSubClassEq(RC))
380f4a2713aSLionel Sambuc     // Use STQFri irrespective of its legality. If STQ is not legal, it will be
381f4a2713aSLionel Sambuc     // lowered into two STDs in eliminateFrameIndex.
382f4a2713aSLionel Sambuc     BuildMI(MBB, I, DL, get(SP::STQFri)).addFrameIndex(FI).addImm(0)
383f4a2713aSLionel Sambuc       .addReg(SrcReg,  getKillRegState(isKill)).addMemOperand(MMO);
384f4a2713aSLionel Sambuc   else
385f4a2713aSLionel Sambuc     llvm_unreachable("Can't store this register to stack slot");
386f4a2713aSLionel Sambuc }
387f4a2713aSLionel Sambuc 
388f4a2713aSLionel Sambuc void SparcInstrInfo::
loadRegFromStackSlot(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,unsigned DestReg,int FI,const TargetRegisterClass * RC,const TargetRegisterInfo * TRI) const389f4a2713aSLionel Sambuc loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
390f4a2713aSLionel Sambuc                      unsigned DestReg, int FI,
391f4a2713aSLionel Sambuc                      const TargetRegisterClass *RC,
392f4a2713aSLionel Sambuc                      const TargetRegisterInfo *TRI) const {
393f4a2713aSLionel Sambuc   DebugLoc DL;
394f4a2713aSLionel Sambuc   if (I != MBB.end()) DL = I->getDebugLoc();
395f4a2713aSLionel Sambuc 
396f4a2713aSLionel Sambuc   MachineFunction *MF = MBB.getParent();
397f4a2713aSLionel Sambuc   const MachineFrameInfo &MFI = *MF->getFrameInfo();
398f4a2713aSLionel Sambuc   MachineMemOperand *MMO =
399f4a2713aSLionel Sambuc     MF->getMachineMemOperand(MachinePointerInfo::getFixedStack(FI),
400f4a2713aSLionel Sambuc                              MachineMemOperand::MOLoad,
401f4a2713aSLionel Sambuc                              MFI.getObjectSize(FI),
402f4a2713aSLionel Sambuc                              MFI.getObjectAlignment(FI));
403f4a2713aSLionel Sambuc 
404f4a2713aSLionel Sambuc   if (RC == &SP::I64RegsRegClass)
405f4a2713aSLionel Sambuc     BuildMI(MBB, I, DL, get(SP::LDXri), DestReg).addFrameIndex(FI).addImm(0)
406f4a2713aSLionel Sambuc       .addMemOperand(MMO);
407f4a2713aSLionel Sambuc   else if (RC == &SP::IntRegsRegClass)
408f4a2713aSLionel Sambuc     BuildMI(MBB, I, DL, get(SP::LDri), DestReg).addFrameIndex(FI).addImm(0)
409f4a2713aSLionel Sambuc       .addMemOperand(MMO);
410f4a2713aSLionel Sambuc   else if (RC == &SP::FPRegsRegClass)
411f4a2713aSLionel Sambuc     BuildMI(MBB, I, DL, get(SP::LDFri), DestReg).addFrameIndex(FI).addImm(0)
412f4a2713aSLionel Sambuc       .addMemOperand(MMO);
413f4a2713aSLionel Sambuc   else if (SP::DFPRegsRegClass.hasSubClassEq(RC))
414f4a2713aSLionel Sambuc     BuildMI(MBB, I, DL, get(SP::LDDFri), DestReg).addFrameIndex(FI).addImm(0)
415f4a2713aSLionel Sambuc       .addMemOperand(MMO);
416f4a2713aSLionel Sambuc   else if (SP::QFPRegsRegClass.hasSubClassEq(RC))
417f4a2713aSLionel Sambuc     // Use LDQFri irrespective of its legality. If LDQ is not legal, it will be
418f4a2713aSLionel Sambuc     // lowered into two LDDs in eliminateFrameIndex.
419f4a2713aSLionel Sambuc     BuildMI(MBB, I, DL, get(SP::LDQFri), DestReg).addFrameIndex(FI).addImm(0)
420f4a2713aSLionel Sambuc       .addMemOperand(MMO);
421f4a2713aSLionel Sambuc   else
422f4a2713aSLionel Sambuc     llvm_unreachable("Can't load this register from stack slot");
423f4a2713aSLionel Sambuc }
424f4a2713aSLionel Sambuc 
getGlobalBaseReg(MachineFunction * MF) const425f4a2713aSLionel Sambuc unsigned SparcInstrInfo::getGlobalBaseReg(MachineFunction *MF) const
426f4a2713aSLionel Sambuc {
427f4a2713aSLionel Sambuc   SparcMachineFunctionInfo *SparcFI = MF->getInfo<SparcMachineFunctionInfo>();
428f4a2713aSLionel Sambuc   unsigned GlobalBaseReg = SparcFI->getGlobalBaseReg();
429f4a2713aSLionel Sambuc   if (GlobalBaseReg != 0)
430f4a2713aSLionel Sambuc     return GlobalBaseReg;
431f4a2713aSLionel Sambuc 
432f4a2713aSLionel Sambuc   // Insert the set of GlobalBaseReg into the first MBB of the function
433f4a2713aSLionel Sambuc   MachineBasicBlock &FirstMBB = MF->front();
434f4a2713aSLionel Sambuc   MachineBasicBlock::iterator MBBI = FirstMBB.begin();
435f4a2713aSLionel Sambuc   MachineRegisterInfo &RegInfo = MF->getRegInfo();
436f4a2713aSLionel Sambuc 
437*0a6a1f1dSLionel Sambuc   const TargetRegisterClass *PtrRC =
438*0a6a1f1dSLionel Sambuc     Subtarget.is64Bit() ? &SP::I64RegsRegClass : &SP::IntRegsRegClass;
439*0a6a1f1dSLionel Sambuc   GlobalBaseReg = RegInfo.createVirtualRegister(PtrRC);
440f4a2713aSLionel Sambuc 
441f4a2713aSLionel Sambuc   DebugLoc dl;
442f4a2713aSLionel Sambuc 
443f4a2713aSLionel Sambuc   BuildMI(FirstMBB, MBBI, dl, get(SP::GETPCX), GlobalBaseReg);
444f4a2713aSLionel Sambuc   SparcFI->setGlobalBaseReg(GlobalBaseReg);
445f4a2713aSLionel Sambuc   return GlobalBaseReg;
446f4a2713aSLionel Sambuc }
447