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"
34 FFI_HIDDEN (ffi_closure_LINUX64)
35 .globl ffi_closure_LINUX64
41 addis %r2, %r12, .TOC.-ffi_closure_LINUX64@ha
42 addi %r2, %r2, .TOC.-ffi_closure_LINUX64@l
44 .localentry ffi_closure_LINUX64, . - ffi_closure_LINUX64
50 .quad .L.ffi_closure_LINUX64,.TOC.@tocbase,0
51 .type ffi_closure_LINUX64,@function
53 .L.ffi_closure_LINUX64:
55 FFI_HIDDEN (.ffi_closure_LINUX64)
56 .globl .ffi_closure_LINUX64
57 .quad .ffi_closure_LINUX64,.TOC.@tocbase,0
58 .size ffi_closure_LINUX64,24
59 .type .ffi_closure_LINUX64,@function
66 # 32 byte special reg save area + 64 byte parm save area
67 # + 64 byte retval area + 13*8 fpr save area + round to 16
68 # define STACKFRAME 272
70 # define RETVAL PARMSAVE+64
72 # 48 bytes special reg save area + 64 bytes parm save area
73 # + 16 bytes retval area + 13*8 bytes fpr save area + round to 16
74 # define STACKFRAME 240
76 # define RETVAL PARMSAVE+64
80 ld %r12, FFI_TRAMPOLINE_SIZE(%r11) # closure->cif
82 lwz %r12, 28(%r12) # cif->flags
84 addi %r12, %r1, PARMSAVE
86 # Our caller has not allocated a parameter save area.
87 # We need to allocate one here and use it to pass gprs to
88 # ffi_closure_helper_LINUX64.
89 addi %r12, %r1, -STACKFRAME+PARMSAVE
91 # Save general regs into parm save area
101 # load up the pointer to the parm save area
104 # copy r2 to r11 and load TOC into r2
109 # Save general regs into parm save area
110 # This is the parameter save area set up by our caller.
111 std %r3, PARMSAVE+0(%r1)
112 std %r4, PARMSAVE+8(%r1)
113 std %r5, PARMSAVE+16(%r1)
114 std %r6, PARMSAVE+24(%r1)
115 std %r7, PARMSAVE+32(%r1)
116 std %r8, PARMSAVE+40(%r1)
117 std %r9, PARMSAVE+48(%r1)
118 std %r10, PARMSAVE+56(%r1)
120 # load up the pointer to the parm save area
121 addi %r7, %r1, PARMSAVE
126 ld %r3, FFI_TRAMPOLINE_SIZE(%r11)
128 ld %r4, FFI_TRAMPOLINE_SIZE+8(%r11)
130 ld %r5, FFI_TRAMPOLINE_SIZE+16(%r11)
133 # next save fpr 1 to fpr 13
134 stfd %f1, -104+(0*8)(%r1)
135 stfd %f2, -104+(1*8)(%r1)
136 stfd %f3, -104+(2*8)(%r1)
137 stfd %f4, -104+(3*8)(%r1)
138 stfd %f5, -104+(4*8)(%r1)
139 stfd %f6, -104+(5*8)(%r1)
140 stfd %f7, -104+(6*8)(%r1)
141 stfd %f8, -104+(7*8)(%r1)
142 stfd %f9, -104+(8*8)(%r1)
143 stfd %f10, -104+(9*8)(%r1)
144 stfd %f11, -104+(10*8)(%r1)
145 stfd %f12, -104+(11*8)(%r1)
146 stfd %f13, -104+(12*8)(%r1)
148 # load up the pointer to the saved fpr registers
151 # load up the pointer to the result storage
152 addi %r6, %r1, -STACKFRAME+RETVAL
154 stdu %r1, -STACKFRAME(%r1)
155 .cfi_def_cfa_offset STACKFRAME
159 # if defined _CALL_LINUX || _CALL_ELF == 2
161 bl ffi_closure_helper_LINUX64@notoc
164 bl ffi_closure_helper_LINUX64
169 bl .ffi_closure_helper_LINUX64
174 # now r3 contains the return type
175 # so use it to look up in a table
176 # so we know how to deal with each type
178 # look up the proper starting point in table
179 # by using return type as offset
180 ld %r0, STACKFRAME+16(%r1)
181 cmpldi %r3, FFI_V2_TYPE_SMALL_STRUCT
183 mflr %r4 # move address of .Lret to r4
184 sldi %r3, %r3, 4 # now multiply return type by 16
185 addi %r4, %r4, .Lret_type0 - .Lret
186 add %r3, %r3, %r4 # add contents of table to table address
190 # Each of the ret_typeX code fragments has to be exactly 16 bytes long
191 # (4 instructions). For cache effectiveness we align to a 16 byte boundary
198 addi %r1, %r1, STACKFRAME
199 .cfi_def_cfa_offset 0
201 .cfi_def_cfa_offset STACKFRAME
204 # ifdef __LITTLE_ENDIAN__
205 lwa %r3, RETVAL+0(%r1)
207 lwa %r3, RETVAL+4(%r1)
210 addi %r1, %r1, STACKFRAME
211 .cfi_def_cfa_offset 0
213 .cfi_def_cfa_offset STACKFRAME
214 # case FFI_TYPE_FLOAT
215 lfs %f1, RETVAL+0(%r1)
217 addi %r1, %r1, STACKFRAME
218 .cfi_def_cfa_offset 0
220 .cfi_def_cfa_offset STACKFRAME
221 # case FFI_TYPE_DOUBLE
222 lfd %f1, RETVAL+0(%r1)
224 addi %r1, %r1, STACKFRAME
225 .cfi_def_cfa_offset 0
227 .cfi_def_cfa_offset STACKFRAME
228 # case FFI_TYPE_LONGDOUBLE
229 lfd %f1, RETVAL+0(%r1)
231 lfd %f2, RETVAL+8(%r1)
233 # case FFI_TYPE_UINT8
234 # ifdef __LITTLE_ENDIAN__
235 lbz %r3, RETVAL+0(%r1)
237 lbz %r3, RETVAL+7(%r1)
240 addi %r1, %r1, STACKFRAME
241 .cfi_def_cfa_offset 0
243 .cfi_def_cfa_offset STACKFRAME
244 # case FFI_TYPE_SINT8
245 # ifdef __LITTLE_ENDIAN__
246 lbz %r3, RETVAL+0(%r1)
248 lbz %r3, RETVAL+7(%r1)
253 # case FFI_TYPE_UINT16
254 # ifdef __LITTLE_ENDIAN__
255 lhz %r3, RETVAL+0(%r1)
257 lhz %r3, RETVAL+6(%r1)
261 addi %r1, %r1, STACKFRAME
262 .cfi_def_cfa_offset 0
264 .cfi_def_cfa_offset STACKFRAME
265 # case FFI_TYPE_SINT16
266 # ifdef __LITTLE_ENDIAN__
267 lha %r3, RETVAL+0(%r1)
269 lha %r3, RETVAL+6(%r1)
272 addi %r1, %r1, STACKFRAME
273 .cfi_def_cfa_offset 0
275 .cfi_def_cfa_offset STACKFRAME
276 # case FFI_TYPE_UINT32
277 # ifdef __LITTLE_ENDIAN__
278 lwz %r3, RETVAL+0(%r1)
280 lwz %r3, RETVAL+4(%r1)
283 addi %r1, %r1, STACKFRAME
284 .cfi_def_cfa_offset 0
286 .cfi_def_cfa_offset STACKFRAME
287 # case FFI_TYPE_SINT32
288 # ifdef __LITTLE_ENDIAN__
289 lwa %r3, RETVAL+0(%r1)
291 lwa %r3, RETVAL+4(%r1)
294 addi %r1, %r1, STACKFRAME
295 .cfi_def_cfa_offset 0
297 .cfi_def_cfa_offset STACKFRAME
298 # case FFI_TYPE_UINT64
299 ld %r3, RETVAL+0(%r1)
301 addi %r1, %r1, STACKFRAME
302 .cfi_def_cfa_offset 0
304 .cfi_def_cfa_offset STACKFRAME
305 # case FFI_TYPE_SINT64
306 ld %r3, RETVAL+0(%r1)
308 addi %r1, %r1, STACKFRAME
309 .cfi_def_cfa_offset 0
311 .cfi_def_cfa_offset STACKFRAME
312 # case FFI_TYPE_STRUCT
314 addi %r1, %r1, STACKFRAME
315 .cfi_def_cfa_offset 0
317 .cfi_def_cfa_offset STACKFRAME
319 # case FFI_TYPE_POINTER
320 ld %r3, RETVAL+0(%r1)
322 addi %r1, %r1, STACKFRAME
323 .cfi_def_cfa_offset 0
325 .cfi_def_cfa_offset STACKFRAME
326 # case FFI_V2_TYPE_FLOAT_HOMOG
327 lfs %f1, RETVAL+0(%r1)
328 lfs %f2, RETVAL+4(%r1)
329 lfs %f3, RETVAL+8(%r1)
331 # case FFI_V2_TYPE_DOUBLE_HOMOG
332 lfd %f1, RETVAL+0(%r1)
333 lfd %f2, RETVAL+8(%r1)
334 lfd %f3, RETVAL+16(%r1)
335 lfd %f4, RETVAL+24(%r1)
337 lfd %f5, RETVAL+32(%r1)
338 lfd %f6, RETVAL+40(%r1)
339 lfd %f7, RETVAL+48(%r1)
340 lfd %f8, RETVAL+56(%r1)
341 addi %r1, %r1, STACKFRAME
342 .cfi_def_cfa_offset 0
344 .cfi_def_cfa_offset STACKFRAME
346 lfs %f4, RETVAL+12(%r1)
348 lfs %f5, RETVAL+16(%r1)
349 lfs %f6, RETVAL+20(%r1)
350 lfs %f7, RETVAL+24(%r1)
351 lfs %f8, RETVAL+28(%r1)
352 addi %r1, %r1, STACKFRAME
353 .cfi_def_cfa_offset 0
355 .cfi_def_cfa_offset STACKFRAME
357 # ifdef __LITTLE_ENDIAN__
361 addi %r1, %r1, STACKFRAME
362 .cfi_def_cfa_offset 0
365 # A struct smaller than a dword is returned in the low bits of r3
366 # ie. right justified. Larger structs are passed left justified
367 # in r3 and r4. The return value area on the stack will have
368 # the structs as they are usually stored in memory.
369 cmpldi %r3, FFI_V2_TYPE_SMALL_STRUCT + 7 # size 8 bytes?
375 addi %r1, %r1, STACKFRAME
376 .cfi_def_cfa_offset 0
378 .cfi_def_cfa_offset STACKFRAME
380 addi %r5, %r5, FFI_V2_TYPE_SMALL_STRUCT + 7
383 addi %r1, %r1, STACKFRAME
384 .cfi_def_cfa_offset 0
391 .size ffi_closure_LINUX64,.-ffi_closure_LINUX64
394 .size ffi_closure_LINUX64,.-.L.ffi_closure_LINUX64
397 .byte 0,12,0,1,128,0,0,0
398 .size .ffi_closure_LINUX64,.-.ffi_closure_LINUX64
403 FFI_HIDDEN (ffi_go_closure_linux64)
404 .globl ffi_go_closure_linux64
408 ffi_go_closure_linux64:
410 addis %r2, %r12, .TOC.-ffi_go_closure_linux64@ha
411 addi %r2, %r2, .TOC.-ffi_go_closure_linux64@l
413 .localentry ffi_go_closure_linux64, . - ffi_go_closure_linux64
417 ffi_go_closure_linux64:
419 .quad .L.ffi_go_closure_linux64,.TOC.@tocbase,0
420 .type ffi_go_closure_linux64,@function
422 .L.ffi_go_closure_linux64:
424 FFI_HIDDEN (.ffi_go_closure_linux64)
425 .globl .ffi_go_closure_linux64
426 .quad .ffi_go_closure_linux64,.TOC.@tocbase,0
427 .size ffi_go_closure_linux64,24
428 .type .ffi_go_closure_linux64,@function
430 .ffi_go_closure_linux64:
435 ld %r12, 8(%r11) # closure->cif
437 lwz %r12, 28(%r12) # cif->flags
439 addi %r12, %r1, PARMSAVE
441 # Our caller has not allocated a parameter save area.
442 # We need to allocate one here and use it to pass gprs to
443 # ffi_closure_helper_LINUX64.
444 addi %r12, %r1, -STACKFRAME+PARMSAVE
446 # Save general regs into parm save area
456 # load up the pointer to the parm save area
460 # Save general regs into parm save area
461 # This is the parameter save area set up by our caller.
462 std %r3, PARMSAVE+0(%r1)
463 std %r4, PARMSAVE+8(%r1)
464 std %r5, PARMSAVE+16(%r1)
465 std %r6, PARMSAVE+24(%r1)
466 std %r7, PARMSAVE+32(%r1)
467 std %r8, PARMSAVE+40(%r1)
468 std %r9, PARMSAVE+48(%r1)
469 std %r10, PARMSAVE+56(%r1)
471 # load up the pointer to the parm save area
472 addi %r7, %r1, PARMSAVE
486 .size ffi_go_closure_linux64,.-ffi_go_closure_linux64
489 .size ffi_go_closure_linux64,.-.L.ffi_go_closure_linux64
492 .byte 0,12,0,1,128,0,0,0
493 .size .ffi_go_closure_linux64,.-.ffi_go_closure_linux64
498 #if (defined __ELF__ && defined __linux__) || _CALL_ELF == 2
499 .section .note.GNU-stack,"",@progbits