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 14 typedef long __va_greg; 15 typedef float __va_freg; 16 17 typedef 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 27 typedef 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 91 void va_end (__gnuc_va_list); /* Defined in libgcc.a */ 92 93 /* Values returned by __builtin_classify_type. */ 94 95 enum __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