Annotation of sys/arch/powerpc/include/va-ppc.h, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: va-ppc.h,v 1.13 2006/04/09 03:07:53 deraadt Exp $ */
! 2: /* GNU C varargs support for the PowerPC with either the V.4 or Windows NT calling sequences */
! 3:
! 4: #include <sys/cdefs.h>
! 5:
! 6: #ifndef _WIN32
! 7: /* System V.4 support */
! 8: /* Define __gnuc_va_list. */
! 9:
! 10: #ifndef __GNUC_VA_LIST
! 11: #define __GNUC_VA_LIST
! 12:
! 13: #ifndef _SYS_VA_LIST_H
! 14: #define _SYS_VA_LIST_H /* Solaris sys/va_list.h */
! 15:
! 16: /* Solaris decided to rename overflow_arg_area to input_arg_area,
! 17: so handle it via a macro. */
! 18: #define __va_overflow(AP) (AP)->overflow_arg_area
! 19:
! 20: /* Note that the names in this structure are in the user's namespace, but
! 21: that the V.4 abi explicitly states that these names should be used. */
! 22: typedef struct __va_list_tag {
! 23: unsigned char gpr; /* index into the array of 8 GPRs stored in the
! 24: register save area gpr=0 corresponds to r3,
! 25: gpr=1 to r4, etc. */
! 26: unsigned char fpr; /* index into the array of 8 FPRs stored in the
! 27: register save area fpr=0 corresponds to f1,
! 28: fpr=1 to f2, etc. */
! 29: char *overflow_arg_area; /* location on stack that holds the next
! 30: overflow argument */
! 31: char *reg_save_area; /* where r3:r10 and f1:f8, if saved are stored */
! 32: } __gnuc_va_list[1];
! 33:
! 34: #else /* _SYS_VA_LIST */
! 35:
! 36: typedef __va_list __gnuc_va_list;
! 37: #define __va_overflow(AP) (AP)->input_arg_area
! 38:
! 39: #endif /* not _SYS_VA_LIST */
! 40: #endif /* not __GNUC_VA_LIST */
! 41:
! 42: /* If this is for internal libc use, don't define anything but
! 43: __gnuc_va_list. */
! 44: #if defined (_STDARG_H) || defined (_VARARGS_H)
! 45:
! 46: /* Register save area located below the frame pointer */
! 47: #ifndef __VA_PPC_H__
! 48: #define __VA_PPC_H__
! 49: typedef struct {
! 50: long __gp_save[8]; /* save area for GP registers */
! 51: double __fp_save[8]; /* save area for FP registers */
! 52: } __va_regsave_t;
! 53:
! 54: /* Macros to access the register save area */
! 55: /* We cast to void * and then to TYPE * because this avoids
! 56: a warning about increasing the alignment requirement. */
! 57: #define __VA_FP_REGSAVE(AP,OFS,TYPE) \
! 58: ((TYPE *) (void *) (&(((__va_regsave_t *) \
! 59: (AP)->reg_save_area)->__fp_save[OFS])))
! 60:
! 61: #define __VA_GP_REGSAVE(AP,OFS,TYPE) \
! 62: ((TYPE *) (void *) (&(((__va_regsave_t *) \
! 63: (AP)->reg_save_area)->__gp_save[OFS])))
! 64:
! 65: /* Common code for va_start for both varargs and stdarg. We allow all
! 66: the work to be done by __builtin_saveregs. It returns a pointer to
! 67: a va_list that was constructed on the stack; we must simply copy it
! 68: to the user's variable. */
! 69:
! 70: #define __va_start_common(AP, FAKE) \
! 71: __extension__ ({ \
! 72: (AP) = (struct __va_list_tag *)__builtin_alloca(sizeof(__gnuc_va_list)); \
! 73: __builtin_memcpy ((AP), __builtin_saveregs (), sizeof(__gnuc_va_list)); \
! 74: })
! 75:
! 76: #ifdef _STDARG_H /* stdarg.h support */
! 77:
! 78: /* Calling __builtin_next_arg gives the proper error message if LASTARG is
! 79: not indeed the last argument. */
! 80: #ifdef lint
! 81: #define va_start(AP,LASTARG) ((AP) = (AP))
! 82: #else
! 83: #define va_start(AP,LASTARG) \
! 84: (__builtin_next_arg (LASTARG), __va_start_common (AP, 0))
! 85: #endif /* lint */
! 86:
! 87: #else /* varargs.h support */
! 88:
! 89: #define va_start(AP) __va_start_common (AP, 1)
! 90: #define va_alist __va_1st_arg
! 91: #define va_dcl register int va_alist; ...
! 92:
! 93: #endif /* _STDARG_H */
! 94:
! 95: #ifdef _SOFT_FLOAT
! 96: #define __va_float_p(TYPE) 0
! 97: #else
! 98: #define __va_float_p(TYPE) (__builtin_classify_type(*(TYPE *)0) == 8)
! 99: #endif
! 100:
! 101: #define __va_aggregate_p(TYPE) (__builtin_classify_type(*(TYPE *)0) >= 12)
! 102: #define __va_size(TYPE) ((sizeof(TYPE) + sizeof (long) - 1) / sizeof (long))
! 103:
! 104: /* This symbol isn't defined. It is used to flag type promotion violations
! 105: at link time. We can only do this when optimizing. Use __builtin_trap
! 106: instead of abort so that we don't require a prototype for abort.
! 107:
! 108: __builtin_trap stuff is not available on the gcc-2.95 branch, so we just
! 109: avoid calling it for now. */
! 110:
! 111: #ifdef __OPTIMIZE__
! 112: extern void __va_arg_type_violation(void) __attribute__((__noreturn__));
! 113: #else
! 114: #define __va_arg_type_violation()
! 115: #endif
! 116:
! 117: #define va_arg(AP,TYPE) \
! 118: __extension__ (*({ \
! 119: register TYPE *__ptr; \
! 120: \
! 121: if (__va_float_p (TYPE) && sizeof (TYPE) < 16) \
! 122: { \
! 123: unsigned char __fpr = (AP)->fpr; \
! 124: if (__fpr < 8) \
! 125: { \
! 126: __ptr = __VA_FP_REGSAVE (AP, __fpr, TYPE); \
! 127: (AP)->fpr = __fpr + 1; \
! 128: } \
! 129: else if (sizeof (TYPE) == 8) \
! 130: { \
! 131: unsigned long __addr = (unsigned long) (__va_overflow (AP)); \
! 132: __ptr = (TYPE *)((__addr + 7) & -8); \
! 133: __va_overflow (AP) = (char *)(__ptr + 1); \
! 134: } \
! 135: else \
! 136: { \
! 137: /* float is promoted to double. */ \
! 138: __va_arg_type_violation (); \
! 139: } \
! 140: } \
! 141: \
! 142: /* Aggregates and long doubles are passed by reference. */ \
! 143: else if (__va_aggregate_p (TYPE) || __va_float_p (TYPE)) \
! 144: { \
! 145: unsigned char __gpr = (AP)->gpr; \
! 146: if (__gpr < 8) \
! 147: { \
! 148: __ptr = * __VA_GP_REGSAVE (AP, __gpr, TYPE *); \
! 149: (AP)->gpr = __gpr + 1; \
! 150: } \
! 151: else \
! 152: { \
! 153: TYPE **__pptr = (TYPE **) (__va_overflow (AP)); \
! 154: __ptr = * __pptr; \
! 155: __va_overflow (AP) = (char *) (__pptr + 1); \
! 156: } \
! 157: } \
! 158: \
! 159: /* Only integrals remaining. */ \
! 160: else \
! 161: { \
! 162: /* longlong is aligned. */ \
! 163: if (sizeof (TYPE) == 8) \
! 164: { \
! 165: unsigned char __gpr = (AP)->gpr; \
! 166: if (__gpr < 7) \
! 167: { \
! 168: __gpr += __gpr & 1; \
! 169: __ptr = __VA_GP_REGSAVE (AP, __gpr, TYPE); \
! 170: (AP)->gpr = __gpr + 2; \
! 171: } \
! 172: else \
! 173: { \
! 174: unsigned long __addr = (unsigned long) (__va_overflow (AP)); \
! 175: __ptr = (TYPE *)((__addr + 7) & -8); \
! 176: (AP)->gpr = 8; \
! 177: __va_overflow (AP) = (char *)(__ptr + 1); \
! 178: } \
! 179: } \
! 180: else if (sizeof (TYPE) == 4) \
! 181: { \
! 182: unsigned char __gpr = (AP)->gpr; \
! 183: if (__gpr < 8) \
! 184: { \
! 185: __ptr = __VA_GP_REGSAVE (AP, __gpr, TYPE); \
! 186: (AP)->gpr = __gpr + 1; \
! 187: } \
! 188: else \
! 189: { \
! 190: __ptr = (TYPE *) __va_overflow (AP); \
! 191: __va_overflow (AP) = (char *)(__ptr + 1); \
! 192: } \
! 193: } \
! 194: else \
! 195: { \
! 196: /* Everything else was promoted to int. */ \
! 197: __va_arg_type_violation (); \
! 198: } \
! 199: } \
! 200: __ptr; \
! 201: }))
! 202:
! 203: #define va_end(AP)
! 204:
! 205: /* Copy __gnuc_va_list into another variable of this type. */
! 206: #define __va_copy(dest, src) \
! 207: __extension__ ({ \
! 208: (dest) = \
! 209: (struct __va_list_tag *)__builtin_alloca(sizeof(__gnuc_va_list)); \
! 210: *(dest) = *(src);\
! 211: })
! 212:
! 213: #if __ISO_C_VISIBLE >= 1999
! 214: #define va_copy(dest, src) __va_copy(dest, src)
! 215: #endif
! 216:
! 217: #endif /* __VA_PPC_H__ */
! 218: #endif /* defined (_STDARG_H) || defined (_VARARGS_H) */
! 219:
! 220:
! 221: #else
! 222: /* Windows NT */
! 223: /* Define __gnuc_va_list. */
! 224:
! 225: #ifndef __GNUC_VA_LIST
! 226: #define __GNUC_VA_LIST
! 227: typedef char *__gnuc_va_list;
! 228: #endif /* not __GNUC_VA_LIST */
! 229:
! 230: /* If this is for internal libc use, don't define anything but
! 231: __gnuc_va_list. */
! 232: #if defined (_STDARG_H) || defined (_VARARGS_H)
! 233:
! 234: #define __va_start_common(AP, LASTARG, FAKE) \
! 235: ((__builtin_saveregs ()), ((AP) = ((char *) &LASTARG) + __va_rounded_size (AP)), 0)
! 236:
! 237: #ifdef _STDARG_H /* stdarg.h support */
! 238:
! 239: /* Calling __builtin_next_arg gives the proper error message if LASTARG is
! 240: not indeed the last argument. */
! 241: #define va_start(AP,LASTARG) \
! 242: (__builtin_saveregs (), \
! 243: (AP) = __builtin_next_arg (LASTARG), \
! 244: 0)
! 245:
! 246: #else /* varargs.h support */
! 247:
! 248: #define va_start(AP) \
! 249: (__builtin_saveregs (), \
! 250: (AP) = __builtin_next_arg (__va_1st_arg) - sizeof (int), \
! 251: 0)
! 252:
! 253: #define va_alist __va_1st_arg
! 254: #define va_dcl register int __va_1st_arg; ...
! 255:
! 256: #endif /* _STDARG_H */
! 257:
! 258: #define __va_rounded_size(TYPE) ((sizeof (TYPE) + 3) & ~3)
! 259: #define __va_align(AP, TYPE) \
! 260: ((((unsigned long)(AP)) + ((sizeof (TYPE) >= 8) ? 7 : 3)) \
! 261: & ~((sizeof (TYPE) >= 8) ? 7 : 3))
! 262:
! 263: #define va_arg(AP,TYPE) \
! 264: ( *(TYPE *)((AP = (char *) (__va_align(AP, TYPE) \
! 265: + __va_rounded_size(TYPE))) \
! 266: - __va_rounded_size(TYPE)))
! 267:
! 268: #define va_end(AP)
! 269:
! 270: /* Copy __gnuc_va_list into another variable of this type. */
! 271: #define __va_copy(dest, src) (dest) = (src)
! 272:
! 273: #endif /* defined (_STDARG_H) || defined (_VARARGS_H) */
! 274: #endif /* Windows NT */
CVSweb