1 /* vacall function for mips CPU */
2
3 /*
4 * Copyright 1995-2021 Bruno Haible <bruno@clisp.org>
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20 #include "vacall-internal.h"
21
22 #ifndef REENTRANT
23 typedef void (*func_pointer)(va_alist);
24 #else /* REENTRANT */
25 #define vacall_receiver callback_receiver
26 typedef void (*func_pointer)(void*,va_alist);
27 register struct { func_pointer vacall_function; void* arg; }
28 * env __asm__("$2");
29 #endif
30 register void* sp __asm__("$sp");
31 register __varword iarg0 __asm__("$4");
32 register __varword iarg1 __asm__("$5");
33 register __varword iarg2 __asm__("$6");
34 register __varword iarg3 __asm__("$7");
35 register __varword iarg4 __asm__("$8");
36 register __varword iarg5 __asm__("$9");
37 register __varword iarg6 __asm__("$10");
38 register __varword iarg7 __asm__("$11");
39 register float farg0 __asm__("$f12");
40 register float farg1 __asm__("$f13");
41 register float farg2 __asm__("$f14");
42 register float farg3 __asm__("$f15");
43 register float farg4 __asm__("$f16");
44 register float farg5 __asm__("$f17");
45 register float farg6 __asm__("$f18");
46 register float farg7 __asm__("$f19");
47 register double darg0 __asm__("$f12");
48 register double darg1 __asm__("$f13");
49 register double darg2 __asm__("$f14");
50 register double darg3 __asm__("$f15");
51 register double darg4 __asm__("$f16");
52 register double darg5 __asm__("$f17");
53 register double darg6 __asm__("$f18");
54 register double darg7 __asm__("$f19");
55 register __varword iret __asm__("$2");
56 register __varword iret2 __asm__("$3");
57 register float fret __asm__("$f0");
58 register float fret2 __asm__("$f2");
59 register double dret __asm__("$f0");
60 register double dret2 __asm__("$f2");
61
62 /* The ABI requires that the first 8 general-purpose argument words are
63 being passed in registers, even if these words belong to a struct. No room
64 is allocated for these register words on the stack by the caller, but the
65 callee allocates room for them - at the right place in the stack frame,
66 that is, above the usual {fp, retaddr} combo - if and only if they are part
67 of a larger struct that extends to the stack and the address of this struct
68 is taken. */
69 struct gpargsequence {
70 __vaword word1; /* r4 */
71 __vaword word2; /* r5 */
72 __vaword word3; /* r6 */
73 __vaword word4; /* r7 */
74 __vaword word5; /* r8 */
75 __vaword word6; /* r9 */
76 __vaword word7; /* r10 */
77 __vaword word8; /* r11 */
78 __vaword firststackword;
79 };
80
81 #ifdef REENTRANT
82 static
83 #endif
84 void /* the return type is variable, not void! */
vacall_receiver(struct gpargsequence gpargs)85 vacall_receiver (struct gpargsequence gpargs)
86 {
87 __va_alist list;
88 list.darg[0] = darg0;
89 list.darg[1] = darg1;
90 list.darg[2] = darg2;
91 list.darg[3] = darg3;
92 list.darg[4] = darg4;
93 list.darg[5] = darg5;
94 list.darg[6] = darg6;
95 list.darg[7] = darg7;
96 list.farg[0] = farg0;
97 list.farg[1] = farg1;
98 list.farg[2] = farg2;
99 list.farg[3] = farg3;
100 list.farg[4] = farg4;
101 list.farg[5] = farg5;
102 list.farg[6] = farg6;
103 list.farg[7] = farg7;
104 /* Prepare the va_alist. */
105 list.flags = 0;
106 list.aptr = (long)&gpargs;
107 list.raddr = (void*)0;
108 list.rtype = __VAvoid;
109 list.anum = 0;
110 /* Call vacall_function. The macros do all the rest. */
111 #ifndef REENTRANT
112 (*vacall_function) (&list);
113 #else /* REENTRANT */
114 (*env->vacall_function) (env->arg,&list);
115 #endif
116 /* Put return value into proper register. */
117 if (list.rtype == __VAvoid) {
118 } else
119 if (list.rtype == __VAchar) {
120 iret = list.tmp._char;
121 } else
122 if (list.rtype == __VAschar) {
123 iret = list.tmp._schar;
124 } else
125 if (list.rtype == __VAuchar) {
126 iret = list.tmp._uchar;
127 } else
128 if (list.rtype == __VAshort) {
129 iret = list.tmp._short;
130 } else
131 if (list.rtype == __VAushort) {
132 iret = list.tmp._ushort;
133 } else
134 if (list.rtype == __VAint) {
135 iret = list.tmp._int;
136 } else
137 if (list.rtype == __VAuint) {
138 iret = list.tmp._uint;
139 } else
140 if (list.rtype == __VAlong) {
141 iret = list.tmp._long;
142 } else
143 if (list.rtype == __VAulong) {
144 iret = list.tmp._ulong;
145 } else
146 if (list.rtype == __VAlonglong) {
147 iret = list.tmp._longlong;
148 } else
149 if (list.rtype == __VAulonglong) {
150 iret = list.tmp._ulonglong;
151 } else
152 if (list.rtype == __VAfloat) {
153 fret = list.tmp._float;
154 } else
155 if (list.rtype == __VAdouble) {
156 dret = list.tmp._double;
157 } else
158 if (list.rtype == __VAvoidp) {
159 iret = (long)list.tmp._ptr;
160 } else
161 if (list.rtype == __VAstruct) {
162 if (list.flags & __VA_REGISTER_STRUCT_RETURN) {
163 if (list.flags & __VA_GCC_STRUCT_RETURN) {
164 /* gcc returns structs of size 1,2,4,8 in registers. */
165 if (list.rsize == sizeof(char)) {
166 iret = *(unsigned char *) list.raddr;
167 } else
168 if (list.rsize == sizeof(short)) {
169 iret = *(unsigned short *) list.raddr;
170 } else
171 if (list.rsize == sizeof(int)) {
172 iret = *(unsigned int *) list.raddr;
173 } else
174 if (list.rsize == sizeof(long long)) {
175 iret = *(unsigned long long *) list.raddr;
176 }
177 } else {
178 /* cc returns structs of size <= 16 in registers. */
179 /* Maybe this big if cascade could be replaced with
180 * if (list.rsize > 0 && list.rsize <= 16)
181 * __asm__ ("ldl $2,%0 ; ldr $2,%1"
182 * : : "m" (((unsigned char *) list.raddr)[0]),
183 * "m" (((unsigned char *) list.raddr)[7]));
184 */
185 if (list.rsize > 0 && list.rsize <= 16) {
186 #if 0 /* Unoptimized */
187 if (list.rsize == 1) {
188 #if defined(_MIPSEL)
189 iret = (__varword)((unsigned char *) list.raddr)[0];
190 #else
191 iret = (__varword)((unsigned char *) list.raddr)[0] << 56;
192 #endif
193 } else
194 if (list.rsize == 2) {
195 #if defined(_MIPSEL)
196 iret = ((__varword)((unsigned char *) list.raddr)[0])
197 | ((__varword)((unsigned char *) list.raddr)[1] << 8);
198 #else
199 iret = ((__varword)((unsigned char *) list.raddr)[0] << 56)
200 | ((__varword)((unsigned char *) list.raddr)[1] << 48);
201 #endif
202 } else
203 if (list.rsize == 3) {
204 #if defined(_MIPSEL)
205 iret = ((__varword)((unsigned char *) list.raddr)[0])
206 | ((__varword)((unsigned char *) list.raddr)[1] << 8)
207 | ((__varword)((unsigned char *) list.raddr)[2] << 16);
208 #else
209 iret = ((__varword)((unsigned char *) list.raddr)[0] << 56)
210 | ((__varword)((unsigned char *) list.raddr)[1] << 48)
211 | ((__varword)((unsigned char *) list.raddr)[2] << 40);
212 #endif
213 } else
214 if (list.rsize == 4) {
215 #if defined(_MIPSEL)
216 iret = ((__varword)((unsigned char *) list.raddr)[0])
217 | ((__varword)((unsigned char *) list.raddr)[1] << 8)
218 | ((__varword)((unsigned char *) list.raddr)[2] << 16)
219 | ((__varword)((unsigned char *) list.raddr)[3] << 24);
220 #else
221 iret = ((__varword)((unsigned char *) list.raddr)[0] << 56)
222 | ((__varword)((unsigned char *) list.raddr)[1] << 48)
223 | ((__varword)((unsigned char *) list.raddr)[2] << 40)
224 | ((__varword)((unsigned char *) list.raddr)[3] << 32);
225 #endif
226 } else
227 if (list.rsize == 5) {
228 #if defined(_MIPSEL)
229 iret = ((__varword)((unsigned char *) list.raddr)[0])
230 | ((__varword)((unsigned char *) list.raddr)[1] << 8)
231 | ((__varword)((unsigned char *) list.raddr)[2] << 16)
232 | ((__varword)((unsigned char *) list.raddr)[3] << 24)
233 | ((__varword)((unsigned char *) list.raddr)[4] << 32);
234 #else
235 iret = ((__varword)((unsigned char *) list.raddr)[0] << 56)
236 | ((__varword)((unsigned char *) list.raddr)[1] << 48)
237 | ((__varword)((unsigned char *) list.raddr)[2] << 40)
238 | ((__varword)((unsigned char *) list.raddr)[3] << 32)
239 | ((__varword)((unsigned char *) list.raddr)[4] << 24);
240 #endif
241 } else
242 if (list.rsize == 6) {
243 #if defined(_MIPSEL)
244 iret = ((__varword)((unsigned char *) list.raddr)[0])
245 | ((__varword)((unsigned char *) list.raddr)[1] << 8)
246 | ((__varword)((unsigned char *) list.raddr)[2] << 16)
247 | ((__varword)((unsigned char *) list.raddr)[3] << 24)
248 | ((__varword)((unsigned char *) list.raddr)[4] << 32)
249 | ((__varword)((unsigned char *) list.raddr)[5] << 40);
250 #else
251 iret = ((__varword)((unsigned char *) list.raddr)[0] << 56)
252 | ((__varword)((unsigned char *) list.raddr)[1] << 48)
253 | ((__varword)((unsigned char *) list.raddr)[2] << 40)
254 | ((__varword)((unsigned char *) list.raddr)[3] << 32)
255 | ((__varword)((unsigned char *) list.raddr)[4] << 24)
256 | ((__varword)((unsigned char *) list.raddr)[5] << 16);
257 #endif
258 } else
259 if (list.rsize == 7) {
260 #if defined(_MIPSEL)
261 iret = ((__varword)((unsigned char *) list.raddr)[0])
262 | ((__varword)((unsigned char *) list.raddr)[1] << 8)
263 | ((__varword)((unsigned char *) list.raddr)[2] << 16)
264 | ((__varword)((unsigned char *) list.raddr)[3] << 24)
265 | ((__varword)((unsigned char *) list.raddr)[4] << 32)
266 | ((__varword)((unsigned char *) list.raddr)[5] << 40)
267 | ((__varword)((unsigned char *) list.raddr)[6] << 48);
268 #else
269 iret = ((__varword)((unsigned char *) list.raddr)[0] << 56)
270 | ((__varword)((unsigned char *) list.raddr)[1] << 48)
271 | ((__varword)((unsigned char *) list.raddr)[2] << 40)
272 | ((__varword)((unsigned char *) list.raddr)[3] << 32)
273 | ((__varword)((unsigned char *) list.raddr)[4] << 24)
274 | ((__varword)((unsigned char *) list.raddr)[5] << 16)
275 | ((__varword)((unsigned char *) list.raddr)[6] << 8);
276 #endif
277 } else
278 if (list.rsize >= 8 && list.rsize <= 16) {
279 #if defined(_MIPSEL)
280 iret = ((__varword)((unsigned char *) list.raddr)[0])
281 | ((__varword)((unsigned char *) list.raddr)[1] << 8)
282 | ((__varword)((unsigned char *) list.raddr)[2] << 16)
283 | ((__varword)((unsigned char *) list.raddr)[3] << 24)
284 | ((__varword)((unsigned char *) list.raddr)[4] << 32)
285 | ((__varword)((unsigned char *) list.raddr)[5] << 40)
286 | ((__varword)((unsigned char *) list.raddr)[6] << 48)
287 | ((__varword)((unsigned char *) list.raddr)[7] << 56);
288 #else
289 iret = ((__varword)((unsigned char *) list.raddr)[0] << 56)
290 | ((__varword)((unsigned char *) list.raddr)[1] << 48)
291 | ((__varword)((unsigned char *) list.raddr)[2] << 40)
292 | ((__varword)((unsigned char *) list.raddr)[3] << 32)
293 | ((__varword)((unsigned char *) list.raddr)[4] << 24)
294 | ((__varword)((unsigned char *) list.raddr)[5] << 16)
295 | ((__varword)((unsigned char *) list.raddr)[6] << 8)
296 | (__varword)((unsigned char *) list.raddr)[7];
297 #endif
298 /* Maybe this big if cascade could be replaced with
299 * if (list.rsize > 8 && list.rsize <= 16)
300 * __asm__ ("ldl $3,%0 ; ldr $3,%1"
301 * : : "m" (((unsigned char *) list.raddr)[8]),
302 * "m" (((unsigned char *) list.raddr)[15]));
303 */
304 if (list.rsize == 8) {
305 } else
306 if (list.rsize == 9) {
307 #if defined(_MIPSEL)
308 iret2 = (__varword)((unsigned char *) list.raddr)[8];
309 #else
310 iret2 = (__varword)((unsigned char *) list.raddr)[8] << 56;
311 #endif
312 } else
313 if (list.rsize == 10) {
314 #if defined(_MIPSEL)
315 iret2 = ((__varword)((unsigned char *) list.raddr)[8])
316 | ((__varword)((unsigned char *) list.raddr)[9] << 8);
317 #else
318 iret2 = ((__varword)((unsigned char *) list.raddr)[8] << 56)
319 | ((__varword)((unsigned char *) list.raddr)[9] << 48);
320 #endif
321 } else
322 if (list.rsize == 11) {
323 #if defined(_MIPSEL)
324 iret2 = ((__varword)((unsigned char *) list.raddr)[8])
325 | ((__varword)((unsigned char *) list.raddr)[9] << 8)
326 | ((__varword)((unsigned char *) list.raddr)[10] << 16);
327 #else
328 iret2 = ((__varword)((unsigned char *) list.raddr)[8] << 56)
329 | ((__varword)((unsigned char *) list.raddr)[9] << 48)
330 | ((__varword)((unsigned char *) list.raddr)[10] << 40);
331 #endif
332 } else
333 if (list.rsize == 12) {
334 #if defined(_MIPSEL)
335 iret2 = ((__varword)((unsigned char *) list.raddr)[8])
336 | ((__varword)((unsigned char *) list.raddr)[9] << 8)
337 | ((__varword)((unsigned char *) list.raddr)[10] << 16)
338 | ((__varword)((unsigned char *) list.raddr)[11] << 24);
339 #else
340 iret2 = ((__varword)((unsigned char *) list.raddr)[8] << 56)
341 | ((__varword)((unsigned char *) list.raddr)[9] << 48)
342 | ((__varword)((unsigned char *) list.raddr)[10] << 40)
343 | ((__varword)((unsigned char *) list.raddr)[11] << 32);
344 #endif
345 } else
346 if (list.rsize == 13) {
347 #if defined(_MIPSEL)
348 iret2 = ((__varword)((unsigned char *) list.raddr)[8])
349 | ((__varword)((unsigned char *) list.raddr)[9] << 8)
350 | ((__varword)((unsigned char *) list.raddr)[10] << 16)
351 | ((__varword)((unsigned char *) list.raddr)[11] << 24)
352 | ((__varword)((unsigned char *) list.raddr)[12] << 32);
353 #else
354 iret2 = ((__varword)((unsigned char *) list.raddr)[8] << 56)
355 | ((__varword)((unsigned char *) list.raddr)[9] << 48)
356 | ((__varword)((unsigned char *) list.raddr)[10] << 40)
357 | ((__varword)((unsigned char *) list.raddr)[11] << 32)
358 | ((__varword)((unsigned char *) list.raddr)[12] << 24);
359 #endif
360 } else
361 if (list.rsize == 14) {
362 #if defined(_MIPSEL)
363 iret2 = ((__varword)((unsigned char *) list.raddr)[8])
364 | ((__varword)((unsigned char *) list.raddr)[9] << 8)
365 | ((__varword)((unsigned char *) list.raddr)[10] << 16)
366 | ((__varword)((unsigned char *) list.raddr)[11] << 24)
367 | ((__varword)((unsigned char *) list.raddr)[12] << 32)
368 | ((__varword)((unsigned char *) list.raddr)[13] << 40);
369 #else
370 iret2 = ((__varword)((unsigned char *) list.raddr)[8] << 56)
371 | ((__varword)((unsigned char *) list.raddr)[9] << 48)
372 | ((__varword)((unsigned char *) list.raddr)[10] << 40)
373 | ((__varword)((unsigned char *) list.raddr)[11] << 32)
374 | ((__varword)((unsigned char *) list.raddr)[12] << 24)
375 | ((__varword)((unsigned char *) list.raddr)[13] << 16);
376 #endif
377 } else
378 if (list.rsize == 15) {
379 #if defined(_MIPSEL)
380 iret2 = ((__varword)((unsigned char *) list.raddr)[8])
381 | ((__varword)((unsigned char *) list.raddr)[9] << 8)
382 | ((__varword)((unsigned char *) list.raddr)[10] << 16)
383 | ((__varword)((unsigned char *) list.raddr)[11] << 24)
384 | ((__varword)((unsigned char *) list.raddr)[12] << 32)
385 | ((__varword)((unsigned char *) list.raddr)[13] << 40)
386 | ((__varword)((unsigned char *) list.raddr)[14] << 48);
387 #else
388 iret2 = ((__varword)((unsigned char *) list.raddr)[8] << 56)
389 | ((__varword)((unsigned char *) list.raddr)[9] << 48)
390 | ((__varword)((unsigned char *) list.raddr)[10] << 40)
391 | ((__varword)((unsigned char *) list.raddr)[11] << 32)
392 | ((__varword)((unsigned char *) list.raddr)[12] << 24)
393 | ((__varword)((unsigned char *) list.raddr)[13] << 16)
394 | ((__varword)((unsigned char *) list.raddr)[14] << 8);
395 #endif
396 } else
397 if (list.rsize == 16) {
398 #if defined(_MIPSEL)
399 iret2 = ((__varword)((unsigned char *) list.raddr)[8])
400 | ((__varword)((unsigned char *) list.raddr)[9] << 8)
401 | ((__varword)((unsigned char *) list.raddr)[10] << 16)
402 | ((__varword)((unsigned char *) list.raddr)[11] << 24)
403 | ((__varword)((unsigned char *) list.raddr)[12] << 32)
404 | ((__varword)((unsigned char *) list.raddr)[13] << 40)
405 | ((__varword)((unsigned char *) list.raddr)[14] << 48)
406 | ((__varword)((unsigned char *) list.raddr)[15] << 56);
407 #else
408 iret2 = ((__varword)((unsigned char *) list.raddr)[8] << 56)
409 | ((__varword)((unsigned char *) list.raddr)[9] << 48)
410 | ((__varword)((unsigned char *) list.raddr)[10] << 40)
411 | ((__varword)((unsigned char *) list.raddr)[11] << 32)
412 | ((__varword)((unsigned char *) list.raddr)[12] << 24)
413 | ((__varword)((unsigned char *) list.raddr)[13] << 16)
414 | ((__varword)((unsigned char *) list.raddr)[14] << 8)
415 | (__varword)((unsigned char *) list.raddr)[15];
416 #endif
417 }
418 }
419 #else /* Optimized: fewer conditional jumps, fewer memory accesses */
420 uintptr_t count = list.rsize; /* > 0, ≤ 2*sizeof(__varword) */
421 __varword* wordaddr = (__varword*)((uintptr_t)list.raddr & ~(uintptr_t)(sizeof(__varword)-1));
422 uintptr_t start_offset = (uintptr_t)list.raddr & (uintptr_t)(sizeof(__varword)-1); /* ≥ 0, < sizeof(__varword) */
423 uintptr_t end_offset = start_offset + count; /* > 0, < 3*sizeof(__varword) */
424 #if defined(_MIPSEL)
425 if (count <= sizeof(__varword)) {
426 /* Assign iret. */
427 if (end_offset <= sizeof(__varword)) {
428 /* 0 < end_offset ≤ sizeof(__varword) */
429 __varword mask0 = ((__varword)2 << (end_offset*8-1)) - 1;
430 iret = (wordaddr[0] & mask0) >> (start_offset*8);
431 } else {
432 /* sizeof(__varword) < end_offset < 2*sizeof(__varword), start_offset > 0 */
433 __varword mask1 = ((__varword)2 << (end_offset*8-sizeof(__varword)*8-1)) - 1;
434 iret = (wordaddr[0] >> (start_offset*8)) | ((wordaddr[1] & mask1) << (sizeof(__varword)*8-start_offset*8));
435 }
436 } else {
437 /* Assign iret, iret2. */
438 if (end_offset <= 2*sizeof(__varword)) {
439 /* sizeof(__varword) < end_offset ≤ 2*sizeof(__varword) */
440 __varword mask1 = ((__varword)2 << (end_offset*8-sizeof(__varword)*8-1)) - 1;
441 iret = (wordaddr[0] >> (start_offset*8)) | ((wordaddr[1] & mask1) << (sizeof(__varword)*4-start_offset*4) << (sizeof(__varword)*4-start_offset*4));
442 iret2 = (wordaddr[1] & mask1) >> (start_offset*8);
443 } else {
444 /* 2*sizeof(__varword) < end_offset < 3*sizeof(__varword), start_offset > 0 */
445 __varword mask2 = ((__varword)2 << (end_offset*8-2*sizeof(__varword)*8-1)) - 1;
446 iret = (wordaddr[0] >> (start_offset*8)) | (wordaddr[1] << (sizeof(__varword)*8-start_offset*8));
447 iret2 = (wordaddr[1] >> (start_offset*8)) | ((wordaddr[2] & mask2) << (sizeof(__varword)*8-start_offset*8));
448 }
449 }
450 #else
451 if (count <= sizeof(__varword)) {
452 /* Assign iret. */
453 if (end_offset <= sizeof(__varword)) {
454 /* 0 < end_offset ≤ sizeof(__varword) */
455 __varword mask0 = - ((__varword)1 << (sizeof(__varword)*8-end_offset*8));
456 iret = (wordaddr[0] & mask0) << (start_offset*8);
457 } else {
458 /* sizeof(__varword) < end_offset < 2*sizeof(__varword), start_offset > 0 */
459 __varword mask1 = - ((__varword)1 << (2*sizeof(__varword)*8-end_offset*8));
460 iret = (wordaddr[0] << (start_offset*8)) | ((wordaddr[1] & mask1) >> (sizeof(__varword)*8-start_offset*8));
461 }
462 } else {
463 /* Assign iret, iret2. */
464 if (end_offset <= 2*sizeof(__varword)) {
465 /* sizeof(__varword) < end_offset ≤ 2*sizeof(__varword) */
466 __varword mask1 = - ((__varword)1 << (2*sizeof(__varword)*8-end_offset*8));
467 iret = (wordaddr[0] << (start_offset*8)) | ((wordaddr[1] & mask1) >> (sizeof(__varword)*4-start_offset*4) >> (sizeof(__varword)*4-start_offset*4));
468 iret2 = (wordaddr[1] & mask1) << (start_offset*8);
469 } else {
470 /* 2*sizeof(__varword) < end_offset < 3*sizeof(__varword), start_offset > 0 */
471 __varword mask2 = - ((__varword)1 << (3*sizeof(__varword)*8-end_offset*8));
472 iret = (wordaddr[0] << (start_offset*8)) | (wordaddr[1] >> (sizeof(__varword)*8-start_offset*8));
473 iret2 = (wordaddr[1] << (start_offset*8)) | ((wordaddr[2] & mask2) >> (sizeof(__varword)*8-start_offset*8));
474 }
475 }
476 #endif
477 #endif
478 }
479 if (list.flags & __VA_REGISTER_FLOATSTRUCT_RETURN) {
480 if (list.rsize == sizeof(float)) {
481 fret = *(float*)list.raddr;
482 } else
483 if (list.rsize == 2*sizeof(float)) {
484 fret = *(float*)list.raddr;
485 fret2 = *(float*)((char*)list.raddr + 4);
486 }
487 }
488 if (list.flags & __VA_REGISTER_DOUBLESTRUCT_RETURN) {
489 if (list.rsize == sizeof(double)) {
490 dret = *(double*)list.raddr;
491 } else
492 if (list.rsize == 2*sizeof(double)) {
493 dret = *(double*)list.raddr;
494 dret2 = *(double*)((char*)list.raddr + 8);
495 }
496 }
497 }
498 }
499 }
500 }
501
502 #ifdef REENTRANT
503 __vacall_r_t
callback_get_receiver(void)504 callback_get_receiver (void)
505 {
506 return (__vacall_r_t)(void*)&callback_receiver;
507 }
508 #endif
509