1/* stdarg/varargs support for the ARC */
2
3/* Define __gnuc_va_list.  */
4
5#ifndef __GNUC_VA_LIST
6#define __GNUC_VA_LIST
7typedef void * __gnuc_va_list;
8#endif /* not __GNUC_VA_LIST */
9
10/* If this is for internal libc use, don't define anything but
11   __gnuc_va_list.  */
12#if defined (_STDARG_H) || defined (_VARARGS_H)
13
14/* In GCC version 2, we want an ellipsis at the end of the declaration
15   of the argument list.  GCC version 1 can't parse it.  */
16
17#if __GNUC__ > 1
18#define __va_ellipsis ...
19#else
20#define __va_ellipsis
21#endif
22
23/* See arc_setup_incoming_varargs for reasons for the oddity in va_start.  */
24#ifdef _STDARG_H
25#define va_start(AP, LASTARG) \
26(AP = (__gnuc_va_list) ((int *) __builtin_next_arg (LASTARG) \
27			+ (__builtin_args_info (0) < 8 \
28			   ? (__builtin_args_info (0) & 1) \
29			   : 0)))
30#else
31#define va_alist  __builtin_va_alist
32#define va_dcl    int __builtin_va_alist; __va_ellipsis
33#define va_start(AP) \
34(AP = (__gnuc_va_list) ((int *) &__builtin_va_alist \
35			+ (__builtin_args_info (0) < 8 \
36			   ? (__builtin_args_info (0) & 1) \
37			   : 0)))
38#endif
39
40#ifndef va_end
41void va_end (__gnuc_va_list);		/* Defined in libgcc.a */
42
43/* Values returned by __builtin_classify_type.  */
44
45enum __va_type_classes {
46  __no_type_class = -1,
47  __void_type_class,
48  __integer_type_class,
49  __char_type_class,
50  __enumeral_type_class,
51  __boolean_type_class,
52  __pointer_type_class,
53  __reference_type_class,
54  __offset_type_class,
55  __real_type_class,
56  __complex_type_class,
57  __function_type_class,
58  __method_type_class,
59  __record_type_class,
60  __union_type_class,
61  __array_type_class,
62  __string_type_class,
63  __set_type_class,
64  __file_type_class,
65  __lang_type_class
66};
67
68#endif
69#define va_end(AP)	((void)0)
70
71/* Avoid errors if compiling GCC v2 with GCC v1.  */
72#if __GNUC__ == 1
73#define __extension__
74#endif
75
76/* All aggregates are passed by reference.  All scalar types larger than 8
77   bytes are passed by reference.  */
78/* We cast to void * and then to TYPE * because this avoids
79   a warning about increasing the alignment requirement.
80   The casts to char * avoid warnings about invalid pointer arithmetic.  */
81
82#define __va_rounded_size(TYPE)  \
83  (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int))
84
85#ifdef __big_endian__
86#define va_arg(AP,TYPE) \
87__extension__							\
88(*({((__builtin_classify_type (*(TYPE*) 0) >= __record_type_class \
89      || __va_rounded_size (TYPE) > 8)				\
90     ? ((AP) = (char *)(AP) + __va_rounded_size (TYPE *),	\
91	*(TYPE **) (void *) ((char *)(AP) - __va_rounded_size (TYPE *))) \
92     : ((TYPE *) (void *)					\
93	(AP = (void *) ((__alignof__ (TYPE) > 4			\
94			 ? ((int) AP + 8 - 1) & -8		\
95			 : (int) AP)				\
96			 + __va_rounded_size (TYPE))) - 1));}))
97#else
98#define va_arg(AP,TYPE) \
99__extension__							\
100(*({((__builtin_classify_type (*(TYPE*) 0) >= __record_type_class \
101      || __va_rounded_size (TYPE) > 8)				\
102     ? ((AP) = (char *)(AP) + __va_rounded_size (TYPE *),	\
103	*(TYPE **) (void *) ((char *)(AP) - __va_rounded_size (TYPE *))) \
104     : ((AP = (void *) ((__alignof__ (TYPE) > 4			\
105			? ((int) AP + 8 - 1) & -8		\
106			: (int) AP)				\
107		       + __va_rounded_size (TYPE))),		\
108	(TYPE *) (void *) (AP - __va_rounded_size (TYPE))));}))
109#endif
110
111#endif /* defined (_STDARG_H) || defined (_VARARGS_H) */
112