Annotation of sys/arch/powerpc/include/va-ppc.h, Revision 1.1.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