b1e12197a2b2c5fe439f020dc63cfb57d72fc82b
[platform/upstream/gcc48.git] / libffi / src / powerpc / linux64_closure.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 #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         .section        ".opd","aw"
37         .align  3
38 ffi_closure_LINUX64:
39 #ifdef _CALL_LINUX
40         .quad   .L.ffi_closure_LINUX64,.TOC.@tocbase,0
41         .type   ffi_closure_LINUX64,@function
42         .text
43 .L.ffi_closure_LINUX64:
44 #else
45         FFI_HIDDEN (.ffi_closure_LINUX64)
46         .globl  .ffi_closure_LINUX64
47         .quad   .ffi_closure_LINUX64,.TOC.@tocbase,0
48         .size   ffi_closure_LINUX64,24
49         .type   .ffi_closure_LINUX64,@function
50         .text
51 .ffi_closure_LINUX64:
52 #endif
53 .LFB1:
54         # save general regs into parm save area
55         std     %r3, 48(%r1)
56         std     %r4, 56(%r1)
57         std     %r5, 64(%r1)
58         std     %r6, 72(%r1)
59         mflr    %r0
60
61         std     %r7, 80(%r1)
62         std     %r8, 88(%r1)
63         std     %r9, 96(%r1)
64         std     %r10, 104(%r1)
65         std     %r0, 16(%r1)
66
67         # mandatory 48 bytes special reg save area + 64 bytes parm save area
68         # + 16 bytes retval area + 13*8 bytes fpr save area + round to 16
69         stdu    %r1, -240(%r1)
70 .LCFI0:
71
72         # next save fpr 1 to fpr 13
73         stfd  %f1, 128+(0*8)(%r1)
74         stfd  %f2, 128+(1*8)(%r1)
75         stfd  %f3, 128+(2*8)(%r1)
76         stfd  %f4, 128+(3*8)(%r1)
77         stfd  %f5, 128+(4*8)(%r1)
78         stfd  %f6, 128+(5*8)(%r1)
79         stfd  %f7, 128+(6*8)(%r1)
80         stfd  %f8, 128+(7*8)(%r1)
81         stfd  %f9, 128+(8*8)(%r1)
82         stfd  %f10, 128+(9*8)(%r1)
83         stfd  %f11, 128+(10*8)(%r1)
84         stfd  %f12, 128+(11*8)(%r1)
85         stfd  %f13, 128+(12*8)(%r1)
86
87         # set up registers for the routine that actually does the work
88         # get the context pointer from the trampoline
89         mr %r3, %r11
90
91         # now load up the pointer to the result storage
92         addi %r4, %r1, 112
93
94         # now load up the pointer to the parameter save area
95         # in the previous frame
96         addi %r5, %r1, 240 + 48
97
98         # now load up the pointer to the saved fpr registers */
99         addi %r6, %r1, 128
100
101         # make the call
102 #ifdef _CALL_LINUX
103         bl ffi_closure_helper_LINUX64
104 #else
105         bl .ffi_closure_helper_LINUX64
106 #endif
107 .Lret:
108
109         # now r3 contains the return type
110         # so use it to look up in a table
111         # so we know how to deal with each type
112
113         # look up the proper starting point in table
114         # by using return type as offset
115         mflr %r4                # move address of .Lret to r4
116         sldi %r3, %r3, 4        # now multiply return type by 16
117         addi %r4, %r4, .Lret_type0 - .Lret
118         ld %r0, 240+16(%r1)
119         add %r3, %r3, %r4       # add contents of table to table address
120         mtctr %r3
121         bctr                    # jump to it
122
123 # Each of the ret_typeX code fragments has to be exactly 16 bytes long
124 # (4 instructions). For cache effectiveness we align to a 16 byte boundary
125 # first.
126         .align 4
127
128 .Lret_type0:
129 # case FFI_TYPE_VOID
130         mtlr %r0
131         addi %r1, %r1, 240
132         blr
133         nop
134 # case FFI_TYPE_INT
135         lwa %r3, 112+4(%r1)
136         mtlr %r0
137         addi %r1, %r1, 240
138         blr
139 # case FFI_TYPE_FLOAT
140         lfs %f1, 112+0(%r1)
141         mtlr %r0
142         addi %r1, %r1, 240
143         blr
144 # case FFI_TYPE_DOUBLE
145         lfd %f1, 112+0(%r1)
146         mtlr %r0
147         addi %r1, %r1, 240
148         blr
149 # case FFI_TYPE_LONGDOUBLE
150         lfd %f1, 112+0(%r1)
151         mtlr %r0
152         lfd %f2, 112+8(%r1)
153         b .Lfinish
154 # case FFI_TYPE_UINT8
155         lbz %r3, 112+7(%r1)
156         mtlr %r0
157         addi %r1, %r1, 240
158         blr
159 # case FFI_TYPE_SINT8
160         lbz %r3, 112+7(%r1)
161         extsb %r3,%r3
162         mtlr %r0
163         b .Lfinish
164 # case FFI_TYPE_UINT16
165         lhz %r3, 112+6(%r1)
166         mtlr %r0
167 .Lfinish:
168         addi %r1, %r1, 240
169         blr
170 # case FFI_TYPE_SINT16
171         lha %r3, 112+6(%r1)
172         mtlr %r0
173         addi %r1, %r1, 240
174         blr
175 # case FFI_TYPE_UINT32
176         lwz %r3, 112+4(%r1)
177         mtlr %r0
178         addi %r1, %r1, 240
179         blr
180 # case FFI_TYPE_SINT32
181         lwa %r3, 112+4(%r1)
182         mtlr %r0
183         addi %r1, %r1, 240
184         blr
185 # case FFI_TYPE_UINT64
186         ld %r3, 112+0(%r1)
187         mtlr %r0
188         addi %r1, %r1, 240
189         blr
190 # case FFI_TYPE_SINT64
191         ld %r3, 112+0(%r1)
192         mtlr %r0
193         addi %r1, %r1, 240
194         blr
195 # case FFI_TYPE_STRUCT
196         mtlr %r0
197         addi %r1, %r1, 240
198         blr
199         nop
200 # case FFI_TYPE_POINTER
201         ld %r3, 112+0(%r1)
202         mtlr %r0
203         addi %r1, %r1, 240
204         blr
205 # esac
206 .LFE1:
207         .long   0
208         .byte   0,12,0,1,128,0,0,0
209 #ifdef _CALL_LINUX
210         .size   ffi_closure_LINUX64,.-.L.ffi_closure_LINUX64
211 #else
212         .size   .ffi_closure_LINUX64,.-.ffi_closure_LINUX64
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   0xe      # DW_CFA_def_cfa_offset
242         .uleb128 240
243         .byte   0x11     # DW_CFA_offset_extended_sf
244         .uleb128 0x41
245         .sleb128 -2
246         .align 3
247 .LEFDE1:
248 #endif
249
250 #if defined __ELF__ && defined __linux__
251         .section        .note.GNU-stack,"",@progbits
252 #endif