summaryrefslogtreecommitdiffstats
path: root/lib/Target/PowerPC/PPCFrameInfo.h
blob: 65f113e6fb9aff31490282eb820efd225acea542 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
//===-- PPCFrameInfo.h - Define TargetFrameInfo for PowerPC -----*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//
//===----------------------------------------------------------------------===//

#ifndef POWERPC_FRAMEINFO_H
#define POWERPC_FRAMEINFO_H

#include "PPC.h"
#include "PPCSubtarget.h"
#include "llvm/Target/TargetFrameInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/ADT/STLExtras.h"

namespace llvm {

class PPCFrameInfo: public TargetFrameInfo {
  const TargetMachine &TM;

public:
  PPCFrameInfo(const TargetMachine &tm, bool LP64)
    : TargetFrameInfo(TargetFrameInfo::StackGrowsDown, 16, 0), TM(tm) {
  }

  /// getReturnSaveOffset - Return the previous frame offset to save the
  /// return address.
  static unsigned getReturnSaveOffset(bool isPPC64, bool isDarwinABI) {
    if (isDarwinABI)
      return isPPC64 ? 16 : 8;
    // SVR4 ABI:
    return isPPC64 ? 16 : 4;
  }

  /// getFramePointerSaveOffset - Return the previous frame offset to save the
  /// frame pointer.
  static unsigned getFramePointerSaveOffset(bool isPPC64, bool isDarwinABI) {
    // For the Darwin ABI:
    // Use the TOC save slot in the PowerPC linkage area for saving the frame
    // pointer (if needed.)  LLVM does not generate code that uses the TOC (R2
    // is treated as a caller saved register.)
    if (isDarwinABI)
      return isPPC64 ? 40 : 20;
    
    // SVR4 ABI: First slot in the general register save area.
    return -4U;
  }
  
  /// getLinkageSize - Return the size of the PowerPC ABI linkage area.
  ///
  static unsigned getLinkageSize(bool isPPC64, bool isDarwinABI) {
    if (isDarwinABI || isPPC64)
      return 6 * (isPPC64 ? 8 : 4);
    
    // SVR4 ABI:
    return 8;
  }

  /// getMinCallArgumentsSize - Return the size of the minium PowerPC ABI
  /// argument area.
  static unsigned getMinCallArgumentsSize(bool isPPC64, bool isDarwinABI) {
    // For the Darwin ABI / 64-bit SVR4 ABI:
    // The prolog code of the callee may store up to 8 GPR argument registers to
    // the stack, allowing va_start to index over them in memory if its varargs.
    // Because we cannot tell if this is needed on the caller side, we have to
    // conservatively assume that it is needed.  As such, make sure we have at
    // least enough stack space for the caller to store the 8 GPRs.
    if (isDarwinABI || isPPC64)
      return 8 * (isPPC64 ? 8 : 4);
    
    // 32-bit SVR4 ABI:
    // There is no default stack allocated for the 8 first GPR arguments.
    return 0;
  }

  /// getMinCallFrameSize - Return the minimum size a call frame can be using
  /// the PowerPC ABI.
  static unsigned getMinCallFrameSize(bool isPPC64, bool isDarwinABI) {
    // The call frame needs to be at least big enough for linkage and 8 args.
    return getLinkageSize(isPPC64, isDarwinABI) +
           getMinCallArgumentsSize(isPPC64, isDarwinABI);
  }

  // With the SVR4 ABI, callee-saved registers have fixed offsets on the stack.
  const SpillSlot *
  getCalleeSavedSpillSlots(unsigned &NumEntries) const {
    // Early exit if not using the SVR4 ABI.
    if (!TM.getSubtarget<PPCSubtarget>().isSVR4ABI()) {
      NumEntries = 0;
      return 0;
    }

    static const SpillSlot Offsets[] = {
      // Floating-point register save area offsets.
      {PPC::F31, -8},
      {PPC::F30, -16},
      {PPC::F29, -24},
      {PPC::F28, -32},
      {PPC::F27, -40},
      {PPC::F26, -48},
      {PPC::F25, -56},
      {PPC::F24, -64},
      {PPC::F23, -72},
      {PPC::F22, -80},
      {PPC::F21, -88},
      {PPC::F20, -96},
      {PPC::F19, -104},
      {PPC::F18, -112},
      {PPC::F17, -120},
      {PPC::F16, -128},
      {PPC::F15, -136},
      {PPC::F14, -144},

      // General register save area offsets.
      {PPC::R31, -4},
      {PPC::R30, -8},
      {PPC::R29, -12},
      {PPC::R28, -16},
      {PPC::R27, -20},
      {PPC::R26, -24},
      {PPC::R25, -28},
      {PPC::R24, -32},
      {PPC::R23, -36},
      {PPC::R22, -40},
      {PPC::R21, -44},
      {PPC::R20, -48},
      {PPC::R19, -52},
      {PPC::R18, -56},
      {PPC::R17, -60},
      {PPC::R16, -64},
      {PPC::R15, -68},
      {PPC::R14, -72},

      // CR save area offset.
      // FIXME SVR4: Disable CR save area for now.
//      {PPC::CR2, -4},
//      {PPC::CR3, -4},
//      {PPC::CR4, -4},
//      {PPC::CR2LT, -4},
//      {PPC::CR2GT, -4},
//      {PPC::CR2EQ, -4},
//      {PPC::CR2UN, -4},
//      {PPC::CR3LT, -4},
//      {PPC::CR3GT, -4},
//      {PPC::CR3EQ, -4},
//      {PPC::CR3UN, -4},
//      {PPC::CR4LT, -4},
//      {PPC::CR4GT, -4},
//      {PPC::CR4EQ, -4},
//      {PPC::CR4UN, -4},

      // VRSAVE save area offset.
      {PPC::VRSAVE, -4},

      // Vector register save area
      {PPC::V31, -16},
      {PPC::V30, -32},
      {PPC::V29, -48},
      {PPC::V28, -64},
      {PPC::V27, -80},
      {PPC::V26, -96},
      {PPC::V25, -112},
      {PPC::V24, -128},
      {PPC::V23, -144},
      {PPC::V22, -160},
      {PPC::V21, -176},
      {PPC::V20, -192}
    };

    static const SpillSlot Offsets64[] = {
      // Floating-point register save area offsets.
      {PPC::F31, -8},
      {PPC::F30, -16},
      {PPC::F29, -24},
      {PPC::F28, -32},
      {PPC::F27, -40},
      {PPC::F26, -48},
      {PPC::F25, -56},
      {PPC::F24, -64},
      {PPC::F23, -72},
      {PPC::F22, -80},
      {PPC::F21, -88},
      {PPC::F20, -96},
      {PPC::F19, -104},
      {PPC::F18, -112},
      {PPC::F17, -120},
      {PPC::F16, -128},
      {PPC::F15, -136},
      {PPC::F14, -144},

      // General register save area offsets.
      // FIXME 64-bit SVR4: Are 32-bit registers actually allocated in 64-bit
      //                    mode?
      {PPC::R31, -4},
      {PPC::R30, -12},
      {PPC::R29, -20},
      {PPC::R28, -28},
      {PPC::R27, -36},
      {PPC::R26, -44},
      {PPC::R25, -52},
      {PPC::R24, -60},
      {PPC::R23, -68},
      {PPC::R22, -76},
      {PPC::R21, -84},
      {PPC::R20, -92},
      {PPC::R19, -100},
      {PPC::R18, -108},
      {PPC::R17, -116},
      {PPC::R16, -124},
      {PPC::R15, -132},
      {PPC::R14, -140},

      {PPC::X31, -8},
      {PPC::X30, -16},
      {PPC::X29, -24},
      {PPC::X28, -32},
      {PPC::X27, -40},
      {PPC::X26, -48},
      {PPC::X25, -56},
      {PPC::X24, -64},
      {PPC::X23, -72},
      {PPC::X22, -80},
      {PPC::X21, -88},
      {PPC::X20, -96},
      {PPC::X19, -104},
      {PPC::X18, -112},
      {PPC::X17, -120},
      {PPC::X16, -128},
      {PPC::X15, -136},
      {PPC::X14, -144},

      // CR save area offset.
      // FIXME SVR4: Disable CR save area for now.
//      {PPC::CR2, -4},
//      {PPC::CR3, -4},
//      {PPC::CR4, -4},
//      {PPC::CR2LT, -4},
//      {PPC::CR2GT, -4},
//      {PPC::CR2EQ, -4},
//      {PPC::CR2UN, -4},
//      {PPC::CR3LT, -4},
//      {PPC::CR3GT, -4},
//      {PPC::CR3EQ, -4},
//      {PPC::CR3UN, -4},
//      {PPC::CR4LT, -4},
//      {PPC::CR4GT, -4},
//      {PPC::CR4EQ, -4},
//      {PPC::CR4UN, -4},

      // VRSAVE save area offset.
      {PPC::VRSAVE, -4},

      // Vector register save area
      {PPC::V31, -16},
      {PPC::V30, -32},
      {PPC::V29, -48},
      {PPC::V28, -64},
      {PPC::V27, -80},
      {PPC::V26, -96},
      {PPC::V25, -112},
      {PPC::V24, -128},
      {PPC::V23, -144},
      {PPC::V22, -160},
      {PPC::V21, -176},
      {PPC::V20, -192}
    };

    if (TM.getSubtarget<PPCSubtarget>().isPPC64()) {
      NumEntries = array_lengthof(Offsets64);

      return Offsets64;
    } else {
      NumEntries = array_lengthof(Offsets);

      return Offsets;
    }
  }
};

} // End llvm namespace

#endif
OpenPOWER on IntegriCloud