• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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	.text
36	.cfi_startproc
37# if _CALL_ELF == 2
38ffi_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
45ffi_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)
68
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
76
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
88
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
96
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 3-7 of the flags.  */
105	mtcrf	0xc0, %r31
106
107	/* Get the address to call into CTR.  */
108	mtctr	%r12
109	/* Load all those argument registers.  */
110	addi	%r29, %r28, -32-(8*8)
111	ld	%r3,  (0*8)(%r29)
112	ld	%r4,  (1*8)(%r29)
113	ld	%r5,  (2*8)(%r29)
114	ld	%r6,  (3*8)(%r29)
115	bf-	5, 1f
116	ld	%r7,  (4*8)(%r29)
117	ld	%r8,  (5*8)(%r29)
118	ld	%r9,  (6*8)(%r29)
119	ld	%r10, (7*8)(%r29)
1201:
121
122	/* Load all the FP registers.  */
123	bf-	6, 2f
124	addi	%r29, %r29, -(14*8)
125	lfd	%f1,  ( 1*8)(%r29)
126	lfd	%f2,  ( 2*8)(%r29)
127	lfd	%f3,  ( 3*8)(%r29)
128	lfd	%f4,  ( 4*8)(%r29)
129	lfd	%f5,  ( 5*8)(%r29)
130	lfd	%f6,  ( 6*8)(%r29)
131	lfd	%f7,  ( 7*8)(%r29)
132	lfd	%f8,  ( 8*8)(%r29)
133	lfd	%f9,  ( 9*8)(%r29)
134	lfd	%f10, (10*8)(%r29)
135	lfd	%f11, (11*8)(%r29)
136	lfd	%f12, (12*8)(%r29)
137	lfd	%f13, (13*8)(%r29)
1382:
139
140	/* Load all the vector registers.  */
141	bf-	3, 3f
142	addi	%r29, %r29, -16
143	lvx	%v13, 0, %r29
144	addi	%r29, %r29, -16
145	lvx	%v12, 0, %r29
146	addi	%r29, %r29, -16
147	lvx	%v11, 0, %r29
148	addi	%r29, %r29, -16
149	lvx	%v10, 0, %r29
150	addi	%r29, %r29, -16
151	lvx	%v9,  0, %r29
152	addi	%r29, %r29, -16
153	lvx	%v8,  0, %r29
154	addi	%r29, %r29, -16
155	lvx	%v7,  0, %r29
156	addi	%r29, %r29, -16
157	lvx	%v6,  0, %r29
158	addi	%r29, %r29, -16
159	lvx	%v5,  0, %r29
160	addi	%r29, %r29, -16
161	lvx	%v4,  0, %r29
162	addi	%r29, %r29, -16
163	lvx	%v3,  0, %r29
164	addi	%r29, %r29, -16
165	lvx	%v2,  0, %r29
1663:
167
168	/* Make the call.  */
169	ld	%r11, 8(%r28)
170	bctrl
171
172	/* This must follow the call immediately, the unwinder
173	   uses this to find out if r2 has been saved or not.  */
174# if _CALL_ELF == 2
175	ld	%r2, 24(%r1)
176# else
177	ld	%r2, 40(%r1)
178# endif
179
180	/* Now, deal with the return value.  */
181	mtcrf	0x01, %r31
182	bt	31, .Lstruct_return_value
183	bt	30, .Ldone_return_value
184	bt	29, .Lfp_return_value
185	bt	28, .Lvec_return_value
186	std	%r3, 0(%r30)
187	/* Fall through...  */
188
189.Ldone_return_value:
190	/* Restore the registers we used and return.  */
191	mr	%r1, %r28
192	.cfi_def_cfa_register 1
193	ld	%r0, 16(%r28)
194	ld	%r28, -32(%r28)
195	mtlr	%r0
196	ld	%r29, -24(%r1)
197	ld	%r30, -16(%r1)
198	ld	%r31, -8(%r1)
199	blr
200
201.Lvec_return_value:
202	stvx	%v2, 0, %r30
203	b	.Ldone_return_value
204
205.Lfp_return_value:
206	.cfi_def_cfa_register 28
207	mtcrf	0x02, %r31 /* cr6  */
208	bf	27, .Lfloat_return_value
209	stfd	%f1, 0(%r30)
210	bf	26, .Ldone_return_value
211	stfd	%f2, 8(%r30)
212	b	.Ldone_return_value
213.Lfloat_return_value:
214	stfs	%f1, 0(%r30)
215	b	.Ldone_return_value
216
217.Lstruct_return_value:
218	bf	29, .Lvec_homog_or_small_struct
219	mtcrf	0x02, %r31 /* cr6  */
220	bf	27, .Lfloat_homog_return_value
221	stfd	%f1, 0(%r30)
222	stfd	%f2, 8(%r30)
223	stfd	%f3, 16(%r30)
224	stfd	%f4, 24(%r30)
225	stfd	%f5, 32(%r30)
226	stfd	%f6, 40(%r30)
227	stfd	%f7, 48(%r30)
228	stfd	%f8, 56(%r30)
229	b	.Ldone_return_value
230
231.Lfloat_homog_return_value:
232	stfs	%f1, 0(%r30)
233	stfs	%f2, 4(%r30)
234	stfs	%f3, 8(%r30)
235	stfs	%f4, 12(%r30)
236	stfs	%f5, 16(%r30)
237	stfs	%f6, 20(%r30)
238	stfs	%f7, 24(%r30)
239	stfs	%f8, 28(%r30)
240	b	.Ldone_return_value
241
242.Lvec_homog_or_small_struct:
243	bf	28, .Lsmall_struct
244	stvx	%v2, 0, %r30
245	addi	%r30, %r30, 16
246	stvx	%v3, 0, %r30
247	addi	%r30, %r30, 16
248	stvx	%v4, 0, %r30
249	addi	%r30, %r30, 16
250	stvx	%v5, 0, %r30
251	addi	%r30, %r30, 16
252	stvx	%v6, 0, %r30
253	addi	%r30, %r30, 16
254	stvx	%v7, 0, %r30
255	addi	%r30, %r30, 16
256	stvx	%v8, 0, %r30
257	addi	%r30, %r30, 16
258	stvx	%v9, 0, %r30
259	b	.Ldone_return_value
260
261.Lsmall_struct:
262	std	%r3, 0(%r30)
263	std	%r4, 8(%r30)
264	b	.Ldone_return_value
265
266	.cfi_endproc
267# if _CALL_ELF == 2
268	.size	ffi_call_LINUX64,.-ffi_call_LINUX64
269# else
270#  ifdef _CALL_LINUX
271	.size	ffi_call_LINUX64,.-.L.ffi_call_LINUX64
272#  else
273	.long	0
274	.byte	0,12,0,1,128,4,0,0
275	.size	.ffi_call_LINUX64,.-.ffi_call_LINUX64
276#  endif
277# endif
278
279#endif
280
281#if (defined __ELF__ && defined __linux__) || _CALL_ELF == 2
282	.section	.note.GNU-stack,"",@progbits
283#endif
284