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
39 addis %r2, %r12, .TOC.-ffi_closure_LINUX64@ha
40 addi %r2, %r2, .TOC.-ffi_closure_LINUX64@l
41 .localentry ffi_closure_LINUX64, . - ffi_closure_LINUX64
47 .quad .L.ffi_closure_LINUX64,.TOC.@tocbase,0
48 .type ffi_closure_LINUX64,@function
50 .L.ffi_closure_LINUX64:
52 FFI_HIDDEN (.ffi_closure_LINUX64)
53 .globl .ffi_closure_LINUX64
54 .quad .ffi_closure_LINUX64,.TOC.@tocbase,0
55 .size ffi_closure_LINUX64,24
56 .type .ffi_closure_LINUX64,@function
63 # 32 byte special reg save area + 64 byte parm save area
64 # + 64 byte retval area + 13*8 fpr save area + round to 16
65 # define STACKFRAME 272
67 # define RETVAL PARMSAVE+64
69 # 48 bytes special reg save area + 64 bytes parm save area
70 # + 16 bytes retval area + 13*8 bytes fpr save area + round to 16
71 # define STACKFRAME 240
73 # define RETVAL PARMSAVE+64
78 ld %r12, FFI_TRAMPOLINE_SIZE(%r11) # closure->cif
80 lwz %r12, 28(%r12) # cif->flags
82 addi %r12, %r1, PARMSAVE
84 # Our caller has not allocated a parameter save area.
85 # We need to allocate one here and use it to pass gprs to
86 # ffi_closure_helper_LINUX64.
87 addi %r12, %r1, -STACKFRAME+PARMSAVE
90 # Save general regs into parm save area
100 # load up the pointer to the parm save area
103 # copy r2 to r11 and load TOC into r2
108 # Save general regs into parm save area
109 # This is the parameter save area set up by our caller.
110 std %r3, PARMSAVE+0(%r1)
111 std %r4, PARMSAVE+8(%r1)
112 std %r5, PARMSAVE+16(%r1)
113 std %r6, PARMSAVE+24(%r1)
114 std %r7, PARMSAVE+32(%r1)
115 std %r8, PARMSAVE+40(%r1)
116 std %r9, PARMSAVE+48(%r1)
117 std %r10, PARMSAVE+56(%r1)
121 # load up the pointer to the parm save area
122 addi %r5, %r1, PARMSAVE
125 # next save fpr 1 to fpr 13
126 stfd %f1, -104+(0*8)(%r1)
127 stfd %f2, -104+(1*8)(%r1)
128 stfd %f3, -104+(2*8)(%r1)
129 stfd %f4, -104+(3*8)(%r1)
130 stfd %f5, -104+(4*8)(%r1)
131 stfd %f6, -104+(5*8)(%r1)
132 stfd %f7, -104+(6*8)(%r1)
133 stfd %f8, -104+(7*8)(%r1)
134 stfd %f9, -104+(8*8)(%r1)
135 stfd %f10, -104+(9*8)(%r1)
136 stfd %f11, -104+(10*8)(%r1)
137 stfd %f12, -104+(11*8)(%r1)
138 stfd %f13, -104+(12*8)(%r1)
140 # load up the pointer to the saved fpr registers */
143 # load up the pointer to the result storage
144 addi %r4, %r1, -STACKFRAME+RETVAL
146 stdu %r1, -STACKFRAME(%r1)
149 # get the context pointer from the trampoline
153 # if defined _CALL_LINUX || _CALL_ELF == 2
154 bl ffi_closure_helper_LINUX64
156 bl .ffi_closure_helper_LINUX64
160 # now r3 contains the return type
161 # so use it to look up in a table
162 # so we know how to deal with each type
164 # look up the proper starting point in table
165 # by using return type as offset
166 ld %r0, STACKFRAME+16(%r1)
167 cmpldi %r3, FFI_V2_TYPE_SMALL_STRUCT
169 mflr %r4 # move address of .Lret to r4
170 sldi %r3, %r3, 4 # now multiply return type by 16
171 addi %r4, %r4, .Lret_type0 - .Lret
172 add %r3, %r3, %r4 # add contents of table to table address
176 # Each of the ret_typeX code fragments has to be exactly 16 bytes long
177 # (4 instructions). For cache effectiveness we align to a 16 byte boundary
184 addi %r1, %r1, STACKFRAME
188 # ifdef __LITTLE_ENDIAN__
189 lwa %r3, RETVAL+0(%r1)
191 lwa %r3, RETVAL+4(%r1)
194 addi %r1, %r1, STACKFRAME
196 # case FFI_TYPE_FLOAT
197 lfs %f1, RETVAL+0(%r1)
199 addi %r1, %r1, STACKFRAME
201 # case FFI_TYPE_DOUBLE
202 lfd %f1, RETVAL+0(%r1)
204 addi %r1, %r1, STACKFRAME
206 # case FFI_TYPE_LONGDOUBLE
207 lfd %f1, RETVAL+0(%r1)
209 lfd %f2, RETVAL+8(%r1)
211 # case FFI_TYPE_UINT8
212 # ifdef __LITTLE_ENDIAN__
213 lbz %r3, RETVAL+0(%r1)
215 lbz %r3, RETVAL+7(%r1)
218 addi %r1, %r1, STACKFRAME
220 # case FFI_TYPE_SINT8
221 # ifdef __LITTLE_ENDIAN__
222 lbz %r3, RETVAL+0(%r1)
224 lbz %r3, RETVAL+7(%r1)
229 # case FFI_TYPE_UINT16
230 # ifdef __LITTLE_ENDIAN__
231 lhz %r3, RETVAL+0(%r1)
233 lhz %r3, RETVAL+6(%r1)
237 addi %r1, %r1, STACKFRAME
239 # case FFI_TYPE_SINT16
240 # ifdef __LITTLE_ENDIAN__
241 lha %r3, RETVAL+0(%r1)
243 lha %r3, RETVAL+6(%r1)
246 addi %r1, %r1, STACKFRAME
248 # case FFI_TYPE_UINT32
249 # ifdef __LITTLE_ENDIAN__
250 lwz %r3, RETVAL+0(%r1)
252 lwz %r3, RETVAL+4(%r1)
255 addi %r1, %r1, STACKFRAME
257 # case FFI_TYPE_SINT32
258 # ifdef __LITTLE_ENDIAN__
259 lwa %r3, RETVAL+0(%r1)
261 lwa %r3, RETVAL+4(%r1)
264 addi %r1, %r1, STACKFRAME
266 # case FFI_TYPE_UINT64
267 ld %r3, RETVAL+0(%r1)
269 addi %r1, %r1, STACKFRAME
271 # case FFI_TYPE_SINT64
272 ld %r3, RETVAL+0(%r1)
274 addi %r1, %r1, STACKFRAME
276 # case FFI_TYPE_STRUCT
278 addi %r1, %r1, STACKFRAME
281 # case FFI_TYPE_POINTER
282 ld %r3, RETVAL+0(%r1)
284 addi %r1, %r1, STACKFRAME
286 # case FFI_V2_TYPE_FLOAT_HOMOG
287 lfs %f1, RETVAL+0(%r1)
288 lfs %f2, RETVAL+4(%r1)
289 lfs %f3, RETVAL+8(%r1)
291 # case FFI_V2_TYPE_DOUBLE_HOMOG
292 lfd %f1, RETVAL+0(%r1)
293 lfd %f2, RETVAL+8(%r1)
294 lfd %f3, RETVAL+16(%r1)
295 lfd %f4, RETVAL+24(%r1)
297 lfd %f5, RETVAL+32(%r1)
298 lfd %f6, RETVAL+40(%r1)
299 lfd %f7, RETVAL+48(%r1)
300 lfd %f8, RETVAL+56(%r1)
301 addi %r1, %r1, STACKFRAME
304 lfs %f4, RETVAL+12(%r1)
306 lfs %f5, RETVAL+16(%r1)
307 lfs %f6, RETVAL+20(%r1)
308 lfs %f7, RETVAL+24(%r1)
309 lfs %f8, RETVAL+28(%r1)
310 addi %r1, %r1, STACKFRAME
313 # ifdef __LITTLE_ENDIAN__
317 addi %r1, %r1, STACKFRAME
320 # A struct smaller than a dword is returned in the low bits of r3
321 # ie. right justified. Larger structs are passed left justified
322 # in r3 and r4. The return value area on the stack will have
323 # the structs as they are usually stored in memory.
324 cmpldi %r3, FFI_V2_TYPE_SMALL_STRUCT + 7 # size 8 bytes?
330 addi %r1, %r1, STACKFRAME
333 addi %r5, %r5, FFI_V2_TYPE_SMALL_STRUCT + 7
336 addi %r1, %r1, STACKFRAME
343 .byte 0,12,0,1,128,0,0,0
345 .size ffi_closure_LINUX64,.-ffi_closure_LINUX64
348 .size ffi_closure_LINUX64,.-.L.ffi_closure_LINUX64
350 .size .ffi_closure_LINUX64,.-.ffi_closure_LINUX64
354 .section .eh_frame,EH_FRAME_FLAGS,@progbits
356 .4byte .LECIE1-.LSCIE1 # Length of Common Information Entry
358 .4byte 0x0 # CIE Identifier Tag
359 .byte 0x1 # CIE Version
360 .ascii "zR\0" # CIE Augmentation
361 .uleb128 0x1 # CIE Code Alignment Factor
362 .sleb128 -8 # CIE Data Alignment Factor
363 .byte 0x41 # CIE RA Column
364 .uleb128 0x1 # Augmentation size
365 .byte 0x14 # FDE Encoding (pcrel udata8)
366 .byte 0xc # DW_CFA_def_cfa
372 .4byte .LEFDE1-.LASFDE1 # FDE Length
374 .4byte .LASFDE1-.Lframe1 # FDE CIE offset
375 .8byte .LFB1-. # FDE initial location
376 .8byte .LFE1-.LFB1 # FDE address range
377 .uleb128 0x0 # Augmentation size
378 .byte 0x2 # DW_CFA_advance_loc1
380 .byte 0xe # DW_CFA_def_cfa_offset
382 .byte 0x11 # DW_CFA_offset_extended_sf
388 # if defined __ELF__ && defined __linux__
389 .section .note.GNU-stack,"",@progbits