OSDN Git Service

Compile in support for closures
[android-x86/external-libffi.git] / src / powerpc / linux64.S
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
28 #define LIBFFI_ASM
29 #include <fficonfig.h>
30 #include <ffi.h>
31
32 #ifdef POWERPC64
33         .hidden ffi_call_LINUX64
34         .globl  ffi_call_LINUX64
35 # if _CALL_ELF == 2
36         .text
37 ffi_call_LINUX64:
38         addis   %r2, %r12, .TOC.-ffi_call_LINUX64@ha
39         addi    %r2, %r2, .TOC.-ffi_call_LINUX64@l
40         .localentry ffi_call_LINUX64, . - ffi_call_LINUX64
41 # else
42         .section        ".opd","aw"
43         .align  3
44 ffi_call_LINUX64:
45 #  ifdef _CALL_LINUX
46         .quad   .L.ffi_call_LINUX64,.TOC.@tocbase,0
47         .type   ffi_call_LINUX64,@function
48         .text
49 .L.ffi_call_LINUX64:
50 #  else
51         .hidden .ffi_call_LINUX64
52         .globl  .ffi_call_LINUX64
53         .quad   .ffi_call_LINUX64,.TOC.@tocbase,0
54         .size   ffi_call_LINUX64,24
55         .type   .ffi_call_LINUX64,@function
56         .text
57 .ffi_call_LINUX64:
58 #  endif
59 # endif
60 .LFB1:
61         mflr    %r0
62         std     %r28, -32(%r1)
63         std     %r29, -24(%r1)
64         std     %r30, -16(%r1)
65         std     %r31, -8(%r1)
66         std     %r0, 16(%r1)
67
68         mr      %r28, %r1       /* our AP.  */
69 .LCFI0:
70         stdux   %r1, %r1, %r4
71         mr      %r31, %r5       /* flags, */
72         mr      %r30, %r6       /* rvalue, */
73         mr      %r29, %r7       /* function address.  */
74 /* Save toc pointer, not for the ffi_prep_args64 call, but for the later
75    bctrl function call.  */
76 # if _CALL_ELF == 2
77         std     %r2, 24(%r1)
78 # else
79         std     %r2, 40(%r1)
80 # endif
81
82         /* Call ffi_prep_args64.  */
83         mr      %r4, %r1
84 # if defined _CALL_LINUX || _CALL_ELF == 2
85         bl      ffi_prep_args64
86 # else
87         bl      .ffi_prep_args64
88 # endif
89
90 # if _CALL_ELF == 2
91         mr      %r12, %r29
92 # else
93         ld      %r12, 0(%r29)
94         ld      %r2, 8(%r29)
95         ld      %r11, 16(%r29)
96 # endif
97         /* Now do the call.  */
98         /* Set up cr1 with bits 4-7 of the flags.  */
99         mtcrf   0x40, %r31
100
101         /* Get the address to call into CTR.  */
102         mtctr   %r12
103         /* Load all those argument registers.  */
104         ld      %r3, -32-(8*8)(%r28)
105         ld      %r4, -32-(7*8)(%r28)
106         ld      %r5, -32-(6*8)(%r28)
107         ld      %r6, -32-(5*8)(%r28)
108         bf-     5, 1f
109         ld      %r7, -32-(4*8)(%r28)
110         ld      %r8, -32-(3*8)(%r28)
111         ld      %r9, -32-(2*8)(%r28)
112         ld      %r10, -32-(1*8)(%r28)
113 1:
114
115         /* Load all the FP registers.  */
116         bf-     6, 2f
117         lfd     %f1, -32-(21*8)(%r28)
118         lfd     %f2, -32-(20*8)(%r28)
119         lfd     %f3, -32-(19*8)(%r28)
120         lfd     %f4, -32-(18*8)(%r28)
121         lfd     %f5, -32-(17*8)(%r28)
122         lfd     %f6, -32-(16*8)(%r28)
123         lfd     %f7, -32-(15*8)(%r28)
124         lfd     %f8, -32-(14*8)(%r28)
125         lfd     %f9, -32-(13*8)(%r28)
126         lfd     %f10, -32-(12*8)(%r28)
127         lfd     %f11, -32-(11*8)(%r28)
128         lfd     %f12, -32-(10*8)(%r28)
129         lfd     %f13, -32-(9*8)(%r28)
130 2:
131
132         /* Make the call.  */
133         bctrl
134
135         /* This must follow the call immediately, the unwinder
136            uses this to find out if r2 has been saved or not.  */
137 # if _CALL_ELF == 2
138         ld      %r2, 24(%r1)
139 # else
140         ld      %r2, 40(%r1)
141 # endif
142
143         /* Now, deal with the return value.  */
144         mtcrf   0x01, %r31
145         bt      31, .Lstruct_return_value
146         bt      30, .Ldone_return_value
147         bt      29, .Lfp_return_value
148         std     %r3, 0(%r30)
149         /* Fall through...  */
150
151 .Ldone_return_value:
152         /* Restore the registers we used and return.  */
153         mr      %r1, %r28
154         ld      %r0, 16(%r28)
155         ld      %r28, -32(%r28)
156         mtlr    %r0
157         ld      %r29, -24(%r1)
158         ld      %r30, -16(%r1)
159         ld      %r31, -8(%r1)
160         blr
161
162 .Lfp_return_value:
163         bf      28, .Lfloat_return_value
164         stfd    %f1, 0(%r30)
165         mtcrf   0x02, %r31 /* cr6  */
166         bf      27, .Ldone_return_value
167         stfd    %f2, 8(%r30)
168         b       .Ldone_return_value
169 .Lfloat_return_value:
170         stfs    %f1, 0(%r30)
171         b       .Ldone_return_value
172
173 .Lstruct_return_value:
174         bf      29, .Lsmall_struct
175         bf      28, .Lfloat_homog_return_value
176         stfd    %f1, 0(%r30)
177         stfd    %f2, 8(%r30)
178         stfd    %f3, 16(%r30)
179         stfd    %f4, 24(%r30)
180         stfd    %f5, 32(%r30)
181         stfd    %f6, 40(%r30)
182         stfd    %f7, 48(%r30)
183         stfd    %f8, 56(%r30)
184         b       .Ldone_return_value
185
186 .Lfloat_homog_return_value:
187         stfs    %f1, 0(%r30)
188         stfs    %f2, 4(%r30)
189         stfs    %f3, 8(%r30)
190         stfs    %f4, 12(%r30)
191         stfs    %f5, 16(%r30)
192         stfs    %f6, 20(%r30)
193         stfs    %f7, 24(%r30)
194         stfs    %f8, 28(%r30)
195         b       .Ldone_return_value
196
197 .Lsmall_struct:
198         std     %r3, 0(%r30)
199         std     %r4, 8(%r30)
200         b       .Ldone_return_value
201
202 .LFE1:
203         .long   0
204         .byte   0,12,0,1,128,4,0,0
205 # if _CALL_ELF == 2
206         .size   ffi_call_LINUX64,.-ffi_call_LINUX64
207 # else
208 #  ifdef _CALL_LINUX
209         .size   ffi_call_LINUX64,.-.L.ffi_call_LINUX64
210 #  else
211         .size   .ffi_call_LINUX64,.-.ffi_call_LINUX64
212 #  endif
213 # endif
214
215         .section        .eh_frame,EH_FRAME_FLAGS,@progbits
216 .Lframe1:
217         .4byte  .LECIE1-.LSCIE1  # Length of Common Information Entry
218 .LSCIE1:
219         .4byte  0x0      # CIE Identifier Tag
220         .byte   0x1      # CIE Version
221         .ascii "zR\0"    # CIE Augmentation
222         .uleb128 0x1     # CIE Code Alignment Factor
223         .sleb128 -8      # CIE Data Alignment Factor
224         .byte   0x41     # CIE RA Column
225         .uleb128 0x1     # Augmentation size
226         .byte   0x14     # FDE Encoding (pcrel udata8)
227         .byte   0xc      # DW_CFA_def_cfa
228         .uleb128 0x1
229         .uleb128 0x0
230         .align 3
231 .LECIE1:
232 .LSFDE1:
233         .4byte  .LEFDE1-.LASFDE1         # FDE Length
234 .LASFDE1:
235         .4byte  .LASFDE1-.Lframe1        # FDE CIE offset
236         .8byte  .LFB1-.  # FDE initial location
237         .8byte  .LFE1-.LFB1      # FDE address range
238         .uleb128 0x0     # Augmentation size
239         .byte   0x2      # DW_CFA_advance_loc1
240         .byte   .LCFI0-.LFB1
241         .byte   0xd      # DW_CFA_def_cfa_register
242         .uleb128 0x1c
243         .byte   0x11     # DW_CFA_offset_extended_sf
244         .uleb128 0x41
245         .sleb128 -2
246         .byte   0x9f     # DW_CFA_offset, column 0x1f
247         .uleb128 0x1
248         .byte   0x9e     # DW_CFA_offset, column 0x1e
249         .uleb128 0x2
250         .byte   0x9d     # DW_CFA_offset, column 0x1d
251         .uleb128 0x3
252         .byte   0x9c     # DW_CFA_offset, column 0x1c
253         .uleb128 0x4
254         .align 3
255 .LEFDE1:
256
257 #endif
258
259 #if (defined __ELF__ && defined __linux__) || _CALL_ELF == 2
260         .section        .note.GNU-stack,"",@progbits
261 #endif