1/*  Special support for trampolines
2 *
3 *   Copyright (C) 1996-2022 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          cmpwi     cr1,r4,trampoline_size        /* verify that the trampoline is big enough */
68          srwi      r4,r4,2             /* # words to move */
69          addi      r9,r3,-4  /* adjust pointer for lwzu */
70          mtctr     r4
71          blt       cr1,.Labort
72
73          mtlr      r0
74
75          /* Copy the instructions to the stack */
76.Lmove:
77          lwzu      r10,4(r7)
78          stwu      r10,4(r9)
79          bdnz      .Lmove
80
81          /* Store correct function and static chain */
82          stw       r5,.Lfunc(r3)
83          stw       r6,.Lchain(r3)
84
85          /* Now flush both caches */
86          mtctr     r4
87.Lcache:
88          icbi      0,r3
89          dcbf      0,r3
90          addi      r3,r3,4
91          bdnz      .Lcache
92
93          /* Finally synchronize things & return */
94          sync
95          isync
96          blr
97
98.Labort:
99/* Use a longcall sequence in the non PIC case on VxWorks, to prevent
100   possible relocation errors if this is module-loaded very far away from
101   the 'abort' entry point.  */
102#if defined (__VXWORKS__) && ! (defined __PIC__ || defined __pic__)
103        lis   r11,JUMP_TARGET(abort)@ha
104        addic r11,r11,JUMP_TARGET(abort)@l
105        mtlr  r11
106        blrl
107#else
108
109#if (defined __PIC__ || defined __pic__) && defined HAVE_AS_REL16
110          bcl       20,31,1f
1111:        mflr      r30
112          addis     r30,r30,_GLOBAL_OFFSET_TABLE_-1b@ha
113          addi      r30,r30,_GLOBAL_OFFSET_TABLE_-1b@l
114#endif
115          bl        JUMP_TARGET(abort)
116#endif
117          .cfi_endproc
118FUNC_END(__trampoline_setup)
119
120#elif _CALL_ELF == 2
121          .type     trampoline_initial,@object
122          .align    3
123trampoline_initial:
124          ld        r11,.Lchain(r12)
125          ld        r12,.Lfunc(r12)
126          mtctr     r12
127          bctr
128.Lfunc = .-trampoline_initial
129          .quad     0                             /* will be replaced with function address */
130.Lchain = .-trampoline_initial
131          .quad     0                             /* will be replaced with static chain */
132
133trampoline_size = .-trampoline_initial
134          .size     trampoline_initial,trampoline_size
135
136
137/* R3 = stack address to store trampoline */
138/* R4 = length of trampoline area */
139/* R5 = function address */
140/* R6 = static chain */
141
142#ifndef __PCREL__
143          .pushsection ".toc","aw"
144.LC0:
145          .quad     trampoline_initial-8
146          .popsection
147#endif
148
149FUNC_START(__trampoline_setup)
150          .cfi_startproc
151#ifdef __PCREL__
152          pla 7,(trampoline_initial-8)@pcrel
153#else
154          addis 7,2,.LC0@toc@ha
155          ld 7,.LC0@toc@l(7)  /* trampoline address -8 */
156#endif
157
158          cmpwi     cr1,r4,trampoline_size        /* verify that the trampoline is big enough */
159          srwi      r4,r4,3             /* # doublewords to move */
160          addi      r9,r3,-8  /* adjust pointer for stdu */
161          mtctr     r4
162          blt       cr1,.Labort
163
164          /* Copy the instructions to the stack */
165.Lmove:
166          ldu       r10,8(r7)
167          stdu      r10,8(r9)
168          bdnz      .Lmove
169
170          /* Store correct function and static chain */
171          std       r5,.Lfunc(r3)
172          std       r6,.Lchain(r3)
173
174          /* Now flush both caches */
175          mtctr     r4
176.Lcache:
177          icbi      0,r3
178          dcbf      0,r3
179          addi      r3,r3,8
180          bdnz      .Lcache
181
182          /* Finally synchronize things & return */
183          sync
184          isync
185          blr
186
187.Labort:
188          bl        JUMP_TARGET(abort)
189          nop
190          .cfi_endproc
191FUNC_END(__trampoline_setup)
192
193#endif
194