1/* Note:  We must use the name __builtin_savregs.  GCC attaches special
2   significance to that name.  In particular, regardless of where in a
3   function __builtin_saveregs is called, GCC moves the call up to the
4   very start of the function.  */
5
6
7/* Define __gnuc_va_list.  */
8
9#ifndef __GNUC_VA_LIST
10#define __GNUC_VA_LIST
11
12typedef union {
13  float		__freg[8];
14  double	__dreg[4];
15} __f_regs;
16
17typedef struct {
18#if defined (__SVR4__) || defined (__svr4__) || defined (__alliant__) || defined (__PARAGON__)
19  __f_regs __float_regs; long __ireg[12];
20#else /* pre-SVR4 */
21  long __ireg[12]; __f_regs __float_regs;
22#endif
23} __va_saved_regs;
24
25typedef struct {
26#if defined(__SVR4__) || defined(__svr4__) || defined(__alliant__) || defined (__PARAGON__)
27  unsigned	__ireg_used;	/* How many int regs consumed 'til now? */
28  unsigned	__freg_used;	/* How many flt regs consumed 'til now? */
29  long		*__reg_base;	/* Address of where we stored the regs. */
30  long *	__mem_ptr;	/* Address of memory overflow args area. */
31#else /* pre-SVR4 */
32  long		*__reg_base;	/* Address of where we stored the regs. */
33  long *	__mem_ptr;	/* Address of memory overflow args area. */
34  unsigned	__ireg_used;	/* How many int regs consumed 'til now? */
35  unsigned	__freg_used;	/* How many flt regs consumed 'til now? */
36#endif
37} __gnuc_va_list;
38#endif /* not __GNUC_VA_LIST */
39
40/* If this is for internal libc use, don't define anything but
41   __gnuc_va_list.  */
42#if defined (_STDARG_H) || defined (_VARARGS_H)
43
44#if !defined(_STDARG_H)
45
46/* varargs support */
47#define va_alist __builtin_va_alist
48#if defined (__PARAGON__)
49#define va_dcl int va_alist;
50#else	/* __PARAGON__ */
51#define va_dcl
52#endif	/* __PARAGON__ */
53#define va_start(pvar) ((pvar) = * (__gnuc_va_list *) __builtin_saveregs ())
54
55#else /* STDARG.H */
56
57/* ANSI alternative.  */
58/* Note that CUMULATIVE_ARGS elements are measured in bytes on the i860,
59   so we divide by 4 to get # of registers.  */
60#define va_start(pvar, firstarg) \
61 ((pvar) = *(__gnuc_va_list *) __builtin_saveregs (),			\
62  (pvar).__ireg_used = __builtin_args_info (0) / 4,		\
63  (pvar).__freg_used = __builtin_args_info (1) / 4,		\
64  (pvar).__mem_ptr = __builtin_next_arg (firstarg))
65
66#endif /* _STDARG_H */
67
68/* Values returned by __builtin_classify_type.  */
69
70#ifndef va_end
71enum {
72  __no_type_class = -1,
73  __void_type_class,
74  __integer_type_class,
75  __char_type_class,
76  __enumeral_type_class,
77  __boolean_type_class,
78  __pointer_type_class,
79  __reference_type_class,
80  __offset_type_class,
81  __real_type_class,
82  __complex_type_class,
83  __function_type_class,
84  __method_type_class,
85  __record_type_class,
86  __union_type_class,
87  __array_type_class,
88  __string_type_class,
89  __set_type_class,
90  __file_type_class,
91  __lang_type_class
92};
93
94void va_end (__gnuc_va_list);		/* Defined in libgcc.a */
95#endif
96#define va_end(__va)	((void) 0)
97
98#define __NUM_PARM_FREGS	8
99#define __NUM_PARM_IREGS	12
100
101#define __savereg(__va) ((__va_saved_regs *) ((__va).__reg_base))
102
103/* This macro works both for SVR4 and pre-SVR4 environments.  */
104
105/* Note that parameters are always aligned at least to a word boundary
106   (when passed) regardless of what GCC's __alignof__ operator says.  */
107
108/* Make allowances here for adding 128-bit (long double) floats someday.  */
109
110#if 0 /* What was this for? */
111#ifndef __GNU_VA_LIST
112#define __ireg_used ireg_used
113#define __freg_used freg_used
114#define __mem_ptr mem_ptr
115#define __reg_base reg_base
116#endif
117#endif /* 0 */
118
119/* Avoid errors if compiling GCC v2 with GCC v1.  */
120#if __GNUC__ == 1
121#define __extension__
122#endif
123
124#define va_arg(__va, __type)						\
125__extension__								\
126(* (__type *)								\
127({									\
128  register void *__rv;  /* result value */				\
129  register unsigned __align;						\
130  switch (__builtin_classify_type (* (__type *) 0))			\
131    {									\
132    case __real_type_class:						\
133      switch (sizeof (__type))						\
134	{								\
135	  case sizeof (float):						\
136	  case sizeof (double):						\
137	    if ((__va).__freg_used < __NUM_PARM_FREGS - 1)		\
138	      {								\
139	        if (((__va).__freg_used & 1) != 0)			\
140	          (__va).__freg_used++;	/* skip odd */			\
141	        __rv = &__savereg((__va))->__float_regs.__freg[(__va).__freg_used];\
142		(__va).__freg_used += 2;				\
143	      }								\
144	    else							\
145	      {								\
146	        if ((((unsigned) (__va).__mem_ptr) & (sizeof(double)-1)) != 0) \
147	          (__va).__mem_ptr++;	/* skip odd */			\
148	        __rv = (__va).__mem_ptr;				\
149	        (__va).__mem_ptr += 2;					\
150	      }								\
151	    if (sizeof (__type) == sizeof (float))			\
152	      {								\
153	        *((float *) __rv) = *((double *) __rv);			\
154		*(((long *) __rv) + 1) = 0xfff00001;			\
155	      }								\
156	    break;							\
157	  default:							\
158	    abort ();							\
159	}								\
160      break;								\
161    case __void_type_class:						\
162    case __integer_type_class:						\
163    case __char_type_class:						\
164    case __enumeral_type_class:						\
165    case __boolean_type_class:						\
166    case __pointer_type_class:						\
167    case __reference_type_class:					\
168    case __offset_type_class:						\
169      if (sizeof (__type) <= 4)						\
170	{								\
171          __rv = ((__va).__ireg_used < __NUM_PARM_IREGS			\
172	          ? (&__savereg((__va))->__ireg[(__va).__ireg_used++])	\
173	          : (__va).__mem_ptr++);				\
174	  break;							\
175	}								\
176      else if ((__va).__ireg_used + sizeof (__type) / 4 <= __NUM_PARM_IREGS) \
177	{								\
178	  __rv = &__savereg((__va))->__ireg[(__va).__ireg_used];	\
179	  (__va).__ireg_used += sizeof (__type) / 4;			\
180          break;							\
181	}								\
182      /* Fall through to fetch from memory.  */				\
183    case __record_type_class:						\
184    case __union_type_class:						\
185      __align = (__alignof__ (__type) < sizeof (long)			\
186		 ? sizeof (long)					\
187		 : __alignof__ (__type));				\
188      (__va).__mem_ptr							\
189	= (long *)							\
190	  ((((unsigned) (__va).__mem_ptr) + (__align-1)) & ~(__align-1)); \
191      __rv = (__va).__mem_ptr;						\
192      (__va).__mem_ptr							\
193	+= ((sizeof (__type) + sizeof (long) - 1) / sizeof (long));	\
194      break;								\
195    case __complex_type_class:						\
196    case __function_type_class:						\
197    case __method_type_class:						\
198    case __array_type_class:						\
199    case __string_type_class:						\
200    case __set_type_class:						\
201    case __file_type_class:						\
202    case __lang_type_class:						\
203    case __no_type_class:						\
204    default:								\
205	abort ();							\
206    }									\
207  __rv;									\
208}))
209
210/* Copy __gnuc_va_list into another variable of this type.  */
211#define __va_copy(dest, src) (dest) = (src)
212
213#endif /* defined (_STDARG_H) || defined (_VARARGS_H) */
214
215