3
/* -----------------------------------------------------------------------
4
darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation,
5
Inc. based on ppc_closure.S
9
Permission is hereby granted, free of charge, to any person obtaining
10
a copy of this software and associated documentation files (the
11
``Software''), to deal in the Software without restriction, including
12
without limitation the rights to use, copy, modify, merge, publish,
13
distribute, sublicense, and/or sell copies of the Software, and to
14
permit persons to whom the Software is furnished to do so, subject to
15
the following conditions:
17
The above copyright notice and this permission notice shall be included
18
in all copies or substantial portions of the Software.
20
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
21
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
24
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
25
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
26
OTHER DEALINGS IN THE SOFTWARE.
27
----------------------------------------------------------------------- */
32
#include <ppc-ffitarget.h> // for FFI_TRAMPOLINE_SIZE
33
#include <ppc-darwin.h>
34
#include <architecture/ppc/mode_independent_asm.h>
36
.file "ppc64-darwin_closure.S"
39
.globl _ffi_closure_ASM
47
stg r0,SF_RETURN(r1) // save return address
49
// Save GPRs 3 - 10 (aligned to 8) in the parents outgoing area.
60
/* 48 bytes (Linkage Area)
61
64 bytes (outgoing parameter area, always reserved)
62
112 bytes (14*8 for incoming FPR)
64
112 bytes (14*8 for outgoing FPR)
65
16 bytes (2 saved registers)
69
std r31,-8(r1) // Save registers we use.
71
mr r30,r1 // Save the old SP.
72
mr r31,r11 // Save the ffi_closure around ffi64_data_size.
74
// Calculate the space we need.
75
stdu r1,-SF_MINSIZE(r1)
76
ld r3,FFI_TRAMPOLINE_SIZE(r31) // ffi_closure->cif*
77
ld r3,16(r3) // ffi_cif->rtype*
78
bl Lffi64_data_size$stub
81
addi r3,r3,352 // Add our overhead.
83
li r0,-32 // Align to 32 bytes.
85
stdux r1,r1,r3 // Grow the stack.
87
mr r11,r31 // Copy the ffi_closure back.
90
// We want to build up an area for the parameters passed
91
// in registers. (both floating point and integer)
93
/* 320 bytes (callee stack frame aligned to 32)
94
48 bytes (caller linkage area)
95
368 (start of caller parameter area aligned to 8)
98
// Save FPRs 1 - 14. (aligned to 8)
114
// Set up registers for the routine that actually does the work.
115
mr r3,r11 // context pointer from the trampoline
116
addi r4,r1,224 // result storage
117
addi r5,r30,SF_ARG1 // saved GPRs
118
addi r6,r1,112 // saved FPRs
119
bl Lffi_closure_helper_DARWIN$stub
121
// Look the proper starting point in table
122
// by using return type as an offset.
123
addi r5,r1,224 // Get pointer to results area.
124
bl Lget_ret_type0_addr // Get pointer to Lret_type0 into LR.
125
mflr r4 // Move to r4.
126
slwi r3,r3,4 // Now multiply return type by 16.
127
add r3,r3,r4 // Add contents of table to table address.
132
// Each of the ret_typeX code fragments has to be exactly 16 bytes long
133
// (4 instructions). For cache effectiveness we align to a 16 byte
143
// case FFI_TYPE_VOID
157
// case FFI_TYPE_FLOAT
164
// case FFI_TYPE_DOUBLE
171
// case FFI_TYPE_LONGDOUBLE
178
// case FFI_TYPE_UINT8
185
// case FFI_TYPE_SINT8
192
// case FFI_TYPE_UINT16
199
// case FFI_TYPE_SINT16
206
// case FFI_TYPE_UINT32
207
Lret_type9: // same as Lret_type1
213
// case FFI_TYPE_SINT32
214
Lret_type10: // same as Lret_type1
220
// case FFI_TYPE_UINT64
227
// case FFI_TYPE_SINT64
228
Lret_type12: // same as Lret_type11
234
// case FFI_TYPE_STRUCT
241
// ** End 16-byte aligned cases **
242
// case FFI_TYPE_POINTER
243
// This case assumes that FFI_TYPE_POINTER == FFI_TYPE_LAST. If more types
244
// are added in future, the following code will need to be updated and
245
// padded to 16 bytes.
250
// copy struct into registers
252
ld r31,FFI_TRAMPOLINE_SIZE(r31) // ffi_closure->cif*
253
ld r3,16(r31) // ffi_cif->rtype*
254
ld r31,24(r31) // ffi_cif->flags
255
mr r4,r5 // copy struct* to 2nd arg
256
addi r7,r1,SF_ARG9 // GPR return area
257
addi r9,r30,-16-(14*8) // FPR return area
258
li r5,0 // struct offset ptr (NULL)
259
li r6,0 // FPR used count ptr (NULL)
260
li r8,0 // GPR return area size ptr (NULL)
261
li r10,0 // FPR return area size ptr (NULL)
262
bl Lffi64_struct_to_reg_form$stub
279
lfd f1,-16-(14*8)(r30)
280
lfd f2,-16-(13*8)(r30)
281
lfd f3,-16-(12*8)(r30)
282
lfd f4,-16-(11*8)(r30)
284
lfd f5,-16-(10*8)(r30)
285
lfd f6,-16-(9*8)(r30)
286
lfd f7,-16-(8*8)(r30)
287
lfd f8,-16-(7*8)(r30)
289
lfd f9,-16-(6*8)(r30)
290
lfd f10,-16-(5*8)(r30)
291
lfd f11,-16-(4*8)(r30)
292
lfd f12,-16-(3*8)(r30)
294
lfd f13,-16-(2*8)(r30)
295
lfd f14,-16-(1*8)(r30)
300
lg r1,0(r1) // Restore stack pointer.
301
ld r31,-8(r1) // Restore registers we used.
303
lg r0,SF_RETURN(r1) // Get return address.
304
mtlr r0 // Reset link register.
307
// END(ffi_closure_ASM)
309
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
311
.set L$set$0,LECIE1-LSCIE1
312
.long L$set$0 ; Length of Common Information Entry
314
.long 0x0 ; CIE Identifier Tag
315
.byte 0x1 ; CIE Version
316
.ascii "zR\0" ; CIE Augmentation
317
.byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor
318
.byte 0x7c ; sleb128 -4; CIE Data Alignment Factor
319
.byte 0x41 ; CIE RA Column
320
.byte 0x1 ; uleb128 0x1; Augmentation size
321
.byte 0x90 ; FDE Encoding (indirect pcrel)
322
.byte 0xc ; DW_CFA_def_cfa
323
.byte 0x1 ; uleb128 0x1
324
.byte 0x0 ; uleb128 0x0
325
.align LOG2_GPR_BYTES
327
.globl _ffi_closure_ASM.eh
330
.set L$set$1,LEFDE1-LASFDE1
331
.long L$set$1 ; FDE Length
334
.long LASFDE1-EH_frame1 ; FDE CIE offset
335
.g_long LLFB1$non_lazy_ptr-. ; FDE initial location
336
.set L$set$3,LFE1-LFB1
337
.g_long L$set$3 ; FDE address range
338
.byte 0x0 ; uleb128 0x0; Augmentation size
339
.byte 0x4 ; DW_CFA_advance_loc4
340
.set L$set$3,LCFI1-LCFI0
342
.byte 0xe ; DW_CFA_def_cfa_offset
343
.byte 176,1 ; uleb128 176
344
.byte 0x4 ; DW_CFA_advance_loc4
345
.set L$set$4,LCFI0-LFB1
347
.byte 0x11 ; DW_CFA_offset_extended_sf
348
.byte 0x41 ; uleb128 0x41
349
.byte 0x7e ; sleb128 -2
350
.align LOG2_GPR_BYTES
354
.align LOG2_GPR_BYTES
356
.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
357
.align LOG2_GPR_BYTES
359
Lffi_closure_helper_DARWIN$stub:
360
.indirect_symbol _ffi_closure_helper_DARWIN
362
bcl 20,31,LO$ffi_closure_helper_DARWIN
364
LO$ffi_closure_helper_DARWIN:
366
addis r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)
368
lgu r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)(r11)
373
L_ffi_closure_helper_DARWIN$lazy_ptr:
374
.indirect_symbol _ffi_closure_helper_DARWIN
375
.g_long dyld_stub_binding_helper
378
.align LOG2_GPR_BYTES
382
.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
383
.align LOG2_GPR_BYTES
385
Lffi64_struct_to_reg_form$stub:
386
.indirect_symbol _ffi64_struct_to_reg_form
388
bcl 20,31,LO$ffi64_struct_to_reg_form
390
LO$ffi64_struct_to_reg_form:
392
addis r11,r11,ha16(L_ffi64_struct_to_reg_form$lazy_ptr - LO$ffi64_struct_to_reg_form)
394
lgu r12,lo16(L_ffi64_struct_to_reg_form$lazy_ptr - LO$ffi64_struct_to_reg_form)(r11)
398
.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
399
.align LOG2_GPR_BYTES
401
Lffi64_data_size$stub:
402
.indirect_symbol _ffi64_data_size
404
bcl 20,31,LO$ffi64_data_size
408
addis r11,r11,ha16(L_ffi64_data_size$lazy_ptr - LO$ffi64_data_size)
410
lgu r12,lo16(L_ffi64_data_size$lazy_ptr - LO$ffi64_data_size)(r11)
415
L_ffi64_struct_to_reg_form$lazy_ptr:
416
.indirect_symbol _ffi64_struct_to_reg_form
417
.g_long dyld_stub_binding_helper
419
L_ffi64_data_size$lazy_ptr:
420
.indirect_symbol _ffi64_data_size
421
.g_long dyld_stub_binding_helper