2017-12-07 Vladimir Makarov <vmakarov@redhat.com>
[official-gcc.git] / libffi / src / powerpc / linux64.S
blobb2ae60ead6e13b309fd547d6bb84c37518769e06
1 /* -----------------------------------------------------------------------
2    sysv.h - Copyright (c) 2003 Jakub Jelinek <jakub@redhat.com>
3             Copyright (c) 2008 Red Hat, Inc.
5    PowerPC64 Assembly glue.
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,
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    ----------------------------------------------------------------------- */
28 #define LIBFFI_ASM
29 #include <fficonfig.h>
30 #include <ffi.h>
32 #ifdef POWERPC64
33         .hidden ffi_call_LINUX64
34         .globl  ffi_call_LINUX64
35         .text
36         .cfi_startproc
37 # if _CALL_ELF == 2
38 ffi_call_LINUX64:
39         addis   %r2, %r12, .TOC.-ffi_call_LINUX64@ha
40         addi    %r2, %r2, .TOC.-ffi_call_LINUX64@l
41         .localentry ffi_call_LINUX64, . - ffi_call_LINUX64
42 # else
43         .section        ".opd","aw"
44         .align  3
45 ffi_call_LINUX64:
46 #  ifdef _CALL_LINUX
47         .quad   .L.ffi_call_LINUX64,.TOC.@tocbase,0
48         .type   ffi_call_LINUX64,@function
49         .text
50 .L.ffi_call_LINUX64:
51 #  else
52         .hidden .ffi_call_LINUX64
53         .globl  .ffi_call_LINUX64
54         .quad   .ffi_call_LINUX64,.TOC.@tocbase,0
55         .size   ffi_call_LINUX64,24
56         .type   .ffi_call_LINUX64,@function
57         .text
58 .ffi_call_LINUX64:
59 #  endif
60 # endif
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     %r7, 8(%r1)     /* closure, saved in cr field.  */
67         std     %r0, 16(%r1)
69         mr      %r28, %r1       /* our AP.  */
70         .cfi_def_cfa_register 28
71         .cfi_offset 65, 16
72         .cfi_offset 31, -8
73         .cfi_offset 30, -16
74         .cfi_offset 29, -24
75         .cfi_offset 28, -32
77         stdux   %r1, %r1, %r8
78         mr      %r31, %r6       /* flags, */
79         mr      %r30, %r5       /* rvalue, */
80         mr      %r29, %r4       /* function address.  */
81 /* Save toc pointer, not for the ffi_prep_args64 call, but for the later
82    bctrl function call.  */
83 # if _CALL_ELF == 2
84         std     %r2, 24(%r1)
85 # else
86         std     %r2, 40(%r1)
87 # endif
89         /* Call ffi_prep_args64.  */
90         mr      %r4, %r1
91 # if defined _CALL_LINUX || _CALL_ELF == 2
92         bl      ffi_prep_args64
93 # else
94         bl      .ffi_prep_args64
95 # endif
97 # if _CALL_ELF == 2
98         mr      %r12, %r29
99 # else
100         ld      %r12, 0(%r29)
101         ld      %r2, 8(%r29)
102 # endif
103         /* Now do the call.  */
104         /* Set up cr1 with bits 4-7 of the flags.  */
105         mtcrf   0x40, %r31
107         /* Get the address to call into CTR.  */
108         mtctr   %r12
109         /* Load all those argument registers.  */
110         ld      %r3, -32-(8*8)(%r28)
111         ld      %r4, -32-(7*8)(%r28)
112         ld      %r5, -32-(6*8)(%r28)
113         ld      %r6, -32-(5*8)(%r28)
114         bf-     5, 1f
115         ld      %r7, -32-(4*8)(%r28)
116         ld      %r8, -32-(3*8)(%r28)
117         ld      %r9, -32-(2*8)(%r28)
118         ld      %r10, -32-(1*8)(%r28)
121         /* Load all the FP registers.  */
122         bf-     6, 2f
123         lfd     %f1, -32-(21*8)(%r28)
124         lfd     %f2, -32-(20*8)(%r28)
125         lfd     %f3, -32-(19*8)(%r28)
126         lfd     %f4, -32-(18*8)(%r28)
127         lfd     %f5, -32-(17*8)(%r28)
128         lfd     %f6, -32-(16*8)(%r28)
129         lfd     %f7, -32-(15*8)(%r28)
130         lfd     %f8, -32-(14*8)(%r28)
131         lfd     %f9, -32-(13*8)(%r28)
132         lfd     %f10, -32-(12*8)(%r28)
133         lfd     %f11, -32-(11*8)(%r28)
134         lfd     %f12, -32-(10*8)(%r28)
135         lfd     %f13, -32-(9*8)(%r28)
138         /* Make the call.  */
139         ld      %r11, 8(%r28)
140         bctrl
142         /* This must follow the call immediately, the unwinder
143            uses this to find out if r2 has been saved or not.  */
144 # if _CALL_ELF == 2
145         ld      %r2, 24(%r1)
146 # else
147         ld      %r2, 40(%r1)
148 # endif
150         /* Now, deal with the return value.  */
151         mtcrf   0x01, %r31
152         bt      31, .Lstruct_return_value
153         bt      30, .Ldone_return_value
154         bt      29, .Lfp_return_value
155         std     %r3, 0(%r30)
156         /* Fall through...  */
158 .Ldone_return_value:
159         /* Restore the registers we used and return.  */
160         mr      %r1, %r28
161         .cfi_def_cfa_register 1
162         ld      %r0, 16(%r28)
163         ld      %r28, -32(%r28)
164         mtlr    %r0
165         ld      %r29, -24(%r1)
166         ld      %r30, -16(%r1)
167         ld      %r31, -8(%r1)
168         blr
170 .Lfp_return_value:
171         .cfi_def_cfa_register 28
172         bf      28, .Lfloat_return_value
173         stfd    %f1, 0(%r30)
174         mtcrf   0x02, %r31 /* cr6  */
175         bf      27, .Ldone_return_value
176         stfd    %f2, 8(%r30)
177         b       .Ldone_return_value
178 .Lfloat_return_value:
179         stfs    %f1, 0(%r30)
180         b       .Ldone_return_value
182 .Lstruct_return_value:
183         bf      29, .Lsmall_struct
184         bf      28, .Lfloat_homog_return_value
185         stfd    %f1, 0(%r30)
186         stfd    %f2, 8(%r30)
187         stfd    %f3, 16(%r30)
188         stfd    %f4, 24(%r30)
189         stfd    %f5, 32(%r30)
190         stfd    %f6, 40(%r30)
191         stfd    %f7, 48(%r30)
192         stfd    %f8, 56(%r30)
193         b       .Ldone_return_value
195 .Lfloat_homog_return_value:
196         stfs    %f1, 0(%r30)
197         stfs    %f2, 4(%r30)
198         stfs    %f3, 8(%r30)
199         stfs    %f4, 12(%r30)
200         stfs    %f5, 16(%r30)
201         stfs    %f6, 20(%r30)
202         stfs    %f7, 24(%r30)
203         stfs    %f8, 28(%r30)
204         b       .Ldone_return_value
206 .Lsmall_struct:
207         std     %r3, 0(%r30)
208         std     %r4, 8(%r30)
209         b       .Ldone_return_value
211         .cfi_endproc
212 # if _CALL_ELF == 2
213         .size   ffi_call_LINUX64,.-ffi_call_LINUX64
214 # else
215 #  ifdef _CALL_LINUX
216         .size   ffi_call_LINUX64,.-.L.ffi_call_LINUX64
217 #  else
218         .long   0
219         .byte   0,12,0,1,128,4,0,0
220         .size   .ffi_call_LINUX64,.-.ffi_call_LINUX64
221 #  endif
222 # endif
224 #endif
226 #if (defined __ELF__ && defined __linux__) || _CALL_ELF == 2
227         .section        .note.GNU-stack,"",@progbits
228 #endif