111
|
1 /* -----------------------------------------------------------------------
|
|
2 linux.S - (c) 2003-2004 Randolph Chung <tausq@debian.org>
|
|
3 (c) 2008 Red Hat, Inc.
|
|
4 (c) 2016 John David Anglin
|
|
5
|
|
6 HPPA Foreign Function Interface
|
|
7
|
|
8 Permission is hereby granted, free of charge, to any person obtaining
|
|
9 a copy of this software and associated documentation files (the
|
|
10 ``Software''), to deal in the Software without restriction, including
|
|
11 without limitation the rights to use, copy, modify, merge, publish,
|
|
12 distribute, sublicense, and/or sell copies of the Software, and to
|
|
13 permit persons to whom the Software is furnished to do so, subject to
|
|
14 the following conditions:
|
|
15
|
|
16 The above copyright notice and this permission notice shall be included
|
|
17 in all copies or substantial portions of the Software.
|
|
18
|
|
19 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
20 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
21 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
22 IN NO EVENT SHALL RENESAS TECHNOLOGY BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
23 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
24 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
25 OTHER DEALINGS IN THE SOFTWARE.
|
|
26 ----------------------------------------------------------------------- */
|
|
27
|
|
28 #define LIBFFI_ASM
|
|
29 #include <fficonfig.h>
|
|
30 #include <ffi.h>
|
|
31
|
|
32 .text
|
|
33 .level 1.1
|
|
34 .align 4
|
|
35
|
|
36 /* void ffi_call_pa32(void (*)(char *, extended_cif *),
|
|
37 extended_cif *ecif,
|
|
38 unsigned bytes,
|
|
39 unsigned flags,
|
|
40 unsigned *rvalue,
|
|
41 void (*fn)(void),
|
|
42 ffi_go_closure *closure);
|
|
43 */
|
|
44
|
|
45 .export ffi_call_pa32,code
|
|
46 .import ffi_prep_args_pa32,code
|
|
47
|
|
48 .type ffi_call_pa32, @function
|
|
49 .cfi_startproc
|
|
50 ffi_call_pa32:
|
|
51 .proc
|
|
52 .callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=4
|
|
53 .entry
|
|
54 stw %rp, -20(%sp)
|
|
55 copy %r3, %r1
|
|
56 .cfi_offset 2, -20
|
|
57 .cfi_register 3, 1
|
|
58
|
|
59 copy %sp, %r3
|
|
60 .cfi_def_cfa_register 3
|
|
61
|
|
62 /* Setup the stack for calling prep_args...
|
|
63 We want the stack to look like this:
|
|
64
|
|
65 [ Previous stack ] <- %r3
|
|
66
|
|
67 [ 64-bytes register save area ] <- %r4
|
|
68
|
|
69 [ Stack space for actual call, passed as ] <- %arg0
|
|
70 [ arg0 to ffi_prep_args_pa32 ]
|
|
71
|
|
72 [ Stack for calling prep_args ] <- %sp
|
|
73 */
|
|
74
|
|
75 stwm %r1, 64(%sp)
|
|
76 .cfi_offset 3, 0
|
|
77 stw %r4, 12(%r3)
|
|
78 copy %sp, %r4
|
|
79
|
|
80 addl %arg2, %r4, %arg0 /* arg stack */
|
|
81 stw %arg3, -48(%r3) /* save flags; we need it later */
|
|
82
|
|
83 /* Call prep_args:
|
|
84 %arg0(stack) -- set up above
|
|
85 %arg1(ecif) -- same as incoming param
|
|
86 %arg2(bytes) -- same as incoming param */
|
|
87 bl ffi_prep_args_pa32,%r2
|
|
88 ldo 64(%arg0), %sp
|
|
89 ldo -64(%sp), %sp
|
|
90
|
|
91 /* now %sp should point where %arg0 was pointing. */
|
|
92
|
|
93 /* Load the arguments that should be passed in registers
|
|
94 The fp args were loaded by the prep_args function. */
|
|
95 ldw -36(%sp), %arg0
|
|
96 ldw -40(%sp), %arg1
|
|
97 ldw -44(%sp), %arg2
|
|
98 ldw -48(%sp), %arg3
|
|
99
|
|
100 /* in case the function is going to return a structure
|
|
101 we need to give it a place to put the result. */
|
|
102 ldw -52(%r3), %ret0 /* %ret0 <- rvalue */
|
|
103 ldw -56(%r3), %r22 /* %r22 <- function to call */
|
|
104 ldw -60(%r3), %ret1 /* %ret1 <- closure */
|
|
105 bl $$dyncall, %r31 /* Call the user function */
|
|
106 copy %r31, %rp
|
|
107
|
|
108 /* Prepare to store the result; we need to recover flags and rvalue. */
|
|
109 ldw -48(%r3), %r21 /* r21 <- flags */
|
|
110 ldw -52(%r3), %r20 /* r20 <- rvalue */
|
|
111
|
|
112 /* Store the result according to the return type. */
|
|
113
|
|
114 .Lcheckint:
|
|
115 comib,<>,n FFI_TYPE_INT, %r21, .Lcheckint8
|
|
116 b .Ldone
|
|
117 stw %ret0, 0(%r20)
|
|
118
|
|
119 .Lcheckint8:
|
|
120 comib,<>,n FFI_TYPE_UINT8, %r21, .Lcheckint16
|
|
121 b .Ldone
|
|
122 stb %ret0, 0(%r20)
|
|
123
|
|
124 .Lcheckint16:
|
|
125 comib,<>,n FFI_TYPE_UINT16, %r21, .Lcheckdbl
|
|
126 b .Ldone
|
|
127 sth %ret0, 0(%r20)
|
|
128
|
|
129 .Lcheckdbl:
|
|
130 comib,<>,n FFI_TYPE_DOUBLE, %r21, .Lcheckfloat
|
|
131 b .Ldone
|
|
132 fstd %fr4,0(%r20)
|
|
133
|
|
134 .Lcheckfloat:
|
|
135 comib,<>,n FFI_TYPE_FLOAT, %r21, .Lcheckll
|
|
136 b .Ldone
|
|
137 fstw %fr4L,0(%r20)
|
|
138
|
|
139 .Lcheckll:
|
|
140 comib,<>,n FFI_TYPE_UINT64, %r21, .Lchecksmst2
|
|
141 stw %ret0, 0(%r20)
|
|
142 b .Ldone
|
|
143 stw %ret1, 4(%r20)
|
|
144
|
|
145 .Lchecksmst2:
|
|
146 comib,<>,n FFI_TYPE_SMALL_STRUCT2, %r21, .Lchecksmst3
|
|
147 /* 2-byte structs are returned in ret0 as ????xxyy. */
|
|
148 extru %ret0, 23, 8, %r22
|
|
149 stbs,ma %r22, 1(%r20)
|
|
150 b .Ldone
|
|
151 stb %ret0, 0(%r20)
|
|
152
|
|
153 .Lchecksmst3:
|
|
154 comib,<>,n FFI_TYPE_SMALL_STRUCT3, %r21, .Lchecksmst4
|
|
155 /* 3-byte structs are returned in ret0 as ??xxyyzz. */
|
|
156 extru %ret0, 15, 8, %r22
|
|
157 stbs,ma %r22, 1(%r20)
|
|
158 extru %ret0, 23, 8, %r22
|
|
159 stbs,ma %r22, 1(%r20)
|
|
160 b .Ldone
|
|
161 stb %ret0, 0(%r20)
|
|
162
|
|
163 .Lchecksmst4:
|
|
164 comib,<>,n FFI_TYPE_SMALL_STRUCT4, %r21, .Lchecksmst5
|
|
165 /* 4-byte structs are returned in ret0 as wwxxyyzz. */
|
|
166 extru %ret0, 7, 8, %r22
|
|
167 stbs,ma %r22, 1(%r20)
|
|
168 extru %ret0, 15, 8, %r22
|
|
169 stbs,ma %r22, 1(%r20)
|
|
170 extru %ret0, 23, 8, %r22
|
|
171 stbs,ma %r22, 1(%r20)
|
|
172 b .Ldone
|
|
173 stb %ret0, 0(%r20)
|
|
174
|
|
175 .Lchecksmst5:
|
|
176 comib,<>,n FFI_TYPE_SMALL_STRUCT5, %r21, .Lchecksmst6
|
|
177 /* 5 byte values are returned right justified:
|
|
178 ret0 ret1
|
|
179 5: ??????aa bbccddee */
|
|
180 stbs,ma %ret0, 1(%r20)
|
|
181 extru %ret1, 7, 8, %r22
|
|
182 stbs,ma %r22, 1(%r20)
|
|
183 extru %ret1, 15, 8, %r22
|
|
184 stbs,ma %r22, 1(%r20)
|
|
185 extru %ret1, 23, 8, %r22
|
|
186 stbs,ma %r22, 1(%r20)
|
|
187 b .Ldone
|
|
188 stb %ret1, 0(%r20)
|
|
189
|
|
190 .Lchecksmst6:
|
|
191 comib,<>,n FFI_TYPE_SMALL_STRUCT6, %r21, .Lchecksmst7
|
|
192 /* 6 byte values are returned right justified:
|
|
193 ret0 ret1
|
|
194 6: ????aabb ccddeeff */
|
|
195 extru %ret0, 23, 8, %r22
|
|
196 stbs,ma %r22, 1(%r20)
|
|
197 stbs,ma %ret0, 1(%r20)
|
|
198 extru %ret1, 7, 8, %r22
|
|
199 stbs,ma %r22, 1(%r20)
|
|
200 extru %ret1, 15, 8, %r22
|
|
201 stbs,ma %r22, 1(%r20)
|
|
202 extru %ret1, 23, 8, %r22
|
|
203 stbs,ma %r22, 1(%r20)
|
|
204 b .Ldone
|
|
205 stb %ret1, 0(%r20)
|
|
206
|
|
207 .Lchecksmst7:
|
|
208 comib,<>,n FFI_TYPE_SMALL_STRUCT7, %r21, .Lchecksmst8
|
|
209 /* 7 byte values are returned right justified:
|
|
210 ret0 ret1
|
|
211 7: ??aabbcc ddeeffgg */
|
|
212 extru %ret0, 15, 8, %r22
|
|
213 stbs,ma %r22, 1(%r20)
|
|
214 extru %ret0, 23, 8, %r22
|
|
215 stbs,ma %r22, 1(%r20)
|
|
216 stbs,ma %ret0, 1(%r20)
|
|
217 extru %ret1, 7, 8, %r22
|
|
218 stbs,ma %r22, 1(%r20)
|
|
219 extru %ret1, 15, 8, %r22
|
|
220 stbs,ma %r22, 1(%r20)
|
|
221 extru %ret1, 23, 8, %r22
|
|
222 stbs,ma %r22, 1(%r20)
|
|
223 b .Ldone
|
|
224 stb %ret1, 0(%r20)
|
|
225
|
|
226 .Lchecksmst8:
|
|
227 comib,<>,n FFI_TYPE_SMALL_STRUCT8, %r21, .Ldone
|
|
228 /* 8 byte values are returned right justified:
|
|
229 ret0 ret1
|
|
230 8: aabbccdd eeffgghh */
|
|
231 extru %ret0, 7, 8, %r22
|
|
232 stbs,ma %r22, 1(%r20)
|
|
233 extru %ret0, 15, 8, %r22
|
|
234 stbs,ma %r22, 1(%r20)
|
|
235 extru %ret0, 23, 8, %r22
|
|
236 stbs,ma %r22, 1(%r20)
|
|
237 stbs,ma %ret0, 1(%r20)
|
|
238 extru %ret1, 7, 8, %r22
|
|
239 stbs,ma %r22, 1(%r20)
|
|
240 extru %ret1, 15, 8, %r22
|
|
241 stbs,ma %r22, 1(%r20)
|
|
242 extru %ret1, 23, 8, %r22
|
|
243 stbs,ma %r22, 1(%r20)
|
|
244 stb %ret1, 0(%r20)
|
|
245
|
|
246 .Ldone:
|
|
247 /* all done, return */
|
|
248 copy %r4, %sp /* pop arg stack */
|
|
249 ldw 12(%r3), %r4
|
|
250 ldwm -64(%sp), %r3 /* .. and pop stack */
|
|
251 ldw -20(%sp), %rp
|
|
252 bv %r0(%rp)
|
|
253 nop
|
|
254 .exit
|
|
255 .procend
|
|
256 .cfi_endproc
|
|
257
|
|
258 /* void ffi_closure_pa32(void);
|
|
259 Called with ffi_closure argument in %r21. */
|
|
260 .export ffi_closure_pa32,code
|
|
261 .import ffi_closure_inner_pa32,code
|
|
262 .type ffi_closure_pa32, @function
|
|
263 .cfi_startproc
|
|
264 ffi_closure_pa32:
|
|
265 .proc
|
|
266 .callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=3
|
|
267 .entry
|
|
268
|
|
269 stw %rp, -20(%sp)
|
|
270 copy %r3, %r1
|
|
271 .cfi_offset 2, -20
|
|
272 .cfi_register 3, 1
|
|
273 copy %sp, %r3
|
|
274 .cfi_def_cfa_register 3
|
|
275 stwm %r1, 64(%sp)
|
|
276 .cfi_offset 3, 0
|
|
277
|
|
278 /* Put arguments onto the stack and call ffi_closure_inner. */
|
|
279 stw %arg0, -36(%r3)
|
|
280 stw %arg1, -40(%r3)
|
|
281 stw %arg2, -44(%r3)
|
|
282 stw %arg3, -48(%r3)
|
|
283
|
|
284 /* Closure type 0. */
|
|
285 copy %r21, %arg0
|
|
286 copy %r0, %arg2
|
|
287 bl ffi_closure_inner_pa32, %r2
|
|
288 copy %r3, %arg1
|
|
289
|
|
290 ldwm -64(%sp), %r3
|
|
291 ldw -20(%sp), %rp
|
|
292 ldw -36(%sp), %ret0
|
|
293 bv %r0(%r2)
|
|
294 ldw -40(%sp), %ret1
|
|
295
|
|
296 .exit
|
|
297 .procend
|
|
298 .cfi_endproc
|
|
299
|
|
300 /* void ffi_go_closure_pa32(void);
|
|
301 Called with ffi_go_closure argument in %ret1. */
|
|
302 .export ffi_go_closure_pa32,code
|
|
303 .import ffi_closure_inner_pa32,code
|
|
304 .type ffi_go_closure_pa32, @function
|
|
305 .cfi_startproc
|
|
306 ffi_go_closure_pa32:
|
|
307 .proc
|
|
308 .callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=3
|
|
309 .entry
|
|
310
|
|
311 stw %rp, -20(%sp)
|
|
312 copy %r3, %r1
|
|
313 .cfi_offset 2, -20
|
|
314 .cfi_register 3, 1
|
|
315 copy %sp, %r3
|
|
316 .cfi_def_cfa_register 3
|
|
317 stwm %r1, 64(%sp)
|
|
318 .cfi_offset 3, 0
|
|
319
|
|
320 /* Put arguments onto the stack and call ffi_closure_inner. */
|
|
321 stw %arg0, -36(%r3)
|
|
322 stw %arg1, -40(%r3)
|
|
323 stw %arg2, -44(%r3)
|
|
324 stw %arg3, -48(%r3)
|
|
325
|
|
326 /* Closure type 1. */
|
|
327 copy %ret1, %arg0
|
|
328 ldi 1, %arg2
|
|
329 bl ffi_closure_inner_pa32, %r2
|
|
330 copy %r3, %arg1
|
|
331
|
|
332 ldwm -64(%sp), %r3
|
|
333 ldw -20(%sp), %rp
|
|
334 ldw -36(%sp), %ret0
|
|
335 bv %r0(%r2)
|
|
336 ldw -40(%sp), %ret1
|
|
337
|
|
338 .exit
|
|
339 .procend
|
|
340 .cfi_endproc
|