73fd7a4899de8fdce0a7f1a4e9e561d691daa91d
[oota-llvm.git] / lib / Target / ARM / ARMRegisterInfo.cpp
1 //===- ARMRegisterInfo.cpp - ARM Register Information -----------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file was developed by the "Instituto Nokia de Tecnologia" and
6 // is distributed under the University of Illinois Open Source
7 // License. See LICENSE.TXT for details.
8 //
9 //===----------------------------------------------------------------------===//
10 //
11 // This file contains the ARM implementation of the MRegisterInfo class.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "ARM.h"
16 #include "ARMRegisterInfo.h"
17 #include "llvm/CodeGen/MachineInstrBuilder.h"
18 #include "llvm/CodeGen/MachineFunction.h"
19 #include "llvm/CodeGen/MachineFrameInfo.h"
20 #include "llvm/CodeGen/MachineLocation.h"
21 #include "llvm/Type.h"
22 #include "llvm/Target/TargetFrameInfo.h"
23 #include "llvm/Target/TargetMachine.h"
24 #include "llvm/Target/TargetOptions.h"
25 #include "llvm/Target/TargetInstrInfo.h"
26 #include "llvm/ADT/STLExtras.h"
27 using namespace llvm;
28
29 // hasFP - Return true if the specified function should have a dedicated frame
30 // pointer register.  This is true if the function has variable sized allocas or
31 // if frame pointer elimination is disabled.
32 //
33 static bool hasFP(const MachineFunction &MF) {
34   const MachineFrameInfo *MFI = MF.getFrameInfo();
35   return NoFramePointerElim || MFI->hasVarSizedObjects();
36 }
37
38 static inline unsigned rotateL(unsigned x, unsigned n){
39   return ((x << n) | (x  >> (32 - n)));
40 }
41
42 static inline unsigned rotateR(unsigned x, unsigned n){
43   return ((x >> n) | (x  << (32 - n)));
44 }
45
46 // finds the end position of largest sequence of zeros in binary representation
47 // of 'immediate'.
48 static int findLargestZeroSequence(unsigned immediate){
49   int max_zero_pos;
50   int max_zero_length = 0;
51   int zero_pos;
52   int zero_length;
53   int pos = 0;
54   int end_pos;
55
56   while ((immediate & 0x3) == 0) {
57     immediate = rotateR(immediate, 2);
58     pos+=2;
59   }
60   end_pos = pos+32;
61
62   while (pos<end_pos){
63     while ((immediate & 0x3) != 0) {
64       immediate = rotateR(immediate, 2);
65       pos+=2;
66     }
67     zero_pos = pos;
68     while ((immediate & 0x3) == 0) {
69       immediate = rotateR(immediate, 2);
70       pos+=2;
71     }
72     zero_length = pos - zero_pos;
73     if (zero_length > max_zero_length){
74       max_zero_length = zero_length;
75       max_zero_pos = zero_pos % 32;
76     }
77
78   }
79
80   return (max_zero_pos + max_zero_length) % 32;
81 }
82
83 static void splitInstructionWithImmediate(MachineBasicBlock &BB,
84                                        MachineBasicBlock::iterator I,
85                                        const TargetInstrDescriptor &TID,
86                                        unsigned DestReg,
87                                        unsigned OrigReg,
88                                        unsigned immediate){
89
90   if (immediate == 0){
91     BuildMI(BB, I, TID, DestReg).addReg(OrigReg).addImm(0)
92         .addImm(0).addImm(ARMShift::LSL);
93     return;
94   }
95
96   int start_pos = findLargestZeroSequence(immediate);
97   unsigned immediate_tmp = rotateR(immediate, start_pos);
98
99   int pos = 0;
100   while (pos < 32){
101     while(((immediate_tmp&0x3) == 0)&&(pos<32)){
102       immediate_tmp = rotateR(immediate_tmp,2);
103       pos+=2;
104     }
105     if (pos < 32){
106       BuildMI(BB, I, TID, DestReg).addReg(OrigReg)
107         .addImm(rotateL(immediate_tmp&0xFF, (start_pos + pos) % 32 ))
108         .addImm(0).addImm(ARMShift::LSL);
109       immediate_tmp = rotateR(immediate_tmp,8);
110       pos+=8;
111     }
112   }
113
114 }
115
116 ARMRegisterInfo::ARMRegisterInfo(const TargetInstrInfo &tii)
117   : ARMGenRegisterInfo(ARM::ADJCALLSTACKDOWN, ARM::ADJCALLSTACKUP),
118     TII(tii) {
119 }
120
121 void ARMRegisterInfo::
122 storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
123                     unsigned SrcReg, int FI,
124                     const TargetRegisterClass *RC) const {
125   assert (RC == ARM::IntRegsRegisterClass);
126   BuildMI(MBB, I, TII.get(ARM::STR)).addReg(SrcReg).addFrameIndex(FI).addImm(0);
127 }
128
129 void ARMRegisterInfo::
130 loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
131                      unsigned DestReg, int FI,
132                      const TargetRegisterClass *RC) const {
133   assert (RC == ARM::IntRegsRegisterClass);
134   BuildMI(MBB, I, TII.get(ARM::LDR), DestReg).addFrameIndex(FI).addImm(0);
135 }
136
137 void ARMRegisterInfo::copyRegToReg(MachineBasicBlock &MBB,
138                                      MachineBasicBlock::iterator I,
139                                      unsigned DestReg, unsigned SrcReg,
140                                      const TargetRegisterClass *RC) const {
141   assert(RC == ARM::IntRegsRegisterClass ||
142          RC == ARM::FPRegsRegisterClass  ||
143          RC == ARM::DFPRegsRegisterClass);
144
145   if (RC == ARM::IntRegsRegisterClass)
146     BuildMI(MBB, I, TII.get(ARM::MOV), DestReg).addReg(SrcReg).addImm(0)
147       .addImm(ARMShift::LSL);
148   else if (RC == ARM::FPRegsRegisterClass)
149     BuildMI(MBB, I, TII.get(ARM::FCPYS), DestReg).addReg(SrcReg);
150   else
151     BuildMI(MBB, I, TII.get(ARM::FCPYD), DestReg).addReg(SrcReg);
152 }
153
154 MachineInstr *ARMRegisterInfo::foldMemoryOperand(MachineInstr* MI,
155                                                    unsigned OpNum,
156                                                    int FI) const {
157   return NULL;
158 }
159
160 const unsigned* ARMRegisterInfo::getCalleeSaveRegs() const {
161   static const unsigned CalleeSaveRegs[] = {
162     ARM::R4,  ARM::R5, ARM::R6,  ARM::R7,
163     ARM::R8,  ARM::R9, ARM::R10, ARM::R11,
164     ARM::R14, 0
165   };
166   return CalleeSaveRegs;
167 }
168
169 const TargetRegisterClass* const *
170 ARMRegisterInfo::getCalleeSaveRegClasses() const {
171   static const TargetRegisterClass * const CalleeSaveRegClasses[] = {
172     &ARM::IntRegsRegClass, &ARM::IntRegsRegClass, &ARM::IntRegsRegClass, &ARM::IntRegsRegClass,
173     &ARM::IntRegsRegClass, &ARM::IntRegsRegClass, &ARM::IntRegsRegClass, &ARM::IntRegsRegClass,
174     &ARM::IntRegsRegClass, 0
175   };
176   return CalleeSaveRegClasses;
177 }
178
179 void ARMRegisterInfo::
180 eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
181                               MachineBasicBlock::iterator I) const {
182   if (hasFP(MF)) {
183     MachineInstr *Old = I;
184     unsigned Amount = Old->getOperand(0).getImmedValue();
185     if (Amount != 0) {
186       unsigned Align = MF.getTarget().getFrameInfo()->getStackAlignment();
187       Amount = (Amount+Align-1)/Align*Align;
188
189       if (Old->getOpcode() == ARM::ADJCALLSTACKDOWN) {
190         // sub sp, sp, amount
191         splitInstructionWithImmediate(MBB, I, TII.get(ARM::SUB), ARM::R13,
192                                    ARM::R13, Amount);
193       } else {
194         // add sp, sp, amount
195         assert(Old->getOpcode() == ARM::ADJCALLSTACKUP);
196         splitInstructionWithImmediate(MBB, I, TII.get(ARM::ADD), ARM::R13,
197                                    ARM::R13, Amount);
198       }
199     }
200   }
201   MBB.erase(I);
202 }
203
204 void
205 ARMRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II) const {
206   MachineInstr &MI = *II;
207   MachineBasicBlock &MBB = *MI.getParent();
208   MachineFunction &MF = *MBB.getParent();
209
210   assert (MI.getOpcode() == ARM::LDR ||
211           MI.getOpcode() == ARM::STR ||
212           MI.getOpcode() == ARM::ADD);
213
214   unsigned FrameIdx = 1;
215   unsigned   OffIdx = 2;
216
217   int FrameIndex = MI.getOperand(FrameIdx).getFrameIndex();
218
219   int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex) +
220                MI.getOperand(OffIdx).getImmedValue();
221
222   unsigned StackSize = MF.getFrameInfo()->getStackSize();
223
224   Offset += StackSize;
225
226   assert (Offset >= 0);
227   unsigned BaseRegister = hasFP(MF) ? ARM::R11 : ARM::R13;
228   if (Offset < 4096) {
229     // Replace the FrameIndex with r13
230     MI.getOperand(FrameIdx).ChangeToRegister(BaseRegister, false);
231     // Replace the ldr offset with Offset
232     MI.getOperand(OffIdx).ChangeToImmediate(Offset);
233   } else {
234     // Insert a set of r12 with the full address
235     // r12 = r13 + offset
236     MachineBasicBlock *MBB2 = MI.getParent();
237     splitInstructionWithImmediate(*MBB2, II, TII.get(ARM::ADD), ARM::R12,
238                                BaseRegister, Offset);
239
240     // Replace the FrameIndex with r12
241     MI.getOperand(FrameIdx).ChangeToRegister(ARM::R12, false);
242   }
243 }
244
245 void ARMRegisterInfo::
246 processFunctionBeforeFrameFinalized(MachineFunction &MF) const {}
247
248 void ARMRegisterInfo::emitPrologue(MachineFunction &MF) const {
249   MachineBasicBlock &MBB = MF.front();
250   MachineBasicBlock::iterator MBBI = MBB.begin();
251   MachineFrameInfo  *MFI = MF.getFrameInfo();
252   int           NumBytes = (int) MFI->getStackSize();
253
254   bool HasFP = hasFP(MF);
255
256   if (MFI->hasCalls()) {
257     // We reserve argument space for call sites in the function immediately on
258     // entry to the current function.  This eliminates the need for add/sub
259     // brackets around call sites.
260     NumBytes += MFI->getMaxCallFrameSize();
261   }
262
263   if (HasFP)
264     // Add space for storing the FP
265     NumBytes += 4;
266
267   // Align to 8 bytes
268   NumBytes = ((NumBytes + 7) / 8) * 8;
269
270   MFI->setStackSize(NumBytes);
271
272   //sub sp, sp, #NumBytes
273   splitInstructionWithImmediate(MBB, MBBI, TII.get(ARM::SUB), ARM::R13,
274                              ARM::R13, NumBytes);
275
276
277   if (HasFP) {
278     BuildMI(MBB, MBBI, TII.get(ARM::STR))
279       .addReg(ARM::R11).addReg(ARM::R13).addImm(0);
280     BuildMI(MBB, MBBI, TII.get(ARM::MOV), ARM::R11).addReg(ARM::R13).addImm(0).
281       addImm(ARMShift::LSL);
282   }
283 }
284
285 void ARMRegisterInfo::emitEpilogue(MachineFunction &MF,
286                                    MachineBasicBlock &MBB) const {
287   MachineBasicBlock::iterator MBBI = prior(MBB.end());
288   assert(MBBI->getOpcode() == ARM::bx &&
289          "Can only insert epilog into returning blocks");
290
291   MachineFrameInfo *MFI = MF.getFrameInfo();
292   int          NumBytes = (int) MFI->getStackSize();
293
294   if (hasFP(MF)) {
295     BuildMI(MBB, MBBI, TII.get(ARM::MOV), ARM::R13).addReg(ARM::R11).addImm(0).
296       addImm(ARMShift::LSL);
297     BuildMI(MBB, MBBI, TII.get(ARM::LDR), ARM::R11).addReg(ARM::R13).addImm(0);
298   }
299
300   //add sp, sp, #NumBytes
301   splitInstructionWithImmediate(MBB, MBBI, TII.get(ARM::ADD), ARM::R13,
302                              ARM::R13, NumBytes);
303
304 }
305
306 unsigned ARMRegisterInfo::getRARegister() const {
307   return ARM::R14;
308 }
309
310 unsigned ARMRegisterInfo::getFrameRegister(MachineFunction &MF) const {
311   return hasFP(MF) ? ARM::R11 : ARM::R13;
312 }
313
314 #include "ARMGenRegisterInfo.inc"
315