OSDN Git Service

Merge "Add default code reviewers into OWNERS"
[android-x86/external-libffi.git] / src / powerpc / darwin.S
1 /* -----------------------------------------------------------------------
2    darwin.S - Copyright (c) 2000 John Hornkvist
3               Copyright (c) 2004, 2010 Free Software Foundation, Inc.
4
5    PowerPC Assembly glue.
6
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:
14
15    The above copyright notice and this permission notice shall be included
16    in all copies or substantial portions of the Software.
17
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    ----------------------------------------------------------------------- */
26
27 #define LIBFFI_ASM
28 #if defined(__ppc64__)
29 #define MODE_CHOICE(x, y) y
30 #else
31 #define MODE_CHOICE(x, y) x
32 #endif
33
34 #define machine_choice  MODE_CHOICE(ppc7400,ppc64)
35
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)
42
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" */
47
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 */
52
53 /* If there is any FP stuff we make space for all of the regs.  */
54 #define SAVED_FPR_COUNT 13
55 #define FPR_SIZE        8
56 #define RESULT_BYTES    16
57
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)
61
62 #include <fficonfig.h>
63 #include <ffi.h>
64
65 #define JUMPTARGET(name) name
66 #define L(x) x
67
68         .text
69         .align 2
70         .globl _ffi_prep_args
71
72         .align 2
73         .globl _ffi_call_DARWIN
74
75         /* We arrive here with:
76            r3 = ptr to extended cif.
77            r4 = -bytes.
78            r5 = cif flags.
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.  */
83
84 _ffi_call_DARWIN:
85 Lstartcode:
86         mr      r12,r8  /* We only need r12 until the call,
87                            so it does not have to be saved.  */
88 LFB1:
89         /* Save the old stack pointer as AP.  */
90         mr      r8,r1
91 LCFI0:
92         
93         /* Save the retval type in parents frame.  */
94         sg      r9,(LINKAGE_SIZE+6*GPR_BYTES)(r8)
95
96         /* Allocate the stack space we need.  */
97         sgux    r1,r1,r4
98
99         /* Save registers we use.  */
100         mflr    r9
101         sg      r9,SAVED_LR_OFFSET(r8)
102
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)
107
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)
111 #endif
112
113 LCFI1:
114
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.  */
120 LCFI2:
121         /* Call ffi_prep_args. r3 = extended cif, r4 = stack ptr copy.  */
122         mr      r4,r1
123         li      r9,0
124
125         mtctr   r12 /* r12 holds address of _ffi_prep_args.  */
126         bctrl
127
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)
131 #endif
132         /* Now do the call.
133            Set up cr1 with bits 4-7 of the flags.  */
134         mtcrf   0x40,r31
135         /* Get the address to call into CTR.  */
136         mtctr   r29
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)
143         nop
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)
148
149 L1:
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)
156         nop
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)
161         nop
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)
166         nop
167         lfd     f13,-SAVE_REGS_SIZE-( 1*FPR_SIZE)(r28)
168
169 L2:
170         mr      r12,r29 /* Put the target address in r12 as specified.  */
171         mtctr   r12
172         nop
173         nop
174
175         /* Make the call.  */
176         bctrl
177
178         /* Now, deal with the return value.  */
179
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.  */
183
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
189         
190         /* OK, so we have a struct.  */
191 #if defined(__ppc64__)
192         bt      31,L(maybe_return_128) ; FLAG_RETURNS_128BITS, special case 
193
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)
198
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)
203         nop
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
209            the fprs...  */
210         mr      r3,r30 ; dest
211         addi    r4,r28,LINKAGE_SIZE ; source
212         /* The size is a size_t, should be long.  */
213         lg      r5,0(r29)
214         /* Figure out small structs */
215         cmpi    0,r5,4
216         bgt     L3      ; 1, 2 and 4 bytes have special rules.
217         cmpi    0,r5,3
218         beq     L3      ; not 3
219         addi    r4,r4,8
220         subf    r4,r5,r4
221 L3:
222         bl      _memcpy
223         
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)
231         nop
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)
236         nop
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)
241         nop
242         stfd    f13,-SAVE_REGS_SIZE-( 1*FPR_SIZE)(r28)
243
244         mr      r3,r29  ; ffi_type *
245         mr      r4,r30  ; dest
246         addi    r5,r28,-SAVE_REGS_SIZE-(13*FPR_SIZE) ; fprs
247         xor     r6,r6,r6
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
251
252         b L(done_return_value)
253 #else
254         stw     r3,0(r30) ; m32 the only struct return in reg is 4 bytes.
255 #endif
256         b L(done_return_value)
257
258 L(fp_return_value):
259         /* Do we have long double to store?  */
260         bf      31,L(fd_return_value) ; FLAG_RETURNS_128BITS
261         stfd    f1,0(r30)
262         stfd    f2,FPR_SIZE(r30)
263         b       L(done_return_value)
264
265 L(fd_return_value):
266         /* Do we have double to store?  */
267         bf      28,L(float_return_value)
268         stfd    f1,0(r30)
269         b       L(done_return_value)
270
271 L(float_return_value):
272         /* We only have a float to store.  */
273         stfs    f1,0(r30)
274         b       L(done_return_value)
275
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 
281
282 #if defined(__ppc64__)
283 L(maybe_return_128):
284         std     r3,0(r30)
285         bf      31,L(done_return_value) ; not FLAG_RETURNS_128BITS 
286         std     r4,8(r30)
287 #else
288         stw     r4,4(r30)
289 #endif
290
291         /* Fall through.  */
292         /* We want this at the end to simplify eh epilog computation.  */
293
294 L(done_return_value):
295         /* Restore the registers we used and return.  */
296         lg      r29,SAVED_LR_OFFSET(r28)
297         ; epilog
298         lg      r31,-(1 * GPR_BYTES)(r28)
299         mtlr    r29
300         lg      r30,-(2 * GPR_BYTES)(r28)
301         lg      r29,-(3 * GPR_BYTES)(r28)
302         lg      r28,-(4 * GPR_BYTES)(r28)
303         lg      r1,0(r1)
304         blr
305 LFE1:
306         .align  1
307 /* END(_ffi_call_DARWIN)  */
308
309 /* Provide a null definition of _ffi_call_AIX.  */
310         .text
311         .globl _ffi_call_AIX
312         .align 2
313 _ffi_call_AIX:
314         blr
315 /* END(_ffi_call_AIX)  */
316
317 /* EH stuff.  */
318
319 #define EH_DATA_ALIGN_FACT MODE_CHOICE(0x7c,0x78)
320
321         .section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
322 EH_frame1:
323         .set    L$set$0,LECIE1-LSCIE1
324         .long   L$set$0 ; Length of Common Information Entry
325 LSCIE1:
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
338 LECIE1:
339
340         .globl _ffi_call_DARWIN.eh
341 _ffi_call_DARWIN.eh:
342 LSFDE1:
343         .set    L$set$1,LEFDE1-LASFDE1
344         .long   L$set$1 ; FDE Length
345 LASFDE1:
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
353         .long   L$set$4
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
358         .long   L$set$5
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
372         .long   L$set$6
373         .byte   0xd     ; DW_CFA_def_cfa_register
374         .byte   0x1c    ; uleb128 0x1c
375         .align LOG2_GPR_BYTES
376 LEFDE1:
377         .align 1
378