xref: /netbsd-src/external/gpl3/gcc/dist/libgcc/config/rs6000/tramp.S (revision 9fb66d812c00ebfb445c0b47dea128f32aa6fe96)
1/*  Special support for trampolines
2 *
3 *   Copyright (C) 1996-2020 Free Software Foundation, Inc.
4 *   Written By Michael Meissner
5 *
6 * This file is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 3, or (at your option) any
9 * later version.
10 *
11 * This file is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * General Public License for more details.
15 *
16 * Under Section 7 of GPL version 3, you are granted additional
17 * permissions described in the GCC Runtime Library Exception, version
18 * 3.1, as published by the Free Software Foundation.
19 *
20 * You should have received a copy of the GNU General Public License and
21 * a copy of the GCC Runtime Library Exception along with this program;
22 * see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23 * <http://www.gnu.org/licenses/>.
24 */
25
26/* Set up trampolines.  */
27
28	.section ".text"
29#include "ppc-asm.h"
30#include "config.h"
31
32#ifndef __powerpc64__
33	.type	trampoline_initial,@object
34	.align	2
35trampoline_initial:
36	mflr	r0
37	bcl	20,31,1f
38.Lfunc = .-trampoline_initial
39	.long	0			/* will be replaced with function address */
40.Lchain = .-trampoline_initial
41	.long	0			/* will be replaced with static chain */
421:	mflr	r11
43	mtlr	r0
44	lwz	r0,0(r11)		/* function address */
45	lwz	r11,4(r11)		/* static chain */
46	mtctr	r0
47	bctr
48
49trampoline_size = .-trampoline_initial
50	.size	trampoline_initial,trampoline_size
51
52
53/* R3 = stack address to store trampoline */
54/* R4 = length of trampoline area */
55/* R5 = function address */
56/* R6 = static chain */
57
58FUNC_START(__trampoline_setup)
59	.cfi_startproc
60	mflr	r0		/* save return address */
61        bcl	20,31,.LCF0	/* load up __trampoline_initial into r7 */
62	.cfi_register lr,r0
63.LCF0:
64        mflr	r11
65        addi	r7,r11,trampoline_initial-4-.LCF0 /* trampoline address -4 */
66
67	li	r8,trampoline_size	/* verify that the trampoline is big enough */
68	cmpw	cr1,r8,r4
69	srwi	r4,r4,2		/* # words to move */
70	addi	r9,r3,-4	/* adjust pointer for lwzu */
71	mtctr	r4
72	blt	cr1,.Labort
73
74	mtlr	r0
75
76	/* Copy the instructions to the stack */
77.Lmove:
78	lwzu	r10,4(r7)
79	stwu	r10,4(r9)
80	bdnz	.Lmove
81
82	/* Store correct function and static chain */
83	stw	r5,.Lfunc(r3)
84	stw	r6,.Lchain(r3)
85
86	/* Now flush both caches */
87	mtctr	r4
88.Lcache:
89	icbi	0,r3
90	dcbf	0,r3
91	addi	r3,r3,4
92	bdnz	.Lcache
93
94	/* Finally synchronize things & return */
95	sync
96	isync
97	blr
98
99.Labort:
100/* Use a longcall sequence in the non PIC case on VxWorks, to prevent
101   possible relocation errors if this is module-loaded very far away from
102   the 'abort' entry point.  */
103#if defined (__VXWORKS__) && ! (defined __PIC__ || defined __pic__)
104        lis   r11,JUMP_TARGET(abort)@ha
105        addic r11,r11,JUMP_TARGET(abort)@l
106        mtlr  r11
107        blrl
108#else
109
110#if (defined __PIC__ || defined __pic__) && defined HAVE_AS_REL16
111	bcl	20,31,1f
1121:	mflr	r30
113	addis	r30,r30,_GLOBAL_OFFSET_TABLE_-1b@ha
114	addi	r30,r30,_GLOBAL_OFFSET_TABLE_-1b@l
115#endif
116	bl	JUMP_TARGET(abort)
117#endif
118	.cfi_endproc
119FUNC_END(__trampoline_setup)
120
121#elif _CALL_ELF == 2
122	.type	trampoline_initial,@object
123	.align	3
124trampoline_initial:
125	ld	r11,.Lchain(r12)
126	ld	r12,.Lfunc(r12)
127	mtctr	r12
128	bctr
129.Lfunc = .-trampoline_initial
130	.quad	0			/* will be replaced with function address */
131.Lchain = .-trampoline_initial
132	.quad	0			/* will be replaced with static chain */
133
134trampoline_size = .-trampoline_initial
135	.size	trampoline_initial,trampoline_size
136
137
138/* R3 = stack address to store trampoline */
139/* R4 = length of trampoline area */
140/* R5 = function address */
141/* R6 = static chain */
142
143	.pushsection ".toc","aw"
144.LC0:
145	.quad	trampoline_initial-8
146	.popsection
147
148FUNC_START(__trampoline_setup)
149	.cfi_startproc
150	addis 7,2,.LC0@toc@ha
151	ld 7,.LC0@toc@l(7)	/* trampoline address -8 */
152
153	li	r8,trampoline_size	/* verify that the trampoline is big enough */
154	cmpw	cr1,r8,r4
155	srwi	r4,r4,3		/* # doublewords to move */
156	addi	r9,r3,-8	/* adjust pointer for stdu */
157	mtctr	r4
158	blt	cr1,.Labort
159
160	/* Copy the instructions to the stack */
161.Lmove:
162	ldu	r10,8(r7)
163	stdu	r10,8(r9)
164	bdnz	.Lmove
165
166	/* Store correct function and static chain */
167	std	r5,.Lfunc(r3)
168	std	r6,.Lchain(r3)
169
170	/* Now flush both caches */
171	mtctr	r4
172.Lcache:
173	icbi	0,r3
174	dcbf	0,r3
175	addi	r3,r3,8
176	bdnz	.Lcache
177
178	/* Finally synchronize things & return */
179	sync
180	isync
181	blr
182
183.Labort:
184	bl	JUMP_TARGET(abort)
185	nop
186	.cfi_endproc
187FUNC_END(__trampoline_setup)
188
189#endif
190