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