]> git.ipfire.org Git - thirdparty/gcc.git/blame_incremental - libffi/src/powerpc/linux64_closure.S
cobol: Respect error in cobol.install-common.
[thirdparty/gcc.git] / libffi / src / powerpc / linux64_closure.S
... / ...
CommitLineData
1/* -----------------------------------------------------------------------
2 sysv.h - Copyright (c) 2003 Jakub Jelinek <jakub@redhat.com>
3 Copyright (c) 2008 Red Hat, Inc.
4
5 PowerPC64 Assembly glue.
6
7 Permission is hereby granted, free of charge, to any person obtaining
8 a copy of this software and associated documentation files (the
9 ``Software''), to deal in the Software without restriction, including
10 without limitation the rights to use, copy, modify, merge, publish,
11 distribute, sublicense, and/or sell copies of the Software, and to
12 permit persons to whom the Software is furnished to do so, subject to
13 the following conditions:
14
15 The above copyright notice and this permission notice shall be included
16 in all copies or substantial portions of the Software.
17
18 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 DEALINGS IN THE SOFTWARE.
26 ----------------------------------------------------------------------- */
27#define LIBFFI_ASM
28#include <fficonfig.h>
29#include <ffi.h>
30
31 .file "linux64_closure.S"
32
33 .machine altivec
34
35#ifdef POWERPC64
36 FFI_HIDDEN (ffi_closure_LINUX64)
37 .globl ffi_closure_LINUX64
38 .text
39 .cfi_startproc
40# if _CALL_ELF == 2
41ffi_closure_LINUX64:
42# ifndef __PCREL__
43 addis %r2, %r12, .TOC.-ffi_closure_LINUX64@ha
44 addi %r2, %r2, .TOC.-ffi_closure_LINUX64@l
45# endif
46 .localentry ffi_closure_LINUX64, . - ffi_closure_LINUX64
47# else
48 .section ".opd","aw"
49 .align 3
50ffi_closure_LINUX64:
51# ifdef _CALL_LINUX
52 .quad .L.ffi_closure_LINUX64,.TOC.@tocbase,0
53 .type ffi_closure_LINUX64,@function
54 .text
55.L.ffi_closure_LINUX64:
56# else
57 FFI_HIDDEN (.ffi_closure_LINUX64)
58 .globl .ffi_closure_LINUX64
59 .quad .ffi_closure_LINUX64,.TOC.@tocbase,0
60 .size ffi_closure_LINUX64,24
61 .type .ffi_closure_LINUX64,@function
62 .text
63.ffi_closure_LINUX64:
64# endif
65# endif
66
67# if _CALL_ELF == 2
68# ifdef __VEC__
69# 32 byte special reg save area + 64 byte parm save area
70# + 128 byte retval area + 13*8 fpr save area + 12*16 vec save area + round to 16
71# define STACKFRAME 528
72# else
73# 32 byte special reg save area + 64 byte parm save area
74# + 64 byte retval area + 13*8 fpr save area + round to 16
75# define STACKFRAME 272
76# endif
77# define PARMSAVE 32
78# define RETVAL PARMSAVE+64
79# else
80# 48 bytes special reg save area + 64 bytes parm save area
81# + 16 bytes retval area + 13*8 bytes fpr save area + round to 16
82# define STACKFRAME 240
83# define PARMSAVE 48
84# define RETVAL PARMSAVE+64
85# endif
86
87# if _CALL_ELF == 2
88 ld %r12, FFI_TRAMPOLINE_SIZE(%r11) # closure->cif
89 mflr %r0
90 lwz %r12, 28(%r12) # cif->flags
91 mtcrf 0x40, %r12
92 addi %r12, %r1, PARMSAVE
93 bt 7, 0f
94 # Our caller has not allocated a parameter save area.
95 # We need to allocate one here and use it to pass gprs to
96 # ffi_closure_helper_LINUX64.
97 addi %r12, %r1, -STACKFRAME+PARMSAVE
980:
99 # Save general regs into parm save area
100 std %r3, 0(%r12)
101 std %r4, 8(%r12)
102 std %r5, 16(%r12)
103 std %r6, 24(%r12)
104 std %r7, 32(%r12)
105 std %r8, 40(%r12)
106 std %r9, 48(%r12)
107 std %r10, 56(%r12)
108
109 # load up the pointer to the parm save area
110 mr %r7, %r12
111# else
112 # copy r2 to r11 and load TOC into r2
113 mr %r11, %r2
114 ld %r2, 16(%r2)
115
116 mflr %r0
117 # Save general regs into parm save area
118 # This is the parameter save area set up by our caller.
119 std %r3, PARMSAVE+0(%r1)
120 std %r4, PARMSAVE+8(%r1)
121 std %r5, PARMSAVE+16(%r1)
122 std %r6, PARMSAVE+24(%r1)
123 std %r7, PARMSAVE+32(%r1)
124 std %r8, PARMSAVE+40(%r1)
125 std %r9, PARMSAVE+48(%r1)
126 std %r10, PARMSAVE+56(%r1)
127
128 # load up the pointer to the parm save area
129 addi %r7, %r1, PARMSAVE
130# endif
131 std %r0, 16(%r1)
132
133 # closure->cif
134 ld %r3, FFI_TRAMPOLINE_SIZE(%r11)
135 # closure->fun
136 ld %r4, FFI_TRAMPOLINE_SIZE+8(%r11)
137 # closure->user_data
138 ld %r5, FFI_TRAMPOLINE_SIZE+16(%r11)
139
140.Ldoclosure:
141 # next save fpr 1 to fpr 13
142 stfd %f1, -104+(0*8)(%r1)
143 stfd %f2, -104+(1*8)(%r1)
144 stfd %f3, -104+(2*8)(%r1)
145 stfd %f4, -104+(3*8)(%r1)
146 stfd %f5, -104+(4*8)(%r1)
147 stfd %f6, -104+(5*8)(%r1)
148 stfd %f7, -104+(6*8)(%r1)
149 stfd %f8, -104+(7*8)(%r1)
150 stfd %f9, -104+(8*8)(%r1)
151 stfd %f10, -104+(9*8)(%r1)
152 stfd %f11, -104+(10*8)(%r1)
153 stfd %f12, -104+(11*8)(%r1)
154 stfd %f13, -104+(12*8)(%r1)
155
156 # load up the pointer to the saved fpr registers
157 addi %r8, %r1, -104
158
159# ifdef __VEC__
160 # load up the pointer to the saved vector registers
161 # 8 bytes padding for 16-byte alignment at -112(%r1)
162 addi %r9, %r8, -24
163 stvx %v13, 0, %r9
164 addi %r9, %r9, -16
165 stvx %v12, 0, %r9
166 addi %r9, %r9, -16
167 stvx %v11, 0, %r9
168 addi %r9, %r9, -16
169 stvx %v10, 0, %r9
170 addi %r9, %r9, -16
171 stvx %v9, 0, %r9
172 addi %r9, %r9, -16
173 stvx %v8, 0, %r9
174 addi %r9, %r9, -16
175 stvx %v7, 0, %r9
176 addi %r9, %r9, -16
177 stvx %v6, 0, %r9
178 addi %r9, %r9, -16
179 stvx %v5, 0, %r9
180 addi %r9, %r9, -16
181 stvx %v4, 0, %r9
182 addi %r9, %r9, -16
183 stvx %v3, 0, %r9
184 addi %r9, %r9, -16
185 stvx %v2, 0, %r9
186# endif
187
188 # load up the pointer to the result storage
189 addi %r6, %r1, -STACKFRAME+RETVAL
190
191 stdu %r1, -STACKFRAME(%r1)
192 .cfi_def_cfa_offset STACKFRAME
193 .cfi_offset 65, 16
194
195 # make the call
196# if defined _CALL_LINUX || _CALL_ELF == 2
197# ifdef __PCREL__
198 bl ffi_closure_helper_LINUX64@notoc
199.Lret:
200# else
201 bl ffi_closure_helper_LINUX64
202.Lret:
203 nop
204# endif
205# else
206 bl .ffi_closure_helper_LINUX64
207.Lret:
208 nop
209# endif
210
211 # now r3 contains the return type
212 # so use it to look up in a table
213 # so we know how to deal with each type
214
215 # look up the proper starting point in table
216 # by using return type as offset
217 ld %r0, STACKFRAME+16(%r1)
218 cmpldi %r3, FFI_V2_TYPE_SMALL_STRUCT
219 bge .Lsmall
220 mflr %r4 # move address of .Lret to r4
221 sldi %r3, %r3, 4 # now multiply return type by 16
222 addi %r4, %r4, .Lret_type0 - .Lret
223 add %r3, %r3, %r4 # add contents of table to table address
224 mtctr %r3
225 bctr # jump to it
226
227# Each of the ret_typeX code fragments has to be exactly 16 bytes long
228# (4 instructions). For cache effectiveness we align to a 16 byte boundary
229# first.
230 .align 4
231
232.Lret_type0:
233# case FFI_TYPE_VOID
234 mtlr %r0
235 addi %r1, %r1, STACKFRAME
236 .cfi_def_cfa_offset 0
237 blr
238 .cfi_def_cfa_offset STACKFRAME
239 nop
240# case FFI_TYPE_INT
241# ifdef __LITTLE_ENDIAN__
242 lwa %r3, RETVAL+0(%r1)
243# else
244 lwa %r3, RETVAL+4(%r1)
245# endif
246 mtlr %r0
247 addi %r1, %r1, STACKFRAME
248 .cfi_def_cfa_offset 0
249 blr
250 .cfi_def_cfa_offset STACKFRAME
251# case FFI_TYPE_FLOAT
252 lfs %f1, RETVAL+0(%r1)
253 mtlr %r0
254 addi %r1, %r1, STACKFRAME
255 .cfi_def_cfa_offset 0
256 blr
257 .cfi_def_cfa_offset STACKFRAME
258# case FFI_TYPE_DOUBLE
259 lfd %f1, RETVAL+0(%r1)
260 mtlr %r0
261 addi %r1, %r1, STACKFRAME
262 .cfi_def_cfa_offset 0
263 blr
264 .cfi_def_cfa_offset STACKFRAME
265# case FFI_TYPE_LONGDOUBLE
266 lfd %f1, RETVAL+0(%r1)
267 mtlr %r0
268 lfd %f2, RETVAL+8(%r1)
269 b .Lfinish
270# case FFI_TYPE_UINT8
271# ifdef __LITTLE_ENDIAN__
272 lbz %r3, RETVAL+0(%r1)
273# else
274 lbz %r3, RETVAL+7(%r1)
275# endif
276 mtlr %r0
277 addi %r1, %r1, STACKFRAME
278 .cfi_def_cfa_offset 0
279 blr
280 .cfi_def_cfa_offset STACKFRAME
281# case FFI_TYPE_SINT8
282# ifdef __LITTLE_ENDIAN__
283 lbz %r3, RETVAL+0(%r1)
284# else
285 lbz %r3, RETVAL+7(%r1)
286# endif
287 extsb %r3,%r3
288 mtlr %r0
289 b .Lfinish
290# case FFI_TYPE_UINT16
291# ifdef __LITTLE_ENDIAN__
292 lhz %r3, RETVAL+0(%r1)
293# else
294 lhz %r3, RETVAL+6(%r1)
295# endif
296 mtlr %r0
297.Lfinish:
298 addi %r1, %r1, STACKFRAME
299 .cfi_def_cfa_offset 0
300 blr
301 .cfi_def_cfa_offset STACKFRAME
302# case FFI_TYPE_SINT16
303# ifdef __LITTLE_ENDIAN__
304 lha %r3, RETVAL+0(%r1)
305# else
306 lha %r3, RETVAL+6(%r1)
307# endif
308 mtlr %r0
309 addi %r1, %r1, STACKFRAME
310 .cfi_def_cfa_offset 0
311 blr
312 .cfi_def_cfa_offset STACKFRAME
313# case FFI_TYPE_UINT32
314# ifdef __LITTLE_ENDIAN__
315 lwz %r3, RETVAL+0(%r1)
316# else
317 lwz %r3, RETVAL+4(%r1)
318# endif
319 mtlr %r0
320 addi %r1, %r1, STACKFRAME
321 .cfi_def_cfa_offset 0
322 blr
323 .cfi_def_cfa_offset STACKFRAME
324# case FFI_TYPE_SINT32
325# ifdef __LITTLE_ENDIAN__
326 lwa %r3, RETVAL+0(%r1)
327# else
328 lwa %r3, RETVAL+4(%r1)
329# endif
330 mtlr %r0
331 addi %r1, %r1, STACKFRAME
332 .cfi_def_cfa_offset 0
333 blr
334 .cfi_def_cfa_offset STACKFRAME
335# case FFI_TYPE_UINT64
336 ld %r3, RETVAL+0(%r1)
337 mtlr %r0
338 addi %r1, %r1, STACKFRAME
339 .cfi_def_cfa_offset 0
340 blr
341 .cfi_def_cfa_offset STACKFRAME
342# case FFI_TYPE_SINT64
343 ld %r3, RETVAL+0(%r1)
344 mtlr %r0
345 addi %r1, %r1, STACKFRAME
346 .cfi_def_cfa_offset 0
347 blr
348 .cfi_def_cfa_offset STACKFRAME
349# case FFI_TYPE_STRUCT
350 mtlr %r0
351 addi %r1, %r1, STACKFRAME
352 .cfi_def_cfa_offset 0
353 blr
354 .cfi_def_cfa_offset STACKFRAME
355 nop
356# case FFI_TYPE_POINTER
357 ld %r3, RETVAL+0(%r1)
358 mtlr %r0
359 addi %r1, %r1, STACKFRAME
360 .cfi_def_cfa_offset 0
361 blr
362 .cfi_def_cfa_offset STACKFRAME
363# case FFI_V2_TYPE_VECTOR
364 addi %r3, %r1, RETVAL
365 lvx %v2, 0, %r3
366 mtlr %r0
367 b .Lfinish
368# case FFI_V2_TYPE_VECTOR_HOMOG
369 addi %r3, %r1, RETVAL
370 lvx %v2, 0, %r3
371 addi %r3, %r3, 16
372 b .Lmorevector
373# case FFI_V2_TYPE_FLOAT_HOMOG
374 lfs %f1, RETVAL+0(%r1)
375 lfs %f2, RETVAL+4(%r1)
376 lfs %f3, RETVAL+8(%r1)
377 b .Lmorefloat
378# case FFI_V2_TYPE_DOUBLE_HOMOG
379 lfd %f1, RETVAL+0(%r1)
380 lfd %f2, RETVAL+8(%r1)
381 lfd %f3, RETVAL+16(%r1)
382 lfd %f4, RETVAL+24(%r1)
383 mtlr %r0
384 lfd %f5, RETVAL+32(%r1)
385 lfd %f6, RETVAL+40(%r1)
386 lfd %f7, RETVAL+48(%r1)
387 lfd %f8, RETVAL+56(%r1)
388 addi %r1, %r1, STACKFRAME
389 .cfi_def_cfa_offset 0
390 blr
391 .cfi_def_cfa_offset STACKFRAME
392.Lmorevector:
393 lvx %v3, 0, %r3
394 addi %r3, %r3, 16
395 lvx %v4, 0, %r3
396 addi %r3, %r3, 16
397 lvx %v5, 0, %r3
398 mtlr %r0
399 addi %r3, %r3, 16
400 lvx %v6, 0, %r3
401 addi %r3, %r3, 16
402 lvx %v7, 0, %r3
403 addi %r3, %r3, 16
404 lvx %v8, 0, %r3
405 addi %r3, %r3, 16
406 lvx %v9, 0, %r3
407 addi %r1, %r1, STACKFRAME
408 .cfi_def_cfa_offset 0
409 blr
410 .cfi_def_cfa_offset STACKFRAME
411.Lmorefloat:
412 lfs %f4, RETVAL+12(%r1)
413 mtlr %r0
414 lfs %f5, RETVAL+16(%r1)
415 lfs %f6, RETVAL+20(%r1)
416 lfs %f7, RETVAL+24(%r1)
417 lfs %f8, RETVAL+28(%r1)
418 addi %r1, %r1, STACKFRAME
419 .cfi_def_cfa_offset 0
420 blr
421 .cfi_def_cfa_offset STACKFRAME
422.Lsmall:
423# ifdef __LITTLE_ENDIAN__
424 ld %r3,RETVAL+0(%r1)
425 mtlr %r0
426 ld %r4,RETVAL+8(%r1)
427 addi %r1, %r1, STACKFRAME
428 .cfi_def_cfa_offset 0
429 blr
430# else
431 # A struct smaller than a dword is returned in the low bits of r3
432 # ie. right justified. Larger structs are passed left justified
433 # in r3 and r4. The return value area on the stack will have
434 # the structs as they are usually stored in memory.
435 cmpldi %r3, FFI_V2_TYPE_SMALL_STRUCT + 7 # size 8 bytes?
436 neg %r5, %r3
437 ld %r3,RETVAL+0(%r1)
438 blt .Lsmalldown
439 mtlr %r0
440 ld %r4,RETVAL+8(%r1)
441 addi %r1, %r1, STACKFRAME
442 .cfi_def_cfa_offset 0
443 blr
444 .cfi_def_cfa_offset STACKFRAME
445.Lsmalldown:
446 addi %r5, %r5, FFI_V2_TYPE_SMALL_STRUCT + 7
447 mtlr %r0
448 sldi %r5, %r5, 3
449 addi %r1, %r1, STACKFRAME
450 .cfi_def_cfa_offset 0
451 srd %r3, %r3, %r5
452 blr
453# endif
454
455 .cfi_endproc
456# if _CALL_ELF == 2
457 .size ffi_closure_LINUX64,.-ffi_closure_LINUX64
458# else
459# ifdef _CALL_LINUX
460 .size ffi_closure_LINUX64,.-.L.ffi_closure_LINUX64
461# else
462 .long 0
463 .byte 0,12,0,1,128,0,0,0
464 .size .ffi_closure_LINUX64,.-.ffi_closure_LINUX64
465# endif
466# endif
467
468
469 FFI_HIDDEN (ffi_go_closure_linux64)
470 .globl ffi_go_closure_linux64
471 .text
472 .cfi_startproc
473# if _CALL_ELF == 2
474ffi_go_closure_linux64:
475# ifndef __PCREL__
476 addis %r2, %r12, .TOC.-ffi_go_closure_linux64@ha
477 addi %r2, %r2, .TOC.-ffi_go_closure_linux64@l
478# endif
479 .localentry ffi_go_closure_linux64, . - ffi_go_closure_linux64
480# else
481 .section ".opd","aw"
482 .align 3
483ffi_go_closure_linux64:
484# ifdef _CALL_LINUX
485 .quad .L.ffi_go_closure_linux64,.TOC.@tocbase,0
486 .type ffi_go_closure_linux64,@function
487 .text
488.L.ffi_go_closure_linux64:
489# else
490 FFI_HIDDEN (.ffi_go_closure_linux64)
491 .globl .ffi_go_closure_linux64
492 .quad .ffi_go_closure_linux64,.TOC.@tocbase,0
493 .size ffi_go_closure_linux64,24
494 .type .ffi_go_closure_linux64,@function
495 .text
496.ffi_go_closure_linux64:
497# endif
498# endif
499
500# if _CALL_ELF == 2
501 ld %r12, 8(%r11) # closure->cif
502 mflr %r0
503 lwz %r12, 28(%r12) # cif->flags
504 mtcrf 0x40, %r12
505 addi %r12, %r1, PARMSAVE
506 bt 7, 0f
507 # Our caller has not allocated a parameter save area.
508 # We need to allocate one here and use it to pass gprs to
509 # ffi_closure_helper_LINUX64.
510 addi %r12, %r1, -STACKFRAME+PARMSAVE
5110:
512 # Save general regs into parm save area
513 std %r3, 0(%r12)
514 std %r4, 8(%r12)
515 std %r5, 16(%r12)
516 std %r6, 24(%r12)
517 std %r7, 32(%r12)
518 std %r8, 40(%r12)
519 std %r9, 48(%r12)
520 std %r10, 56(%r12)
521
522 # load up the pointer to the parm save area
523 mr %r7, %r12
524# else
525 mflr %r0
526 # Save general regs into parm save area
527 # This is the parameter save area set up by our caller.
528 std %r3, PARMSAVE+0(%r1)
529 std %r4, PARMSAVE+8(%r1)
530 std %r5, PARMSAVE+16(%r1)
531 std %r6, PARMSAVE+24(%r1)
532 std %r7, PARMSAVE+32(%r1)
533 std %r8, PARMSAVE+40(%r1)
534 std %r9, PARMSAVE+48(%r1)
535 std %r10, PARMSAVE+56(%r1)
536
537 # load up the pointer to the parm save area
538 addi %r7, %r1, PARMSAVE
539# endif
540 std %r0, 16(%r1)
541
542 # closure->cif
543 ld %r3, 8(%r11)
544 # closure->fun
545 ld %r4, 16(%r11)
546 # user_data
547 mr %r5, %r11
548 b .Ldoclosure
549
550 .cfi_endproc
551# if _CALL_ELF == 2
552 .size ffi_go_closure_linux64,.-ffi_go_closure_linux64
553# else
554# ifdef _CALL_LINUX
555 .size ffi_go_closure_linux64,.-.L.ffi_go_closure_linux64
556# else
557 .long 0
558 .byte 0,12,0,1,128,0,0,0
559 .size .ffi_go_closure_linux64,.-.ffi_go_closure_linux64
560# endif
561# endif
562#endif
563
564#if (defined __ELF__ && defined __linux__) || _CALL_ELF == 2
565 .section .note.GNU-stack,"",@progbits
566#endif