]> CyberLeo.Net >> Repos - FreeBSD/releng/9.0.git/blob - contrib/llvm/lib/Target/Blackfin/BlackfinRegisterInfo.cpp
Copy stable/9 to releng/9.0 as part of the FreeBSD 9.0-RELEASE release
[FreeBSD/releng/9.0.git] / contrib / llvm / lib / Target / Blackfin / BlackfinRegisterInfo.cpp
1 //===- BlackfinRegisterInfo.cpp - Blackfin Register 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 TargetRegisterInfo
11 // class.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "Blackfin.h"
16 #include "BlackfinRegisterInfo.h"
17 #include "BlackfinSubtarget.h"
18 #include "llvm/Support/Debug.h"
19 #include "llvm/Support/ErrorHandling.h"
20 #include "llvm/CodeGen/MachineInstrBuilder.h"
21 #include "llvm/CodeGen/MachineFunction.h"
22 #include "llvm/CodeGen/MachineFrameInfo.h"
23 #include "llvm/CodeGen/RegisterScavenging.h"
24 #include "llvm/Target/TargetFrameLowering.h"
25 #include "llvm/Target/TargetMachine.h"
26 #include "llvm/Target/TargetOptions.h"
27 #include "llvm/Target/TargetInstrInfo.h"
28 #include "llvm/Type.h"
29 #include "llvm/ADT/BitVector.h"
30 #include "llvm/ADT/STLExtras.h"
31
32 #define GET_REGINFO_TARGET_DESC
33 #include "BlackfinGenRegisterInfo.inc"
34
35 using namespace llvm;
36
37 BlackfinRegisterInfo::BlackfinRegisterInfo(BlackfinSubtarget &st,
38                                            const TargetInstrInfo &tii)
39   : BlackfinGenRegisterInfo(BF::RETS), Subtarget(st), TII(tii) {}
40
41 const unsigned*
42 BlackfinRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
43   using namespace BF;
44   static const unsigned CalleeSavedRegs[] = {
45     FP,
46     R4, R5, R6, R7,
47     P3, P4, P5,
48     0 };
49   return  CalleeSavedRegs;
50 }
51
52 BitVector
53 BlackfinRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
54   const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
55
56   using namespace BF;
57   BitVector Reserved(getNumRegs());
58   Reserved.set(AZ);
59   Reserved.set(AN);
60   Reserved.set(AQ);
61   Reserved.set(AC0);
62   Reserved.set(AC1);
63   Reserved.set(AV0);
64   Reserved.set(AV0S);
65   Reserved.set(AV1);
66   Reserved.set(AV1S);
67   Reserved.set(V);
68   Reserved.set(VS);
69   Reserved.set(CYCLES).set(CYCLES2);
70   Reserved.set(L0);
71   Reserved.set(L1);
72   Reserved.set(L2);
73   Reserved.set(L3);
74   Reserved.set(SP);
75   Reserved.set(RETS);
76   if (TFI->hasFP(MF))
77     Reserved.set(FP);
78   return Reserved;
79 }
80
81 bool BlackfinRegisterInfo::
82 requiresRegisterScavenging(const MachineFunction &MF) const {
83   return true;
84 }
85
86 // Emit instructions to add delta to D/P register. ScratchReg must be of the
87 // same class as Reg (P).
88 void BlackfinRegisterInfo::adjustRegister(MachineBasicBlock &MBB,
89                                           MachineBasicBlock::iterator I,
90                                           DebugLoc DL,
91                                           unsigned Reg,
92                                           unsigned ScratchReg,
93                                           int delta) const {
94   if (!delta)
95     return;
96   if (isInt<7>(delta)) {
97     BuildMI(MBB, I, DL, TII.get(BF::ADDpp_imm7), Reg)
98       .addReg(Reg)              // No kill on two-addr operand
99       .addImm(delta);
100     return;
101   }
102
103   // We must load delta into ScratchReg and add that.
104   loadConstant(MBB, I, DL, ScratchReg, delta);
105   if (BF::PRegClass.contains(Reg)) {
106     assert(BF::PRegClass.contains(ScratchReg) &&
107            "ScratchReg must be a P register");
108     BuildMI(MBB, I, DL, TII.get(BF::ADDpp), Reg)
109       .addReg(Reg, RegState::Kill)
110       .addReg(ScratchReg, RegState::Kill);
111   } else {
112     assert(BF::DRegClass.contains(Reg) && "Reg must be a D or P register");
113     assert(BF::DRegClass.contains(ScratchReg) &&
114            "ScratchReg must be a D register");
115     BuildMI(MBB, I, DL, TII.get(BF::ADD), Reg)
116       .addReg(Reg, RegState::Kill)
117       .addReg(ScratchReg, RegState::Kill);
118   }
119 }
120
121 // Emit instructions to load a constant into D/P register
122 void BlackfinRegisterInfo::loadConstant(MachineBasicBlock &MBB,
123                                         MachineBasicBlock::iterator I,
124                                         DebugLoc DL,
125                                         unsigned Reg,
126                                         int value) const {
127   if (isInt<7>(value)) {
128     BuildMI(MBB, I, DL, TII.get(BF::LOADimm7), Reg).addImm(value);
129     return;
130   }
131
132   if (isUInt<16>(value)) {
133     BuildMI(MBB, I, DL, TII.get(BF::LOADuimm16), Reg).addImm(value);
134     return;
135   }
136
137   if (isInt<16>(value)) {
138     BuildMI(MBB, I, DL, TII.get(BF::LOADimm16), Reg).addImm(value);
139     return;
140   }
141
142   // We must split into halves
143   BuildMI(MBB, I, DL,
144           TII.get(BF::LOAD16i), getSubReg(Reg, BF::hi16))
145     .addImm((value >> 16) & 0xffff)
146     .addReg(Reg, RegState::ImplicitDefine);
147   BuildMI(MBB, I, DL,
148           TII.get(BF::LOAD16i), getSubReg(Reg, BF::lo16))
149     .addImm(value & 0xffff)
150     .addReg(Reg, RegState::ImplicitKill)
151     .addReg(Reg, RegState::ImplicitDefine);
152 }
153
154 void BlackfinRegisterInfo::
155 eliminateCallFramePseudoInstr(MachineFunction &MF,
156                               MachineBasicBlock &MBB,
157                               MachineBasicBlock::iterator I) const {
158   const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
159
160   if (!TFI->hasReservedCallFrame(MF)) {
161     int64_t Amount = I->getOperand(0).getImm();
162     if (Amount != 0) {
163       assert(Amount%4 == 0 && "Unaligned call frame size");
164       if (I->getOpcode() == BF::ADJCALLSTACKDOWN) {
165         adjustRegister(MBB, I, I->getDebugLoc(), BF::SP, BF::P1, -Amount);
166       } else {
167         assert(I->getOpcode() == BF::ADJCALLSTACKUP &&
168                "Unknown call frame pseudo instruction");
169         adjustRegister(MBB, I, I->getDebugLoc(), BF::SP, BF::P1, Amount);
170       }
171     }
172   }
173   MBB.erase(I);
174 }
175
176 /// findScratchRegister - Find a 'free' register. Try for a call-clobbered
177 /// register first and then a spilled callee-saved register if that fails.
178 static unsigned findScratchRegister(MachineBasicBlock::iterator II,
179                                     RegScavenger *RS,
180                                     const TargetRegisterClass *RC,
181                                     int SPAdj) {
182   assert(RS && "Register scavenging must be on");
183   unsigned Reg = RS->FindUnusedReg(RC);
184   if (Reg == 0)
185     Reg = RS->scavengeRegister(RC, II, SPAdj);
186   return Reg;
187 }
188
189 void
190 BlackfinRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
191                                           int SPAdj, RegScavenger *RS) const {
192   MachineInstr &MI = *II;
193   MachineBasicBlock &MBB = *MI.getParent();
194   MachineFunction &MF = *MBB.getParent();
195   const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
196   DebugLoc DL = MI.getDebugLoc();
197
198   unsigned FIPos;
199   for (FIPos=0; !MI.getOperand(FIPos).isFI(); ++FIPos) {
200     assert(FIPos < MI.getNumOperands() &&
201            "Instr doesn't have FrameIndex operand!");
202   }
203   int FrameIndex = MI.getOperand(FIPos).getIndex();
204   assert(FIPos+1 < MI.getNumOperands() && MI.getOperand(FIPos+1).isImm());
205   int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex)
206     + MI.getOperand(FIPos+1).getImm();
207   unsigned BaseReg = BF::FP;
208   if (TFI->hasFP(MF)) {
209     assert(SPAdj==0 && "Unexpected SP adjust in function with frame pointer");
210   } else {
211     BaseReg = BF::SP;
212     Offset += MF.getFrameInfo()->getStackSize() + SPAdj;
213   }
214
215   bool isStore = false;
216
217   switch (MI.getOpcode()) {
218   case BF::STORE32fi:
219     isStore = true;
220   case BF::LOAD32fi: {
221     assert(Offset%4 == 0 && "Unaligned i32 stack access");
222     assert(FIPos==1 && "Bad frame index operand");
223     MI.getOperand(FIPos).ChangeToRegister(BaseReg, false);
224     MI.getOperand(FIPos+1).setImm(Offset);
225     if (isUInt<6>(Offset)) {
226       MI.setDesc(TII.get(isStore
227                          ? BF::STORE32p_uimm6m4
228                          : BF::LOAD32p_uimm6m4));
229       return;
230     }
231     if (BaseReg == BF::FP && isUInt<7>(-Offset)) {
232       MI.setDesc(TII.get(isStore
233                          ? BF::STORE32fp_nimm7m4
234                          : BF::LOAD32fp_nimm7m4));
235       MI.getOperand(FIPos+1).setImm(-Offset);
236       return;
237     }
238     if (isInt<18>(Offset)) {
239       MI.setDesc(TII.get(isStore
240                          ? BF::STORE32p_imm18m4
241                          : BF::LOAD32p_imm18m4));
242       return;
243     }
244     // Use RegScavenger to calculate proper offset...
245     MI.dump();
246     llvm_unreachable("Stack frame offset too big");
247     break;
248   }
249   case BF::ADDpp: {
250     assert(MI.getOperand(0).isReg() && "ADD instruction needs a register");
251     unsigned DestReg = MI.getOperand(0).getReg();
252     // We need to produce a stack offset in a P register. We emit:
253     // P0 = offset;
254     // P0 = BR + P0;
255     assert(FIPos==1 && "Bad frame index operand");
256     loadConstant(MBB, II, DL, DestReg, Offset);
257     MI.getOperand(1).ChangeToRegister(DestReg, false, false, true);
258     MI.getOperand(2).ChangeToRegister(BaseReg, false);
259     break;
260   }
261   case BF::STORE16fi:
262     isStore = true;
263   case BF::LOAD16fi: {
264     assert(Offset%2 == 0 && "Unaligned i16 stack access");
265     assert(FIPos==1 && "Bad frame index operand");
266     // We need a P register to use as an address
267     unsigned ScratchReg = findScratchRegister(II, RS, &BF::PRegClass, SPAdj);
268     assert(ScratchReg && "Could not scavenge register");
269     loadConstant(MBB, II, DL, ScratchReg, Offset);
270     BuildMI(MBB, II, DL, TII.get(BF::ADDpp), ScratchReg)
271       .addReg(ScratchReg, RegState::Kill)
272       .addReg(BaseReg);
273     MI.setDesc(TII.get(isStore ? BF::STORE16pi : BF::LOAD16pi));
274     MI.getOperand(1).ChangeToRegister(ScratchReg, false, false, true);
275     MI.RemoveOperand(2);
276     break;
277   }
278   case BF::STORE8fi: {
279     // This is an AnyCC spill, we need a scratch register.
280     assert(FIPos==1 && "Bad frame index operand");
281     MachineOperand SpillReg = MI.getOperand(0);
282     unsigned ScratchReg = findScratchRegister(II, RS, &BF::DRegClass, SPAdj);
283     assert(ScratchReg && "Could not scavenge register");
284     if (SpillReg.getReg()==BF::NCC) {
285       BuildMI(MBB, II, DL, TII.get(BF::MOVENCC_z), ScratchReg)
286         .addOperand(SpillReg);
287       BuildMI(MBB, II, DL, TII.get(BF::BITTGL), ScratchReg)
288         .addReg(ScratchReg).addImm(0);
289     } else {
290       BuildMI(MBB, II, DL, TII.get(BF::MOVECC_zext), ScratchReg)
291         .addOperand(SpillReg);
292     }
293     // STORE D
294     MI.setDesc(TII.get(BF::STORE8p_imm16));
295     MI.getOperand(0).ChangeToRegister(ScratchReg, false, false, true);
296     MI.getOperand(FIPos).ChangeToRegister(BaseReg, false);
297     MI.getOperand(FIPos+1).setImm(Offset);
298     break;
299   }
300   case BF::LOAD8fi: {
301     // This is an restore, we need a scratch register.
302     assert(FIPos==1 && "Bad frame index operand");
303     MachineOperand SpillReg = MI.getOperand(0);
304     unsigned ScratchReg = findScratchRegister(II, RS, &BF::DRegClass, SPAdj);
305     assert(ScratchReg && "Could not scavenge register");
306     MI.setDesc(TII.get(BF::LOAD32p_imm16_8z));
307     MI.getOperand(0).ChangeToRegister(ScratchReg, true);
308     MI.getOperand(FIPos).ChangeToRegister(BaseReg, false);
309     MI.getOperand(FIPos+1).setImm(Offset);
310     ++II;
311     if (SpillReg.getReg()==BF::CC) {
312       // CC = D
313       BuildMI(MBB, II, DL, TII.get(BF::MOVECC_nz), BF::CC)
314         .addReg(ScratchReg, RegState::Kill);
315     } else {
316       // Restore NCC (CC = D==0)
317       BuildMI(MBB, II, DL, TII.get(BF::SETEQri_not), BF::NCC)
318         .addReg(ScratchReg, RegState::Kill)
319         .addImm(0);
320     }
321     break;
322   }
323   default:
324     llvm_unreachable("Cannot eliminate frame index");
325     break;
326   }
327 }
328
329 unsigned
330 BlackfinRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
331   const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
332
333   return TFI->hasFP(MF) ? BF::FP : BF::SP;
334 }
335
336 unsigned BlackfinRegisterInfo::getEHExceptionRegister() const {
337   llvm_unreachable("What is the exception register");
338   return 0;
339 }
340
341 unsigned BlackfinRegisterInfo::getEHHandlerRegister() const {
342   llvm_unreachable("What is the exception handler register");
343   return 0;
344 }