1/* The ! __SH3E_VARG case is similar to the default gvarargs.h . */ 2 3#if (defined (__SH3E__) || defined (__SH4_SINGLE__) || defined (__SH4__) || defined (__SH4_SINGLE_ONLY__)) && ! defined (__HITACHI__) 4#define __SH3E_VARG 5#endif 6 7/* Define __gnuc_va_list. */ 8 9#ifndef __GNUC_VA_LIST 10#define __GNUC_VA_LIST 11 12#ifdef __SH3E_VARG 13 14typedef long __va_greg; 15typedef float __va_freg; 16 17typedef struct { 18 __va_greg * __va_next_o; /* next available register */ 19 __va_greg * __va_next_o_limit; /* past last available register */ 20 __va_freg * __va_next_fp; /* next available fp register */ 21 __va_freg * __va_next_fp_limit; /* last available fp register */ 22 __va_greg * __va_next_stack; /* next extended word on stack */ 23} __gnuc_va_list; 24 25#else /* ! SH3E */ 26 27typedef void *__gnuc_va_list; 28 29#endif /* ! SH3E */ 30 31#endif /* __GNUC_VA_LIST */ 32 33/* If this is for internal libc use, don't define anything but 34 __gnuc_va_list. */ 35#if defined (_STDARG_H) || defined (_VARARGS_H) 36 37#ifdef _STDARG_H 38 39#ifdef __SH3E_VARG 40 41#define va_start(AP, LASTARG) \ 42__extension__ \ 43 ({ \ 44 (AP).__va_next_fp = (__va_freg *) __builtin_saveregs (); \ 45 (AP).__va_next_fp_limit = ((AP).__va_next_fp + \ 46 (__builtin_args_info (1) < 8 ? 8 - __builtin_args_info (1) : 0)); \ 47 (AP).__va_next_o = (__va_greg *) (AP).__va_next_fp_limit; \ 48 (AP).__va_next_o_limit = ((AP).__va_next_o + \ 49 (__builtin_args_info (0) < 4 ? 4 - __builtin_args_info (0) : 0)); \ 50 (AP).__va_next_stack = (__va_greg *) __builtin_next_arg (LASTARG); \ 51 }) 52 53#else /* ! SH3E */ 54 55#define va_start(AP, LASTARG) \ 56 ((AP) = ((__gnuc_va_list) __builtin_next_arg (LASTARG))) 57 58#endif /* ! SH3E */ 59 60#else /* _VARARGS_H */ 61 62#define va_alist __builtin_va_alist 63#define va_dcl int __builtin_va_alist;... 64 65#ifdef __SH3E_VARG 66 67#define va_start(AP) \ 68__extension__ \ 69 ({ \ 70 (AP).__va_next_fp = (__va_freg *) __builtin_saveregs (); \ 71 (AP).__va_next_fp_limit = ((AP).__va_next_fp + \ 72 (__builtin_args_info (1) < 8 ? 8 - __builtin_args_info (1) : 0)); \ 73 (AP).__va_next_o = (__va_greg *) (AP).__va_next_fp_limit; \ 74 (AP).__va_next_o_limit = ((AP).__va_next_o + \ 75 (__builtin_args_info (0) < 4 ? 4 - __builtin_args_info (0) : 0)); \ 76 (AP).__va_next_stack \ 77 = ((__va_greg *) __builtin_next_arg (__builtin_va_alist) \ 78 - (__builtin_args_info (0) >= 4 || __builtin_args_info (1) >= 8 \ 79 ? 1 : 0)); \ 80 }) 81 82#else /* ! SH3E */ 83 84#define va_start(AP) ((AP) = (char *) &__builtin_va_alist) 85 86#endif /* ! SH3E */ 87 88#endif /* _STDARG */ 89 90#ifndef va_end 91void va_end (__gnuc_va_list); /* Defined in libgcc.a */ 92 93/* Values returned by __builtin_classify_type. */ 94 95enum __va_type_classes { 96 __no_type_class = -1, 97 __void_type_class, 98 __integer_type_class, 99 __char_type_class, 100 __enumeral_type_class, 101 __boolean_type_class, 102 __pointer_type_class, 103 __reference_type_class, 104 __offset_type_class, 105 __real_type_class, 106 __complex_type_class, 107 __function_type_class, 108 __method_type_class, 109 __record_type_class, 110 __union_type_class, 111 __array_type_class, 112 __string_type_class, 113 __set_type_class, 114 __file_type_class, 115 __lang_type_class 116}; 117 118#endif 119#define va_end(pvar) ((void)0) 120 121#ifdef __LITTLE_ENDIAN__ 122#define __LITTLE_ENDIAN_P 1 123#else 124#define __LITTLE_ENDIAN_P 0 125#endif 126 127#define __SCALAR_TYPE(TYPE) \ 128 ((TYPE) == __integer_type_class \ 129 || (TYPE) == __char_type_class \ 130 || (TYPE) == __enumeral_type_class) 131 132/* RECORD_TYPE args passed using the C calling convention are 133 passed by invisible reference. ??? RECORD_TYPE args passed 134 in the stack are made to be word-aligned; for an aggregate that is 135 not word-aligned, we advance the pointer to the first non-reg slot. */ 136 137 /* When this is a smaller-than-int integer, using 138 auto-increment in the promoted (SImode) is fastest; 139 however, there is no way to express that is C. Therefore, 140 we use an asm. 141 We want the MEM_IN_STRUCT_P bit set in the emitted RTL, therefore we 142 use unions even when it would otherwise be unnecessary. */ 143 144/* gcc has an extension that allows to use a casted lvalue as an lvalue, 145 But it doesn't work in C++ with -pedantic - even in the presence of 146 __extension__ . We work around this problem by using a reference type. */ 147#ifdef __cplusplus 148#define __VA_REF & 149#else 150#define __VA_REF 151#endif 152 153#define __va_arg_sh1(AP, TYPE) __extension__ \ 154({(sizeof (TYPE) == 1 \ 155 ? ({union {TYPE t; char c;} __t; \ 156 __asm("" \ 157 : "=r" (__t.c) \ 158 : "0" ((((union { int i, j; } *__VA_REF) (AP))++)->i)); \ 159 __t.t;}) \ 160 : sizeof (TYPE) == 2 \ 161 ? ({union {TYPE t; short s;} __t; \ 162 __asm("" \ 163 : "=r" (__t.s) \ 164 : "0" ((((union { int i, j; } *__VA_REF) (AP))++)->i)); \ 165 __t.t;}) \ 166 : sizeof (TYPE) >= 4 || __LITTLE_ENDIAN_P \ 167 ? (((union { TYPE t; int i;} *__VA_REF) (AP))++)->t \ 168 : ((union {TYPE t;TYPE u;}*) ((char *)++(int *__VA_REF)(AP) - sizeof (TYPE)))->t);}) 169 170#ifdef __SH3E_VARG 171 172#define __PASS_AS_FLOAT(TYPE_CLASS,SIZE) \ 173 (TYPE_CLASS == __real_type_class && SIZE == 4) 174 175#define __TARGET_SH4_P 0 176 177#if defined(__SH4__) || defined(__SH4_SINGLE__) 178#undef __PASS_AS_FLOAT 179#define __PASS_AS_FLOAT(TYPE_CLASS,SIZE) \ 180 (TYPE_CLASS == __real_type_class && SIZE <= 8 \ 181 || TYPE_CLASS == __complex_type_class && SIZE <= 16) 182#undef __TARGET_SH4_P 183#define __TARGET_SH4_P 1 184#endif 185 186#define va_arg(pvar,TYPE) \ 187__extension__ \ 188({int __type = __builtin_classify_type (* (TYPE *) 0); \ 189 void * __result_p; \ 190 if (__PASS_AS_FLOAT (__type, sizeof(TYPE))) \ 191 { \ 192 if ((pvar).__va_next_fp < (pvar).__va_next_fp_limit) \ 193 { \ 194 if (((__type == __real_type_class && sizeof (TYPE) > 4)\ 195 || sizeof (TYPE) > 8) \ 196 && (((int) (pvar).__va_next_fp ^ (int) (pvar).__va_next_fp_limit)\ 197 & 4)) \ 198 (pvar).__va_next_fp++; \ 199 __result_p = &(pvar).__va_next_fp; \ 200 } \ 201 else \ 202 __result_p = &(pvar).__va_next_stack; \ 203 } \ 204 else \ 205 { \ 206 if ((pvar).__va_next_o + ((sizeof (TYPE) + 3) / 4) \ 207 <= (pvar).__va_next_o_limit) \ 208 __result_p = &(pvar).__va_next_o; \ 209 else \ 210 { \ 211 if (sizeof (TYPE) > 4) \ 212 if (! __TARGET_SH4_P) \ 213 (pvar).__va_next_o = (pvar).__va_next_o_limit; \ 214 \ 215 __result_p = &(pvar).__va_next_stack; \ 216 } \ 217 } \ 218 __va_arg_sh1(*(void **)__result_p, TYPE);}) 219 220#else /* ! SH3E */ 221 222#define va_arg(AP, TYPE) __va_arg_sh1((AP), TYPE) 223 224#endif /* SH3E */ 225 226/* Copy __gnuc_va_list into another variable of this type. */ 227#define __va_copy(dest, src) ((dest) = (src)) 228 229#endif /* defined (_STDARG_H) || defined (_VARARGS_H) */ 230