Update copyright notices with scripts/update-copyrights
[glibc.git] / ports / sysdeps / tile / dl-trampoline.S
blob7a4914ef6e1e9de96c7396e8c824f74753fd2b61
1 /* Copyright (C) 2011-2014 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library.  If not, see
17    <http://www.gnu.org/licenses/>.  */
19 #include <sysdep.h>
20 #include <arch/abi.h>
22 /* This function is called via the PLT header, which is called
23    from an individual PLT entry.
25    At this point we have several values passed in:
27    lr:  return address to original user code
28    r28: the tpnt value to pass to _dl_runtime_resolver
29    r29: the PLT index of the invoked jump table entry.
31    We set up a frame entry that looks like this (in int_reg_t units):
33    +57: r25 return values from function...
34    +56: r24
35    [...]
36    +33: r1
37    +32: r0
38    +31: PLT index
39    +30: tpnt
40    +29: stackframe
41    +28: caller lr
42    +27: r25 arguments to function...
43    +26: r24
44    [...]
45    +3:  r1
46    +2:  r0
47    +1:  standard ABI slot (sp)
48    +0:  standard ABI slot (callee lr)
50    The entries from "stackframe" up are only used in _dl_profile_resolve.
51    We save and restore r0 through r25, rather than the strictly
52    architected r0 through r9, to support unusual calling conventions;
53    for example, __tls_get_addr takes r0 and returns r0, but promises
54    not to clobber r1 through r24 to support its usual fast path.  */
56 #define FRAME_SP                (1 * REGSIZE)
57 #define FRAME_REGS              (2 * REGSIZE)
58 #define FRAME_LR                (28 * REGSIZE)  /* Must follow FRAME_REGS */
59 #define FRAME_STACKFRAME        (29 * REGSIZE)
60 #define FRAME_TPNT              (30 * REGSIZE)
61 #define FRAME_INDEX             (31 * REGSIZE)
62 #define FRAME_RETVAL            (32 * REGSIZE)
64 #define FRAME_SIZE_SMALL        (30 * REGSIZE)
65 #define FRAME_SIZE_LARGE        (58 * REGSIZE)
67 #define FOR_EACH_REG(f) \
68         f(r0);  f(r1);  f(r2);  f(r3);  \
69         f(r4);  f(r5);  f(r6);  f(r7);  \
70         f(r8);  f(r9);  f(r10); f(r11); \
71         f(r12); f(r13); f(r14); f(r15); \
72         f(r16); f(r17); f(r18); f(r19); \
73         f(r20); f(r21); f(r22); f(r23); \
74         f(r24); f(r25)
76 #define SAVE(REG) { ST r27, REG; ADDI_PTR r27, r27, REGSIZE }
77 #define RESTORE(REG) { LD REG, r27; ADDI_PTR r27, r27, REGSIZE }
79         .macro dl_resolve, name, profile, framesize
80 .text
81 .global \name
82 .hidden \name
83 /* Note that cpp expands ENTRY(\name) incorrectly. */
84 .type \name,@function
85 .align 8
86 \name:
87         cfi_startproc
88         {
89          ST sp, lr
90          move r26, sp
91         }
92         {
93          ADDLI_PTR sp, sp, -\framesize
94          ADDLI_PTR r27, sp, FRAME_SP - \framesize
95         }
96         cfi_def_cfa_offset (\framesize)
97         {
98          ST r27, r26
99          ADDI_PTR r27, r27, FRAME_REGS - FRAME_SP
100         }
101         FOR_EACH_REG(SAVE)
102         {
103          ST r27, lr
104          ADDLI_PTR r27, sp, FRAME_TPNT
105         }
106         cfi_offset (lr, FRAME_LR - \framesize)
107         .if \profile
108         {
109          move r0, r28  /* tpnt value */
110          ST r27, r28
111          ADDI_PTR r27, r27, FRAME_INDEX - FRAME_TPNT
112         }
113         {
114          move r1, r29  /* PLT index */
115          ST r27, r29
116         }
117         {
118          move r2, lr  /* retaddr */
119          ADDI_PTR r3, sp, FRAME_REGS  /* La_tile_regs pointer */
120         }
121         {
122          ADDLI_PTR r4, sp, FRAME_STACKFRAME  /* framesize pointer */
123          jal _dl_profile_fixup
124         }
125         ADDLI_PTR r28, sp, FRAME_STACKFRAME
126         LD_PTR r28, r28
127         BGTZ r28, 1f
128         .else
129         {
130          move r0, r28  /* tpnt value 1 */
131          move r1, r29  /* PLT index 2 */
132         }
133         jal _dl_fixup
134         .endif
135         {
136          /* Copy aside the return value so we can restore r0 below. */
137          move r29, r0
138          /* Set up r27 to let us start restoring registers. */
139          ADDLI_PTR r27, sp, FRAME_REGS
140         }
141         FOR_EACH_REG(RESTORE)
142         .if \profile
143         ADDLI_PTR r28, sp, FRAME_STACKFRAME
144         LD r28, r28
145         BGTZ r28, 1f
146         .endif
147         {
148          /* Restore original user return address. */
149          LD lr, r27
150          /* Pop off our stack frame. */
151          ADDLI_PTR sp, sp, \framesize
152         }
153         cfi_def_cfa_offset (0)
154         jr r29  /* Transfer control to freshly loaded code. */
155         jrp lr  /* Keep backtracer happy. */
157         .if \profile
158 1:      jalr r29   /* Call resolved function. */
159         {
160          ADDLI_PTR r28, sp, FRAME_TPNT
161          ADDLI_PTR r27, sp, FRAME_RETVAL
162         }
163         FOR_EACH_REG(SAVE)
164         {
165          LD r0, r28
166          ADDI_PTR r28, r28, FRAME_INDEX - FRAME_TPNT
167         }
168         {
169          LD r1, r28
170          ADDLI_PTR r2, sp, FRAME_REGS
171         }
172         {
173          ADDLI_PTR r3, sp, FRAME_RETVAL
174          jal _dl_call_pltexit
175         }
176         {
177          ADDLI_PTR lr, sp, FRAME_LR
178          ADDLI_PTR r27, sp, FRAME_RETVAL
179         }
180         FOR_EACH_REG(RESTORE)
181         {
182          LD lr, lr
183          ADDLI_PTR sp, sp, \framesize
184         }
185         jrp lr
186         .endif
187 END (\name)
188         .endm
190         dl_resolve _dl_runtime_resolve, 0, FRAME_SIZE_SMALL
191 #ifndef PROF
192         dl_resolve _dl_runtime_profile, 1, FRAME_SIZE_LARGE
193 #endif