Analog Devices Blackfin back-end.
[oota-llvm.git] / lib / Target / Blackfin / BlackfinInstrInfo.cpp
1 //===- 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
24 using namespace llvm;
25
26 BlackfinInstrInfo::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.
33 bool 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.
64 unsigned 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.
86 unsigned 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
103 unsigned BlackfinInstrInfo::
104 InsertBranch(MachineBasicBlock &MBB,
105              MachineBasicBlock *TBB,
106              MachineBasicBlock *FBB,
107              const SmallVectorImpl<MachineOperand> &Cond) const {
108   // FIXME this should probably have a DebugLoc operand
109   DebugLoc dl = DebugLoc::getUnknownLoc();
110
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!");
119     BuildMI(&MBB, dl, get(BF::JUMPa)).addMBB(TBB);
120     return 1;
121   }
122
123   // Conditional branch.
124   llvm_unreachable("Implement conditional branches!");
125 }
126
127 static 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
136 bool BlackfinInstrInfo::copyRegToReg(MachineBasicBlock &MBB,
137                                      MachineBasicBlock::iterator I,
138                                      unsigned DestReg,
139                                      unsigned SrcReg,
140                                      const TargetRegisterClass *DestRC,
141                                      const TargetRegisterClass *SrcRC) const {
142   DebugLoc dl = DebugLoc::getUnknownLoc();
143
144   if (inClass(BF::ALLRegClass, DestReg, DestRC) &&
145       inClass(BF::ALLRegClass, SrcReg,  SrcRC)) {
146     BuildMI(MBB, I, dl, get(BF::MOVE), DestReg).addReg(SrcReg);
147     return true;
148   }
149
150   if (inClass(BF::D16RegClass, DestReg, DestRC) &&
151       inClass(BF::D16RegClass, SrcReg,  SrcRC)) {
152     BuildMI(MBB, I, dl, get(BF::SLL16i), DestReg).addReg(SrcReg).addImm(0);
153     return true;
154   }
155
156   if (inClass(BF::AnyCCRegClass, SrcReg, SrcRC) &&
157       inClass(BF::DRegClass, DestReg, DestRC)) {
158     if (inClass(BF::NotCCRegClass, SrcReg, SrcRC)) {
159       BuildMI(MBB, I, dl, get(BF::MOVENCC_z), DestReg).addReg(SrcReg);
160       BuildMI(MBB, I, dl, get(BF::BITTGL), DestReg).addReg(DestReg).addImm(0);
161     } else {
162       BuildMI(MBB, I, dl, get(BF::MOVECC_zext), DestReg).addReg(SrcReg);
163     }
164     return true;
165   }
166
167   if (inClass(BF::AnyCCRegClass, DestReg, DestRC) &&
168       inClass(BF::DRegClass, SrcReg,  SrcRC)) {
169     if (inClass(BF::NotCCRegClass, DestReg, DestRC))
170       BuildMI(MBB, I, dl, get(BF::SETEQri_not), DestReg).addReg(SrcReg);
171     else
172       BuildMI(MBB, I, dl, get(BF::MOVECC_nz), DestReg).addReg(SrcReg);
173     return true;
174   }
175
176   if (inClass(BF::NotCCRegClass, DestReg, DestRC) &&
177       inClass(BF::JustCCRegClass, SrcReg,  SrcRC)) {
178     BuildMI(MBB, I, dl, get(BF::MOVE_ncccc), DestReg).addReg(SrcReg);
179     return true;
180   }
181
182   if (inClass(BF::JustCCRegClass, DestReg, DestRC) &&
183       inClass(BF::NotCCRegClass, SrcReg,  SrcRC)) {
184     BuildMI(MBB, I, dl, get(BF::MOVE_ccncc), DestReg).addReg(SrcReg);
185     return true;
186   }
187
188   llvm_unreachable((std::string("Bad regclasses for reg-to-reg copy: ")+
189                     SrcRC->getName() + " -> " + DestRC->getName()).c_str());
190   return false;
191 }
192
193 void
194 BlackfinInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
195                                        MachineBasicBlock::iterator I,
196                                        unsigned SrcReg,
197                                        bool isKill,
198                                        int FI,
199                                        const TargetRegisterClass *RC) const {
200   DebugLoc DL = I != MBB.end() ?
201     I->getDebugLoc() : DebugLoc::getUnknownLoc();
202
203   if (inClass(BF::DPRegClass, SrcReg, RC)) {
204     BuildMI(MBB, I, DL, get(BF::STORE32fi))
205       .addReg(SrcReg, getKillRegState(isKill))
206       .addFrameIndex(FI)
207       .addImm(0);
208     return;
209   }
210
211   if (inClass(BF::D16RegClass, SrcReg, RC)) {
212     BuildMI(MBB, I, DL, get(BF::STORE16fi))
213       .addReg(SrcReg, getKillRegState(isKill))
214       .addFrameIndex(FI)
215       .addImm(0);
216     return;
217   }
218
219   if (inClass(BF::AnyCCRegClass, SrcReg, RC)) {
220     BuildMI(MBB, I, DL, get(BF::STORE8fi))
221       .addReg(SrcReg, getKillRegState(isKill))
222       .addFrameIndex(FI)
223       .addImm(0);
224     return;
225   }
226
227   llvm_unreachable((std::string("Cannot store regclass to stack slot: ")+
228                     RC->getName()).c_str());
229 }
230
231 void BlackfinInstrInfo::
232 storeRegToAddr(MachineFunction &MF,
233                unsigned SrcReg,
234                bool isKill,
235                SmallVectorImpl<MachineOperand> &Addr,
236                const TargetRegisterClass *RC,
237                SmallVectorImpl<MachineInstr*> &NewMIs) const {
238   llvm_unreachable("storeRegToAddr not implemented");
239 }
240
241 void
242 BlackfinInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
243                                         MachineBasicBlock::iterator I,
244                                         unsigned DestReg,
245                                         int FI,
246                                         const TargetRegisterClass *RC) const {
247   DebugLoc DL = I != MBB.end() ?
248     I->getDebugLoc() : DebugLoc::getUnknownLoc();
249   if (inClass(BF::DPRegClass, DestReg, RC)) {
250     BuildMI(MBB, I, DL, get(BF::LOAD32fi), DestReg)
251       .addFrameIndex(FI)
252       .addImm(0);
253     return;
254   }
255
256   if (inClass(BF::D16RegClass, DestReg, RC)) {
257     BuildMI(MBB, I, DL, get(BF::LOAD16fi), DestReg)
258       .addFrameIndex(FI)
259       .addImm(0);
260     return;
261   }
262
263   if (inClass(BF::AnyCCRegClass, DestReg, RC)) {
264     BuildMI(MBB, I, DL, get(BF::LOAD8fi), DestReg)
265       .addFrameIndex(FI)
266       .addImm(0);
267     return;
268   }
269
270   llvm_unreachable("Cannot load regclass from stack slot");
271 }
272
273 void BlackfinInstrInfo::
274 loadRegFromAddr(MachineFunction &MF,
275                 unsigned DestReg,
276                 SmallVectorImpl<MachineOperand> &Addr,
277                 const TargetRegisterClass *RC,
278                 SmallVectorImpl<MachineInstr*> &NewMIs) const {
279   llvm_unreachable("loadRegFromAddr not implemented");
280 }