1 /* -----------------------------------------------------------------------
2 darwin.S - Copyright (c) 2000 John Hornkvist
3 Copyright (c) 2004, 2010 Free Software Foundation, Inc.
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, EXPRESS
19 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 OTHER DEALINGS IN THE SOFTWARE.
25 ----------------------------------------------------------------------- */
28 #if defined(__ppc64__)
29 #define MODE_CHOICE(x, y) y
31 #define MODE_CHOICE(x, y) x
34 #define machine_choice MODE_CHOICE(ppc7400,ppc64)
36 ; Define some pseudo-opcodes for size-independent load & store of GPRs ...
37 #define lgu MODE_CHOICE(lwzu, ldu)
38 #define lg MODE_CHOICE(lwz,ld)
39 #define sg MODE_CHOICE(stw,std)
40 #define sgu MODE_CHOICE(stwu,stdu)
41 #define sgux MODE_CHOICE(stwux,stdux)
43 ; ... and the size of GPRs and their storage indicator.
44 #define GPR_BYTES MODE_CHOICE(4,8)
45 #define LOG2_GPR_BYTES MODE_CHOICE(2,3) /* log2(GPR_BYTES) */
46 #define g_long MODE_CHOICE(long, quad) /* usage is ".g_long" */
48 ; From the ABI doc: "Mac OS X ABI Function Call Guide" Version 2009-02-04.
49 #define LINKAGE_SIZE MODE_CHOICE(24,48)
50 #define PARAM_AREA MODE_CHOICE(32,64)
51 #define SAVED_LR_OFFSET MODE_CHOICE(8,16) /* save position for lr */
53 /* If there is any FP stuff we make space for all of the regs. */
54 #define SAVED_FPR_COUNT 13
56 #define RESULT_BYTES 16
58 /* This should be kept in step with the same value in ffi_darwin.c. */
59 #define ASM_NEEDS_REGISTERS 4
60 #define SAVE_REGS_SIZE (ASM_NEEDS_REGISTERS * GPR_BYTES)
62 #include <fficonfig.h>
65 #define JUMPTARGET(name) name
73 .globl _ffi_call_DARWIN
75 /* We arrive here with:
76 r3 = ptr to extended cif.
79 r6 = ptr to return value.
80 r7 = fn pointer (user func).
81 r8 = fn pointer (ffi_prep_args).
82 r9 = ffi_type* for the ret val. */
86 mr r12,r8 /* We only need r12 until the call,
87 so it does not have to be saved. */
89 /* Save the old stack pointer as AP. */
93 /* Save the retval type in parents frame. */
94 sg r9,(LINKAGE_SIZE+6*GPR_BYTES)(r8)
96 /* Allocate the stack space we need. */
99 /* Save registers we use. */
101 sg r9,SAVED_LR_OFFSET(r8)
103 sg r28,-(4 * GPR_BYTES)(r8)
104 sg r29,-(3 * GPR_BYTES)(r8)
105 sg r30,-(2 * GPR_BYTES)(r8)
106 sg r31,-( GPR_BYTES)(r8)
108 #if !defined(POWERPC_DARWIN)
109 /* The TOC slot is reserved in the Darwin ABI and r2 is volatile. */
110 sg r2,(5 * GPR_BYTES)(r1)
115 /* Save arguments over call. */
116 mr r31,r5 /* flags, */
117 mr r30,r6 /* rvalue, */
118 mr r29,r7 /* function address, */
119 mr r28,r8 /* our AP. */
121 /* Call ffi_prep_args. r3 = extended cif, r4 = stack ptr copy. */
125 mtctr r12 /* r12 holds address of _ffi_prep_args. */
128 #if !defined(POWERPC_DARWIN)
129 /* The TOC slot is reserved in the Darwin ABI and r2 is volatile. */
130 lg r2,(5 * GPR_BYTES)(r1)
133 Set up cr1 with bits 4-7 of the flags. */
135 /* Get the address to call into CTR. */
137 /* Load all those argument registers.
138 We have set up a nice stack frame, just load it into registers. */
139 lg r3, (LINKAGE_SIZE )(r1)
140 lg r4, (LINKAGE_SIZE + GPR_BYTES)(r1)
141 lg r5, (LINKAGE_SIZE + 2 * GPR_BYTES)(r1)
142 lg r6, (LINKAGE_SIZE + 3 * GPR_BYTES)(r1)
144 lg r7, (LINKAGE_SIZE + 4 * GPR_BYTES)(r1)
145 lg r8, (LINKAGE_SIZE + 5 * GPR_BYTES)(r1)
146 lg r9, (LINKAGE_SIZE + 6 * GPR_BYTES)(r1)
147 lg r10,(LINKAGE_SIZE + 7 * GPR_BYTES)(r1)
150 /* ... Load all the FP registers. */
151 bf 6,L2 /* No floats to load. */
152 lfd f1, -SAVE_REGS_SIZE-(13*FPR_SIZE)(r28)
153 lfd f2, -SAVE_REGS_SIZE-(12*FPR_SIZE)(r28)
154 lfd f3, -SAVE_REGS_SIZE-(11*FPR_SIZE)(r28)
155 lfd f4, -SAVE_REGS_SIZE-(10*FPR_SIZE)(r28)
157 lfd f5, -SAVE_REGS_SIZE-( 9*FPR_SIZE)(r28)
158 lfd f6, -SAVE_REGS_SIZE-( 8*FPR_SIZE)(r28)
159 lfd f7, -SAVE_REGS_SIZE-( 7*FPR_SIZE)(r28)
160 lfd f8, -SAVE_REGS_SIZE-( 6*FPR_SIZE)(r28)
162 lfd f9, -SAVE_REGS_SIZE-( 5*FPR_SIZE)(r28)
163 lfd f10,-SAVE_REGS_SIZE-( 4*FPR_SIZE)(r28)
164 lfd f11,-SAVE_REGS_SIZE-( 3*FPR_SIZE)(r28)
165 lfd f12,-SAVE_REGS_SIZE-( 2*FPR_SIZE)(r28)
167 lfd f13,-SAVE_REGS_SIZE-( 1*FPR_SIZE)(r28)
170 mr r12,r29 /* Put the target address in r12 as specified. */
178 /* Now, deal with the return value. */
180 /* m64 structure returns can occupy the same set of registers as
181 would be used to pass such a structure as arg0 - so take care
182 not to step on any possibly hot regs. */
184 /* Get the flags.. */
185 mtcrf 0x03,r31 ; we need c6 & cr7 now.
186 ; FLAG_RETURNS_NOTHING also covers struct ret-by-ref.
187 bt 30,L(done_return_value) ; FLAG_RETURNS_NOTHING
188 bf 27,L(scalar_return_value) ; not FLAG_RETURNS_STRUCT
190 /* OK, so we have a struct. */
191 #if defined(__ppc64__)
192 bt 31,L(maybe_return_128) ; FLAG_RETURNS_128BITS, special case
194 /* OK, we have to map the return back to a mem struct.
195 We are about to trample the parents param area, so recover the
196 return type. r29 is free, since the call is done. */
197 lg r29,(LINKAGE_SIZE + 6 * GPR_BYTES)(r28)
199 sg r3, (LINKAGE_SIZE )(r28)
200 sg r4, (LINKAGE_SIZE + GPR_BYTES)(r28)
201 sg r5, (LINKAGE_SIZE + 2 * GPR_BYTES)(r28)
202 sg r6, (LINKAGE_SIZE + 3 * GPR_BYTES)(r28)
204 sg r7, (LINKAGE_SIZE + 4 * GPR_BYTES)(r28)
205 sg r8, (LINKAGE_SIZE + 5 * GPR_BYTES)(r28)
206 sg r9, (LINKAGE_SIZE + 6 * GPR_BYTES)(r28)
207 sg r10,(LINKAGE_SIZE + 7 * GPR_BYTES)(r28)
208 /* OK, so do the block move - we trust that memcpy will not trample
211 addi r4,r28,LINKAGE_SIZE ; source
212 /* The size is a size_t, should be long. */
214 /* Figure out small structs */
216 bgt L3 ; 1, 2 and 4 bytes have special rules.
224 /* ... do we need the FP registers? - recover the flags.. */
225 mtcrf 0x03,r31 ; we need c6 & cr7 now.
226 bf 29,L(done_return_value) /* No floats in the struct. */
227 stfd f1, -SAVE_REGS_SIZE-(13*FPR_SIZE)(r28)
228 stfd f2, -SAVE_REGS_SIZE-(12*FPR_SIZE)(r28)
229 stfd f3, -SAVE_REGS_SIZE-(11*FPR_SIZE)(r28)
230 stfd f4, -SAVE_REGS_SIZE-(10*FPR_SIZE)(r28)
232 stfd f5, -SAVE_REGS_SIZE-( 9*FPR_SIZE)(r28)
233 stfd f6, -SAVE_REGS_SIZE-( 8*FPR_SIZE)(r28)
234 stfd f7, -SAVE_REGS_SIZE-( 7*FPR_SIZE)(r28)
235 stfd f8, -SAVE_REGS_SIZE-( 6*FPR_SIZE)(r28)
237 stfd f9, -SAVE_REGS_SIZE-( 5*FPR_SIZE)(r28)
238 stfd f10,-SAVE_REGS_SIZE-( 4*FPR_SIZE)(r28)
239 stfd f11,-SAVE_REGS_SIZE-( 3*FPR_SIZE)(r28)
240 stfd f12,-SAVE_REGS_SIZE-( 2*FPR_SIZE)(r28)
242 stfd f13,-SAVE_REGS_SIZE-( 1*FPR_SIZE)(r28)
244 mr r3,r29 ; ffi_type *
246 addi r5,r28,-SAVE_REGS_SIZE-(13*FPR_SIZE) ; fprs
248 sg r6,(LINKAGE_SIZE + 7 * GPR_BYTES)(r28)
249 addi r6,r28,(LINKAGE_SIZE + 7 * GPR_BYTES) ; point to a zeroed counter.
250 bl _darwin64_struct_floats_to_mem
252 b L(done_return_value)
254 stw r3,0(r30) ; m32 the only struct return in reg is 4 bytes.
256 b L(done_return_value)
259 /* Do we have long double to store? */
260 bf 31,L(fd_return_value) ; FLAG_RETURNS_128BITS
262 stfd f2,FPR_SIZE(r30)
263 b L(done_return_value)
266 /* Do we have double to store? */
267 bf 28,L(float_return_value)
269 b L(done_return_value)
271 L(float_return_value):
272 /* We only have a float to store. */
274 b L(done_return_value)
276 L(scalar_return_value):
277 bt 29,L(fp_return_value) ; FLAG_RETURNS_FP
278 ; ffi_arg is defined as unsigned long.
279 sg r3,0(r30) ; Save the reg.
280 bf 28,L(done_return_value) ; not FLAG_RETURNS_64BITS
282 #if defined(__ppc64__)
285 bf 31,L(done_return_value) ; not FLAG_RETURNS_128BITS
292 /* We want this at the end to simplify eh epilog computation. */
294 L(done_return_value):
295 /* Restore the registers we used and return. */
296 lg r29,SAVED_LR_OFFSET(r28)
298 lg r31,-(1 * GPR_BYTES)(r28)
300 lg r30,-(2 * GPR_BYTES)(r28)
301 lg r29,-(3 * GPR_BYTES)(r28)
302 lg r28,-(4 * GPR_BYTES)(r28)
307 /* END(_ffi_call_DARWIN) */
309 /* Provide a null definition of _ffi_call_AIX. */
315 /* END(_ffi_call_AIX) */
319 #define EH_DATA_ALIGN_FACT MODE_CHOICE(0x7c,0x78)
321 .section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
323 .set L$set$0,LECIE1-LSCIE1
324 .long L$set$0 ; Length of Common Information Entry
326 .long 0x0 ; CIE Identifier Tag
327 .byte 0x1 ; CIE Version
328 .ascii "zR\0" ; CIE Augmentation
329 .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor
330 .byte EH_DATA_ALIGN_FACT ; sleb128 -4; CIE Data Alignment Factor
331 .byte 0x41 ; CIE RA Column
332 .byte 0x1 ; uleb128 0x1; Augmentation size
333 .byte 0x10 ; FDE Encoding (pcrel)
334 .byte 0xc ; DW_CFA_def_cfa
335 .byte 0x1 ; uleb128 0x1
336 .byte 0x0 ; uleb128 0x0
337 .align LOG2_GPR_BYTES
340 .globl _ffi_call_DARWIN.eh
343 .set L$set$1,LEFDE1-LASFDE1
344 .long L$set$1 ; FDE Length
346 .long LASFDE1-EH_frame1 ; FDE CIE offset
347 .g_long Lstartcode-. ; FDE initial location
348 .set L$set$3,LFE1-Lstartcode
349 .g_long L$set$3 ; FDE address range
350 .byte 0x0 ; uleb128 0x0; Augmentation size
351 .byte 0x4 ; DW_CFA_advance_loc4
352 .set L$set$4,LCFI0-Lstartcode
354 .byte 0xd ; DW_CFA_def_cfa_register
355 .byte 0x08 ; uleb128 0x08
356 .byte 0x4 ; DW_CFA_advance_loc4
357 .set L$set$5,LCFI1-LCFI0
359 .byte 0x11 ; DW_CFA_offset_extended_sf
360 .byte 0x41 ; uleb128 0x41
361 .byte 0x7e ; sleb128 -2
362 .byte 0x9f ; DW_CFA_offset, column 0x1f
363 .byte 0x1 ; uleb128 0x1
364 .byte 0x9e ; DW_CFA_offset, column 0x1e
365 .byte 0x2 ; uleb128 0x2
366 .byte 0x9d ; DW_CFA_offset, column 0x1d
367 .byte 0x3 ; uleb128 0x3
368 .byte 0x9c ; DW_CFA_offset, column 0x1c
369 .byte 0x4 ; uleb128 0x4
370 .byte 0x4 ; DW_CFA_advance_loc4
371 .set L$set$6,LCFI2-LCFI1
373 .byte 0xd ; DW_CFA_def_cfa_register
374 .byte 0x1c ; uleb128 0x1c
375 .align LOG2_GPR_BYTES