OSDN Git Service

Merge "Add default code reviewers into OWNERS"
[android-x86/external-libffi.git] / src / powerpc / linux64_closure.S.orig
1 /* -----------------------------------------------------------------------
2    sysv.h - Copyright (c) 2003 Jakub Jelinek <jakub@redhat.com>
3             Copyright (c) 2008 Red Hat, Inc.
4
5    PowerPC64 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,
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    ----------------------------------------------------------------------- */
27 #define LIBFFI_ASM
28 #include <fficonfig.h>
29 #include <ffi.h>
30
31         .file   "linux64_closure.S"
32
33 #ifdef POWERPC64
34         FFI_HIDDEN (ffi_closure_LINUX64)
35         .globl  ffi_closure_LINUX64
36 # if _CALL_ELF == 2
37         .text
38 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
42 # else
43         .section        ".opd","aw"
44         .align  3
45 ffi_closure_LINUX64:
46 #  ifdef _CALL_LINUX
47         .quad   .L.ffi_closure_LINUX64,.TOC.@tocbase,0
48         .type   ffi_closure_LINUX64,@function
49         .text
50 .L.ffi_closure_LINUX64:
51 #  else
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
57         .text
58 .ffi_closure_LINUX64:
59 #  endif
60 # endif
61
62 # if _CALL_ELF == 2
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
66 #  define PARMSAVE 32
67 #  define RETVAL PARMSAVE+64
68 # else
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
72 #  define PARMSAVE 48
73 #  define RETVAL PARMSAVE+64
74 # endif
75
76 .LFB1:
77 # if _CALL_ELF == 2
78         ld      %r12, FFI_TRAMPOLINE_SIZE(%r11)         # closure->cif
79         mflr    %r0
80         lwz     %r12, 28(%r12)                          # cif->flags
81         mtcrf   0x40, %r12
82         addi    %r12, %r1, PARMSAVE
83         bt      7, .Lparmsave
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
88 .Lparmsave:
89         std     %r0, 16(%r1)
90         # Save general regs into parm save area
91         std     %r3, 0(%r12)
92         std     %r4, 8(%r12)
93         std     %r5, 16(%r12)
94         std     %r6, 24(%r12)
95         std     %r7, 32(%r12)
96         std     %r8, 40(%r12)
97         std     %r9, 48(%r12)
98         std     %r10, 56(%r12)
99
100         # load up the pointer to the parm save area
101         mr      %r5, %r12
102 # else
103         # copy r2 to r11 and load TOC into r2
104         mr      %r11, %r2
105         ld      %r2, 16(%r11)
106
107         mflr    %r0
108         # Save general regs into parm save area
109         # This is the parameter save area set up by our caller.
110         std     %r3, PARMSAVE+0(%r1)
111         std     %r4, PARMSAVE+8(%r1)
112         std     %r5, PARMSAVE+16(%r1)
113         std     %r6, PARMSAVE+24(%r1)
114         std     %r7, PARMSAVE+32(%r1)
115         std     %r8, PARMSAVE+40(%r1)
116         std     %r9, PARMSAVE+48(%r1)
117         std     %r10, PARMSAVE+56(%r1)
118
119         std     %r0, 16(%r1)
120
121         # load up the pointer to the parm save area
122         addi    %r5, %r1, PARMSAVE
123 # endif
124
125         # next save fpr 1 to fpr 13
126         stfd    %f1, -104+(0*8)(%r1)
127         stfd    %f2, -104+(1*8)(%r1)
128         stfd    %f3, -104+(2*8)(%r1)
129         stfd    %f4, -104+(3*8)(%r1)
130         stfd    %f5, -104+(4*8)(%r1)
131         stfd    %f6, -104+(5*8)(%r1)
132         stfd    %f7, -104+(6*8)(%r1)
133         stfd    %f8, -104+(7*8)(%r1)
134         stfd    %f9, -104+(8*8)(%r1)
135         stfd    %f10, -104+(9*8)(%r1)
136         stfd    %f11, -104+(10*8)(%r1)
137         stfd    %f12, -104+(11*8)(%r1)
138         stfd    %f13, -104+(12*8)(%r1)
139
140         # load up the pointer to the saved fpr registers */
141         addi    %r6, %r1, -104
142
143         # load up the pointer to the result storage
144         addi    %r4, %r1, -STACKFRAME+RETVAL
145
146         stdu    %r1, -STACKFRAME(%r1)
147 .LCFI0:
148
149         # get the context pointer from the trampoline
150         mr      %r3, %r11
151
152         # make the call
153 # if defined _CALL_LINUX || _CALL_ELF == 2
154         bl ffi_closure_helper_LINUX64
155 # else
156         bl .ffi_closure_helper_LINUX64
157 # endif
158 .Lret:
159
160         # now r3 contains the return type
161         # so use it to look up in a table
162         # so we know how to deal with each type
163
164         # look up the proper starting point in table
165         # by using return type as offset
166         ld %r0, STACKFRAME+16(%r1)
167         cmpldi %r3, FFI_V2_TYPE_SMALL_STRUCT
168         bge .Lsmall
169         mflr %r4                # move address of .Lret to r4
170         sldi %r3, %r3, 4        # now multiply return type by 16
171         addi %r4, %r4, .Lret_type0 - .Lret
172         add %r3, %r3, %r4       # add contents of table to table address
173         mtctr %r3
174         bctr                    # jump to it
175
176 # Each of the ret_typeX code fragments has to be exactly 16 bytes long
177 # (4 instructions). For cache effectiveness we align to a 16 byte boundary
178 # first.
179         .align 4
180
181 .Lret_type0:
182 # case FFI_TYPE_VOID
183         mtlr %r0
184         addi %r1, %r1, STACKFRAME
185         blr
186         nop
187 # case FFI_TYPE_INT
188 # ifdef __LITTLE_ENDIAN__
189         lwa %r3, RETVAL+0(%r1)
190 # else
191         lwa %r3, RETVAL+4(%r1)
192 # endif
193         mtlr %r0
194         addi %r1, %r1, STACKFRAME
195         blr
196 # case FFI_TYPE_FLOAT
197         lfs %f1, RETVAL+0(%r1)
198         mtlr %r0
199         addi %r1, %r1, STACKFRAME
200         blr
201 # case FFI_TYPE_DOUBLE
202         lfd %f1, RETVAL+0(%r1)
203         mtlr %r0
204         addi %r1, %r1, STACKFRAME
205         blr
206 # case FFI_TYPE_LONGDOUBLE
207         lfd %f1, RETVAL+0(%r1)
208         mtlr %r0
209         lfd %f2, RETVAL+8(%r1)
210         b .Lfinish
211 # case FFI_TYPE_UINT8
212 # ifdef __LITTLE_ENDIAN__
213         lbz %r3, RETVAL+0(%r1)
214 # else
215         lbz %r3, RETVAL+7(%r1)
216 # endif
217         mtlr %r0
218         addi %r1, %r1, STACKFRAME
219         blr
220 # case FFI_TYPE_SINT8
221 # ifdef __LITTLE_ENDIAN__
222         lbz %r3, RETVAL+0(%r1)
223 # else
224         lbz %r3, RETVAL+7(%r1)
225 # endif
226         extsb %r3,%r3
227         mtlr %r0
228         b .Lfinish
229 # case FFI_TYPE_UINT16
230 # ifdef __LITTLE_ENDIAN__
231         lhz %r3, RETVAL+0(%r1)
232 # else
233         lhz %r3, RETVAL+6(%r1)
234 # endif
235         mtlr %r0
236 .Lfinish:
237         addi %r1, %r1, STACKFRAME
238         blr
239 # case FFI_TYPE_SINT16
240 # ifdef __LITTLE_ENDIAN__
241         lha %r3, RETVAL+0(%r1)
242 # else
243         lha %r3, RETVAL+6(%r1)
244 # endif
245         mtlr %r0
246         addi %r1, %r1, STACKFRAME
247         blr
248 # case FFI_TYPE_UINT32
249 # ifdef __LITTLE_ENDIAN__
250         lwz %r3, RETVAL+0(%r1)
251 # else
252         lwz %r3, RETVAL+4(%r1)
253 # endif
254         mtlr %r0
255         addi %r1, %r1, STACKFRAME
256         blr
257 # case FFI_TYPE_SINT32
258 # ifdef __LITTLE_ENDIAN__
259         lwa %r3, RETVAL+0(%r1)
260 # else
261         lwa %r3, RETVAL+4(%r1)
262 # endif
263         mtlr %r0
264         addi %r1, %r1, STACKFRAME
265         blr
266 # case FFI_TYPE_UINT64
267         ld %r3, RETVAL+0(%r1)
268         mtlr %r0
269         addi %r1, %r1, STACKFRAME
270         blr
271 # case FFI_TYPE_SINT64
272         ld %r3, RETVAL+0(%r1)
273         mtlr %r0
274         addi %r1, %r1, STACKFRAME
275         blr
276 # case FFI_TYPE_STRUCT
277         mtlr %r0
278         addi %r1, %r1, STACKFRAME
279         blr
280         nop
281 # case FFI_TYPE_POINTER
282         ld %r3, RETVAL+0(%r1)
283         mtlr %r0
284         addi %r1, %r1, STACKFRAME
285         blr
286 # case FFI_V2_TYPE_FLOAT_HOMOG
287         lfs %f1, RETVAL+0(%r1)
288         lfs %f2, RETVAL+4(%r1)
289         lfs %f3, RETVAL+8(%r1)
290         b .Lmorefloat
291 # case FFI_V2_TYPE_DOUBLE_HOMOG
292         lfd %f1, RETVAL+0(%r1)
293         lfd %f2, RETVAL+8(%r1)
294         lfd %f3, RETVAL+16(%r1)
295         lfd %f4, RETVAL+24(%r1)
296         mtlr %r0
297         lfd %f5, RETVAL+32(%r1)
298         lfd %f6, RETVAL+40(%r1)
299         lfd %f7, RETVAL+48(%r1)
300         lfd %f8, RETVAL+56(%r1)
301         addi %r1, %r1, STACKFRAME
302         blr
303 .Lmorefloat:
304         lfs %f4, RETVAL+12(%r1)
305         mtlr %r0
306         lfs %f5, RETVAL+16(%r1)
307         lfs %f6, RETVAL+20(%r1)
308         lfs %f7, RETVAL+24(%r1)
309         lfs %f8, RETVAL+28(%r1)
310         addi %r1, %r1, STACKFRAME
311         blr
312 .Lsmall:
313 # ifdef __LITTLE_ENDIAN__
314         ld %r3,RETVAL+0(%r1)
315         mtlr %r0
316         ld %r4,RETVAL+8(%r1)
317         addi %r1, %r1, STACKFRAME
318         blr
319 # else
320         # A struct smaller than a dword is returned in the low bits of r3
321         # ie. right justified.  Larger structs are passed left justified
322         # in r3 and r4.  The return value area on the stack will have
323         # the structs as they are usually stored in memory.
324         cmpldi %r3, FFI_V2_TYPE_SMALL_STRUCT + 7 # size 8 bytes?
325         neg %r5, %r3
326         ld %r3,RETVAL+0(%r1)
327         blt .Lsmalldown
328         mtlr %r0
329         ld %r4,RETVAL+8(%r1)
330         addi %r1, %r1, STACKFRAME
331         blr
332 .Lsmalldown:
333         addi %r5, %r5, FFI_V2_TYPE_SMALL_STRUCT + 7
334         mtlr %r0
335         sldi %r5, %r5, 3
336         addi %r1, %r1, STACKFRAME
337         srd %r3, %r3, %r5
338         blr
339 # endif
340
341 .LFE1:
342         .long   0
343         .byte   0,12,0,1,128,0,0,0
344 # if _CALL_ELF == 2
345         .size   ffi_closure_LINUX64,.-ffi_closure_LINUX64
346 # else
347 #  ifdef _CALL_LINUX
348         .size   ffi_closure_LINUX64,.-.L.ffi_closure_LINUX64
349 #  else
350         .size   .ffi_closure_LINUX64,.-.ffi_closure_LINUX64
351 #  endif
352 # endif
353
354         .section        .eh_frame,EH_FRAME_FLAGS,@progbits
355 .Lframe1:
356         .4byte  .LECIE1-.LSCIE1  # Length of Common Information Entry
357 .LSCIE1:
358         .4byte  0x0      # CIE Identifier Tag
359         .byte   0x1      # CIE Version
360         .ascii "zR\0"    # CIE Augmentation
361         .uleb128 0x1     # CIE Code Alignment Factor
362         .sleb128 -8      # CIE Data Alignment Factor
363         .byte   0x41     # CIE RA Column
364         .uleb128 0x1     # Augmentation size
365         .byte   0x14     # FDE Encoding (pcrel udata8)
366         .byte   0xc      # DW_CFA_def_cfa
367         .uleb128 0x1
368         .uleb128 0x0
369         .align 3
370 .LECIE1:
371 .LSFDE1:
372         .4byte  .LEFDE1-.LASFDE1         # FDE Length
373 .LASFDE1:
374         .4byte  .LASFDE1-.Lframe1        # FDE CIE offset
375         .8byte  .LFB1-.  # FDE initial location
376         .8byte  .LFE1-.LFB1      # FDE address range
377         .uleb128 0x0     # Augmentation size
378         .byte   0x2      # DW_CFA_advance_loc1
379         .byte   .LCFI0-.LFB1
380         .byte   0xe      # DW_CFA_def_cfa_offset
381         .uleb128 STACKFRAME
382         .byte   0x11     # DW_CFA_offset_extended_sf
383         .uleb128 0x41
384         .sleb128 -2
385         .align 3
386 .LEFDE1:
387
388 # if defined __ELF__ && defined __linux__
389         .section        .note.GNU-stack,"",@progbits
390 # endif
391 #endif