4 #include <powerpc/asm.h>
10 ENTRY(ffi_closure_SYSV)
18 # we want to build up an areas for the parameters passed
19 # in registers (both floating point and integer)
21 # so first save gpr 3 to gpr 10 (aligned to 4)
31 # next save fpr 1 to fpr 8 (aligned to 8)
41 # set up registers for the routine that actually does the work
42 # get the context pointer from the trampoline
45 # now load up the pointer to the result storage
48 # now load up the pointer to the saved gpr registers
51 # now load up the pointer to the saved fpr registers */
54 # now load up the pointer to the outgoing parameter
55 # stack in the previous frame
56 # i.e. the previous frame pointer + 8
60 bl ffi_closure_helper_SYSV@local
62 # now r3 contains the return type
63 # so use it to look up in a table
64 # so we know how to deal with each type
66 # Extract the size of the return type for small structures.
67 # Then calculate (4 - size) and multiply the result by 8.
68 # This gives the value needed for the shift operation below.
69 # This part is only needed for FFI_SYSV and small structures.
70 addi %r5,%r3,-(FFI_SYSV_TYPE_SMALL_STRUCT)
79 # look up the proper starting point in table
80 # by using return type as offset
81 addi %r6,%r1,112 # get pointer to results area
82 bl .Lget_ret_type0_addr # get pointer to .Lret_type0 into LR
84 slwi %r3,%r3,4 # now multiply return type by 16
85 add %r3,%r3,%r4 # add contents of table to table address
90 # Each of the ret_typeX code fragments has to be exactly 16 bytes long
91 # (4 instructions). For cache effectiveness we align to a 16 byte boundary
115 # case FFI_TYPE_FLOAT
122 # case FFI_TYPE_DOUBLE
129 # case FFI_TYPE_LONGDOUBLE
136 # case FFI_TYPE_UINT8
143 # case FFI_TYPE_SINT8
150 # case FFI_TYPE_UINT16
157 # case FFI_TYPE_SINT16
164 # case FFI_TYPE_UINT32
171 # case FFI_TYPE_SINT32
178 # case FFI_TYPE_UINT64
185 # case FFI_TYPE_SINT64
192 # case FFI_TYPE_STRUCT
199 # case FFI_TYPE_POINTER
206 # The return types below are only used when the ABI type is FFI_SYSV.
207 # case FFI_SYSV_TYPE_SMALL_STRUCT + 1. One byte struct.
215 # case FFI_SYSV_TYPE_SMALL_STRUCT + 2. Two byte struct.
223 # case FFI_SYSV_TYPE_SMALL_STRUCT + 3. Three byte struct.
231 # case FFI_SYSV_TYPE_SMALL_STRUCT + 4. Four byte struct.
233 # this one handles the structs from above too.
239 # case FFI_SYSV_TYPE_SMALL_STRUCT + 5. Five byte struct.
247 # case FFI_SYSV_TYPE_SMALL_STRUCT + 6. Six byte struct.
255 # case FFI_SYSV_TYPE_SMALL_STRUCT + 7. Seven byte struct.
263 # case FFI_SYSV_TYPE_SMALL_STRUCT + 8. Eight byte struct.
265 # this one handles the above unhandled structs.
268 bl __lshrdi3 # libgcc function to shift r3/r4, shift value in r5.
278 END(ffi_closure_SYSV)
280 .section ".eh_frame",EH_FRAME_FLAGS,@progbits
282 .4byte .LECIE1-.LSCIE1 # Length of Common Information Entry
284 .4byte 0x0 # CIE Identifier Tag
285 .byte 0x1 # CIE Version
286 #if defined _RELOCATABLE || defined __PIC__
287 .ascii "zR\0" # CIE Augmentation
289 .ascii "\0" # CIE Augmentation
291 .uleb128 0x1 # CIE Code Alignment Factor
292 .sleb128 -4 # CIE Data Alignment Factor
293 .byte 0x41 # CIE RA Column
294 #if defined _RELOCATABLE || defined __PIC__
295 .uleb128 0x1 # Augmentation size
296 .byte 0x1b # FDE Encoding (pcrel sdata4)
298 .byte 0xc # DW_CFA_def_cfa
304 .4byte .LEFDE1-.LASFDE1 # FDE Length
306 .4byte .LASFDE1-.Lframe1 # FDE CIE offset
307 #if defined _RELOCATABLE || defined __PIC__
308 .4byte .LFB1-. # FDE initial location
310 .4byte .LFB1 # FDE initial location
312 .4byte .LFE1-.LFB1 # FDE address range
313 #if defined _RELOCATABLE || defined __PIC__
314 .uleb128 0x0 # Augmentation size
316 .byte 0x4 # DW_CFA_advance_loc4
318 .byte 0xe # DW_CFA_def_cfa_offset
320 .byte 0x4 # DW_CFA_advance_loc4
322 .byte 0x11 # DW_CFA_offset_extended_sf