Update copyright notices with scripts/update-copyrights
[jlayton/glibc.git] / sysdeps / powerpc / powerpc64 / sysdep.h
1 /* Assembly macros for 64-bit PowerPC.
2    Copyright (C) 2002-2014 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <http://www.gnu.org/licenses/>.  */
18
19 #include <sysdeps/powerpc/sysdep.h>
20
21 #ifdef __ASSEMBLER__
22
23 /* Stack frame offsets.  */
24 #if _CALL_ELF != 2
25 #define FRAME_MIN_SIZE          112
26 #define FRAME_MIN_SIZE_PARM     112
27 #define FRAME_BACKCHAIN         0
28 #define FRAME_CR_SAVE           8
29 #define FRAME_LR_SAVE           16
30 #define FRAME_TOC_SAVE          40
31 #define FRAME_PARM_SAVE         48
32 #define FRAME_PARM1_SAVE        48
33 #define FRAME_PARM2_SAVE        56
34 #define FRAME_PARM3_SAVE        64
35 #define FRAME_PARM4_SAVE        72
36 #define FRAME_PARM5_SAVE        80
37 #define FRAME_PARM6_SAVE        88
38 #define FRAME_PARM7_SAVE        96
39 #define FRAME_PARM8_SAVE        104
40 #define FRAME_PARM9_SAVE        112
41 #else
42 #define FRAME_MIN_SIZE          32
43 #define FRAME_MIN_SIZE_PARM     96
44 #define FRAME_BACKCHAIN         0
45 #define FRAME_CR_SAVE           8
46 #define FRAME_LR_SAVE           16
47 #define FRAME_TOC_SAVE          24
48 #define FRAME_PARM_SAVE         32
49 #define FRAME_PARM1_SAVE        32
50 #define FRAME_PARM2_SAVE        40
51 #define FRAME_PARM3_SAVE        48
52 #define FRAME_PARM4_SAVE        56
53 #define FRAME_PARM5_SAVE        64
54 #define FRAME_PARM6_SAVE        72
55 #define FRAME_PARM7_SAVE        80
56 #define FRAME_PARM8_SAVE        88
57 #define FRAME_PARM9_SAVE        96
58 #endif
59
60 /* Support macros for CALL_MCOUNT.  */
61 #if _CALL_ELF == 2
62 #define call_mcount_parm_offset (-64)
63 #else
64 #define call_mcount_parm_offset FRAME_PARM_SAVE
65 #endif
66         .macro SAVE_ARG NARG
67         .if \NARG
68         SAVE_ARG \NARG-1
69         std     2+\NARG,call_mcount_parm_offset-8+8*(\NARG)(1)
70         .endif
71         .endm
72
73         .macro REST_ARG NARG
74         .if \NARG
75         REST_ARG \NARG-1
76         ld      2+\NARG,FRAME_MIN_SIZE_PARM+call_mcount_parm_offset-8+8*(\NARG)(1)
77         .endif
78         .endm
79
80         .macro CFI_SAVE_ARG NARG
81         .if \NARG
82         CFI_SAVE_ARG \NARG-1
83         cfi_offset(2+\NARG,call_mcount_parm_offset-8+8*(\NARG))
84         .endif
85         .endm
86
87         .macro CFI_REST_ARG NARG
88         .if \NARG
89         CFI_REST_ARG \NARG-1
90         cfi_restore(2+\NARG)
91         .endif
92         .endm
93
94 /* If compiled for profiling, call `_mcount' at the start of each function.
95    see ppc-mcount.S for more details.  */
96         .macro CALL_MCOUNT NARG
97 #ifdef  PROF
98         mflr    r0
99         SAVE_ARG \NARG
100         std     r0,FRAME_LR_SAVE(r1)
101         stdu    r1,-FRAME_MIN_SIZE_PARM(r1)
102         cfi_adjust_cfa_offset(FRAME_MIN_SIZE_PARM)
103         cfi_offset(lr,FRAME_LR_SAVE)
104         CFI_SAVE_ARG \NARG
105         bl      JUMPTARGET (_mcount)
106 #ifndef SHARED
107         nop
108 #endif
109         ld      r0,FRAME_MIN_SIZE_PARM+FRAME_LR_SAVE(r1)
110         REST_ARG \NARG
111         mtlr    r0
112         addi    r1,r1,FRAME_MIN_SIZE_PARM
113         cfi_adjust_cfa_offset(-FRAME_MIN_SIZE_PARM)
114         cfi_restore(lr)
115         CFI_REST_ARG \NARG
116 #endif
117         .endm
118
119 #if _CALL_ELF != 2
120
121 /* Macro to prepare for calling via a function pointer.  */
122         .macro PPC64_LOAD_FUNCPTR PTR
123         ld      r12,0(\PTR)
124         ld      r2,8(\PTR)
125         mtctr   r12
126         ld      r11,16(\PTR)
127         .endm
128
129 #ifdef USE_PPC64_OVERLAPPING_OPD
130 # define OPD_ENT(name)  .quad BODY_LABEL (name), .TOC.@tocbase
131 #else
132 # define OPD_ENT(name)  .quad BODY_LABEL (name), .TOC.@tocbase, 0
133 #endif
134
135 #define ENTRY_1(name)   \
136         .type BODY_LABEL(name),@function;       \
137         .globl name;                            \
138         .section ".opd","aw";                   \
139         .align 3;                               \
140 name##: OPD_ENT (name);                         \
141         .previous;
142
143 #ifdef HAVE_ASM_GLOBAL_DOT_NAME
144 # define DOT_LABEL(X) .##X
145 # define BODY_LABEL(X) .##X
146 # define ENTRY_2(name)  \
147         .globl BODY_LABEL(name);                \
148         ENTRY_1(name)                           \
149         .size name, 24;
150 # define END_2(name)    \
151         .size BODY_LABEL(name),.-BODY_LABEL(name);
152 #else
153 # define DOT_LABEL(X) X
154 # define BODY_LABEL(X) .LY##X
155 # define ENTRY_2(name)  \
156         .type name,@function;                   \
157         ENTRY_1(name)
158 # define END_2(name)    \
159         .size name,.-BODY_LABEL(name);          \
160         .size BODY_LABEL(name),.-BODY_LABEL(name);
161 #endif
162 #define LOCALENTRY(name)
163
164 #else /* _CALL_ELF */
165
166 /* Macro to prepare for calling via a function pointer.  */
167         .macro PPC64_LOAD_FUNCPTR PTR
168         mr      r12,\PTR
169         mtctr   r12
170         .endm
171
172 #define DOT_LABEL(X) X
173 #define BODY_LABEL(X) X
174 #define ENTRY_2(name)   \
175         .globl name;                            \
176         .type name,@function;
177 #define END_2(name)     \
178         .size name,.-name;
179 #define LOCALENTRY(name)        \
180 1:      addis   r2,r12,.TOC.-1b@ha; \
181         addi    r2,r2,.TOC.-1b@l; \
182         .localentry name,.-name;
183
184 #endif /* _CALL_ELF */
185
186 #define ENTRY(name)     \
187         .section        ".text";                \
188         ENTRY_2(name)                           \
189         .align ALIGNARG(2);                     \
190 BODY_LABEL(name):                               \
191         cfi_startproc;                          \
192         LOCALENTRY(name)
193
194 #define EALIGN_W_0  /* No words to insert.  */
195 #define EALIGN_W_1  nop
196 #define EALIGN_W_2  nop;nop
197 #define EALIGN_W_3  nop;nop;nop
198 #define EALIGN_W_4  EALIGN_W_3;nop
199 #define EALIGN_W_5  EALIGN_W_4;nop
200 #define EALIGN_W_6  EALIGN_W_5;nop
201 #define EALIGN_W_7  EALIGN_W_6;nop
202
203 /* EALIGN is like ENTRY, but does alignment to 'words'*4 bytes
204    past a 2^alignt boundary.  */
205 #define EALIGN(name, alignt, words) \
206         .section        ".text";                \
207         ENTRY_2(name)                           \
208         .align ALIGNARG(alignt);                \
209         EALIGN_W_##words;                       \
210 BODY_LABEL(name):                               \
211         cfi_startproc;                          \
212         LOCALENTRY(name)
213
214 /* Local labels stripped out by the linker.  */
215 #undef L
216 #define L(x) .L##x
217
218 #define tostring(s) #s
219 #define stringify(s) tostring(s)
220 #define XGLUE(a,b) a##b
221 #define GLUE(a,b) XGLUE(a,b)
222 #define LT_LABEL(name) GLUE(.LT,name)
223 #define LT_LABELSUFFIX(name,suffix) GLUE(GLUE(.LT,name),suffix)
224
225 /* Support Traceback tables */
226 #define TB_ASM                  0x000c000000000000
227 #define TB_GLOBALLINK           0x0000800000000000
228 #define TB_IS_EPROL             0x0000400000000000
229 #define TB_HAS_TBOFF            0x0000200000000000
230 #define TB_INT_PROC             0x0000100000000000
231 #define TB_HAS_CTL              0x0000080000000000
232 #define TB_TOCLESS              0x0000040000000000
233 #define TB_FP_PRESENT           0x0000020000000000
234 #define TB_LOG_ABORT            0x0000010000000000
235 #define TB_INT_HANDL            0x0000008000000000
236 #define TB_NAME_PRESENT         0x0000004000000000
237 #define TB_USES_ALLOCA          0x0000002000000000
238 #define TB_SAVES_CR             0x0000000200000000
239 #define TB_SAVES_LR             0x0000000100000000
240 #define TB_STORES_BC            0x0000000080000000
241 #define TB_FIXUP                0x0000000040000000
242 #define TB_FP_SAVED(fprs)       (((fprs) & 0x3f) << 24)
243 #define TB_GPR_SAVED(gprs)      (((fprs) & 0x3f) << 16)
244 #define TB_FIXEDPARMS(parms)    (((parms) & 0xff) << 8)
245 #define TB_FLOATPARMS(parms)    (((parms) & 0x7f) << 1)
246 #define TB_PARMSONSTK           0x0000000000000001
247
248 #define PPC_HIGHER(v)           (((v) >> 32) & 0xffff)
249 #define TB_DEFAULT              TB_ASM | TB_HAS_TBOFF | TB_NAME_PRESENT
250
251 #define TRACEBACK(name) \
252 LT_LABEL(name): ; \
253         .long   0 ; \
254         .quad   TB_DEFAULT ; \
255         .long   LT_LABEL(name)-BODY_LABEL(name) ; \
256         .short  LT_LABELSUFFIX(name,_name_end)-LT_LABELSUFFIX(name,_name_start) ; \
257 LT_LABELSUFFIX(name,_name_start): ;\
258         .ascii  stringify(name) ; \
259 LT_LABELSUFFIX(name,_name_end): ; \
260         .align  2 ;
261
262 #define TRACEBACK_MASK(name,mask) \
263 LT_LABEL(name): ; \
264         .long   0 ; \
265         .quad   TB_DEFAULT | mask ; \
266         .long   LT_LABEL(name)-BODY_LABEL(name) ; \
267         .short  LT_LABELSUFFIX(name,_name_end)-LT_LABELSUFFIX(name,_name_start) ; \
268 LT_LABELSUFFIX(name,_name_start): ;\
269         .ascii  stringify(name) ; \
270 LT_LABELSUFFIX(name,_name_end): ; \
271         .align  2 ;
272
273 /* END generates Traceback tables */
274 #undef  END
275 #define END(name) \
276   cfi_endproc;                  \
277   TRACEBACK(name)               \
278   END_2(name)
279
280 /* This form supports more informative traceback tables */
281 #define END_GEN_TB(name,mask)   \
282   cfi_endproc;                  \
283   TRACEBACK_MASK(name,mask)     \
284   END_2(name)
285
286 #define DO_CALL(syscall) \
287     li 0,syscall; \
288     sc
289
290 /* ppc64 is always PIC */
291 #undef JUMPTARGET
292 #define JUMPTARGET(name) DOT_LABEL(name)
293
294 #define PSEUDO(name, syscall_name, args) \
295   .section ".text";     \
296   ENTRY (name) \
297   DO_CALL (SYS_ify (syscall_name));
298
299 #ifdef SHARED
300 #define TAIL_CALL_SYSCALL_ERROR \
301     b JUMPTARGET(__syscall_error)
302 #else
303 /* Static version might be linked into a large app with a toc exceeding
304    64k.  We can't put a toc adjusting stub on a plain branch, so can't
305    tail call __syscall_error.  */
306 #define TAIL_CALL_SYSCALL_ERROR \
307     .ifdef .Local_syscall_error; \
308     b .Local_syscall_error; \
309     .else; \
310 .Local_syscall_error: \
311     mflr 0; \
312     std 0,FRAME_LR_SAVE(1); \
313     stdu 1,-FRAME_MIN_SIZE(1); \
314     cfi_adjust_cfa_offset(FRAME_MIN_SIZE); \
315     cfi_offset(lr,FRAME_LR_SAVE); \
316     bl JUMPTARGET(__syscall_error); \
317     nop; \
318     ld 0,FRAME_MIN_SIZE+FRAME_LR_SAVE(1); \
319     addi 1,1,FRAME_MIN_SIZE; \
320     cfi_adjust_cfa_offset(-FRAME_MIN_SIZE); \
321     mtlr 0; \
322     cfi_restore(lr); \
323     blr; \
324     .endif
325 #endif
326
327 #define PSEUDO_RET \
328     bnslr+; \
329     TAIL_CALL_SYSCALL_ERROR
330
331 #define ret PSEUDO_RET
332
333 #undef  PSEUDO_END
334 #define PSEUDO_END(name) \
335   END (name)
336
337 #define PSEUDO_NOERRNO(name, syscall_name, args) \
338   .section ".text";     \
339   ENTRY (name) \
340   DO_CALL (SYS_ify (syscall_name));
341
342 #define PSEUDO_RET_NOERRNO \
343     blr
344
345 #define ret_NOERRNO PSEUDO_RET_NOERRNO
346
347 #undef  PSEUDO_END_NOERRNO
348 #define PSEUDO_END_NOERRNO(name) \
349   END (name)
350
351 #define PSEUDO_ERRVAL(name, syscall_name, args) \
352   .section ".text";     \
353   ENTRY (name) \
354   DO_CALL (SYS_ify (syscall_name));
355
356 #define PSEUDO_RET_ERRVAL \
357     blr
358
359 #define ret_ERRVAL PSEUDO_RET_ERRVAL
360
361 #undef  PSEUDO_END_ERRVAL
362 #define PSEUDO_END_ERRVAL(name) \
363   END (name)
364
365 #else /* !__ASSEMBLER__ */
366
367 #if _CALL_ELF != 2
368
369 #define PPC64_LOAD_FUNCPTR(ptr) \
370         "ld     12,0(" #ptr ");\n"                                      \
371         "ld     2,8(" #ptr ");\n"                                       \
372         "mtctr  12;\n"                                                  \
373         "ld     11,16(" #ptr ");"
374
375 #ifdef USE_PPC64_OVERLAPPING_OPD
376 # define OPD_ENT(name)  ".quad " BODY_PREFIX #name ", .TOC.@tocbase;"
377 #else
378 # define OPD_ENT(name)  ".quad " BODY_PREFIX #name ", .TOC.@tocbase, 0;"
379 #endif
380
381 #define ENTRY_1(name)   \
382         ".type   " BODY_PREFIX #name ",@function;\n"                    \
383         ".globl " #name ";\n"                                           \
384         ".pushsection \".opd\",\"aw\";\n"                               \
385         ".align  3;\n"                                                  \
386 #name ":\n"                                                             \
387         OPD_ENT (name) "\n"                                             \
388         ".popsection;"
389
390 #ifdef HAVE_ASM_GLOBAL_DOT_NAME
391 # define DOT_PREFIX "."
392 # define BODY_PREFIX "."
393 # define ENTRY_2(name)  \
394         ".globl " BODY_PREFIX #name ";\n"                               \
395         ENTRY_1(name) "\n"                                              \
396         ".size  " #name ", 24;"
397 # define END_2(name)    \
398         ".size " BODY_PREFIX #name ",.-" BODY_PREFIX #name ";"
399 #else
400 # define DOT_PREFIX ""
401 # define BODY_PREFIX ".LY"
402 # define ENTRY_2(name)  \
403         ".type " #name ",@function;\n"                                  \
404         ENTRY_1(name)
405 # define END_2(name)    \
406         ".size " #name ",.-" BODY_PREFIX #name ";\n"                    \
407         ".size " BODY_PREFIX #name ",.-" BODY_PREFIX #name ";"
408 #endif
409 #define LOCALENTRY(name)
410
411 #else /* _CALL_ELF */
412
413 #define PPC64_LOAD_FUNCPTR(ptr) \
414         "mr     12," #ptr ";\n"                                         \
415         "mtctr  12;"
416
417 #define DOT_PREFIX ""
418 #define BODY_PREFIX ""
419 #define ENTRY_2(name)   \
420         ".type " #name ",@function;\n"                                  \
421         ".globl " #name ";"
422 #define END_2(name)     \
423         ".size " #name ",.-" #name ";"
424 #define LOCALENTRY(name)        \
425         "1: addis 2,12,.TOC.-1b@ha;\n"                                  \
426         "addi   2,2,.TOC.-1b@l;\n"                                      \
427         ".localentry " #name ",.-" #name ";"
428
429 #endif /* _CALL_ELF */
430
431 #endif  /* __ASSEMBLER__ */