1 /* -----------------------------------------------------------------------
2 sysv.h - Copyright (c) 2003 Jakub Jelinek <jakub@redhat.com>
3 Copyright (c) 2008 Red Hat, Inc.
5 PowerPC64 Assembly glue.
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:
15 The above copyright notice and this permission notice shall be included
16 in all copies or substantial portions of the Software.
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 ----------------------------------------------------------------------- */
28 #include <fficonfig.h>
31 .file "linux64_closure.S"
36 FFI_HIDDEN (ffi_closure_LINUX64)
37 .globl ffi_closure_LINUX64
43 addis %r2, %r12, .TOC.-ffi_closure_LINUX64@ha
44 addi %r2, %r2, .TOC.-ffi_closure_LINUX64@l
46 .localentry ffi_closure_LINUX64, . - ffi_closure_LINUX64
52 .quad .L.ffi_closure_LINUX64,.TOC.@tocbase,0
53 .type ffi_closure_LINUX64,@function
55 .L.ffi_closure_LINUX64:
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
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
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
78 # define RETVAL PARMSAVE+64
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
84 # define RETVAL PARMSAVE+64
88 ld %r12, FFI_TRAMPOLINE_SIZE(%r11) # closure->cif
90 lwz %r12, 28(%r12) # cif->flags
92 addi %r12, %r1, PARMSAVE
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
99 # Save general regs into parm save area
109 # load up the pointer to the parm save area
112 # copy r2 to r11 and load TOC into r2
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)
128 # load up the pointer to the parm save area
129 addi %r7, %r1, PARMSAVE
134 ld %r3, FFI_TRAMPOLINE_SIZE(%r11)
136 ld %r4, FFI_TRAMPOLINE_SIZE+8(%r11)
138 ld %r5, FFI_TRAMPOLINE_SIZE+16(%r11)
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)
156 # load up the pointer to the saved fpr registers
160 # load up the pointer to the saved vector registers
161 # 8 bytes padding for 16-byte alignment at -112(%r1)
188 # load up the pointer to the result storage
189 addi %r6, %r1, -STACKFRAME+RETVAL
191 stdu %r1, -STACKFRAME(%r1)
192 .cfi_def_cfa_offset STACKFRAME
196 # if defined _CALL_LINUX || _CALL_ELF == 2
198 bl ffi_closure_helper_LINUX64@notoc
201 bl ffi_closure_helper_LINUX64
206 bl .ffi_closure_helper_LINUX64
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
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
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
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
235 addi %r1, %r1, STACKFRAME
236 .cfi_def_cfa_offset 0
238 .cfi_def_cfa_offset STACKFRAME
241 # ifdef __LITTLE_ENDIAN__
242 lwa %r3, RETVAL+0(%r1)
244 lwa %r3, RETVAL+4(%r1)
247 addi %r1, %r1, STACKFRAME
248 .cfi_def_cfa_offset 0
250 .cfi_def_cfa_offset STACKFRAME
251 # case FFI_TYPE_FLOAT
252 lfs %f1, RETVAL+0(%r1)
254 addi %r1, %r1, STACKFRAME
255 .cfi_def_cfa_offset 0
257 .cfi_def_cfa_offset STACKFRAME
258 # case FFI_TYPE_DOUBLE
259 lfd %f1, RETVAL+0(%r1)
261 addi %r1, %r1, STACKFRAME
262 .cfi_def_cfa_offset 0
264 .cfi_def_cfa_offset STACKFRAME
265 # case FFI_TYPE_LONGDOUBLE
266 lfd %f1, RETVAL+0(%r1)
268 lfd %f2, RETVAL+8(%r1)
270 # case FFI_TYPE_UINT8
271 # ifdef __LITTLE_ENDIAN__
272 lbz %r3, RETVAL+0(%r1)
274 lbz %r3, RETVAL+7(%r1)
277 addi %r1, %r1, STACKFRAME
278 .cfi_def_cfa_offset 0
280 .cfi_def_cfa_offset STACKFRAME
281 # case FFI_TYPE_SINT8
282 # ifdef __LITTLE_ENDIAN__
283 lbz %r3, RETVAL+0(%r1)
285 lbz %r3, RETVAL+7(%r1)
290 # case FFI_TYPE_UINT16
291 # ifdef __LITTLE_ENDIAN__
292 lhz %r3, RETVAL+0(%r1)
294 lhz %r3, RETVAL+6(%r1)
298 addi %r1, %r1, STACKFRAME
299 .cfi_def_cfa_offset 0
301 .cfi_def_cfa_offset STACKFRAME
302 # case FFI_TYPE_SINT16
303 # ifdef __LITTLE_ENDIAN__
304 lha %r3, RETVAL+0(%r1)
306 lha %r3, RETVAL+6(%r1)
309 addi %r1, %r1, STACKFRAME
310 .cfi_def_cfa_offset 0
312 .cfi_def_cfa_offset STACKFRAME
313 # case FFI_TYPE_UINT32
314 # ifdef __LITTLE_ENDIAN__
315 lwz %r3, RETVAL+0(%r1)
317 lwz %r3, RETVAL+4(%r1)
320 addi %r1, %r1, STACKFRAME
321 .cfi_def_cfa_offset 0
323 .cfi_def_cfa_offset STACKFRAME
324 # case FFI_TYPE_SINT32
325 # ifdef __LITTLE_ENDIAN__
326 lwa %r3, RETVAL+0(%r1)
328 lwa %r3, RETVAL+4(%r1)
331 addi %r1, %r1, STACKFRAME
332 .cfi_def_cfa_offset 0
334 .cfi_def_cfa_offset STACKFRAME
335 # case FFI_TYPE_UINT64
336 ld %r3, RETVAL+0(%r1)
338 addi %r1, %r1, STACKFRAME
339 .cfi_def_cfa_offset 0
341 .cfi_def_cfa_offset STACKFRAME
342 # case FFI_TYPE_SINT64
343 ld %r3, RETVAL+0(%r1)
345 addi %r1, %r1, STACKFRAME
346 .cfi_def_cfa_offset 0
348 .cfi_def_cfa_offset STACKFRAME
349 # case FFI_TYPE_STRUCT
351 addi %r1, %r1, STACKFRAME
352 .cfi_def_cfa_offset 0
354 .cfi_def_cfa_offset STACKFRAME
356 # case FFI_TYPE_POINTER
357 ld %r3, RETVAL+0(%r1)
359 addi %r1, %r1, STACKFRAME
360 .cfi_def_cfa_offset 0
362 .cfi_def_cfa_offset STACKFRAME
363 # case FFI_V2_TYPE_VECTOR
364 addi %r3, %r1, RETVAL
368 # case FFI_V2_TYPE_VECTOR_HOMOG
369 addi %r3, %r1, RETVAL
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)
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)
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
391 .cfi_def_cfa_offset STACKFRAME
407 addi %r1, %r1, STACKFRAME
408 .cfi_def_cfa_offset 0
410 .cfi_def_cfa_offset STACKFRAME
412 lfs %f4, RETVAL+12(%r1)
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
421 .cfi_def_cfa_offset STACKFRAME
423 # ifdef __LITTLE_ENDIAN__
427 addi %r1, %r1, STACKFRAME
428 .cfi_def_cfa_offset 0
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?
441 addi %r1, %r1, STACKFRAME
442 .cfi_def_cfa_offset 0
444 .cfi_def_cfa_offset STACKFRAME
446 addi %r5, %r5, FFI_V2_TYPE_SMALL_STRUCT + 7
449 addi %r1, %r1, STACKFRAME
450 .cfi_def_cfa_offset 0
457 .size ffi_closure_LINUX64,.-ffi_closure_LINUX64
460 .size ffi_closure_LINUX64,.-.L.ffi_closure_LINUX64
463 .byte 0,12,0,1,128,0,0,0
464 .size .ffi_closure_LINUX64,.-.ffi_closure_LINUX64
469 FFI_HIDDEN (ffi_go_closure_linux64)
470 .globl ffi_go_closure_linux64
474 ffi_go_closure_linux64:
476 addis %r2, %r12, .TOC.-ffi_go_closure_linux64@ha
477 addi %r2, %r2, .TOC.-ffi_go_closure_linux64@l
479 .localentry ffi_go_closure_linux64, . - ffi_go_closure_linux64
483 ffi_go_closure_linux64:
485 .quad .L.ffi_go_closure_linux64,.TOC.@tocbase,0
486 .type ffi_go_closure_linux64,@function
488 .L.ffi_go_closure_linux64:
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
496 .ffi_go_closure_linux64:
501 ld %r12, 8(%r11) # closure->cif
503 lwz %r12, 28(%r12) # cif->flags
505 addi %r12, %r1, PARMSAVE
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
512 # Save general regs into parm save area
522 # load up the pointer to the parm save area
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)
537 # load up the pointer to the parm save area
538 addi %r7, %r1, PARMSAVE
552 .size ffi_go_closure_linux64,.-ffi_go_closure_linux64
555 .size ffi_go_closure_linux64,.-.L.ffi_go_closure_linux64
558 .byte 0,12,0,1,128,0,0,0
559 .size .ffi_go_closure_linux64,.-.ffi_go_closure_linux64
564 #if (defined __ELF__ && defined __linux__) || _CALL_ELF == 2
565 .section .note.GNU-stack,"",@progbits