blob: 73924b750a1c9d3899e831255b5c6fb578ed6c88 [file] [log] [blame]
Jakob Stoklund Olesend9509412009-08-02 17:32:10 +00001//===- BlackfinInstrInfo.cpp - Blackfin Instruction Information -*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file contains the Blackfin implementation of the TargetInstrInfo class.
11//
12//===----------------------------------------------------------------------===//
13
14#include "BlackfinInstrInfo.h"
15#include "BlackfinSubtarget.h"
16#include "Blackfin.h"
17#include "llvm/ADT/STLExtras.h"
18#include "llvm/ADT/SmallVector.h"
19#include "llvm/CodeGen/MachineRegisterInfo.h"
20#include "llvm/CodeGen/MachineInstrBuilder.h"
21#include "llvm/Support/ErrorHandling.h"
22#include "BlackfinGenInstrInfo.inc"
23
24using namespace llvm;
25
26BlackfinInstrInfo::BlackfinInstrInfo(BlackfinSubtarget &ST)
27 : TargetInstrInfoImpl(BlackfinInsts, array_lengthof(BlackfinInsts)),
28 RI(ST, *this),
29 Subtarget(ST) {}
30
31/// Return true if the instruction is a register to register move and
32/// leave the source and dest operands in the passed parameters.
33bool BlackfinInstrInfo::isMoveInstr(const MachineInstr &MI,
34 unsigned &SrcReg,
35 unsigned &DstReg,
36 unsigned &SrcSR,
37 unsigned &DstSR) const {
38 SrcSR = DstSR = 0; // No sub-registers.
39 switch (MI.getOpcode()) {
40 case BF::MOVE:
41 case BF::MOVE_ncccc:
42 case BF::MOVE_ccncc:
43 case BF::MOVECC_zext:
44 case BF::MOVECC_nz:
45 DstReg = MI.getOperand(0).getReg();
46 SrcReg = MI.getOperand(1).getReg();
47 return true;
48 case BF::SLL16i:
49 if (MI.getOperand(2).getImm()!=0)
50 return false;
51 DstReg = MI.getOperand(0).getReg();
52 SrcReg = MI.getOperand(1).getReg();
53 return true;
54 default:
55 return false;
56 }
57}
58
59/// isLoadFromStackSlot - If the specified machine instruction is a direct
60/// load from a stack slot, return the virtual or physical register number of
61/// the destination along with the FrameIndex of the loaded stack slot. If
62/// not, return 0. This predicate must return 0 if the instruction has
63/// any side effects other than loading from the stack slot.
64unsigned BlackfinInstrInfo::isLoadFromStackSlot(const MachineInstr *MI,
65 int &FrameIndex) const {
66 switch (MI->getOpcode()) {
67 default: break;
68 case BF::LOAD32fi:
69 case BF::LOAD16fi:
70 if (MI->getOperand(1).isFI() &&
71 MI->getOperand(2).isImm() &&
72 MI->getOperand(2).getImm() == 0) {
73 FrameIndex = MI->getOperand(1).getIndex();
74 return MI->getOperand(0).getReg();
75 }
76 break;
77 }
78 return 0;
79}
80
81/// isStoreToStackSlot - If the specified machine instruction is a direct
82/// store to a stack slot, return the virtual or physical register number of
83/// the source reg along with the FrameIndex of the loaded stack slot. If
84/// not, return 0. This predicate must return 0 if the instruction has
85/// any side effects other than storing to the stack slot.
86unsigned BlackfinInstrInfo::isStoreToStackSlot(const MachineInstr *MI,
87 int &FrameIndex) const {
88 switch (MI->getOpcode()) {
89 default: break;
90 case BF::STORE32fi:
91 case BF::STORE16fi:
92 if (MI->getOperand(1).isFI() &&
93 MI->getOperand(2).isImm() &&
94 MI->getOperand(2).getImm() == 0) {
95 FrameIndex = MI->getOperand(1).getIndex();
96 return MI->getOperand(0).getReg();
97 }
98 break;
99 }
100 return 0;
101}
102
103unsigned BlackfinInstrInfo::
104InsertBranch(MachineBasicBlock &MBB,
105 MachineBasicBlock *TBB,
106 MachineBasicBlock *FBB,
107 const SmallVectorImpl<MachineOperand> &Cond) const {
108 // FIXME this should probably have a DebugLoc operand
Chris Lattnerc7f3ace2010-04-02 20:16:16 +0000109 DebugLoc DL;
Jakob Stoklund Olesend9509412009-08-02 17:32:10 +0000110
111 // Shouldn't be a fall through.
112 assert(TBB && "InsertBranch must not be told to insert a fallthrough");
113 assert((Cond.size() == 1 || Cond.size() == 0) &&
114 "Branch conditions have one component!");
115
116 if (Cond.empty()) {
117 // Unconditional branch?
118 assert(!FBB && "Unconditional branch with multiple successors!");
Chris Lattnerc7f3ace2010-04-02 20:16:16 +0000119 BuildMI(&MBB, DL, get(BF::JUMPa)).addMBB(TBB);
Jakob Stoklund Olesend9509412009-08-02 17:32:10 +0000120 return 1;
121 }
122
123 // Conditional branch.
124 llvm_unreachable("Implement conditional branches!");
125}
126
127static bool inClass(const TargetRegisterClass &Test,
128 unsigned Reg,
129 const TargetRegisterClass *RC) {
130 if (TargetRegisterInfo::isPhysicalRegister(Reg))
131 return Test.contains(Reg);
132 else
133 return &Test==RC || Test.hasSubClass(RC);
134}
135
136bool BlackfinInstrInfo::copyRegToReg(MachineBasicBlock &MBB,
137 MachineBasicBlock::iterator I,
138 unsigned DestReg,
139 unsigned SrcReg,
140 const TargetRegisterClass *DestRC,
Dan Gohman34dcc6f2010-05-06 20:33:48 +0000141 const TargetRegisterClass *SrcRC,
142 DebugLoc DL) const {
Jakob Stoklund Olesend9509412009-08-02 17:32:10 +0000143 if (inClass(BF::ALLRegClass, DestReg, DestRC) &&
144 inClass(BF::ALLRegClass, SrcReg, SrcRC)) {
Chris Lattnerc7f3ace2010-04-02 20:16:16 +0000145 BuildMI(MBB, I, DL, get(BF::MOVE), DestReg).addReg(SrcReg);
Jakob Stoklund Olesend9509412009-08-02 17:32:10 +0000146 return true;
147 }
148
149 if (inClass(BF::D16RegClass, DestReg, DestRC) &&
150 inClass(BF::D16RegClass, SrcReg, SrcRC)) {
Chris Lattnerc7f3ace2010-04-02 20:16:16 +0000151 BuildMI(MBB, I, DL, get(BF::SLL16i), DestReg).addReg(SrcReg).addImm(0);
Jakob Stoklund Olesend9509412009-08-02 17:32:10 +0000152 return true;
153 }
154
155 if (inClass(BF::AnyCCRegClass, SrcReg, SrcRC) &&
156 inClass(BF::DRegClass, DestReg, DestRC)) {
157 if (inClass(BF::NotCCRegClass, SrcReg, SrcRC)) {
Chris Lattnerc7f3ace2010-04-02 20:16:16 +0000158 BuildMI(MBB, I, DL, get(BF::MOVENCC_z), DestReg).addReg(SrcReg);
159 BuildMI(MBB, I, DL, get(BF::BITTGL), DestReg).addReg(DestReg).addImm(0);
Jakob Stoklund Olesend9509412009-08-02 17:32:10 +0000160 } else {
Chris Lattnerc7f3ace2010-04-02 20:16:16 +0000161 BuildMI(MBB, I, DL, get(BF::MOVECC_zext), DestReg).addReg(SrcReg);
Jakob Stoklund Olesend9509412009-08-02 17:32:10 +0000162 }
163 return true;
164 }
165
166 if (inClass(BF::AnyCCRegClass, DestReg, DestRC) &&
167 inClass(BF::DRegClass, SrcReg, SrcRC)) {
168 if (inClass(BF::NotCCRegClass, DestReg, DestRC))
Chris Lattnerc7f3ace2010-04-02 20:16:16 +0000169 BuildMI(MBB, I, DL, get(BF::SETEQri_not), DestReg).addReg(SrcReg);
Jakob Stoklund Olesend9509412009-08-02 17:32:10 +0000170 else
Chris Lattnerc7f3ace2010-04-02 20:16:16 +0000171 BuildMI(MBB, I, DL, get(BF::MOVECC_nz), DestReg).addReg(SrcReg);
Jakob Stoklund Olesend9509412009-08-02 17:32:10 +0000172 return true;
173 }
174
175 if (inClass(BF::NotCCRegClass, DestReg, DestRC) &&
176 inClass(BF::JustCCRegClass, SrcReg, SrcRC)) {
Chris Lattnerc7f3ace2010-04-02 20:16:16 +0000177 BuildMI(MBB, I, DL, get(BF::MOVE_ncccc), DestReg).addReg(SrcReg);
Jakob Stoklund Olesend9509412009-08-02 17:32:10 +0000178 return true;
179 }
180
181 if (inClass(BF::JustCCRegClass, DestReg, DestRC) &&
182 inClass(BF::NotCCRegClass, SrcReg, SrcRC)) {
Chris Lattnerc7f3ace2010-04-02 20:16:16 +0000183 BuildMI(MBB, I, DL, get(BF::MOVE_ccncc), DestReg).addReg(SrcReg);
Jakob Stoklund Olesend9509412009-08-02 17:32:10 +0000184 return true;
185 }
186
187 llvm_unreachable((std::string("Bad regclasses for reg-to-reg copy: ")+
188 SrcRC->getName() + " -> " + DestRC->getName()).c_str());
189 return false;
190}
191
192void
193BlackfinInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
194 MachineBasicBlock::iterator I,
195 unsigned SrcReg,
196 bool isKill,
197 int FI,
Evan Cheng746ad692010-05-06 19:06:44 +0000198 const TargetRegisterClass *RC,
199 const TargetRegisterInfo *TRI) const {
Chris Lattnerc7f3ace2010-04-02 20:16:16 +0000200 DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc();
Jakob Stoklund Olesend9509412009-08-02 17:32:10 +0000201
202 if (inClass(BF::DPRegClass, SrcReg, RC)) {
203 BuildMI(MBB, I, DL, get(BF::STORE32fi))
204 .addReg(SrcReg, getKillRegState(isKill))
205 .addFrameIndex(FI)
206 .addImm(0);
207 return;
208 }
209
210 if (inClass(BF::D16RegClass, SrcReg, RC)) {
211 BuildMI(MBB, I, DL, get(BF::STORE16fi))
212 .addReg(SrcReg, getKillRegState(isKill))
213 .addFrameIndex(FI)
214 .addImm(0);
215 return;
216 }
217
218 if (inClass(BF::AnyCCRegClass, SrcReg, RC)) {
219 BuildMI(MBB, I, DL, get(BF::STORE8fi))
220 .addReg(SrcReg, getKillRegState(isKill))
221 .addFrameIndex(FI)
222 .addImm(0);
223 return;
224 }
225
226 llvm_unreachable((std::string("Cannot store regclass to stack slot: ")+
227 RC->getName()).c_str());
228}
229
230void BlackfinInstrInfo::
231storeRegToAddr(MachineFunction &MF,
232 unsigned SrcReg,
233 bool isKill,
234 SmallVectorImpl<MachineOperand> &Addr,
235 const TargetRegisterClass *RC,
236 SmallVectorImpl<MachineInstr*> &NewMIs) const {
237 llvm_unreachable("storeRegToAddr not implemented");
238}
239
240void
241BlackfinInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
242 MachineBasicBlock::iterator I,
243 unsigned DestReg,
244 int FI,
Evan Cheng746ad692010-05-06 19:06:44 +0000245 const TargetRegisterClass *RC,
246 const TargetRegisterInfo *TRI) const {
Chris Lattnerc7f3ace2010-04-02 20:16:16 +0000247 DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc();
Jakob Stoklund Olesend9509412009-08-02 17:32:10 +0000248 if (inClass(BF::DPRegClass, DestReg, RC)) {
249 BuildMI(MBB, I, DL, get(BF::LOAD32fi), DestReg)
250 .addFrameIndex(FI)
251 .addImm(0);
252 return;
253 }
254
255 if (inClass(BF::D16RegClass, DestReg, RC)) {
256 BuildMI(MBB, I, DL, get(BF::LOAD16fi), DestReg)
257 .addFrameIndex(FI)
258 .addImm(0);
259 return;
260 }
261
262 if (inClass(BF::AnyCCRegClass, DestReg, RC)) {
263 BuildMI(MBB, I, DL, get(BF::LOAD8fi), DestReg)
264 .addFrameIndex(FI)
265 .addImm(0);
266 return;
267 }
268
269 llvm_unreachable("Cannot load regclass from stack slot");
270}
271
272void BlackfinInstrInfo::
273loadRegFromAddr(MachineFunction &MF,
274 unsigned DestReg,
275 SmallVectorImpl<MachineOperand> &Addr,
276 const TargetRegisterClass *RC,
277 SmallVectorImpl<MachineInstr*> &NewMIs) const {
278 llvm_unreachable("loadRegFromAddr not implemented");
279}