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