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
104 # Save general regs into parm save area
105 # This is the parameter save area set up by our caller.
106 std %r3, PARMSAVE+0(%r1)
107 std %r4, PARMSAVE+8(%r1)
108 std %r5, PARMSAVE+16(%r1)
109 std %r6, PARMSAVE+24(%r1)
110 std %r7, PARMSAVE+32(%r1)
111 std %r8, PARMSAVE+40(%r1)
112 std %r9, PARMSAVE+48(%r1)
113 std %r10, PARMSAVE+56(%r1)
117 # load up the pointer to the parm save area
118 addi %r5, %r1, PARMSAVE
121 # next save fpr 1 to fpr 13
122 stfd %f1, -104+(0*8)(%r1)
123 stfd %f2, -104+(1*8)(%r1)
124 stfd %f3, -104+(2*8)(%r1)
125 stfd %f4, -104+(3*8)(%r1)
126 stfd %f5, -104+(4*8)(%r1)
127 stfd %f6, -104+(5*8)(%r1)
128 stfd %f7, -104+(6*8)(%r1)
129 stfd %f8, -104+(7*8)(%r1)
130 stfd %f9, -104+(8*8)(%r1)
131 stfd %f10, -104+(9*8)(%r1)
132 stfd %f11, -104+(10*8)(%r1)
133 stfd %f12, -104+(11*8)(%r1)
134 stfd %f13, -104+(12*8)(%r1)
136 # load up the pointer to the saved fpr registers */
139 # load up the pointer to the result storage
140 addi %r4, %r1, -STACKFRAME+RETVAL
142 stdu %r1, -STACKFRAME(%r1)
145 # get the context pointer from the trampoline
149 # if defined _CALL_LINUX || _CALL_ELF == 2
150 bl ffi_closure_helper_LINUX64
152 bl .ffi_closure_helper_LINUX64
156 # now r3 contains the return type
157 # so use it to look up in a table
158 # so we know how to deal with each type
160 # look up the proper starting point in table
161 # by using return type as offset
162 ld %r0, STACKFRAME+16(%r1)
163 cmpldi %r3, FFI_V2_TYPE_SMALL_STRUCT
165 mflr %r4 # move address of .Lret to r4
166 sldi %r3, %r3, 4 # now multiply return type by 16
167 addi %r4, %r4, .Lret_type0 - .Lret
168 add %r3, %r3, %r4 # add contents of table to table address
172 # Each of the ret_typeX code fragments has to be exactly 16 bytes long
173 # (4 instructions). For cache effectiveness we align to a 16 byte boundary
180 addi %r1, %r1, STACKFRAME
184 # ifdef __LITTLE_ENDIAN__
185 lwa %r3, RETVAL+0(%r1)
187 lwa %r3, RETVAL+4(%r1)
190 addi %r1, %r1, STACKFRAME
192 # case FFI_TYPE_FLOAT
193 lfs %f1, RETVAL+0(%r1)
195 addi %r1, %r1, STACKFRAME
197 # case FFI_TYPE_DOUBLE
198 lfd %f1, RETVAL+0(%r1)
200 addi %r1, %r1, STACKFRAME
202 # case FFI_TYPE_LONGDOUBLE
203 lfd %f1, RETVAL+0(%r1)
205 lfd %f2, RETVAL+8(%r1)
207 # case FFI_TYPE_UINT8
208 # ifdef __LITTLE_ENDIAN__
209 lbz %r3, RETVAL+0(%r1)
211 lbz %r3, RETVAL+7(%r1)
214 addi %r1, %r1, STACKFRAME
216 # case FFI_TYPE_SINT8
217 # ifdef __LITTLE_ENDIAN__
218 lbz %r3, RETVAL+0(%r1)
220 lbz %r3, RETVAL+7(%r1)
225 # case FFI_TYPE_UINT16
226 # ifdef __LITTLE_ENDIAN__
227 lhz %r3, RETVAL+0(%r1)
229 lhz %r3, RETVAL+6(%r1)
233 addi %r1, %r1, STACKFRAME
235 # case FFI_TYPE_SINT16
236 # ifdef __LITTLE_ENDIAN__
237 lha %r3, RETVAL+0(%r1)
239 lha %r3, RETVAL+6(%r1)
242 addi %r1, %r1, STACKFRAME
244 # case FFI_TYPE_UINT32
245 # ifdef __LITTLE_ENDIAN__
246 lwz %r3, RETVAL+0(%r1)
248 lwz %r3, RETVAL+4(%r1)
251 addi %r1, %r1, STACKFRAME
253 # case FFI_TYPE_SINT32
254 # ifdef __LITTLE_ENDIAN__
255 lwa %r3, RETVAL+0(%r1)
257 lwa %r3, RETVAL+4(%r1)
260 addi %r1, %r1, STACKFRAME
262 # case FFI_TYPE_UINT64
263 ld %r3, RETVAL+0(%r1)
265 addi %r1, %r1, STACKFRAME
267 # case FFI_TYPE_SINT64
268 ld %r3, RETVAL+0(%r1)
270 addi %r1, %r1, STACKFRAME
272 # case FFI_TYPE_STRUCT
274 addi %r1, %r1, STACKFRAME
277 # case FFI_TYPE_POINTER
278 ld %r3, RETVAL+0(%r1)
280 addi %r1, %r1, STACKFRAME
282 # case FFI_V2_TYPE_FLOAT_HOMOG
283 lfs %f1, RETVAL+0(%r1)
284 lfs %f2, RETVAL+4(%r1)
285 lfs %f3, RETVAL+8(%r1)
287 # case FFI_V2_TYPE_DOUBLE_HOMOG
288 lfd %f1, RETVAL+0(%r1)
289 lfd %f2, RETVAL+8(%r1)
290 lfd %f3, RETVAL+16(%r1)
291 lfd %f4, RETVAL+24(%r1)
293 lfd %f5, RETVAL+32(%r1)
294 lfd %f6, RETVAL+40(%r1)
295 lfd %f7, RETVAL+48(%r1)
296 lfd %f8, RETVAL+56(%r1)
297 addi %r1, %r1, STACKFRAME
300 lfs %f4, RETVAL+12(%r1)
302 lfs %f5, RETVAL+16(%r1)
303 lfs %f6, RETVAL+20(%r1)
304 lfs %f7, RETVAL+24(%r1)
305 lfs %f8, RETVAL+28(%r1)
306 addi %r1, %r1, STACKFRAME
309 # ifdef __LITTLE_ENDIAN__
313 addi %r1, %r1, STACKFRAME
316 # A struct smaller than a dword is returned in the low bits of r3
317 # ie. right justified. Larger structs are passed left justified
318 # in r3 and r4. The return value area on the stack will have
319 # the structs as they are usually stored in memory.
320 cmpldi %r3, FFI_V2_TYPE_SMALL_STRUCT + 7 # size 8 bytes?
326 addi %r1, %r1, STACKFRAME
329 addi %r5, %r5, FFI_V2_TYPE_SMALL_STRUCT + 7
332 addi %r1, %r1, STACKFRAME
339 .byte 0,12,0,1,128,0,0,0
341 .size ffi_closure_LINUX64,.-ffi_closure_LINUX64
344 .size ffi_closure_LINUX64,.-.L.ffi_closure_LINUX64
346 .size .ffi_closure_LINUX64,.-.ffi_closure_LINUX64
350 .section .eh_frame,EH_FRAME_FLAGS,@progbits
352 .4byte .LECIE1-.LSCIE1 # Length of Common Information Entry
354 .4byte 0x0 # CIE Identifier Tag
355 .byte 0x1 # CIE Version
356 .ascii "zR\0" # CIE Augmentation
357 .uleb128 0x1 # CIE Code Alignment Factor
358 .sleb128 -8 # CIE Data Alignment Factor
359 .byte 0x41 # CIE RA Column
360 .uleb128 0x1 # Augmentation size
361 .byte 0x14 # FDE Encoding (pcrel udata8)
362 .byte 0xc # DW_CFA_def_cfa
368 .4byte .LEFDE1-.LASFDE1 # FDE Length
370 .4byte .LASFDE1-.Lframe1 # FDE CIE offset
371 .8byte .LFB1-. # FDE initial location
372 .8byte .LFE1-.LFB1 # FDE address range
373 .uleb128 0x0 # Augmentation size
374 .byte 0x2 # DW_CFA_advance_loc1
376 .byte 0xe # DW_CFA_def_cfa_offset
378 .byte 0x11 # DW_CFA_offset_extended_sf
386 #if (defined __ELF__ && defined __linux__) || _CALL_ELF == 2
387 .section .note.GNU-stack,"",@progbits