implement load effective address similar to the alpha backend
[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/ADT/STLExtras.h"
26 #include <iostream>
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 ARMRegisterInfo::ARMRegisterInfo()
39   : ARMGenRegisterInfo(ARM::ADJCALLSTACKDOWN, ARM::ADJCALLSTACKUP) {
40 }
41
42 void ARMRegisterInfo::
43 storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
44                     unsigned SrcReg, int FI,
45                     const TargetRegisterClass *RC) const {
46   assert (RC == ARM::IntRegsRegisterClass);
47   BuildMI(MBB, I, ARM::STR, 3).addReg(SrcReg).addFrameIndex(FI).addImm(0);
48 }
49
50 void ARMRegisterInfo::
51 loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
52                      unsigned DestReg, int FI,
53                      const TargetRegisterClass *RC) const {
54   assert (RC == ARM::IntRegsRegisterClass);
55   BuildMI(MBB, I, ARM::LDR, 2, DestReg).addFrameIndex(FI).addImm(0);
56 }
57
58 void ARMRegisterInfo::copyRegToReg(MachineBasicBlock &MBB,
59                                      MachineBasicBlock::iterator I,
60                                      unsigned DestReg, unsigned SrcReg,
61                                      const TargetRegisterClass *RC) const {
62   assert(RC == ARM::IntRegsRegisterClass ||
63          RC == ARM::FPRegsRegisterClass  ||
64          RC == ARM::DFPRegsRegisterClass);
65
66   if (RC == ARM::IntRegsRegisterClass)
67     BuildMI(MBB, I, ARM::MOV, 3, DestReg).addReg(SrcReg).addImm(0)
68       .addImm(ARMShift::LSL);
69   else if (RC == ARM::FPRegsRegisterClass)
70     BuildMI(MBB, I, ARM::FCPYS, 1, DestReg).addReg(SrcReg);
71   else
72     BuildMI(MBB, I, ARM::FCPYD, 1, DestReg).addReg(SrcReg);
73 }
74
75 MachineInstr *ARMRegisterInfo::foldMemoryOperand(MachineInstr* MI,
76                                                    unsigned OpNum,
77                                                    int FI) const {
78   return NULL;
79 }
80
81 const unsigned* ARMRegisterInfo::getCalleeSaveRegs() const {
82   static const unsigned CalleeSaveRegs[] = {
83     ARM::R4,  ARM::R5, ARM::R6,  ARM::R7,
84     ARM::R8,  ARM::R9, ARM::R10, ARM::R11,
85     ARM::R14, 0
86   };
87   return CalleeSaveRegs;
88 }
89
90 const TargetRegisterClass* const *
91 ARMRegisterInfo::getCalleeSaveRegClasses() const {
92   static const TargetRegisterClass * const CalleeSaveRegClasses[] = {
93     &ARM::IntRegsRegClass, &ARM::IntRegsRegClass, &ARM::IntRegsRegClass, &ARM::IntRegsRegClass,
94     &ARM::IntRegsRegClass, &ARM::IntRegsRegClass, &ARM::IntRegsRegClass, &ARM::IntRegsRegClass,
95     &ARM::IntRegsRegClass, 0
96   };
97   return CalleeSaveRegClasses;
98 }
99
100 void ARMRegisterInfo::
101 eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
102                               MachineBasicBlock::iterator I) const {
103   if (hasFP(MF)) {
104     MachineInstr *Old = I;
105     unsigned Amount = Old->getOperand(0).getImmedValue();
106     if (Amount != 0) {
107       unsigned Align = MF.getTarget().getFrameInfo()->getStackAlignment();
108       Amount = (Amount+Align-1)/Align*Align;
109
110       if (Old->getOpcode() == ARM::ADJCALLSTACKDOWN) {
111         // sub sp, sp, amount
112         BuildMI(MBB, I, ARM::SUB, 2, ARM::R13).addReg(ARM::R13).addImm(Amount)
113           .addImm(0).addImm(ARMShift::LSL);
114       } else {
115         // add sp, sp, amount
116         assert(Old->getOpcode() == ARM::ADJCALLSTACKUP);
117         BuildMI(MBB, I, ARM::ADD, 2, ARM::R13).addReg(ARM::R13).addImm(Amount)
118           .addImm(0).addImm(ARMShift::LSL);
119       }
120     }
121   }
122   MBB.erase(I);
123 }
124
125 void
126 ARMRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II) const {
127   MachineInstr &MI = *II;
128   MachineBasicBlock &MBB = *MI.getParent();
129   MachineFunction &MF = *MBB.getParent();
130
131   assert (MI.getOpcode() == ARM::LDR ||
132           MI.getOpcode() == ARM::STR ||
133           MI.getOpcode() == ARM::ADD);
134
135   unsigned FrameIdx = 1;
136   unsigned   OffIdx = 2;
137
138   int FrameIndex = MI.getOperand(FrameIdx).getFrameIndex();
139
140   int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex) +
141                MI.getOperand(OffIdx).getImmedValue();
142
143   unsigned StackSize = MF.getFrameInfo()->getStackSize();
144
145   Offset += StackSize;
146
147   assert (Offset >= 0);
148   unsigned BaseRegister = hasFP(MF) ? ARM::R11 : ARM::R13;
149   if (Offset < 4096) {
150     // Replace the FrameIndex with r13
151     MI.getOperand(FrameIdx).ChangeToRegister(BaseRegister, false);
152     // Replace the ldr offset with Offset
153     MI.getOperand(OffIdx).ChangeToImmediate(Offset);
154   } else {
155     // Insert a set of r12 with the full address
156     // r12 = r13 + offset
157     MachineBasicBlock *MBB2 = MI.getParent();
158     BuildMI(*MBB2, II, ARM::ADD, 4, ARM::R12).addReg(BaseRegister)
159       .addImm(Offset).addImm(0).addImm(ARMShift::LSL);
160
161     // Replace the FrameIndex with r12
162     MI.getOperand(FrameIdx).ChangeToRegister(ARM::R12, false);
163   }
164 }
165
166 void ARMRegisterInfo::
167 processFunctionBeforeFrameFinalized(MachineFunction &MF) const {}
168
169 void ARMRegisterInfo::emitPrologue(MachineFunction &MF) const {
170   MachineBasicBlock &MBB = MF.front();
171   MachineBasicBlock::iterator MBBI = MBB.begin();
172   MachineFrameInfo  *MFI = MF.getFrameInfo();
173   int           NumBytes = (int) MFI->getStackSize();
174
175   bool HasFP = hasFP(MF);
176
177   if (MFI->hasCalls()) {
178     // We reserve argument space for call sites in the function immediately on
179     // entry to the current function.  This eliminates the need for add/sub
180     // brackets around call sites.
181     NumBytes += MFI->getMaxCallFrameSize();
182   }
183
184   if (HasFP)
185     // Add space for storing the FP
186     NumBytes += 4;
187
188   // Align to 8 bytes
189   NumBytes = ((NumBytes + 7) / 8) * 8;
190
191   MFI->setStackSize(NumBytes);
192
193   //sub sp, sp, #NumBytes
194   BuildMI(MBB, MBBI, ARM::SUB, 4, ARM::R13).addReg(ARM::R13).addImm(NumBytes)
195           .addImm(0).addImm(ARMShift::LSL);
196
197   if (HasFP) {
198     BuildMI(MBB, MBBI, ARM::STR, 3)
199       .addReg(ARM::R11).addReg(ARM::R13).addImm(0);
200     BuildMI(MBB, MBBI, ARM::MOV, 3, ARM::R11).addReg(ARM::R13).addImm(0).
201       addImm(ARMShift::LSL);
202   }
203 }
204
205 void ARMRegisterInfo::emitEpilogue(MachineFunction &MF,
206                                    MachineBasicBlock &MBB) const {
207   MachineBasicBlock::iterator MBBI = prior(MBB.end());
208   assert(MBBI->getOpcode() == ARM::bx &&
209          "Can only insert epilog into returning blocks");
210
211   MachineFrameInfo *MFI = MF.getFrameInfo();
212   int          NumBytes = (int) MFI->getStackSize();
213
214   if (hasFP(MF)) {
215     BuildMI(MBB, MBBI, ARM::MOV, 3, ARM::R13).addReg(ARM::R11).addImm(0).
216       addImm(ARMShift::LSL);
217     BuildMI(MBB, MBBI, ARM::LDR, 2, ARM::R11).addReg(ARM::R13).addImm(0);
218   }
219
220   //add sp, sp, #NumBytes
221   BuildMI(MBB, MBBI, ARM::ADD, 4, ARM::R13).addReg(ARM::R13).addImm(NumBytes)
222           .addImm(0).addImm(ARMShift::LSL);
223 }
224
225 unsigned ARMRegisterInfo::getRARegister() const {
226   return ARM::R14;
227 }
228
229 unsigned ARMRegisterInfo::getFrameRegister(MachineFunction &MF) const {
230   return hasFP(MF) ? ARM::R11 : ARM::R13;
231 }
232
233 #include "ARMGenRegisterInfo.inc"
234