]>
Commit | Line | Data |
---|---|---|
b80a3db0 | 1 | /* Assembly macros for 64-bit PowerPC. |
bfff8b1b | 2 | Copyright (C) 2002-2017 Free Software Foundation, Inc. |
b80a3db0 RM |
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 | |
59ba27a6 PE |
16 | License along with the GNU C Library; if not, see |
17 | <http://www.gnu.org/licenses/>. */ | |
b80a3db0 | 18 | |
b80a3db0 RM |
19 | #include <sysdeps/powerpc/sysdep.h> |
20 | ||
afe01786 UD |
21 | #ifdef __ASSEMBLER__ |
22 | ||
8b8a692c | 23 | /* Stack frame offsets. */ |
8b8a692c UW |
24 | #define FRAME_BACKCHAIN 0 |
25 | #define FRAME_CR_SAVE 8 | |
26 | #define FRAME_LR_SAVE 16 | |
fb499eb0 AM |
27 | #if _CALL_ELF != 2 |
28 | #define FRAME_MIN_SIZE 112 | |
29 | #define FRAME_MIN_SIZE_PARM 112 | |
8b8a692c UW |
30 | #define FRAME_TOC_SAVE 40 |
31 | #define FRAME_PARM_SAVE 48 | |
8b8a692c UW |
32 | #else |
33 | #define FRAME_MIN_SIZE 32 | |
34 | #define FRAME_MIN_SIZE_PARM 96 | |
8b8a692c UW |
35 | #define FRAME_TOC_SAVE 24 |
36 | #define FRAME_PARM_SAVE 32 | |
8b8a692c UW |
37 | #endif |
38 | ||
d7d06f79 UD |
39 | /* Support macros for CALL_MCOUNT. */ |
40 | .macro SAVE_ARG NARG | |
41 | .if \NARG | |
42 | SAVE_ARG \NARG-1 | |
dd885436 | 43 | std 2+\NARG,-FRAME_MIN_SIZE_PARM+FRAME_PARM_SAVE-8+8*(\NARG)(1) |
d7d06f79 UD |
44 | .endif |
45 | .endm | |
46 | ||
47 | .macro REST_ARG NARG | |
48 | .if \NARG | |
49 | REST_ARG \NARG-1 | |
dd885436 | 50 | ld 2+\NARG,FRAME_PARM_SAVE-8+8*(\NARG)(1) |
bebff237 AM |
51 | .endif |
52 | .endm | |
53 | ||
54 | .macro CFI_SAVE_ARG NARG | |
55 | .if \NARG | |
56 | CFI_SAVE_ARG \NARG-1 | |
dd885436 | 57 | cfi_offset(2+\NARG,-FRAME_MIN_SIZE_PARM+FRAME_PARM_SAVE-8+8*(\NARG)) |
bebff237 AM |
58 | .endif |
59 | .endm | |
60 | ||
61 | .macro CFI_REST_ARG NARG | |
62 | .if \NARG | |
63 | CFI_REST_ARG \NARG-1 | |
64 | cfi_restore(2+\NARG) | |
d7d06f79 UD |
65 | .endif |
66 | .endm | |
67 | ||
b80a3db0 RM |
68 | /* If compiled for profiling, call `_mcount' at the start of each function. |
69 | see ppc-mcount.S for more details. */ | |
d7d06f79 | 70 | .macro CALL_MCOUNT NARG |
b80a3db0 | 71 | #ifdef PROF |
d7d06f79 UD |
72 | mflr r0 |
73 | SAVE_ARG \NARG | |
8b8a692c UW |
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) | |
bebff237 | 78 | CFI_SAVE_ARG \NARG |
d7d06f79 | 79 | bl JUMPTARGET (_mcount) |
bebff237 AM |
80 | #ifndef SHARED |
81 | nop | |
82 | #endif | |
8b8a692c | 83 | ld r0,FRAME_MIN_SIZE_PARM+FRAME_LR_SAVE(r1) |
d7d06f79 | 84 | REST_ARG \NARG |
d7d06f79 | 85 | mtlr r0 |
8b8a692c UW |
86 | addi r1,r1,FRAME_MIN_SIZE_PARM |
87 | cfi_adjust_cfa_offset(-FRAME_MIN_SIZE_PARM) | |
bebff237 AM |
88 | cfi_restore(lr) |
89 | CFI_REST_ARG \NARG | |
d7d06f79 UD |
90 | #endif |
91 | .endm | |
b80a3db0 | 92 | |
696caf1d UW |
93 | #if _CALL_ELF != 2 |
94 | ||
d31beafa UW |
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 | |
102 | ||
590b40f7 UD |
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 | |
b80a3db0 | 108 | |
4b6e7667 | 109 | #define ENTRY_1(name) \ |
590b40f7 UD |
110 | .type BODY_LABEL(name),@function; \ |
111 | .globl name; \ | |
112 | .section ".opd","aw"; \ | |
4b6e7667 AM |
113 | .p2align 3;FUNC_LABEL(name): \ |
114 | OPD_ENT (name); \ | |
115 | .previous | |
590b40f7 | 116 | |
4b6e7667 | 117 | #define FUNC_LABEL(X) X |
5ca10a0c | 118 | #define BODY_LABEL(X) .LY##X |
4b6e7667 | 119 | #define ENTRY_2(name) \ |
590b40f7 UD |
120 | .type name,@function; \ |
121 | ENTRY_1(name) | |
4b6e7667 | 122 | #define END_2(name) \ |
590b40f7 | 123 | .size name,.-BODY_LABEL(name); \ |
4b6e7667 | 124 | .size BODY_LABEL(name),.-BODY_LABEL(name) |
696caf1d UW |
125 | #define LOCALENTRY(name) |
126 | ||
4b6e7667 | 127 | #else /* _CALL_ELF == 2 */ |
696caf1d UW |
128 | |
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 | |
134 | ||
4b6e7667 | 135 | #define FUNC_LABEL(X) X |
696caf1d | 136 | #define BODY_LABEL(X) X |
4b6e7667 | 137 | #define ENTRY_2(name) \ |
696caf1d | 138 | .globl name; \ |
4b6e7667 AM |
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 | |
696caf1d UW |
146 | |
147 | #endif /* _CALL_ELF */ | |
b80a3db0 | 148 | |
590b40f7 | 149 | #define ENTRY(name) \ |
d31beafa | 150 | .section ".text"; \ |
4b6e7667 | 151 | ENTRY_2(name); \ |
590b40f7 | 152 | .align ALIGNARG(2); \ |
9759bbf1 | 153 | BODY_LABEL(name): \ |
696caf1d UW |
154 | cfi_startproc; \ |
155 | LOCALENTRY(name) | |
b80a3db0 RM |
156 | |
157 | #define EALIGN_W_0 /* No words to insert. */ | |
158 | #define EALIGN_W_1 nop | |
159 | #define EALIGN_W_2 nop;nop | |
160 | #define EALIGN_W_3 nop;nop;nop | |
161 | #define EALIGN_W_4 EALIGN_W_3;nop | |
162 | #define EALIGN_W_5 EALIGN_W_4;nop | |
163 | #define EALIGN_W_6 EALIGN_W_5;nop | |
164 | #define EALIGN_W_7 EALIGN_W_6;nop | |
165 | ||
166 | /* EALIGN is like ENTRY, but does alignment to 'words'*4 bytes | |
590b40f7 | 167 | past a 2^alignt boundary. */ |
b80a3db0 | 168 | #define EALIGN(name, alignt, words) \ |
d31beafa | 169 | .section ".text"; \ |
4b6e7667 | 170 | ENTRY_2(name); \ |
590b40f7 UD |
171 | .align ALIGNARG(alignt); \ |
172 | EALIGN_W_##words; \ | |
9759bbf1 | 173 | BODY_LABEL(name): \ |
696caf1d UW |
174 | cfi_startproc; \ |
175 | LOCALENTRY(name) | |
b80a3db0 RM |
176 | |
177 | /* Local labels stripped out by the linker. */ | |
178 | #undef L | |
179 | #define L(x) .L##x | |
180 | ||
181 | #define tostring(s) #s | |
182 | #define stringify(s) tostring(s) | |
183 | #define XGLUE(a,b) a##b | |
184 | #define GLUE(a,b) XGLUE(a,b) | |
185 | #define LT_LABEL(name) GLUE(.LT,name) | |
186 | #define LT_LABELSUFFIX(name,suffix) GLUE(GLUE(.LT,name),suffix) | |
187 | ||
188 | /* Support Traceback tables */ | |
189 | #define TB_ASM 0x000c000000000000 | |
590b40f7 | 190 | #define TB_GLOBALLINK 0x0000800000000000 |
b80a3db0 | 191 | #define TB_IS_EPROL 0x0000400000000000 |
590b40f7 | 192 | #define TB_HAS_TBOFF 0x0000200000000000 |
b80a3db0 RM |
193 | #define TB_INT_PROC 0x0000100000000000 |
194 | #define TB_HAS_CTL 0x0000080000000000 | |
195 | #define TB_TOCLESS 0x0000040000000000 | |
590b40f7 UD |
196 | #define TB_FP_PRESENT 0x0000020000000000 |
197 | #define TB_LOG_ABORT 0x0000010000000000 | |
198 | #define TB_INT_HANDL 0x0000008000000000 | |
199 | #define TB_NAME_PRESENT 0x0000004000000000 | |
200 | #define TB_USES_ALLOCA 0x0000002000000000 | |
b80a3db0 RM |
201 | #define TB_SAVES_CR 0x0000000200000000 |
202 | #define TB_SAVES_LR 0x0000000100000000 | |
590b40f7 | 203 | #define TB_STORES_BC 0x0000000080000000 |
b80a3db0 RM |
204 | #define TB_FIXUP 0x0000000040000000 |
205 | #define TB_FP_SAVED(fprs) (((fprs) & 0x3f) << 24) | |
206 | #define TB_GPR_SAVED(gprs) (((fprs) & 0x3f) << 16) | |
207 | #define TB_FIXEDPARMS(parms) (((parms) & 0xff) << 8) | |
208 | #define TB_FLOATPARMS(parms) (((parms) & 0x7f) << 1) | |
590b40f7 | 209 | #define TB_PARMSONSTK 0x0000000000000001 |
b80a3db0 | 210 | |
590b40f7 UD |
211 | #define PPC_HIGHER(v) (((v) >> 32) & 0xffff) |
212 | #define TB_DEFAULT TB_ASM | TB_HAS_TBOFF | TB_NAME_PRESENT | |
b80a3db0 RM |
213 | |
214 | #define TRACEBACK(name) \ | |
215 | LT_LABEL(name): ; \ | |
216 | .long 0 ; \ | |
217 | .quad TB_DEFAULT ; \ | |
590b40f7 | 218 | .long LT_LABEL(name)-BODY_LABEL(name) ; \ |
b80a3db0 RM |
219 | .short LT_LABELSUFFIX(name,_name_end)-LT_LABELSUFFIX(name,_name_start) ; \ |
220 | LT_LABELSUFFIX(name,_name_start): ;\ | |
221 | .ascii stringify(name) ; \ | |
222 | LT_LABELSUFFIX(name,_name_end): ; \ | |
4b6e7667 | 223 | .p2align 2 |
b80a3db0 RM |
224 | |
225 | #define TRACEBACK_MASK(name,mask) \ | |
226 | LT_LABEL(name): ; \ | |
227 | .long 0 ; \ | |
228 | .quad TB_DEFAULT | mask ; \ | |
590b40f7 | 229 | .long LT_LABEL(name)-BODY_LABEL(name) ; \ |
b80a3db0 RM |
230 | .short LT_LABELSUFFIX(name,_name_end)-LT_LABELSUFFIX(name,_name_start) ; \ |
231 | LT_LABELSUFFIX(name,_name_start): ;\ | |
232 | .ascii stringify(name) ; \ | |
233 | LT_LABELSUFFIX(name,_name_end): ; \ | |
4b6e7667 | 234 | .p2align 2 |
b80a3db0 RM |
235 | |
236 | /* END generates Traceback tables */ | |
237 | #undef END | |
238 | #define END(name) \ | |
9759bbf1 | 239 | cfi_endproc; \ |
4b6e7667 | 240 | TRACEBACK(name); \ |
590b40f7 | 241 | END_2(name) |
b80a3db0 RM |
242 | |
243 | /* This form supports more informative traceback tables */ | |
244 | #define END_GEN_TB(name,mask) \ | |
9759bbf1 | 245 | cfi_endproc; \ |
4b6e7667 | 246 | TRACEBACK_MASK(name,mask); \ |
590b40f7 | 247 | END_2(name) |
b80a3db0 | 248 | |
56cf2763 AZ |
249 | #if !IS_IN(rtld) && defined (ENABLE_LOCK_ELISION) |
250 | # define ABORT_TRANSACTION \ | |
251 | cmpdi 13,0; \ | |
252 | beq 1f; \ | |
253 | lwz 0,TM_CAPABLE(13); \ | |
254 | cmpwi 0,0; \ | |
255 | beq 1f; \ | |
18173559 PM |
256 | li 11,_ABORT_SYSCALL; \ |
257 | tabort. 11; \ | |
4b6e7667 | 258 | .p2align 4; \ |
56cf2763 AZ |
259 | 1: |
260 | #else | |
261 | # define ABORT_TRANSACTION | |
262 | #endif | |
263 | ||
b80a3db0 | 264 | #define DO_CALL(syscall) \ |
56cf2763 | 265 | ABORT_TRANSACTION \ |
b80a3db0 RM |
266 | li 0,syscall; \ |
267 | sc | |
268 | ||
269 | /* ppc64 is always PIC */ | |
29d9a17d | 270 | #undef JUMPTARGET |
4b6e7667 | 271 | #define JUMPTARGET(name) FUNC_LABEL(name) |
b80a3db0 RM |
272 | |
273 | #define PSEUDO(name, syscall_name, args) \ | |
4b6e7667 AM |
274 | .section ".text"; \ |
275 | ENTRY (name); \ | |
276 | DO_CALL (SYS_ify (syscall_name)) | |
b80a3db0 | 277 | |
bebff237 AM |
278 | #ifdef SHARED |
279 | #define TAIL_CALL_SYSCALL_ERROR \ | |
280 | b JUMPTARGET(__syscall_error) | |
281 | #else | |
282 | /* Static version might be linked into a large app with a toc exceeding | |
283 | 64k. We can't put a toc adjusting stub on a plain branch, so can't | |
284 | tail call __syscall_error. */ | |
285 | #define TAIL_CALL_SYSCALL_ERROR \ | |
286 | .ifdef .Local_syscall_error; \ | |
287 | b .Local_syscall_error; \ | |
288 | .else; \ | |
289 | .Local_syscall_error: \ | |
290 | mflr 0; \ | |
8b8a692c UW |
291 | std 0,FRAME_LR_SAVE(1); \ |
292 | stdu 1,-FRAME_MIN_SIZE(1); \ | |
293 | cfi_adjust_cfa_offset(FRAME_MIN_SIZE); \ | |
294 | cfi_offset(lr,FRAME_LR_SAVE); \ | |
bebff237 AM |
295 | bl JUMPTARGET(__syscall_error); \ |
296 | nop; \ | |
8b8a692c UW |
297 | ld 0,FRAME_MIN_SIZE+FRAME_LR_SAVE(1); \ |
298 | addi 1,1,FRAME_MIN_SIZE; \ | |
299 | cfi_adjust_cfa_offset(-FRAME_MIN_SIZE); \ | |
bebff237 AM |
300 | mtlr 0; \ |
301 | cfi_restore(lr); \ | |
302 | blr; \ | |
303 | .endif | |
304 | #endif | |
305 | ||
b80a3db0 | 306 | #define PSEUDO_RET \ |
aff4519d | 307 | bnslr+; \ |
bebff237 | 308 | TAIL_CALL_SYSCALL_ERROR |
b80a3db0 RM |
309 | |
310 | #define ret PSEUDO_RET | |
311 | ||
312 | #undef PSEUDO_END | |
313 | #define PSEUDO_END(name) \ | |
314 | END (name) | |
315 | ||
9eb88290 | 316 | #define PSEUDO_NOERRNO(name, syscall_name, args) \ |
4b6e7667 AM |
317 | .section ".text"; \ |
318 | ENTRY (name); \ | |
319 | DO_CALL (SYS_ify (syscall_name)) | |
9eb88290 UD |
320 | |
321 | #define PSEUDO_RET_NOERRNO \ | |
322 | blr | |
323 | ||
324 | #define ret_NOERRNO PSEUDO_RET_NOERRNO | |
325 | ||
326 | #undef PSEUDO_END_NOERRNO | |
c6289757 | 327 | #define PSEUDO_END_NOERRNO(name) \ |
9eb88290 UD |
328 | END (name) |
329 | ||
137ffcdc | 330 | #define PSEUDO_ERRVAL(name, syscall_name, args) \ |
4b6e7667 AM |
331 | .section ".text"; \ |
332 | ENTRY (name); \ | |
333 | DO_CALL (SYS_ify (syscall_name)) | |
137ffcdc UD |
334 | |
335 | #define PSEUDO_RET_ERRVAL \ | |
336 | blr | |
337 | ||
338 | #define ret_ERRVAL PSEUDO_RET_ERRVAL | |
339 | ||
340 | #undef PSEUDO_END_ERRVAL | |
341 | #define PSEUDO_END_ERRVAL(name) \ | |
342 | END (name) | |
343 | ||
590b40f7 | 344 | #else /* !__ASSEMBLER__ */ |
b80a3db0 | 345 | |
696caf1d UW |
346 | #if _CALL_ELF != 2 |
347 | ||
d31beafa | 348 | #define PPC64_LOAD_FUNCPTR(ptr) \ |
4b6e7667 AM |
349 | "ld 12,0(" #ptr ")\n" \ |
350 | "ld 2,8(" #ptr ")\n" \ | |
351 | "mtctr 12\n" \ | |
352 | "ld 11,16(" #ptr ")" | |
d31beafa | 353 | |
590b40f7 | 354 | #ifdef USE_PPC64_OVERLAPPING_OPD |
4b6e7667 | 355 | # define OPD_ENT(name) ".quad " BODY_PREFIX #name ", .TOC.@tocbase" |
590b40f7 | 356 | #else |
4b6e7667 | 357 | # define OPD_ENT(name) ".quad " BODY_PREFIX #name ", .TOC.@tocbase, 0" |
590b40f7 UD |
358 | #endif |
359 | ||
d31beafa | 360 | #define ENTRY_1(name) \ |
4b6e7667 AM |
361 | ".type " BODY_PREFIX #name ",@function\n" \ |
362 | ".globl " #name "\n" \ | |
363 | ".pushsection \".opd\",\"aw\"\n" \ | |
364 | ".p2align 3\n" \ | |
d31beafa UW |
365 | #name ":\n" \ |
366 | OPD_ENT (name) "\n" \ | |
4b6e7667 | 367 | ".popsection" |
d31beafa | 368 | |
5ca10a0c AZ |
369 | #define DOT_PREFIX "" |
370 | #define BODY_PREFIX ".LY" | |
371 | #define ENTRY_2(name) \ | |
4b6e7667 | 372 | ".type " #name ",@function\n" \ |
d31beafa | 373 | ENTRY_1(name) |
5ca10a0c | 374 | #define END_2(name) \ |
4b6e7667 AM |
375 | ".size " #name ",.-" BODY_PREFIX #name "\n" \ |
376 | ".size " BODY_PREFIX #name ",.-" BODY_PREFIX #name | |
696caf1d UW |
377 | #define LOCALENTRY(name) |
378 | ||
379 | #else /* _CALL_ELF */ | |
380 | ||
381 | #define PPC64_LOAD_FUNCPTR(ptr) \ | |
4b6e7667 AM |
382 | "mr 12," #ptr "\n" \ |
383 | "mtctr 12" | |
696caf1d UW |
384 | |
385 | #define DOT_PREFIX "" | |
386 | #define BODY_PREFIX "" | |
387 | #define ENTRY_2(name) \ | |
4b6e7667 AM |
388 | ".type " #name ",@function\n" \ |
389 | ".globl " #name | |
696caf1d | 390 | #define END_2(name) \ |
4b6e7667 | 391 | ".size " #name ",.-" #name |
696caf1d | 392 | #define LOCALENTRY(name) \ |
4b6e7667 AM |
393 | "1: addis 2,12,.TOC.-1b@ha\n" \ |
394 | "addi 2,2,.TOC.-1b@l\n" \ | |
395 | ".localentry " #name ",.-" #name | |
696caf1d UW |
396 | |
397 | #endif /* _CALL_ELF */ | |
b80a3db0 RM |
398 | |
399 | #endif /* __ASSEMBLER__ */ |