1 /*
2  * Copyright 1995-2021 Bruno Haible <bruno@clisp.org>
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
16  */
17 
18 #ifndef _VACALL_INTERNAL_H
19 #define _VACALL_INTERNAL_H
20 
21 /* Get intptr_t, uintptr_t. */
22 #include "ffcall-stdint.h"
23 
24 /* Include the public definitions,  */
25 #ifndef REENTRANT
26 #include "vacall.h"
27 #else
28 #include "vacall_r.h"
29 #endif
30 
31 
32 /* The platform indicator symbols (__i386__, etc.) come from
33    - "config.h" when compiling vacall-libapi.c,
34    - the GCC command line options when compiling vacall-$(CPU).c.
35  */
36 
37 /* These two variants of powerpc ABIs are quite different. */
38 #if defined(__powerpc__) && !defined(__powerpc64__)
39 #if defined(_AIX) || (defined(__MACH__) && defined(__APPLE__))
40 #define __powerpc_aix__ 1
41 #else
42 #define __powerpc_sysv4__ 1
43 #endif
44 #endif
45 
46 /* The Unix and Windows variants of x86_64 ABIs are quite different. */
47 #if defined(__x86_64__)
48 #if defined(_WIN32) || defined(__CYGWIN__)
49 #define __x86_64_ms__ 1
50 #else
51 #define __x86_64_sysv__ 1
52 #endif
53 #endif
54 
55 
56 /* Max # words in temporary structure storage.
57  */
58 #ifndef __VA_ALIST_WORDS
59 #define __VA_ALIST_WORDS  256
60 #endif
61 
62 /*
63  * Definition of the ‘__va_alist’ type.
64  */
65 /* Note: This struct must not contain members of type 'long' or 'unsigned long',
66    because in the mingw port we use precompiled code that assumes 'long' is
67    64-bit whereas avcall-libapi.c is then compiled by a compiler that has a
68    32-bit 'long' type. */
69 typedef struct vacall_alist
70 {
71   /* some va_... macros need these flags */
72   int            flags;
73   /* temporary storage for return value */
74 #if defined(__i386__) || defined(__arm__) || defined(__armhf__) || (defined(__powerpc__) && !defined(__powerpc64__) && defined(__MACH__) && defined(__APPLE__))
75   /* Filler word, needed if the numbers of words up to now in this structure */
76   /* is odd.                                                                 */
77   /* - On MSVC, alignof(double) = 8, but normally on i386 it is = 4.         */
78   /* - On ARM, GCC 3.1 produces code for an ABI where alignof(double) = 4    */
79   /*   and alignof(long long) = 4. But in the newer AAPCS ABI, these         */
80   /*   alignments are 8.                                                     */
81   /* - On Mac OS X, the Apple compiler has alignof(double) = 8 whereas the   */
82   /*   standard GCC has alignof(double) = 4.                                 */
83   __vaword       filler1;
84 #endif
85   union {
86     char                _char;
87     signed char         _schar;
88     unsigned char       _uchar;
89     short               _short;
90     unsigned short      _ushort;
91     int                 _int;
92     unsigned int        _uint;
93     long                _long;
94     unsigned long       _ulong;
95 #if !(defined(__mips64__) || defined(__sparc64__) || defined(__alpha__) || defined(__hppa64__) || defined(__arm64__) || defined(__powerpc64__) || defined(__ia64__) || defined(__riscv64__))
96     long long           _longlong;
97     unsigned long long  _ulonglong;
98 #endif
99     float               _float;
100     double              _double;
101     void*               _ptr;
102     __vaword            _words[2];
103   }              tmp;
104   /* current pointer into the argument array */
105   uintptr_t      aptr;
106   /* structure return pointer, return type, return type size */
107   void*          raddr;
108   enum __VAtype  rtype;
109   uintptr_t      rsize;
110 #if defined(__i386__) || defined(__m68k__) || (defined(__sparc__) && !defined(__sparc64__)) || defined(__hppa__) || defined(__hppa64__) || defined(__arm64__) || defined(__ia64__)
111   void*          structraddr;
112 #endif
113 #if (defined(__mips__) && !defined(__mipsn32__) && !defined(__mips64__)) || defined(__alpha__) || defined(__hppa__) || defined(__hppa64__)
114   uintptr_t      memargptr;
115 #endif
116 #if defined(__alpha__)
117   long           farg_offset;
118   double         farg[6];
119 #endif
120 #if defined(__hppa__) && !defined(__hppa64__)
121   long           farg_offset;
122   long           darg_offset;
123   float          farg[4];
124   double         darg[2];
125 #endif
126 #if defined(__mips__) && !defined(__mipsn32__) && !defined(__mips64__)
127   unsigned int   anum;
128 #define __VA_FARG_NUM 2
129   unsigned int   fanum;
130   float          farg[__VA_FARG_NUM];
131   double         darg[__VA_FARG_NUM];
132 #endif
133 #if defined(__mipsn32__) || defined(__mips64__)
134   int            anum;
135 #define __VA_FARG_NUM 8
136   float          farg[__VA_FARG_NUM];
137   double         darg[__VA_FARG_NUM];
138 #endif
139 #if defined(__sparc64__)
140   int            anum;
141   float          farg[16];
142   double         darg[16];
143 #endif
144 #if defined(__hppa64__)
145 #define __VA_FARG_NUM 8
146   float          farg[__VA_FARG_NUM];
147   double         darg[__VA_FARG_NUM];
148 #endif
149 #if defined(__armhf__)
150 #define __VA_IARG_NUM 4
151   /* The first __AV_IARG_NUM integer arguments are passed in registers, even if
152      some floating-point arguments have already been allocated on the stack. */
153   __vaword*      iarg;
154   unsigned int   ianum;
155   unsigned int   fanum;
156   float          farg[16];
157   double         darg[8];
158 #endif
159 #if defined(__arm64__)
160 #define __VA_IARG_NUM 8
161   unsigned int   ianum;
162   __varword      iarg[__VA_IARG_NUM];
163 #define __VA_FARG_NUM 8
164   unsigned int   fanum;
165   float          farg[__VA_FARG_NUM];
166   double         darg[__VA_FARG_NUM];
167 #endif
168 #if defined(__powerpc__) || defined(__powerpc64__)
169 #if defined(__powerpc_sysv4__)
170 #define __VA_IARG_NUM 8
171   unsigned int   ianum;
172   __varword      iarg[__VA_IARG_NUM];
173 #define __VA_FARG_NUM 8
174 #else
175 #define __VA_FARG_NUM 13
176 #endif
177   unsigned int   fanum;
178   double         farg[__VA_FARG_NUM];
179 #endif
180 #if defined(__ia64__)
181   __vaword*      saptr;
182 #define __VA_FARG_NUM 8
183   unsigned int   fanum;
184   double         farg[__VA_FARG_NUM];
185 #endif
186 #if defined(__x86_64_sysv__)
187 #define __VA_FARG_NUM 8
188   unsigned int   fanum;
189   double         farg[__VA_FARG_NUM];
190 #define __VA_IARG_NUM 6
191   unsigned int   ianum;
192   __varword      iarg[__VA_IARG_NUM];
193 #endif
194 #if defined(__x86_64_ms__)
195   int            anum;
196 #define __VA_FARG_NUM 4
197   float          farg[__VA_FARG_NUM];
198   double         darg[__VA_FARG_NUM];
199 #endif
200 #if defined(__s390__) && !defined(__s390x__)
201 #define __VA_IARG_NUM 5
202   unsigned int   ianum;
203   __varword      iarg[5];
204 #define __VA_FARG_NUM 2
205   unsigned int   fanum;
206   float          farg[__VA_FARG_NUM];
207   double         darg[__VA_FARG_NUM];
208 #endif
209 #if defined(__s390x__)
210 #define __VA_IARG_NUM 5
211   unsigned int   ianum;
212   __varword      iarg[__VA_IARG_NUM];
213 #define __VA_FARG_NUM 4
214   unsigned int   fanum;
215   float          farg[__VA_FARG_NUM];
216   double         darg[__VA_FARG_NUM];
217 #endif
218 #if defined(__riscv32__) || defined(__riscv64__)
219 #define __VA_IARG_NUM 8
220   unsigned int   ianum;
221   __varword      iarg[__VA_IARG_NUM];
222   /* Note: iarg[7] == ((__vaword *) (initial aptr))[-1]. */
223 #define __VA_FARG_NUM 8
224   unsigned int   fanum;
225   float          farg[__VA_FARG_NUM];
226   double         darg[__VA_FARG_NUM];
227 #endif
228 } __va_alist;
229 
230 
231 /* Avoid macro redefinition warnings on DragonFly BSD. */
232 #undef __va_start
233 #undef __va_arg
234 
235 
236 /*
237  * Definition of the va_start_xxx macros.
238  */
239 
240 #define __va_start(LIST,RETTYPE,FLAGS)  \
241   ((LIST)->flags = (FLAGS),						\
242    (LIST)->rtype = (RETTYPE)						\
243   )
244 
245 /*
246  * va_start_struct: Preparing structure return.
247  */
248 #define __va_start_struct(LIST,TYPE_SIZE,TYPE_ALIGN,TYPE_SPLITTABLE,FLAGS)  \
249   (__va_start(LIST,__VAstruct,FLAGS),					\
250    (LIST)->rsize = (TYPE_SIZE),						\
251    ((LIST)->flags & __VA_SUNPROCC_STRUCT_RETURN				\
252     ? __va_start_struct2(LIST)						\
253     : ((LIST)->flags & __VA_SUNCC_STRUCT_RETURN				\
254        ? ((TYPE_SIZE) <= sizeof(vacall_struct_buffer) || (vacall_error_struct_too_large(TYPE_SIZE), 0), \
255           (LIST)->raddr = &vacall_struct_buffer,			\
256           0								\
257          )								\
258        : (((LIST)->flags & __VA_SMALL_STRUCT_RETURN)			\
259           && __va_reg_struct_return(LIST,TYPE_SIZE,TYPE_SPLITTABLE)	\
260           ? ((LIST)->raddr = &(LIST)->tmp,				\
261              __va_start_struct1(LIST,TYPE_SIZE,TYPE_ALIGN,TYPE_SPLITTABLE) \
262             )								\
263           : __va_start_struct2(LIST)					\
264   ))  )  )
265 /* Determines whether a structure is returned in registers,
266  * depending on its size and its word-splittable flag.
267  */
268 #if (defined(__i386__) && defined(_WIN32))
269 #define __va_reg_struct_return(LIST,TYPE_SIZE,TYPE_SPLITTABLE)  \
270   ((TYPE_SIZE) == 1 || (TYPE_SIZE) == 2 || (TYPE_SIZE) == 4		\
271    || ((TYPE_SIZE) == 8							\
272        && (((LIST)->flags & __VA_MSVC_STRUCT_RETURN)			\
273            || ((TYPE_SPLITTABLE)					\
274                && ((LIST)->flags & __VA_GCC_STRUCT_RETURN)		\
275   )   )   )   )
276 /* Turn on __VA_REGISTER_STRUCT_RETURN if __VA_SMALL_STRUCT_RETURN was set
277  * and the struct will actually be returned in registers.
278  */
279 #define __va_start_struct1(LIST,TYPE_SIZE,TYPE_ALIGN,TYPE_SPLITTABLE)  \
280   ((LIST)->flags |= __VA_REGISTER_STRUCT_RETURN, 0)
281 #endif
282 #if (defined(__i386__) && !defined(_WIN32)) || defined(__m68k__) || (defined(__powerpc__) && !defined(__powerpc64__)) || (defined(__s390__) && !defined(__s390x__))
283 #define __va_reg_struct_return(LIST,TYPE_SIZE,TYPE_SPLITTABLE)  \
284   ((TYPE_SIZE) == 1 || (TYPE_SIZE) == 2 || (TYPE_SIZE) == 4		\
285    || ((TYPE_SIZE) == 8 && (TYPE_SPLITTABLE)				\
286        && ((LIST)->flags & __VA_GCC_STRUCT_RETURN)			\
287   )   )
288 /* Turn on __VA_REGISTER_STRUCT_RETURN if __VA_SMALL_STRUCT_RETURN was set
289  * and the struct will actually be returned in registers.
290  */
291 #define __va_start_struct1(LIST,TYPE_SIZE,TYPE_ALIGN,TYPE_SPLITTABLE)  \
292   ((LIST)->flags |= __VA_REGISTER_STRUCT_RETURN, 0)
293 #endif
294 #if defined(__arm__) || defined(__armhf__)
295 /* structs of size 3 also will be returned in register */
296 #define __va_reg_struct_return(LIST,TYPE_SIZE,TYPE_SPLITTABLE)  \
297   ((TYPE_SIZE) <= 4)
298 /* Turn on __VA_REGISTER_STRUCT_RETURN if __VA_SMALL_STRUCT_RETURN was set
299  * and the struct will actually be returned in registers.
300  */
301 #define __va_start_struct1(LIST,TYPE_SIZE,TYPE_ALIGN,TYPE_SPLITTABLE)  \
302   ((LIST)->flags |= __VA_REGISTER_STRUCT_RETURN, 0)
303 #endif
304 #if defined(__alpha__)
305 #define __va_reg_struct_return(LIST,TYPE_SIZE,TYPE_SPLITTABLE)  \
306   ((TYPE_SIZE) == 1 || (TYPE_SIZE) == 2 || (TYPE_SIZE) == 4 || (TYPE_SIZE) == 8	\
307    || ((TYPE_SIZE) == 16 && (TYPE_SPLITTABLE)				\
308        && ((LIST)->flags & __VA_GCC_STRUCT_RETURN)			\
309   )   )
310 /* Turn on __VA_REGISTER_STRUCT_RETURN if __VA_SMALL_STRUCT_RETURN was set
311  * and the struct will actually be returned in registers.
312  */
313 #define __va_start_struct1(LIST,TYPE_SIZE,TYPE_ALIGN,TYPE_SPLITTABLE)  \
314   ((LIST)->flags |= __VA_REGISTER_STRUCT_RETURN, 0)
315 #endif
316 #if (defined(__hppa__) && !defined(__hppa64__)) || defined(__riscv32__)
317 #define __va_reg_struct_return(LIST,TYPE_SIZE,TYPE_SPLITTABLE)  \
318   ((TYPE_SIZE) <= 8)
319 /* Test __VA_SMALL_STRUCT_RETURN at run time. */
320 #define __va_start_struct1(LIST,TYPE_SIZE,TYPE_ALIGN,TYPE_SPLITTABLE)  \
321   0
322 #endif
323 #if defined(__mips__) && !defined(__mipsn32__) && !defined(__mips64__) || (defined(__sparc__) && !defined(__sparc64__))
324 #define __va_reg_struct_return(LIST,TYPE_SIZE,TYPE_SPLITTABLE)  \
325   ((TYPE_SIZE) == 1 || (TYPE_SIZE) == 2 || (TYPE_SIZE) == 4)
326 /* Test __VA_SMALL_STRUCT_RETURN instead of __VA_REGISTER_STRUCT_RETURN. */
327 #if defined(__mips__) && !defined(__mipsn32__) && !defined(__mips64__)
328 #define __va_start_struct1(LIST,TYPE_SIZE,TYPE_ALIGN,TYPE_SPLITTABLE)  \
329   ((LIST)->anum++,							\
330    0									\
331   )
332 #else
333 #define __va_start_struct1(LIST,TYPE_SIZE,TYPE_ALIGN,TYPE_SPLITTABLE)  \
334   0
335 #endif
336 #endif
337 #if defined(__mipsn32__) || defined(__mips64__)
338 #define __va_reg_struct_return(LIST,TYPE_SIZE,TYPE_SPLITTABLE)  \
339   ((LIST)->flags & __VA_GCC_STRUCT_RETURN				\
340    ? ((TYPE_SIZE) == 1 || (TYPE_SIZE) == 2 || (TYPE_SIZE) == 4 || (TYPE_SIZE) == 8) \
341    : ((TYPE_SIZE) <= 16)						\
342   )
343 /* Turn on __VA_REGISTER_STRUCT_RETURN if __VA_SMALL_STRUCT_RETURN was set
344  * and the struct will actually be returned in registers. Also turn on
345  * __VA_REGISTER_FLOATSTRUCT_RETURN or __VA_REGISTER_DOUBLESTRUCT_RETURN if
346  * the struct will be returned in floating-point registers.
347  */
348 #define __va_start_struct1(LIST,TYPE_SIZE,TYPE_ALIGN,TYPE_SPLITTABLE)  \
349   ((LIST)->flags |= __VA_REGISTER_STRUCT_RETURN,				\
350    (TYPE_ALIGN) == sizeof(float) && (TYPE_SPLITTABLE)				\
351     && ((TYPE_SIZE) == sizeof(float) || (TYPE_SIZE) == 2*sizeof(float))		\
352     && ((LIST)->flags |= __VA_REGISTER_FLOATSTRUCT_RETURN),			\
353    (TYPE_ALIGN) == sizeof(double) && (TYPE_SPLITTABLE)				\
354     && ((TYPE_SIZE) == sizeof(double) || (TYPE_SIZE) == 2*sizeof(double))	\
355     && ((LIST)->flags |= __VA_REGISTER_DOUBLESTRUCT_RETURN),			\
356    0)
357 #endif
358 #if (defined(__powerpc64__) && !defined(__powerpc64_elfv2__)) || defined(__s390x__)
359 #define __va_reg_struct_return(LIST,TYPE_SIZE,TYPE_SPLITTABLE)  \
360   0
361 #define __va_start_struct1(LIST,TYPE_SIZE,TYPE_ALIGN,TYPE_SPLITTABLE)  \
362   0
363 #endif
364 #if defined(__sparc64__) || defined(__ia64__)
365 #define __va_reg_struct_return(LIST,TYPE_SIZE,TYPE_SPLITTABLE)  \
366   ((TYPE_SIZE) <= 32)
367 /* Turn on __VA_REGISTER_STRUCT_RETURN if __VA_SMALL_STRUCT_RETURN was set
368  * and the struct will actually be returned in registers.
369  */
370 #define __va_start_struct1(LIST,TYPE_SIZE,TYPE_ALIGN,TYPE_SPLITTABLE)  \
371   ((LIST)->flags |= __VA_REGISTER_STRUCT_RETURN,			\
372    0)
373 #endif
374 #if defined(__hppa64__) || defined(__arm64__) || (defined(__powerpc64__) && defined(__powerpc64_elfv2__)) || defined(__x86_64_sysv__) || defined(__riscv64__)
375 #define __va_reg_struct_return(LIST,TYPE_SIZE,TYPE_SPLITTABLE)  \
376   ((TYPE_SIZE) <= 16)
377 /* Turn on __VA_REGISTER_STRUCT_RETURN if __VA_SMALL_STRUCT_RETURN was set
378  * and the struct will actually be returned in registers.
379  */
380 #define __va_start_struct1(LIST,TYPE_SIZE,TYPE_ALIGN,TYPE_SPLITTABLE)  \
381   ((LIST)->flags |= __VA_REGISTER_STRUCT_RETURN,			\
382    0)
383 #endif
384 #if defined(__x86_64_ms__)
385 #define __va_reg_struct_return(LIST,TYPE_SIZE,TYPE_SPLITTABLE)  \
386   ((TYPE_SIZE) == 1 || (TYPE_SIZE) == 2 || (TYPE_SIZE) == 4 || (TYPE_SIZE) == 8)
387 /* Turn on __VA_REGISTER_STRUCT_RETURN if __VA_SMALL_STRUCT_RETURN was set
388  * and the struct will actually be returned in registers.
389  */
390 #define __va_start_struct1(LIST,TYPE_SIZE,TYPE_ALIGN,TYPE_SPLITTABLE)  \
391   ((LIST)->flags |= __VA_REGISTER_STRUCT_RETURN,			\
392    0)
393 #endif
394 /*
395  * Preparing structure return in memory.
396  */
397 #if defined(__i386__) || defined(__alpha__) || (defined(__arm__) && !defined(__armhf__)) || defined(__powerpc_aix__) || defined(__powerpc64__)
398 /* Return structure pointer is passed as first arg. */
399 #define __va_start_struct2(LIST)  \
400   ((LIST)->raddr = *(void* *)((LIST)->aptr),				\
401    (LIST)->aptr += sizeof(void*),					\
402    0									\
403   )
404 #endif
405 #if defined(__mips__) || defined(__mipsn32__) || defined(__mips64__) || defined(__sparc64__) || defined(__x86_64_ms__)
406 /* Return structure pointer is passed as first arg. */
407 #define __va_start_struct2(LIST)  \
408   ((LIST)->raddr = *(void* *)((LIST)->aptr),				\
409    (LIST)->aptr += sizeof(void*),					\
410    (LIST)->anum++,							\
411    0									\
412   )
413 #endif
414 #if defined(__armhf__)
415 /* Return structure pointer is passed as first arg. */
416 #define __va_start_struct2(LIST)  \
417   ((LIST)->raddr = (void*)(LIST)->iarg[(LIST)->ianum],			\
418    (LIST)->ianum++,							\
419    0									\
420   )
421 #endif
422 #if defined(__powerpc_sysv4__) || defined(__x86_64_sysv__) || defined(__s390__) || defined(__s390x__) || defined(__riscv32__) || defined(__riscv64__)
423 /* Return structure pointer is passed as first arg. */
424 #define __va_start_struct2(LIST)  \
425   ((LIST)->raddr = (void*)((LIST)->iarg[(LIST)->ianum++]),		\
426    0									\
427   )
428 #endif
429 #if defined(__m68k__) || (defined(__sparc__) && !defined(__sparc64__)) || defined(__hppa__) || defined(__hppa64__) || defined(__arm64__) || defined(__ia64__)
430 /* Return structure pointer is passed in a special register. */
431 #define __va_start_struct2(LIST)  \
432   ((LIST)->raddr = (LIST)->structraddr, 0)
433 #endif
434 
435 
436 /*
437  * Definition of the va_arg_xxx macros.
438  */
439 
440 /* Padding of non-struct arguments. */
441 #define __va_argsize(TYPE_SIZE)  \
442   (((TYPE_SIZE) + sizeof(__vaword)-1) & -(intptr_t)sizeof(__vaword))
443 #if defined(__i386__) || defined(__m68k__) || (defined(__mips__) && !defined(__mipsn32__) && !defined(__mips64__)) || (defined(__sparc__) && !defined(__sparc64__)) || defined(__alpha__) || (defined(__arm__) && !defined(__armhf__)) || defined(__arm64__) || defined(__powerpc_aix__) || defined(__powerpc64__) || defined(__ia64__) || defined(__x86_64_sysv__) || defined(__s390__) || defined(__s390x__) || defined(__riscv32__) || defined(__riscv64__)
444 /* args grow up */
445 /* small structures < 1 word are adjusted depending on compiler */
446 #define __va_arg_leftadjusted(LIST,TYPE_SIZE,TYPE_ALIGN)  \
447   ((LIST)->aptr += __va_argsize(TYPE_SIZE),				\
448    (LIST)->aptr - __va_argsize(TYPE_SIZE)				\
449   )
450 #define __va_arg_rightadjusted(LIST,TYPE_SIZE,TYPE_ALIGN)  \
451   ((LIST)->aptr += __va_argsize(TYPE_SIZE),				\
452    (LIST)->aptr - ((TYPE_SIZE) < sizeof(__vaword)			\
453 		   ? (TYPE_SIZE)					\
454 		   : __va_argsize(TYPE_SIZE)				\
455 		  )							\
456   )
457 #endif
458 #if defined(__armhf__)
459 /* args grow up */
460 /* small structures < 1 word are adjusted depending on compiler */
461 /* the first __VA_IARG_NUM argument words are passed in registers */
462 #define __va_arg_leftadjusted(LIST,TYPE_SIZE,TYPE_ALIGN)  \
463   (((LIST)->ianum + ((TYPE_SIZE) + sizeof(__vaword)-1) / sizeof(__vaword) <= __VA_IARG_NUM \
464     ? ((LIST)->ianum += __va_argsize(TYPE_SIZE) / sizeof(__vaword),	\
465        (char*)&(LIST)->iarg[(LIST)->ianum]				\
466       )									\
467     : (((LIST)->aptr == (uintptr_t)&(LIST)->iarg[__VA_IARG_NUM]		\
468         ? /* split case */						\
469           ((LIST)->aptr = (uintptr_t)&(LIST)->iarg[(LIST)->ianum] + __va_argsize(TYPE_SIZE), \
470            0)								\
471         : ((LIST)->aptr += __va_argsize(TYPE_SIZE),			\
472            0)),								\
473        (LIST)->ianum = __VA_IARG_NUM,					\
474        (char*)(LIST)->aptr						\
475    )  )									\
476    - __va_argsize(TYPE_SIZE)						\
477   )
478 #define __va_arg_rightadjusted(LIST,TYPE_SIZE,TYPE_ALIGN)  \
479   (((LIST)->ianum + ((TYPE_SIZE) + sizeof(__vaword)-1) / sizeof(__vaword) <= __VA_IARG_NUM \
480     ? ((LIST)->ianum += __va_argsize(TYPE_SIZE) / sizeof(__vaword),	\
481        (char*)&(LIST)->iarg[(LIST)->ianum]				\
482       )									\
483     : (((LIST)->aptr == (uintptr_t)&(LIST)->iarg[__VA_IARG_NUM]		\
484         ? /* split case */						\
485           ((LIST)->aptr = (uintptr_t)&(LIST)->iarg[(LIST)->ianum] + __va_argsize(TYPE_SIZE), \
486            0)								\
487         : ((LIST)->aptr += __va_argsize(TYPE_SIZE),			\
488            0)),								\
489        (LIST)->ianum = __VA_IARG_NUM,					\
490        (char*)(LIST)->aptr						\
491    )  )									\
492    - ((TYPE_SIZE) < sizeof(__vaword)					\
493       ? (TYPE_SIZE)							\
494       : __va_argsize(TYPE_SIZE)						\
495      )									\
496   )
497 #endif
498 #if defined(__powerpc_sysv4__)
499 /* args grow up */
500 /* small structures < 1 word are adjusted depending on compiler */
501 /* the first __VA_IARG_NUM argument words are passed in registers */
502 #define __va_arg_leftadjusted(LIST,TYPE_SIZE,TYPE_ALIGN)  \
503   (((LIST)->ianum + ((TYPE_SIZE) + sizeof(__varword)-1) / sizeof(__varword) <= __VA_IARG_NUM \
504     ? ((LIST)->ianum += __va_argsize(TYPE_SIZE) / sizeof(__varword),	\
505        (char*)&(LIST)->iarg[(LIST)->ianum]				\
506       )									\
507     : ((LIST)->aptr += __va_argsize(TYPE_SIZE),				\
508        (char*)(LIST)->aptr						\
509    )  )									\
510    - __va_argsize(TYPE_SIZE)						\
511   )
512 #define __va_arg_rightadjusted(LIST,TYPE_SIZE,TYPE_ALIGN)  \
513   (((LIST)->ianum + ((TYPE_SIZE) + sizeof(__varword)-1) / sizeof(__varword) <= __VA_IARG_NUM \
514     ? ((LIST)->ianum += __va_argsize(TYPE_SIZE) / sizeof(__varword),	\
515        (char*)&(LIST)->iarg[(LIST)->ianum]				\
516       )									\
517     : ((LIST)->aptr += __va_argsize(TYPE_SIZE),				\
518        (char*)(LIST)->aptr						\
519    )  )									\
520    - ((TYPE_SIZE) < sizeof(__vaword)					\
521       ? (TYPE_SIZE)							\
522       : __va_argsize(TYPE_SIZE)						\
523      )									\
524   )
525 #endif
526 #if defined(__mipsn32__) || defined(__mips64__) || defined(__sparc64__) || defined(__x86_64_ms__)
527 /* args grow up */
528 /* small structures < 1 word are adjusted depending on compiler */
529 #define __va_arg_leftadjusted(LIST,TYPE_SIZE,TYPE_ALIGN)  \
530   ((LIST)->anum += __va_argsize(TYPE_SIZE)/sizeof(__vaword),		\
531    (LIST)->aptr += __va_argsize(TYPE_SIZE),				\
532    (LIST)->aptr - __va_argsize(TYPE_SIZE)				\
533   )
534 #define __va_arg_rightadjusted(LIST,TYPE_SIZE,TYPE_ALIGN)  \
535   ((LIST)->anum += __va_argsize(TYPE_SIZE)/sizeof(__vaword),		\
536    (LIST)->aptr += __va_argsize(TYPE_SIZE),				\
537    (LIST)->aptr - ((TYPE_SIZE) < sizeof(__vaword)			\
538 		   ? (TYPE_SIZE)					\
539 		   : __va_argsize(TYPE_SIZE)				\
540 		  )							\
541   )
542 #endif
543 #if defined(__hppa__) && !defined(__hppa64__)
544 /* args grow down */
545 #define __va_arg_leftadjusted(LIST,TYPE_SIZE,TYPE_ALIGN)  \
546   ((LIST)->aptr = (LIST)->aptr - __va_argsize(TYPE_SIZE),		\
547    ((TYPE_SIZE) > 4 && ((LIST)->aptr &= -8)),				\
548    (LIST)->aptr								\
549   )
550 #define __va_arg_rightadjusted(LIST,TYPE_SIZE,TYPE_ALIGN)  \
551   ((LIST)->aptr = (LIST)->aptr - __va_argsize(TYPE_SIZE),		\
552    ((TYPE_SIZE) > 4 && ((LIST)->aptr &= -8)),				\
553    (LIST)->aptr + ((-(TYPE_SIZE)) & 3)					\
554   )
555 #endif
556 #if defined(__hppa64__)
557 /* args grow up */
558 #define __va_arg_leftadjusted(LIST,TYPE_SIZE,TYPE_ALIGN)  \
559   (((TYPE_SIZE) > 8 && ((LIST)->aptr = (((LIST)->aptr +15) & -16))),	\
560    (LIST)->aptr += __va_argsize(TYPE_SIZE),				\
561    (LIST)->aptr - __va_argsize(TYPE_SIZE)				\
562   )
563 #define __va_arg_rightadjusted(LIST,TYPE_SIZE,TYPE_ALIGN)  \
564   (((TYPE_SIZE) > 8 && ((LIST)->aptr = (((LIST)->aptr +15) & -16))),	\
565    (LIST)->aptr += __va_argsize(TYPE_SIZE),				\
566    (LIST)->aptr - ((TYPE_SIZE) < sizeof(__vaword)			\
567 		   ? (TYPE_SIZE)					\
568 		   : __va_argsize(TYPE_SIZE)				\
569 		  )							\
570   )
571 #endif
572 #if defined(__i386__) || ((defined(__mipsn32__) || defined(__mips64__)) && defined(_MIPSEL)) || defined(__alpha__) || ((defined(__arm__) || defined(__armhf__)) && defined(__ARMEL__)) || defined(__ia64__) || (defined(__powerpc64__) && defined(_LITTLE_ENDIAN)) || defined(__x86_64_ms__)
573 /* little endian -> small args < 1 word are adjusted to the left */
574 #define __va_arg_adjusted(LIST,TYPE_SIZE,TYPE_ALIGN)  \
575   (void*)__va_arg_leftadjusted(LIST,TYPE_SIZE,TYPE_ALIGN)
576 #endif
577 #if defined(__m68k__) || ((defined(__mipsn32__) || defined(__mips64__)) && defined(_MIPSEB)) || defined(__sparc__) || defined(__sparc64__) || defined(__hppa__) || defined(__hppa64__) || ((defined(__arm__) || defined(__armhf__)) && !defined(__ARMEL__)) || (defined(__powerpc__) && !defined(__powerpc64__)) || (defined(__powerpc64__) && defined(_BIG_ENDIAN))
578 /* big endian -> small args < 1 word are adjusted to the right */
579 #define __va_arg_adjusted(LIST,TYPE_SIZE,TYPE_ALIGN)  \
580   (void*)__va_arg_rightadjusted(LIST,TYPE_SIZE,TYPE_ALIGN)
581 #endif
582 #if defined(__mips__) && !defined(__mipsn32__) && !defined(__mips64__)
583 #ifdef _MIPSEB
584 /* big endian -> small args < 1 word are adjusted to the right */
585 #define __va_arg_adjusted(LIST,TYPE_SIZE,TYPE_ALIGN)  \
586   ((LIST)->anum++,							\
587    (void*)__va_arg_rightadjusted(LIST,TYPE_SIZE,TYPE_ALIGN))
588 #else /* _MIPSEL */
589 /* little endian -> small args < 1 word are adjusted to the left */
590 #define __va_arg_adjusted(LIST,TYPE_SIZE,TYPE_ALIGN)  \
591   ((LIST)->anum++,							\
592    (void*)__va_arg_leftadjusted(LIST,TYPE_SIZE,TYPE_ALIGN))
593 #endif
594 #endif
595 #if defined(__arm64__)
596 /* the first __VA_IARG_NUM argument words are passed in registers */
597 #define __va_arg_adjusted(LIST,TYPE_SIZE,TYPE_ALIGN)  \
598   ((LIST)->ianum + ((TYPE_SIZE) + sizeof(__varword)-1) / sizeof(__varword) <= __VA_IARG_NUM \
599    ? ((LIST)->ianum += ((TYPE_SIZE) + sizeof(__varword)-1) / sizeof(__varword), \
600       &(LIST)->iarg[(LIST)->ianum - ((TYPE_SIZE) + sizeof(__varword)-1) / sizeof(__varword)] \
601      )									\
602    : ((LIST)->ianum = __VA_IARG_NUM,					\
603       (void*)__va_arg_leftadjusted(LIST,TYPE_SIZE,TYPE_ALIGN)		\
604   )  )
605 #endif
606 #if defined(__x86_64_sysv__)
607 /* the first __VA_IARG_NUM argument words are passed in registers */
608 #define __va_arg_adjusted(LIST,TYPE_SIZE,TYPE_ALIGN)  \
609   (((TYPE_SIZE) <= 2*sizeof(__varword)					\
610     && (LIST)->ianum + ((TYPE_SIZE) + sizeof(__varword)-1) / sizeof(__varword) <= __VA_IARG_NUM) \
611    ? ((LIST)->ianum += ((TYPE_SIZE) + sizeof(__varword)-1) / sizeof(__varword), \
612       &(LIST)->iarg[(LIST)->ianum - ((TYPE_SIZE) + sizeof(__varword)-1) / sizeof(__varword)] \
613      )									\
614    : (void*)__va_arg_leftadjusted(LIST,TYPE_SIZE,TYPE_ALIGN)		\
615   )
616 #endif
617 #if defined(__s390__) || defined(__s390x__)
618 /* the first __VA_IARG_NUM argument words are passed in registers */
619 #define __va_arg_adjusted(LIST,TYPE_SIZE,TYPE_ALIGN)  \
620   ((LIST)->ianum + ((TYPE_SIZE) + sizeof(__varword)-1) / sizeof(__varword) <= __VA_IARG_NUM \
621    ? ((LIST)->ianum += ((TYPE_SIZE) + sizeof(__varword)-1) / sizeof(__varword), \
622       (void*)((uintptr_t)&(LIST)->iarg[(LIST)->ianum] - (TYPE_SIZE))	\
623      )									\
624    : ((LIST)->ianum = __VA_IARG_NUM,					\
625       (void*)__va_arg_rightadjusted(LIST,TYPE_SIZE,TYPE_ALIGN)		\
626   )  )
627 #endif
628 #if defined(__riscv32__) || defined(__riscv64__)
629 /* the first __VA_IARG_NUM argument words are passed in registers */
630 #define __va_arg_adjusted(LIST,TYPE_SIZE,TYPE_ALIGN)  \
631   ((LIST)->ianum + ((TYPE_SIZE) + sizeof(__varword)-1) / sizeof(__varword) <= __VA_IARG_NUM \
632    ? ((LIST)->ianum += ((TYPE_SIZE) + sizeof(__varword)-1) / sizeof(__varword), \
633       &(LIST)->iarg[(LIST)->ianum - ((TYPE_SIZE) + sizeof(__varword)-1) / sizeof(__varword)] \
634      )									\
635    : (((LIST)->ianum < __VA_IARG_NUM					\
636        ? ((LIST)->aptr -= (__VA_IARG_NUM - (LIST)->ianum) * sizeof(__vaword), \
637           (LIST)->ianum = __VA_IARG_NUM,				\
638           0)								\
639        : 0),								\
640       (void*)__va_arg_leftadjusted(LIST,TYPE_SIZE,TYPE_ALIGN)		\
641   )  )
642 #endif
643 #define __va_arg(LIST,TYPE)  \
644   *(TYPE*)__va_arg_adjusted(LIST,sizeof(TYPE),__VA_alignof(TYPE))
645 
646 /* Integer arguments. */
647 
648 #define _va_arg_char(LIST)	__va_arg(LIST,char)
649 #define _va_arg_schar(LIST)	__va_arg(LIST,signed char)
650 #define _va_arg_uchar(LIST)	__va_arg(LIST,unsigned char)
651 #define _va_arg_short(LIST)	__va_arg(LIST,short)
652 #define _va_arg_ushort(LIST)	__va_arg(LIST,unsigned short)
653 #define _va_arg_int(LIST)	__va_arg(LIST,int)
654 #define _va_arg_uint(LIST)	__va_arg(LIST,unsigned int)
655 #define _va_arg_long(LIST)	__va_arg(LIST,long)
656 #define _va_arg_ulong(LIST)	__va_arg(LIST,unsigned long)
657 
658 #if defined(__mips64__) || defined(__sparc64__) || defined(__alpha__) || defined(__hppa64__) || defined(__arm64__) || defined(__powerpc64__) || defined(__ia64__) || (defined(__x86_64__) && !defined(__x86_64_x32__) && !defined(__VA_LLP64)) || defined(__s390x__) || defined(__riscv64__)
659 /* ‘long long’ and ‘long’ are identical. */
660 #define _va_arg_longlong	_va_arg_long
661 #define _va_arg_ulonglong	_va_arg_ulong
662 #elif defined(__mipsn32__) || defined(__x86_64_x32__) || (defined(__x86_64__) && defined(__VA_LLP64))
663 /* ‘long long’ fits in __vaword. */
664 #define _va_arg_longlong(LIST)	__va_arg(LIST,long long)
665 #define _va_arg_ulonglong(LIST)	__va_arg(LIST,unsigned long long)
666 #elif defined(__i386__) || defined(__m68k__) || defined(__mips__) || (defined(__sparc__) && !defined(__sparc64__)) || (defined(__hppa__) && !defined(__hppa64__)) || defined(__arm__) || defined(__armhf__) || defined(__powerpc__) || (defined(__s390__) && !defined(__s390x__)) || defined(__riscv32__)
667 /* ‘long long’s are passed embedded on the arg stack. */
668 #define _va_arg_longlong(LIST)	__va_arg_longlong(LIST,long long)
669 #define _va_arg_ulonglong(LIST)	__va_arg_longlong(LIST,unsigned long long)
670 #if defined(__i386__) || defined(__m68k__) || defined(__powerpc_aix__)
671 /* ‘long long’s are (at most) word-aligned. */
672 #define __va_arg_longlong(LIST,TYPE)	__va_arg(LIST,TYPE)
673 #endif
674 #if defined(__mips__) || defined(__arm__)
675 /* ‘long long’s have alignment 8. */
676 #define __va_arg_longlong(LIST,TYPE)					\
677   ((LIST)->aptr = (((LIST)->aptr+__VA_alignof(TYPE)-1) & -(intptr_t)__VA_alignof(TYPE)), \
678    __va_arg(LIST,TYPE))
679 #endif
680 #if defined(__armhf__)
681 /* ‘long long’s have alignment 8. */
682 #define __va_arg_longlong(LIST,TYPE)					\
683   (((LIST)->ianum < __VA_IARG_NUM					\
684     ? ((LIST)->ianum = (((LIST)->ianum+__VA_alignof(TYPE)/sizeof(__vaword)-1) & -(intptr_t)(__VA_alignof(TYPE)/sizeof(__vaword))), 0) \
685     : ((LIST)->aptr = (((LIST)->aptr+__VA_alignof(TYPE)-1) & -(intptr_t)__VA_alignof(TYPE)), 0) \
686    ),									\
687    __va_arg(LIST,TYPE))
688 #endif
689 #if defined(__powerpc_sysv4__)
690 /* ‘long long’s have alignment 8. */
691 #define __va_arg_longlong(LIST,TYPE)					\
692   (((LIST)->ianum < __VA_IARG_NUM					\
693     ? ((LIST)->ianum = (((LIST)->ianum+__VA_alignof(TYPE)/sizeof(__varword)-1) & -(intptr_t)(__VA_alignof(TYPE)/sizeof(__varword))), 0) \
694     : ((LIST)->aptr = (((LIST)->aptr+__VA_alignof(TYPE)-1) & -(intptr_t)__VA_alignof(TYPE)), 0) \
695    ),									\
696    __va_arg(LIST,TYPE))
697 #endif
698 #if (defined(__s390__) && !defined(__s390x__)) || defined(__riscv32__)
699 /* Within the arg stack, the alignment is only 4, not 8. */
700 #define __va_arg_longlong(LIST,TYPE)	__va_arg(LIST,TYPE)
701 #endif
702 #if (defined(__sparc__) && !defined(__sparc64__))
703 /* Within the arg stack, the alignment is only 4, not 8. */
704 /* Beware against unaligned accesses! */
705 #define __va_arg_longlong(LIST,TYPE)					\
706   ((LIST)->tmp._words[0] = ((__vaword*)((LIST)->aptr))[0],		\
707    (LIST)->tmp._words[1] = ((__vaword*)((LIST)->aptr))[1],		\
708    (LIST)->aptr += sizeof(TYPE),					\
709    (TYPE)((LIST)->tmp._longlong)					\
710   )
711 #endif
712 #if defined(__hppa__) && !defined(__hppa64__)
713 /* ‘long long’s have alignment 8. */
714 #define __va_arg_longlong(LIST,TYPE)					\
715   ((LIST)->aptr = ((LIST)->aptr & -(intptr_t)__VA_alignof(TYPE)),	\
716    __va_arg(LIST,TYPE))
717 #endif
718 #endif
719 
720 /* Floating point arguments. */
721 
722 #if defined(__i386__) || defined(__m68k__) || defined(__mipsn32__) || defined(__mips64__) || defined(__sparc__) || defined(__sparc64__) || defined(__alpha__) || defined(__hppa64__) || defined(__arm64__) || defined(__powerpc__) || defined(__powerpc64__) || defined(__ia64__) || defined(__x86_64__) || defined(__s390__) || defined(__s390x__) || defined(__riscv32__) || defined(__riscv64__)
723 #define __va_align_double(LIST)
724 #endif
725 #if defined(__mips__) && !defined(__mipsn32__) && !defined(__mips64__) || defined(__arm__) || defined(__armhf__)
726 /* __VA_alignof(double) > sizeof(__vaword) */
727 #define __va_align_double(LIST)  \
728   (LIST)->aptr = ((LIST)->aptr + sizeof(double)-1) & -(intptr_t)sizeof(double),
729 #endif
730 #if defined(__hppa__) && !defined(__hppa64__)
731 #define __va_align_double(LIST)  \
732   (LIST)->aptr = (LIST)->aptr & -(intptr_t)sizeof(double),
733 #endif
734 
735 #if defined(__sparc__) && !defined(__sparc64__)
736 /* Beware against unaligned ‘double’ accesses! */
737 #define _va_arg_double(LIST)  \
738   (__va_align_double(LIST)						\
739    (LIST)->tmp._words[0] = ((__vaword*)((LIST)->aptr))[0],		\
740    (LIST)->tmp._words[1] = ((__vaword*)((LIST)->aptr))[1],		\
741    (LIST)->aptr += sizeof(double),					\
742    (LIST)->tmp._double							\
743   )
744 #endif
745 #if defined(__alpha__)
746 /* The first 6 floating point registers have been stored in another place. */
747 #define _va_arg_double(LIST)  \
748   (((LIST)->aptr += sizeof(double)) <= (LIST)->memargptr		\
749    ? *(double*)((LIST)->aptr - sizeof(double) + (LIST)->farg_offset)	\
750    : *(double*)((LIST)->aptr - sizeof(double))				\
751   )
752 #define _va_arg_float(LIST)  \
753   (((LIST)->aptr += sizeof(double)) <= (LIST)->memargptr		\
754    ? /* The first 6 args have been put into memory by "stt" instructions */\
755      /* (see vacall-alpha.s!). Therefore load them as doubles. */	\
756      /* When viewed as floats, the value will be the correct one. */	\
757      (float)*(double*)((LIST)->aptr - sizeof(double) + (LIST)->farg_offset) \
758    : /* These args have been put into memory by "sts" instructions, */	\
759      /* therefore load them as floats. */				\
760      *(float*)((LIST)->aptr - sizeof(double))				\
761   )
762 #endif
763 #if defined(__hppa__) && !defined(__hppa64__)
764 /* The floats and doubles among the first 4 argument words are passed
765  * - in both general registers and floating-point registers when the
766  *   function call is a variadic one, which means:
767  *     - for HP cc: the call is done through a function pointer or
768  *       directly to a function declared with a varargs prototype,
769  *     - for GCC: the function's type is a varargs function.
770  * - in floating-point registers otherwise.
771  * Since the code in tests.c uses a function pointer, casted to a non-varargs
772  * function type, we are in the first case for HP cc, but in the second case
773  * for GCC.
774  * Therefore we need to take the values from the floating-point registers.
775  */
776 #define _va_arg_float(LIST)  \
777   (((LIST)->aptr -= sizeof(float)) >= (LIST)->memargptr			\
778    ? /* The first 4 float args are stored separately. */		\
779      *(float*)((LIST)->aptr + (LIST)->farg_offset)			\
780    : *(float*)((LIST)->aptr)						\
781   )
782 #define _va_arg_double(LIST)  \
783   (__va_align_double(LIST)						\
784    (((LIST)->aptr -= sizeof(double)) >= (LIST)->memargptr		\
785     ? /* The first 2 double args are stored separately. */		\
786       *(double*)((LIST)->aptr + (LIST)->darg_offset)			\
787     : *(double*)((LIST)->aptr)						\
788   ))
789 #endif
790 #if defined(__mips__) && !defined(__mipsn32__) && !defined(__mips64__)
791 /* The first 0,1,2 registers are stored elsewhere if they are floating-point
792  * parameters.
793  */
794 #define _va_arg_float(LIST)  \
795   ((LIST)->aptr += sizeof(float),					\
796    (LIST)->anum++,							\
797    (LIST)->fanum++,							\
798    ((LIST)->anum == (LIST)->fanum && (LIST)->fanum <= __VA_FARG_NUM	\
799     ? /* only floating-point arguments so far */			\
800       (LIST)->farg[(LIST)->fanum - 1]					\
801     : *(float*)((LIST)->aptr - sizeof(float))				\
802   ))
803 #define _va_arg_double(LIST)  \
804   (__va_align_double(LIST)						\
805    (LIST)->aptr += sizeof(double),					\
806    (LIST)->anum++,							\
807    (LIST)->fanum++,							\
808    ((LIST)->anum == (LIST)->fanum && (LIST)->fanum <= __VA_FARG_NUM	\
809     ? /* only floating-point arguments so far */			\
810       (LIST)->darg[(LIST)->fanum - 1]					\
811     : *(double*)((LIST)->aptr - sizeof(double))				\
812   ))
813 #endif
814 #if defined(__mipsn32__) || defined(__mips64__) || defined(__x86_64_ms__)
815 /* The first 0,..,8 registers are stored elsewhere if they are floating-point
816  * parameters.
817  */
818 #define _va_arg_float(LIST)  \
819   (__va_align_double(LIST)						\
820    (LIST)->aptr += sizeof(double),					\
821    (++(LIST)->anum <= __VA_FARG_NUM					\
822     ? (LIST)->farg[(LIST)->anum - 1]					\
823     : *(float*)((LIST)->aptr - sizeof(double))				\
824   ))
825 #define _va_arg_double(LIST)  \
826   (__va_align_double(LIST)						\
827    (LIST)->aptr += sizeof(double),					\
828    (++(LIST)->anum <= __VA_FARG_NUM					\
829     ? (LIST)->darg[(LIST)->anum - 1]					\
830     : *(double*)((LIST)->aptr - sizeof(double))				\
831   ))
832 #endif
833 #if defined(__sparc64__)
834 /* The first 0,..,16 registers are stored elsewhere if they are floating-point
835  * parameters.
836  */
837 #define _va_arg_float(LIST)  \
838   (__va_align_double(LIST)						\
839    (LIST)->aptr += sizeof(double),					\
840    (++(LIST)->anum <= 16						\
841     ? (LIST)->farg[(LIST)->anum - 1]					\
842     : *(float*)((LIST)->aptr - sizeof(float))				\
843   ))
844 #define _va_arg_double(LIST)  \
845   (__va_align_double(LIST)						\
846    (LIST)->aptr += sizeof(double),					\
847    (++(LIST)->anum <= 16						\
848     ? (LIST)->darg[(LIST)->anum - 1]					\
849     : *(double*)((LIST)->aptr - sizeof(double))				\
850   ))
851 #endif
852 #if defined(__hppa64__)
853 /* The floating-point arguments among the first 8 argument words have been
854    stored elsewhere. */
855 #define _va_arg_float(LIST)  \
856   ((LIST)->aptr += sizeof(double),					\
857    ((LIST)->aptr <= (LIST)->memargptr					\
858     ? (LIST)->farg[__VA_FARG_NUM-1-((LIST)->memargptr - (LIST)->aptr)/sizeof(__vaword)] \
859     : ((float*)(LIST)->aptr)[-1]					\
860   ))
861 #define _va_arg_double(LIST)  \
862   ((LIST)->aptr += sizeof(double),					\
863    ((LIST)->aptr <= (LIST)->memargptr					\
864     ? (LIST)->darg[__VA_FARG_NUM-1-((LIST)->memargptr - (LIST)->aptr)/sizeof(__vaword)] \
865     : ((double*)(LIST)->aptr)[-1]					\
866   ))
867 #endif
868 #if defined(__armhf__)
869 #define _va_arg_float(LIST)  \
870   ((LIST)->fanum <= 15							\
871    ? (LIST)->farg[(LIST)->fanum++]					\
872    : ((LIST)->aptr += sizeof(float),					\
873       *(float*)((LIST)->aptr - sizeof(float))				\
874   )  )
875 #define _va_arg_double(LIST)  \
876   (((LIST)->fanum % 2 ? (LIST)->fanum++ : 0),				\
877    ((LIST)->fanum <= 14							\
878     ? ((LIST)->fanum += 2, (LIST)->darg[(LIST)->fanum / 2 - 1])		\
879     : ((LIST)->aptr += sizeof(double),					\
880        *(double*)((LIST)->aptr - sizeof(double))			\
881   ))  )
882 #endif
883 #if defined(__arm64__)
884 /* The first __VA_FARG_NUM floating-point args have been stored elsewhere. */
885 #define _va_arg_float(LIST)  \
886   ((LIST)->fanum < __VA_FARG_NUM					\
887    ? (LIST)->farg[(LIST)->fanum++]					\
888    : ((LIST)->aptr += sizeof(__vaword),					\
889       *(float*)((LIST)->aptr - sizeof(__vaword))			\
890   )  )
891 #define _va_arg_double(LIST)  \
892   ((LIST)->fanum < __VA_FARG_NUM					\
893    ? (LIST)->darg[(LIST)->fanum++]					\
894    : ((LIST)->aptr += sizeof(double),					\
895       *(double*)((LIST)->aptr - sizeof(double))				\
896   )  )
897 #endif
898 #if defined(__powerpc_aix__)
899 /* The first __VA_FARG_NUM floating-point args have been stored elsewhere. */
900 #define _va_arg_float(LIST)  \
901   ((LIST)->aptr += sizeof(float),					\
902    ((LIST)->fanum < __VA_FARG_NUM					\
903     ? (float) (LIST)->farg[(LIST)->fanum++]				\
904     : *(float*)((LIST)->aptr - sizeof(float))				\
905   ))
906 #define _va_arg_double(LIST)  \
907   (__va_align_double(LIST)						\
908    (LIST)->aptr += sizeof(double),					\
909    ((LIST)->fanum < __VA_FARG_NUM					\
910     ? (LIST)->farg[(LIST)->fanum++]					\
911     : *(double*)((LIST)->aptr - sizeof(double))				\
912   ))
913 #endif
914 #if defined(__powerpc_sysv4__)
915 /* The first __VA_FARG_NUM floating-point args have been stored elsewhere. */
916 #define _va_arg_float(LIST)  \
917   ((LIST)->fanum < __VA_FARG_NUM					\
918    ? (float) (LIST)->farg[(LIST)->fanum++]				\
919    : ((LIST)->aptr += sizeof(float),					\
920       *(float*)((LIST)->aptr - sizeof(float))				\
921   )  )
922 #define _va_arg_double(LIST)  \
923   ((LIST)->fanum < __VA_FARG_NUM					\
924    ? (LIST)->farg[(LIST)->fanum++]					\
925    : (__va_align_double(LIST)						\
926       (LIST)->aptr += sizeof(double),					\
927       *(double*)((LIST)->aptr - sizeof(double))				\
928   )  )
929 #endif
930 #if defined(__powerpc64__)
931 /* The first __VA_FARG_NUM floating-point args have been stored elsewhere. */
932 #if defined(_AIX)
933 #define _va_arg_float(LIST)  \
934   ((LIST)->aptr += sizeof(__vaword),					\
935    ((LIST)->fanum < __VA_FARG_NUM					\
936     ? (float) (LIST)->farg[(LIST)->fanum++]				\
937     : ((float*)(LIST)->aptr)[(LIST)->flags & __VA_AIXCC_FLOAT_ARGS ? -2 : -1] \
938   ))
939 #elif defined(_LITTLE_ENDIAN)
940 #define _va_arg_float(LIST)  \
941   ((LIST)->aptr += sizeof(__vaword),					\
942    ((LIST)->fanum < __VA_FARG_NUM					\
943     ? (float) (LIST)->farg[(LIST)->fanum++]				\
944     : ((float*)(LIST)->aptr)[-2]					\
945   ))
946 #else /* _BIG_ENDIAN */
947 #define _va_arg_float(LIST)  \
948   ((LIST)->aptr += sizeof(__vaword),					\
949    ((LIST)->fanum < __VA_FARG_NUM					\
950     ? (float) (LIST)->farg[(LIST)->fanum++]				\
951     : ((float*)(LIST)->aptr)[-1]					\
952   ))
953 #endif
954 #define _va_arg_double(LIST)  \
955   (__va_align_double(LIST)						\
956    (LIST)->aptr += sizeof(double),					\
957    ((LIST)->fanum < __VA_FARG_NUM					\
958     ? (LIST)->farg[(LIST)->fanum++]					\
959     : *(double*)((LIST)->aptr - sizeof(double))				\
960   ))
961 #endif
962 #if defined(__ia64__)
963 /* The first 8 floating-point args have been stored elsewhere. */
964 #define _va_arg_float(LIST)  \
965   ((LIST)->aptr += sizeof(__vaword),					\
966    ((LIST)->fanum < __VA_FARG_NUM					\
967     ? (float) (LIST)->farg[(LIST)->fanum++]				\
968     : *(float*)((LIST)->aptr - sizeof(__vaword))			\
969   ))
970 #define _va_arg_double(LIST)  \
971   (__va_align_double(LIST)						\
972    (LIST)->aptr += sizeof(double),					\
973    ((LIST)->fanum < __VA_FARG_NUM					\
974     ? (LIST)->farg[(LIST)->fanum++]					\
975     : *(double*)((LIST)->aptr - sizeof(double))				\
976   ))
977 #endif
978 #if defined(__x86_64_sysv__)
979 /* The first 8 floating-point args have been stored elsewhere. */
980 #define _va_arg_float(LIST)  \
981   ((LIST)->fanum < __VA_FARG_NUM					\
982    ? *(float*)&(LIST)->farg[(LIST)->fanum++]				\
983    : ((LIST)->aptr += sizeof(__vaword),					\
984       *(float*)((LIST)->aptr - sizeof(__vaword))			\
985   )  )
986 #define _va_arg_double(LIST)  \
987   ((LIST)->fanum < __VA_FARG_NUM					\
988    ? (LIST)->farg[(LIST)->fanum++]					\
989    : ((LIST)->aptr += sizeof(__vaword),					\
990       *(double*)((LIST)->aptr - sizeof(__vaword))			\
991   )  )
992 #endif
993 #if defined(__s390__) || defined(__s390x__)
994 /* The first __VA_FARG_NUM floating-point args have been stored elsewhere. */
995 #define _va_arg_float(LIST)  \
996   ((LIST)->fanum < __VA_FARG_NUM					\
997    ? (LIST)->farg[(LIST)->fanum++]					\
998    : ((LIST)->aptr += sizeof(__vaword),					\
999       ((float*)(LIST)->aptr)[-1]					\
1000   )  )
1001 #define _va_arg_double(LIST)  \
1002   ((LIST)->fanum < __VA_FARG_NUM					\
1003    ? (LIST)->darg[(LIST)->fanum++]					\
1004    : ((LIST)->aptr += sizeof(double),					\
1005       *(double*)((LIST)->aptr - sizeof(double))				\
1006   )  )
1007 #endif
1008 #if defined(__riscv32__) || defined(__riscv64__)
1009 /* The first __VA_FARG_NUM floating-point args have been stored elsewhere. */
1010 #define _va_arg_float(LIST)  \
1011   ((LIST)->fanum < __VA_FARG_NUM					\
1012    ? (LIST)->farg[(LIST)->fanum++]					\
1013    : __va_arg((LIST),float)						\
1014   )
1015 #define _va_arg_double(LIST)  \
1016   ((LIST)->fanum < __VA_FARG_NUM					\
1017    ? (LIST)->darg[(LIST)->fanum++]					\
1018    : __va_arg((LIST),double)						\
1019   )
1020 #endif
1021 #ifndef _va_arg_float
1022 #define _va_arg_float(LIST)	__va_arg(LIST,float)
1023 #endif
1024 #ifndef _va_arg_double
1025 #define _va_arg_double(LIST)  \
1026   (__va_align_double(LIST) __va_arg(LIST,double))
1027 #endif
1028 
1029 /* Pointer arguments. */
1030 #define _va_arg_ptr(LIST)	__va_arg(LIST,void*)
1031 
1032 /* Structure arguments. */
1033 /* Structure argument alignment. */
1034 #if defined(__i386__) && defined(_MSC_VER)
1035 /* In MSVC, doubles inside structures have alignment 8, i.e.
1036  * __VA_alignof(double) = 8, but doubles (and also structures containing
1037  * doubles) are passed on the stack with alignment 4. Looks really weird.
1038  */
1039 #define __va_struct_alignment(TYPE_ALIGN)  \
1040   ((TYPE_ALIGN) <= 4 ? (TYPE_ALIGN) : 4)
1041 #else
1042 #define __va_struct_alignment(TYPE_ALIGN)  \
1043   (TYPE_ALIGN)
1044 #endif
1045 #define __va_align_struct(LIST,TYPE_SIZE,TYPE_ALIGN)  \
1046   (LIST)->aptr = ((LIST)->aptr + __va_struct_alignment(TYPE_ALIGN)-1) & -(intptr_t)__va_struct_alignment(TYPE_ALIGN),
1047 #if defined(__i386__) || defined(__m68k__) || defined(__alpha__) || defined(__arm__) || defined(__armhf__) || (defined(__powerpc64__) && !defined(_AIX)) || defined(__x86_64_sysv__)
1048 #define __va_arg_struct(LIST,TYPE_SIZE,TYPE_ALIGN)  \
1049   (__va_align_struct(LIST,TYPE_SIZE,TYPE_ALIGN)				\
1050    __va_arg_adjusted(LIST,TYPE_SIZE,TYPE_ALIGN)				\
1051   )
1052 #endif
1053 #if defined(__mips__) && !defined(__mipsn32__) && !defined(__mips64__)
1054 /* small structures < 1 word are adjusted depending on compiler */
1055 #define __va_arg_struct(LIST,TYPE_SIZE,TYPE_ALIGN)  \
1056   (__va_align_struct(LIST,TYPE_SIZE,TYPE_ALIGN)				\
1057    ((LIST)->flags & __VA_SGICC_STRUCT_ARGS				\
1058     ? /* SGI MIPS cc passes small structures left-adjusted, although big-endian! */\
1059       (void*)__va_arg_leftadjusted(LIST,TYPE_SIZE,TYPE_ALIGN)		\
1060     : /* SGI MIPS gcc passes small structures within the first four words left-	   \
1061        * adjusted, for compatibility with cc. But structures in memory are passed  \
1062        * right-adjusted!! See gcc-2.6.3/config/mips/mips.c:function_arg().	   \
1063        */									   \
1064       ((LIST)->aptr < (LIST)->memargptr					\
1065        ? (void*)__va_arg_leftadjusted(LIST,TYPE_SIZE,TYPE_ALIGN)	\
1066        : (void*)__va_arg_rightadjusted(LIST,TYPE_SIZE,TYPE_ALIGN)	\
1067   ))  )
1068 #endif
1069 #if defined(__mipsn32__) || defined(__mips64__)
1070 /* small structures < 1 word are adjusted depending on compiler */
1071 #define __va_arg_struct(LIST,TYPE_SIZE,TYPE_ALIGN)  \
1072   (__va_align_struct(LIST,TYPE_SIZE,TYPE_ALIGN)				\
1073    ((LIST)->flags & __VA_SGICC_STRUCT_ARGS				\
1074     ? /* SGI MIPS cc and gcc >= 3.4 passes small structures left-adjusted, although big-endian! */\
1075       (void*)__va_arg_leftadjusted(LIST,TYPE_SIZE,TYPE_ALIGN)		\
1076     : /* SGI MIPS gcc < 3.4 passes small structures right-adjusted. */	\
1077       (void*)__va_arg_rightadjusted(LIST,TYPE_SIZE,TYPE_ALIGN)		\
1078   ))
1079 #endif
1080 #if defined(__powerpc_aix__) || (defined(__powerpc64__) && defined(_AIX))
1081 /* small structures < 1 word are adjusted depending on compiler */
1082 #define __va_arg_struct(LIST,TYPE_SIZE,TYPE_ALIGN)  \
1083   (__va_align_struct(LIST,TYPE_SIZE,TYPE_ALIGN)				\
1084    ((LIST)->flags & __VA_AIXCC_STRUCT_ARGS				\
1085     ? /* AIX cc and xlc pass small structures left-adjusted, although big-endian! */\
1086       (void*)__va_arg_leftadjusted(LIST,TYPE_SIZE,TYPE_ALIGN)		\
1087     : /* gcc passes small structures right-adjusted. */			\
1088       (void*)__va_arg_rightadjusted(LIST,TYPE_SIZE,TYPE_ALIGN)		\
1089   ))
1090 #endif
1091 #if defined(__powerpc_sysv4__)
1092 /* Structures are passed as pointers to caller-made local copies. */
1093 #define __va_arg_struct(LIST,TYPE_SIZE,TYPE_ALIGN)  \
1094   va_arg_ptr(LIST,void*)
1095 #endif
1096 #if defined(__sparc__) && !defined(__sparc64__)
1097 /* Structures are passed as pointers to caller-made local copies. */
1098 #define __va_arg_struct(LIST,TYPE_SIZE,TYPE_ALIGN)  \
1099   va_arg_ptr(LIST,void*)
1100 #endif
1101 #if defined(__sparc64__)
1102 /* Small structures are passed left-adjusted, although big-endian! */
1103 /* Big structures are passed as pointers to caller-made local copies. */
1104 #define __va_arg_struct(LIST,TYPE_SIZE,TYPE_ALIGN)  \
1105   ((TYPE_SIZE) <= 16							\
1106    ? (__va_align_struct(LIST,TYPE_SIZE,TYPE_ALIGN)			\
1107       (void*)__va_arg_leftadjusted(LIST,TYPE_SIZE,TYPE_ALIGN))		\
1108    : va_arg_ptr(LIST,void*)						\
1109   )
1110 #endif
1111 #if defined(__hppa64__)
1112 /* Structures are passed left-adjusted (although big-endian!). */
1113 #define __va_arg_struct(LIST,TYPE_SIZE,TYPE_ALIGN)  \
1114   (__va_align_struct(LIST,TYPE_SIZE,TYPE_ALIGN)				\
1115    (void*)__va_arg_leftadjusted(LIST,TYPE_SIZE,TYPE_ALIGN)		\
1116   )
1117 #endif
1118 #if defined(__arm64__) || defined(__riscv32__) || defined(__riscv64__)
1119 /* Small structures are passed in registers or on the stack. */
1120 /* Big structures are passed as pointers to caller-made local copies. */
1121 #define __va_arg_struct(LIST,TYPE_SIZE,TYPE_ALIGN)  \
1122   ((TYPE_SIZE) <= 2*sizeof(__varword)					\
1123    ? (void*)__va_arg_adjusted(LIST,TYPE_SIZE,TYPE_ALIGN)		\
1124    : va_arg_ptr(LIST,void*)						\
1125   )
1126 #endif
1127 #if defined(__x86_64_ms__) || defined(__s390__) || defined(__s390x__)
1128 /* Structures of 1, 2, 4, 8 bytes are passed as embedded copies on the arg stack.
1129  * Big structures are passed as pointers to caller-made local copies.
1130  */
1131 #define __va_arg_struct(LIST,TYPE_SIZE,TYPE_ALIGN)  \
1132   ((TYPE_SIZE) == 1 || (TYPE_SIZE) == 2 || (TYPE_SIZE) == 4 || (TYPE_SIZE) == 8 \
1133    ? (void*)__va_arg_adjusted(LIST,TYPE_SIZE,TYPE_ALIGN)		\
1134    : va_arg_ptr(LIST,void*)						\
1135   )
1136 #endif
1137 #if defined(__hppa__) && !defined(__hppa64__)
1138 /* Structures <= 8 bytes are passed as embedded copies on the arg stack.
1139  * Big structures are passed as pointers (to caller-made local copies
1140  * with GCC >= 8, without copy otherwise).
1141  */
1142 #define __va_arg_struct(LIST,TYPE_SIZE,TYPE_ALIGN)  \
1143   ((TYPE_SIZE) > 8							\
1144    ? va_arg_ptr(LIST,void*)						\
1145    : /* FIXME: gcc-2.6.3 passes structures <= 4 bytes in memory left-adjusted! ?? */\
1146      (void*)__va_arg_rightadjusted(LIST,TYPE_SIZE,TYPE_ALIGN)		\
1147   )
1148 #endif
1149 #if defined(__ia64__)
1150 /* With GCC < 3, types larger than a word have 2-word alignment. */
1151 #define __va_arg_struct(LIST,TYPE_SIZE,TYPE_ALIGN)  \
1152   (__va_align_struct(LIST,TYPE_SIZE,TYPE_ALIGN)				\
1153    (((LIST)->flags & __VA_OLDGCC_STRUCT_ARGS) && (TYPE_SIZE) > sizeof(__vaword) && (((__vaword*)(LIST)->aptr - (LIST)->saptr) & 1) ? (LIST)->aptr += sizeof(__vaword) : 0), \
1154    __va_arg_adjusted(LIST,TYPE_SIZE,TYPE_ALIGN)				\
1155   )
1156 #endif
1157 
1158 
1159 /*
1160  * Definition of the va_return_xxx macros.
1161  */
1162 #define __va_return(LIST,RETTYPE)  \
1163   (((LIST)->rtype == (RETTYPE)) || (vacall_error_type_mismatch((LIST)->rtype,RETTYPE), 0))
1164 #define _va_return_void(LIST)  \
1165   __va_return(LIST,__VAvoid)
1166 #define _va_return_char(LIST,VAL)  \
1167   (__va_return(LIST,__VAchar), (LIST)->tmp._char = (VAL))
1168 #define _va_return_schar(LIST,VAL)  \
1169   (__va_return(LIST,__VAschar), (LIST)->tmp._schar = (VAL))
1170 #define _va_return_uchar(LIST,VAL)  \
1171   (__va_return(LIST,__VAuchar), (LIST)->tmp._uchar = (VAL))
1172 #define _va_return_short(LIST,VAL)  \
1173   (__va_return(LIST,__VAshort), (LIST)->tmp._short = (VAL))
1174 #define _va_return_ushort(LIST,VAL)  \
1175   (__va_return(LIST,__VAushort), (LIST)->tmp._ushort = (VAL))
1176 #define _va_return_int(LIST,VAL)  \
1177   (__va_return(LIST,__VAint), (LIST)->tmp._int = (VAL))
1178 #define _va_return_uint(LIST,VAL)  \
1179   (__va_return(LIST,__VAuint), (LIST)->tmp._uint = (VAL))
1180 #define _va_return_long(LIST,VAL)  \
1181   (__va_return(LIST,__VAlong), (LIST)->tmp._long = (VAL))
1182 #define _va_return_ulong(LIST,VAL)  \
1183   (__va_return(LIST,__VAulong), (LIST)->tmp._ulong = (VAL))
1184 #if defined(__mips64__) || defined(__sparc64__) || defined(__alpha__) || defined(__hppa64__) || defined(__arm64__) || defined(__powerpc64__) || defined(__ia64__) || (defined(__x86_64__) && !defined(__x86_64_x32__) && !defined(__VA_LLP64)) || defined(__riscv64__)
1185 #define _va_return_longlong(LIST,VAL)  \
1186   (__va_return(LIST,__VAlonglong), (LIST)->tmp._long = (VAL))
1187 #define _va_return_ulonglong(LIST,VAL)  \
1188   (__va_return(LIST,__VAulonglong), (LIST)->tmp._ulong = (VAL))
1189 #else
1190 #define _va_return_longlong(LIST,VAL)  \
1191   (__va_return(LIST,__VAlonglong), (LIST)->tmp._longlong = (VAL))
1192 #define _va_return_ulonglong(LIST,VAL)  \
1193   (__va_return(LIST,__VAulonglong), (LIST)->tmp._ulonglong = (VAL))
1194 #endif
1195 #define _va_return_float(LIST,VAL)  \
1196   (__va_return(LIST,__VAfloat), (LIST)->tmp._float = (VAL))
1197 #define _va_return_double(LIST,VAL)  \
1198   (__va_return(LIST,__VAdouble), (LIST)->tmp._double = (VAL))
1199 #define _va_return_ptr(LIST,VAL)  \
1200   (__va_return(LIST,__VAvoidp), (LIST)->tmp._ptr = (VAL))
1201 #define __va_return_struct(LIST,TYPE_SIZE,TYPE_ALIGN,VAL_ADDR)  \
1202   (__va_return(LIST,__VAstruct),					\
1203    vacall_structcpy((void*)((LIST)->raddr),VAL_ADDR,TYPE_SIZE,TYPE_ALIGN) \
1204   )
1205 
1206 
1207 /*
1208  * Miscellaneous declarations.
1209  */
1210 extern void vacall_structcpy (void* dest, const void* src, unsigned long size, unsigned long alignment);
1211 
1212 
1213 #endif /* _VACALL_INTERNAL_H */
1214