]>
Commit | Line | Data |
---|---|---|
b168057a | 1 | /* Copyright (C) 2011-2015 Free Software Foundation, Inc. |
63d143a2 CM |
2 | This file is part of the GNU C Library. |
3 | Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011. | |
4 | ||
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. | |
9 | ||
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. | |
14 | ||
15 | You should have received a copy of the GNU Lesser General Public | |
ab84e3ff PE |
16 | License along with the GNU C Library. If not, see |
17 | <http://www.gnu.org/licenses/>. */ | |
63d143a2 CM |
18 | |
19 | #include <sysdep.h> | |
20 | #include <arch/abi.h> | |
21 | ||
22 | /* This function is called via the PLT header, which is called | |
23 | from an individual PLT entry. | |
24 | ||
25 | At this point we have several values passed in: | |
26 | ||
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. | |
30 | ||
31 | We set up a frame entry that looks like this (in int_reg_t units): | |
32 | ||
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) | |
49 | ||
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. */ | |
55 | ||
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) | |
63 | ||
64 | #define FRAME_SIZE_SMALL (30 * REGSIZE) | |
65 | #define FRAME_SIZE_LARGE (58 * REGSIZE) | |
66 | ||
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) | |
75 | ||
76 | #define SAVE(REG) { ST r27, REG; ADDI_PTR r27, r27, REGSIZE } | |
77 | #define RESTORE(REG) { LD REG, r27; ADDI_PTR r27, r27, REGSIZE } | |
78 | ||
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. */ | |
156 | ||
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 | |
189 | ||
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 |