1/* ---------------------------------------- */
2/*           VARARGS  for MIPS/GNU CC       */
3/*                                          */
4/*                                          */
5/*                                          */
6/*                                          */
7/* ---------------------------------------- */
8
9
10/* These macros implement varargs for GNU C--either traditional or ANSI.  */
11
12/* Define __gnuc_va_list.  */
13
14#ifndef __GNUC_VA_LIST
15#define __GNUC_VA_LIST
16#if defined (__mips_eabi) && ! defined (__mips_soft_float) && ! defined (__mips_single_float)
17
18typedef struct {
19  /* Pointer to FP regs.  */
20  char *__fp_regs;
21  /* Number of FP regs remaining.  */
22  int __fp_left;
23  /* Pointer to GP regs followed by stack parameters.  */
24  char *__gp_regs;
25} __gnuc_va_list;
26
27#else /* ! (defined (__mips_eabi) && ! defined (__mips_soft_float) && ! defined (__mips_single_float)) */
28
29typedef char * __gnuc_va_list;
30
31#endif /* ! (defined (__mips_eabi) && ! defined (__mips_soft_float) && ! defined (__mips_single_float)) */
32#endif /* not __GNUC_VA_LIST */
33
34/* If this is for internal libc use, don't define anything but
35   __gnuc_va_list.  */
36#if defined (_STDARG_H) || defined (_VARARGS_H)
37
38#ifndef _VA_MIPS_H_ENUM
39#define _VA_MIPS_H_ENUM
40enum {
41  __no_type_class = -1,
42  __void_type_class,
43  __integer_type_class,
44  __char_type_class,
45  __enumeral_type_class,
46  __boolean_type_class,
47  __pointer_type_class,
48  __reference_type_class,
49  __offset_type_class,
50  __real_type_class,
51  __complex_type_class,
52  __function_type_class,
53  __method_type_class,
54  __record_type_class,
55  __union_type_class,
56  __array_type_class,
57  __string_type_class,
58  __set_type_class,
59  __file_type_class,
60  __lang_type_class
61};
62#endif
63
64/* In GCC version 2, we want an ellipsis at the end of the declaration
65   of the argument list.  GCC version 1 can't parse it.  */
66
67#if __GNUC__ > 1
68#define __va_ellipsis ...
69#else
70#define __va_ellipsis
71#endif
72
73#ifdef __mips64
74#define __va_rounded_size(__TYPE)  \
75  (((sizeof (__TYPE) + 8 - 1) / 8) * 8)
76#else
77#define __va_rounded_size(__TYPE)  \
78  (((sizeof (__TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int))
79#endif
80
81#ifdef __mips64
82#define __va_reg_size 8
83#else
84#define __va_reg_size 4
85#endif
86
87/* Get definitions for _MIPS_SIM_ABI64 etc.  */
88#ifdef _MIPS_SIM
89#include <sgidefs.h>
90#endif
91
92#ifdef _STDARG_H
93#if defined (__mips_eabi)
94#if ! defined (__mips_soft_float) && ! defined (__mips_single_float)
95#ifdef __mips64
96#define va_start(__AP, __LASTARG)					\
97  (__AP.__gp_regs = ((char *) __builtin_next_arg (__LASTARG)		\
98		     - (__builtin_args_info (2) < 8			\
99			? (8 - __builtin_args_info (2)) * __va_reg_size	\
100			: 0)),						\
101   __AP.__fp_left = 8 - __builtin_args_info (3),			\
102   __AP.__fp_regs = __AP.__gp_regs - __AP.__fp_left * __va_reg_size)
103#else /* ! defined (__mips64) */
104#define va_start(__AP, __LASTARG)					\
105  (__AP.__gp_regs = ((char *) __builtin_next_arg (__LASTARG)		\
106		     - (__builtin_args_info (2) < 8			\
107			? (8 - __builtin_args_info (2)) * __va_reg_size	\
108			: 0)),						\
109   __AP.__fp_left = (8 - __builtin_args_info (3)) / 2,			\
110   __AP.__fp_regs = __AP.__gp_regs - __AP.__fp_left * 8,		\
111   __AP.__fp_regs = (char *) ((int) __AP.__fp_regs & -8))
112#endif /* ! defined (__mips64) */
113#else /* ! (! defined (__mips_soft_float) && ! defined (__mips_single_float) ) */
114#define va_start(__AP, __LASTARG)					\
115  (__AP = ((__gnuc_va_list) __builtin_next_arg (__LASTARG)		\
116	   - (__builtin_args_info (2) >= 8 ? 0				\
117	      : (8 - __builtin_args_info (2)) * __va_reg_size)))
118#endif /* ! (! defined (__mips_soft_float) && ! defined (__mips_single_float) ) */
119#else /* ! defined (__mips_eabi) */
120#define va_start(__AP, __LASTARG) \
121  (__AP = (__gnuc_va_list) __builtin_next_arg (__LASTARG))
122#endif /* ! (defined (__mips_eabi) && ! defined (__mips_soft_float) && ! defined (__mips_single_float)) */
123#else /* ! _STDARG_H */
124#define va_alist  __builtin_va_alist
125#ifdef __mips64
126/* This assumes that `long long int' is always a 64 bit type.  */
127#define va_dcl    long long int __builtin_va_alist; __va_ellipsis
128#else
129#define va_dcl    int __builtin_va_alist; __va_ellipsis
130#endif
131#if defined (__mips_eabi)
132#if ! defined (__mips_soft_float) && ! defined (__mips_single_float)
133#ifdef __mips64
134#define va_start(__AP)							\
135  (__AP.__gp_regs = ((char *) __builtin_next_arg ()			\
136		     - (__builtin_args_info (2) < 8			\
137			? (8 - __builtin_args_info (2)) * __va_reg_size	\
138			: __va_reg_size)),				\
139   __AP.__fp_left = 8 - __builtin_args_info (3),			\
140   __AP.__fp_regs = __AP.__gp_regs - __AP.__fp_left * __va_reg_size)
141#else /* ! defined (__mips64) */
142#define va_start(__AP)							\
143  (__AP.__gp_regs = ((char *) __builtin_next_arg ()			\
144		     - (__builtin_args_info (2) < 8			\
145			? (8 - __builtin_args_info (2)) * __va_reg_size	\
146			: __va_reg_size)),				\
147   __AP.__fp_left = (8 - __builtin_args_info (3)) / 2,			\
148   __AP.__fp_regs = __AP.__gp_regs - __AP.__fp_left * 8,		\
149   __AP.__fp_regs = (char *) ((int) __AP.__fp_regs & -8))
150#endif /* ! defined (__mips64) */
151#else /* ! (! defined (__mips_soft_float) && ! defined (__mips_single_float)) */
152#define va_start(__AP)							\
153  (__AP = ((__gnuc_va_list) __builtin_next_arg ()			\
154	   - (__builtin_args_info (2) >= 8 ? __va_reg_size		\
155	      : (8 - __builtin_args_info (2)) * __va_reg_size)))
156#endif /* ! (! defined (__mips_soft_float) && ! defined (__mips_single_float)) */
157/* Need alternate code for _MIPS_SIM_ABI64.  */
158#elif defined(_MIPS_SIM) && (_MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32)
159#define va_start(__AP)							\
160  (__AP = (__gnuc_va_list) __builtin_next_arg ()			\
161   + (__builtin_args_info (2) >= 8 ? -8 : 0))
162#else
163#define va_start(__AP)  __AP = (char *) &__builtin_va_alist
164#endif
165#endif /* ! _STDARG_H */
166
167#ifndef va_end
168void va_end (__gnuc_va_list);		/* Defined in libgcc.a */
169#endif
170#define va_end(__AP)	((void)0)
171
172#if defined (__mips_eabi)
173
174#if ! defined (__mips_soft_float) && ! defined (__mips_single_float)
175#ifdef __mips64
176#define __va_next_addr(__AP, __type)					\
177  ((__builtin_classify_type (*(__type *) 0) == __real_type_class	\
178    && __AP.__fp_left > 0)						\
179   ? (--__AP.__fp_left, (__AP.__fp_regs += 8) - 8)			\
180   : (__AP.__gp_regs += __va_reg_size) - __va_reg_size)
181#else
182#define __va_next_addr(__AP, __type)					\
183  ((__builtin_classify_type (*(__type *) 0) == __real_type_class	\
184    && __AP.__fp_left > 0)						\
185   ? (--__AP.__fp_left, (__AP.__fp_regs += 8) - 8)			\
186   : (((__builtin_classify_type (* (__type *) 0) < __record_type_class	\
187	&& __alignof__ (__type) > 4)					\
188       ? __AP.__gp_regs = (char *) (((int) __AP.__gp_regs + 8 - 1) & -8) \
189       : (char *) 0),							\
190      (__builtin_classify_type (* (__type *) 0) >= __record_type_class	\
191       ? (__AP.__gp_regs += __va_reg_size) - __va_reg_size		\
192       : ((__AP.__gp_regs += __va_rounded_size (__type))		\
193	  - __va_rounded_size (__type)))))
194#endif
195#else /* ! (! defined (__mips_soft_float) && ! defined (__mips_single_float)) */
196#ifdef __mips64
197#define __va_next_addr(__AP, __type)					\
198  ((__AP += __va_reg_size) - __va_reg_size)
199#else
200#define __va_next_addr(__AP, __type)					\
201  (((__builtin_classify_type (* (__type *) 0) < __record_type_class	\
202     && __alignof__ (__type) > 4)					\
203    ? __AP = (char *) (((__PTRDIFF_TYPE__) __AP + 8 - 1) & -8)		\
204    : (char *) 0),							\
205   (__builtin_classify_type (* (__type *) 0) >= __record_type_class	\
206    ? (__AP += __va_reg_size) - __va_reg_size				\
207    : ((__AP += __va_rounded_size (__type))				\
208       - __va_rounded_size (__type))))
209#endif
210#endif /* ! (! defined (__mips_soft_float) && ! defined (__mips_single_float)) */
211
212#ifdef __MIPSEB__
213#define va_arg(__AP, __type)						\
214  ((__va_rounded_size (__type) <= __va_reg_size)			\
215   ? *(__type *) (void *) (__va_next_addr (__AP, __type)		\
216			   + __va_reg_size				\
217			   - sizeof (__type))				\
218   : (__builtin_classify_type (*(__type *) 0) >= __record_type_class	\
219      ? **(__type **) (void *) (__va_next_addr (__AP, __type)		\
220				+ __va_reg_size				\
221				- sizeof (char *))			\
222      : *(__type *) (void *) __va_next_addr (__AP, __type)))
223#else
224#define va_arg(__AP, __type)						\
225  ((__va_rounded_size (__type) <= __va_reg_size)			\
226   ? *(__type *) (void *) __va_next_addr (__AP, __type)		\
227   : (__builtin_classify_type (* (__type *) 0) >= __record_type_class	\
228      ? **(__type **) (void *) __va_next_addr (__AP, __type)		\
229      : *(__type *) (void *) __va_next_addr (__AP, __type)))
230#endif
231
232#else /* ! defined (__mips_eabi) */
233
234/* We cast to void * and then to TYPE * because this avoids
235   a warning about increasing the alignment requirement.  */
236/* The __mips64 cases are reversed from the 32 bit cases, because the standard
237   32 bit calling convention left-aligns all parameters smaller than a word,
238   whereas the __mips64 calling convention does not (and hence they are
239   right aligned).  */
240#ifdef __mips64
241#ifdef __MIPSEB__
242#define va_arg(__AP, __type)                                    \
243  ((__type *) (void *) (__AP = (char *)                         \
244                       ((((__PTRDIFF_TYPE__)__AP + 8 - 1) & -8) \
245			   + __va_rounded_size (__type))))[-1]
246#else
247#define va_arg(__AP, __type)                                    \
248  ((__AP = (char *) ((((__PTRDIFF_TYPE__)__AP + 8 - 1) & -8)	\
249		     + __va_rounded_size (__type))),		\
250   *(__type *) (void *) (__AP - __va_rounded_size (__type)))
251#endif
252
253#else /* not __mips64 */
254
255#ifdef __MIPSEB__
256/* For big-endian machines.  */
257#define va_arg(__AP, __type)					\
258  ((__AP = (char *) ((__alignof__ (__type) > 4			\
259		      ? ((__PTRDIFF_TYPE__)__AP + 8 - 1) & -8	\
260		      : ((__PTRDIFF_TYPE__)__AP + 4 - 1) & -4)	\
261		     + __va_rounded_size (__type))),		\
262   *(__type *) (void *) (__AP - __va_rounded_size (__type)))
263#else
264/* For little-endian machines.  */
265#define va_arg(__AP, __type)						    \
266  ((__type *) (void *) (__AP = (char *) ((__alignof__(__type) > 4	    \
267				? ((__PTRDIFF_TYPE__)__AP + 8 - 1) & -8	    \
268				: ((__PTRDIFF_TYPE__)__AP + 4 - 1) & -4)    \
269					 + __va_rounded_size(__type))))[-1]
270#endif
271#endif
272#endif /* ! defined (__mips_eabi)  */
273
274/* Copy __gnuc_va_list into another variable of this type.  */
275#define __va_copy(dest, src) (dest) = (src)
276
277#endif /* defined (_STDARG_H) || defined (_VARARGS_H) */
278