Use libc_hidden_* for fputs (bug 15105).
[glibc.git] / sysdeps / powerpc / powerpc64 / sysdep.h
blob2df1d9b6e6749da4a1a0ccc9d78881326cd99f71
1 /* Assembly macros for 64-bit PowerPC.
2 Copyright (C) 2002-2018 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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.
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.
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/>. */
19 #include <sysdeps/powerpc/sysdep.h>
21 #ifdef __ASSEMBLER__
23 /* Stack frame offsets. */
24 #define FRAME_BACKCHAIN 0
25 #define FRAME_CR_SAVE 8
26 #define FRAME_LR_SAVE 16
27 #if _CALL_ELF != 2
28 #define FRAME_MIN_SIZE 112
29 #define FRAME_MIN_SIZE_PARM 112
30 #define FRAME_TOC_SAVE 40
31 #define FRAME_PARM_SAVE 48
32 #else
33 #define FRAME_MIN_SIZE 32
34 #define FRAME_MIN_SIZE_PARM 96
35 #define FRAME_TOC_SAVE 24
36 #define FRAME_PARM_SAVE 32
37 #endif
39 /* Support macros for CALL_MCOUNT. */
40 .macro SAVE_ARG NARG
41 .if \NARG
42 SAVE_ARG \NARG-1
43 std 2+\NARG,-FRAME_MIN_SIZE_PARM+FRAME_PARM_SAVE-8+8*(\NARG)(1)
44 .endif
45 .endm
47 .macro REST_ARG NARG
48 .if \NARG
49 REST_ARG \NARG-1
50 ld 2+\NARG,FRAME_PARM_SAVE-8+8*(\NARG)(1)
51 .endif
52 .endm
54 .macro CFI_SAVE_ARG NARG
55 .if \NARG
56 CFI_SAVE_ARG \NARG-1
57 cfi_offset(2+\NARG,-FRAME_MIN_SIZE_PARM+FRAME_PARM_SAVE-8+8*(\NARG))
58 .endif
59 .endm
61 .macro CFI_REST_ARG NARG
62 .if \NARG
63 CFI_REST_ARG \NARG-1
64 cfi_restore(2+\NARG)
65 .endif
66 .endm
68 /* If compiled for profiling, call `_mcount' at the start of each function.
69 see ppc-mcount.S for more details. */
70 .macro CALL_MCOUNT NARG
71 #ifdef PROF
72 mflr r0
73 SAVE_ARG \NARG
74 std r0,FRAME_LR_SAVE(r1)
75 stdu r1,-FRAME_MIN_SIZE_PARM(r1)
76 cfi_adjust_cfa_offset(FRAME_MIN_SIZE_PARM)
77 cfi_offset(lr,FRAME_LR_SAVE)
78 CFI_SAVE_ARG \NARG
79 bl JUMPTARGET (_mcount)
80 #ifndef SHARED
81 nop
82 #endif
83 ld r0,FRAME_MIN_SIZE_PARM+FRAME_LR_SAVE(r1)
84 REST_ARG \NARG
85 mtlr r0
86 addi r1,r1,FRAME_MIN_SIZE_PARM
87 cfi_adjust_cfa_offset(-FRAME_MIN_SIZE_PARM)
88 cfi_restore(lr)
89 CFI_REST_ARG \NARG
90 #endif
91 .endm
93 #if _CALL_ELF != 2
95 /* Macro to prepare for calling via a function pointer. */
96 .macro PPC64_LOAD_FUNCPTR PTR
97 ld r12,0(\PTR)
98 ld r2,8(\PTR)
99 mtctr r12
100 ld r11,16(\PTR)
101 .endm
103 #ifdef USE_PPC64_OVERLAPPING_OPD
104 # define OPD_ENT(name) .quad BODY_LABEL (name), .TOC.@tocbase
105 #else
106 # define OPD_ENT(name) .quad BODY_LABEL (name), .TOC.@tocbase, 0
107 #endif
109 #define ENTRY_1(name) \
110 .type BODY_LABEL(name),@function; \
111 .globl name; \
112 .section ".opd","aw"; \
113 .p2align 3;FUNC_LABEL(name): \
114 OPD_ENT (name); \
115 .previous
117 #define FUNC_LABEL(X) X
118 #define BODY_LABEL(X) .LY##X
119 #define ENTRY_2(name) \
120 .type name,@function; \
121 ENTRY_1(name)
122 #define END_2(name) \
123 .size name,.-BODY_LABEL(name); \
124 .size BODY_LABEL(name),.-BODY_LABEL(name)
125 #define LOCALENTRY(name)
127 #else /* _CALL_ELF == 2 */
129 /* Macro to prepare for calling via a function pointer. */
130 .macro PPC64_LOAD_FUNCPTR PTR
131 mr r12,\PTR
132 mtctr r12
133 .endm
135 #define FUNC_LABEL(X) X
136 #define BODY_LABEL(X) X
137 #define ENTRY_2(name) \
138 .globl name; \
139 .type name,@function
140 #define END_2(name) \
141 .size name,.-name
142 #define LOCALENTRY(name) \
143 1: addis r2,r12,.TOC.-1b@ha; \
144 addi r2,r2,.TOC.-1b@l; \
145 .localentry name,.-name
147 #endif /* _CALL_ELF */
149 .macro NOPS NARG
150 .if \NARG
151 NOPS \NARG-1
153 .endif
154 .endm
156 .macro ENTRY_3 name, alignp2=2, nopwords=0
157 .text
158 ENTRY_2(\name)
159 .p2align \alignp2
160 NOPS \nopwords
161 BODY_LABEL(\name):
162 .endm
164 /* Use ENTRY_TOCLESS for functions that make no use of r2 and
165 guarantee r2 is unchanged on exit. Any function that has @toc or
166 @got relocs uses r2. Functions that call other functions via the
167 PLT use r2. Use ENTRY for functions that may use or change r2.
168 The first argument is the function name.
169 The optional second argument specifies alignment of the function's
170 code, as the logarithm base two of the byte alignment. For
171 example, a value of four aligns to a sixteen byte boundary.
172 The optional third argument specifies the number of NOPs to emit
173 before the start of the function's code. */
174 #ifndef PROF
175 #define ENTRY_TOCLESS(name, ...) \
176 ENTRY_3 name, ## __VA_ARGS__; \
177 cfi_startproc
179 #define ENTRY(name, ...) \
180 ENTRY_TOCLESS(name, ## __VA_ARGS__); \
181 LOCALENTRY(name)
182 #else
183 /* The call to _mcount is potentially via the plt, so profiling code
184 is never free of an r2 use. */
185 #define ENTRY_TOCLESS(name, ...) \
186 ENTRY_3 name, ## __VA_ARGS__; \
187 cfi_startproc; \
188 LOCALENTRY(name)
190 #define ENTRY(name, ...) \
191 ENTRY_TOCLESS(name, ## __VA_ARGS__)
192 #endif
194 /* Local labels stripped out by the linker. */
195 #undef L
196 #define L(x) .L##x
198 #define tostring(s) #s
199 #define stringify(s) tostring(s)
200 #define XGLUE(a,b) a##b
201 #define GLUE(a,b) XGLUE(a,b)
202 #define LT_LABEL(name) GLUE(.LT,name)
203 #define LT_LABELSUFFIX(name,suffix) GLUE(GLUE(.LT,name),suffix)
205 /* Support Traceback tables */
206 #define TB_ASM 0x000c000000000000
207 #define TB_GLOBALLINK 0x0000800000000000
208 #define TB_IS_EPROL 0x0000400000000000
209 #define TB_HAS_TBOFF 0x0000200000000000
210 #define TB_INT_PROC 0x0000100000000000
211 #define TB_HAS_CTL 0x0000080000000000
212 #define TB_TOCLESS 0x0000040000000000
213 #define TB_FP_PRESENT 0x0000020000000000
214 #define TB_LOG_ABORT 0x0000010000000000
215 #define TB_INT_HANDL 0x0000008000000000
216 #define TB_NAME_PRESENT 0x0000004000000000
217 #define TB_USES_ALLOCA 0x0000002000000000
218 #define TB_SAVES_CR 0x0000000200000000
219 #define TB_SAVES_LR 0x0000000100000000
220 #define TB_STORES_BC 0x0000000080000000
221 #define TB_FIXUP 0x0000000040000000
222 #define TB_FP_SAVED(fprs) (((fprs) & 0x3f) << 24)
223 #define TB_GPR_SAVED(gprs) (((fprs) & 0x3f) << 16)
224 #define TB_FIXEDPARMS(parms) (((parms) & 0xff) << 8)
225 #define TB_FLOATPARMS(parms) (((parms) & 0x7f) << 1)
226 #define TB_PARMSONSTK 0x0000000000000001
228 #define PPC_HIGHER(v) (((v) >> 32) & 0xffff)
229 #define TB_DEFAULT TB_ASM | TB_HAS_TBOFF | TB_NAME_PRESENT
231 #define TRACEBACK(name) \
232 LT_LABEL(name): ; \
233 .long 0 ; \
234 .quad TB_DEFAULT ; \
235 .long LT_LABEL(name)-BODY_LABEL(name) ; \
236 .short LT_LABELSUFFIX(name,_name_end)-LT_LABELSUFFIX(name,_name_start) ; \
237 LT_LABELSUFFIX(name,_name_start): ;\
238 .ascii stringify(name) ; \
239 LT_LABELSUFFIX(name,_name_end): ; \
240 .p2align 2
242 #define TRACEBACK_MASK(name,mask) \
243 LT_LABEL(name): ; \
244 .long 0 ; \
245 .quad TB_DEFAULT | mask ; \
246 .long LT_LABEL(name)-BODY_LABEL(name) ; \
247 .short LT_LABELSUFFIX(name,_name_end)-LT_LABELSUFFIX(name,_name_start) ; \
248 LT_LABELSUFFIX(name,_name_start): ;\
249 .ascii stringify(name) ; \
250 LT_LABELSUFFIX(name,_name_end): ; \
251 .p2align 2
253 /* END generates Traceback tables */
254 #undef END
255 #define END(name) \
256 cfi_endproc; \
257 TRACEBACK(name); \
258 END_2(name)
260 /* This form supports more informative traceback tables */
261 #define END_GEN_TB(name,mask) \
262 cfi_endproc; \
263 TRACEBACK_MASK(name,mask); \
264 END_2(name)
266 #if !IS_IN(rtld)
267 # define ABORT_TRANSACTION_IMPL \
268 cmpdi 13,0; \
269 beq 1f; \
270 lwz 0,TM_CAPABLE(13); \
271 cmpwi 0,0; \
272 beq 1f; \
273 li 11,_ABORT_SYSCALL; \
274 tabort. 11; \
275 .p2align 4; \
277 #else
278 # define ABORT_TRANSACTION_IMPL
279 #endif
280 #define ABORT_TRANSACTION ABORT_TRANSACTION_IMPL
282 #define DO_CALL(syscall) \
283 ABORT_TRANSACTION \
284 li 0,syscall; \
287 /* ppc64 is always PIC */
288 #undef JUMPTARGET
289 #define JUMPTARGET(name) FUNC_LABEL(name)
291 #define PSEUDO(name, syscall_name, args) \
292 .section ".text"; \
293 ENTRY (name); \
294 DO_CALL (SYS_ify (syscall_name))
296 #ifdef SHARED
297 #define TAIL_CALL_SYSCALL_ERROR \
298 b JUMPTARGET(__syscall_error)
299 #else
300 /* Static version might be linked into a large app with a toc exceeding
301 64k. We can't put a toc adjusting stub on a plain branch, so can't
302 tail call __syscall_error. */
303 #define TAIL_CALL_SYSCALL_ERROR \
304 .ifdef .Local_syscall_error; \
305 b .Local_syscall_error; \
306 .else; \
307 .Local_syscall_error: \
308 mflr 0; \
309 std 0,FRAME_LR_SAVE(1); \
310 stdu 1,-FRAME_MIN_SIZE(1); \
311 cfi_adjust_cfa_offset(FRAME_MIN_SIZE); \
312 cfi_offset(lr,FRAME_LR_SAVE); \
313 bl JUMPTARGET(__syscall_error); \
314 nop; \
315 ld 0,FRAME_MIN_SIZE+FRAME_LR_SAVE(1); \
316 addi 1,1,FRAME_MIN_SIZE; \
317 cfi_adjust_cfa_offset(-FRAME_MIN_SIZE); \
318 mtlr 0; \
319 cfi_restore(lr); \
320 blr; \
321 .endif
322 #endif
324 #define PSEUDO_RET \
325 bnslr+; \
326 TAIL_CALL_SYSCALL_ERROR
328 #define ret PSEUDO_RET
330 #undef PSEUDO_END
331 #define PSEUDO_END(name) \
332 END (name)
334 #define PSEUDO_NOERRNO(name, syscall_name, args) \
335 .section ".text"; \
336 ENTRY (name); \
337 DO_CALL (SYS_ify (syscall_name))
339 #define PSEUDO_RET_NOERRNO \
342 #define ret_NOERRNO PSEUDO_RET_NOERRNO
344 #undef PSEUDO_END_NOERRNO
345 #define PSEUDO_END_NOERRNO(name) \
346 END (name)
348 #define PSEUDO_ERRVAL(name, syscall_name, args) \
349 .section ".text"; \
350 ENTRY (name); \
351 DO_CALL (SYS_ify (syscall_name))
353 #define PSEUDO_RET_ERRVAL \
356 #define ret_ERRVAL PSEUDO_RET_ERRVAL
358 #undef PSEUDO_END_ERRVAL
359 #define PSEUDO_END_ERRVAL(name) \
360 END (name)
362 #else /* !__ASSEMBLER__ */
364 #if _CALL_ELF != 2
366 #define PPC64_LOAD_FUNCPTR(ptr) \
367 "ld 12,0(" #ptr ")\n" \
368 "ld 2,8(" #ptr ")\n" \
369 "mtctr 12\n" \
370 "ld 11,16(" #ptr ")"
372 #ifdef USE_PPC64_OVERLAPPING_OPD
373 # define OPD_ENT(name) ".quad " BODY_PREFIX #name ", .TOC.@tocbase"
374 #else
375 # define OPD_ENT(name) ".quad " BODY_PREFIX #name ", .TOC.@tocbase, 0"
376 #endif
378 #define ENTRY_1(name) \
379 ".type " BODY_PREFIX #name ",@function\n" \
380 ".globl " #name "\n" \
381 ".pushsection \".opd\",\"aw\"\n" \
382 ".p2align 3\n" \
383 #name ":\n" \
384 OPD_ENT (name) "\n" \
385 ".popsection"
387 #define DOT_PREFIX ""
388 #define BODY_PREFIX ".LY"
389 #define ENTRY_2(name) \
390 ".type " #name ",@function\n" \
391 ENTRY_1(name)
392 #define END_2(name) \
393 ".size " #name ",.-" BODY_PREFIX #name "\n" \
394 ".size " BODY_PREFIX #name ",.-" BODY_PREFIX #name
395 #define LOCALENTRY(name)
397 #else /* _CALL_ELF */
399 #define PPC64_LOAD_FUNCPTR(ptr) \
400 "mr 12," #ptr "\n" \
401 "mtctr 12"
403 #define DOT_PREFIX ""
404 #define BODY_PREFIX ""
405 #define ENTRY_2(name) \
406 ".type " #name ",@function\n" \
407 ".globl " #name
408 #define END_2(name) \
409 ".size " #name ",.-" #name
410 #define LOCALENTRY(name) \
411 "1: addis 2,12,.TOC.-1b@ha\n" \
412 "addi 2,2,.TOC.-1b@l\n" \
413 ".localentry " #name ",.-" #name
415 #endif /* _CALL_ELF */
417 #endif /* __ASSEMBLER__ */