1 | /* GNU C varargs support for the PowerPC with V.4 calling sequence */ |
---|
2 | |
---|
3 | /* Define __gnuc_va_list. */ |
---|
4 | |
---|
5 | #ifndef __GNUC_VA_LIST |
---|
6 | #define __GNUC_VA_LIST |
---|
7 | |
---|
8 | /* Note that the names in this structure are in the user's namespace, but |
---|
9 | that the V.4 abi explicitly states that these names should be used. */ |
---|
10 | typedef struct { |
---|
11 | char gpr; /* index into the array of 8 GPRs stored in the |
---|
12 | register save area gpr=0 corresponds to r3, |
---|
13 | gpr=1 to r4, etc. */ |
---|
14 | char fpr; /* index into the array of 8 FPRs stored in the |
---|
15 | register save area fpr=0 corresponds to f1, |
---|
16 | fpr=1 to f2, etc. */ |
---|
17 | char *overflow_arg_area; /* location on stack that holds the next |
---|
18 | overflow argument */ |
---|
19 | char *reg_save_area; /* where r3:r10 and f1:f8, if saved are stored */ |
---|
20 | } __gnuc_va_list[1]; |
---|
21 | #endif /* not __GNUC_VA_LIST */ |
---|
22 | |
---|
23 | /* If this is for internal libc use, don't define anything but |
---|
24 | __gnuc_va_list. */ |
---|
25 | #if defined (_STDARG_H) || defined (_VARARGS_H) |
---|
26 | |
---|
27 | /* Register save area located below the frame pointer */ |
---|
28 | typedef struct { |
---|
29 | long __gp_save[8]; /* save area for GP registers */ |
---|
30 | double __fp_save[8]; /* save area for FP registers */ |
---|
31 | } __va_regsave_t; |
---|
32 | |
---|
33 | /* Macros to access the register save area */ |
---|
34 | /* We cast to void * and then to TYPE * because this avoids |
---|
35 | a warning about increasing the alignment requirement. */ |
---|
36 | #define __VA_FP_REGSAVE(AP,TYPE) \ |
---|
37 | ((TYPE *) (void *) (&(((__va_regsave_t *) \ |
---|
38 | (AP)->reg_save_area)->__fp_save[(int)(AP)->fpr]))) |
---|
39 | |
---|
40 | #define __VA_GP_REGSAVE(AP,TYPE) \ |
---|
41 | ((TYPE *) (void *) (&(((__va_regsave_t *) \ |
---|
42 | (AP)->reg_save_area)->__gp_save[(int)(AP)->gpr]))) |
---|
43 | |
---|
44 | /* Common code for va_start for both varargs and stdarg. This depends |
---|
45 | on the format of rs6000_args in rs6000.h. The fields used are: |
---|
46 | |
---|
47 | #0 WORDS # words used for GP regs/stack values |
---|
48 | #1 FREGNO next available FP register |
---|
49 | #2 NARGS_PROTOTYPE # args left in the current prototype |
---|
50 | #3 ORIG_NARGS original value of NARGS_PROTOTYPE |
---|
51 | #4 VARARGS_OFFSET offset from frame pointer of varargs area */ |
---|
52 | |
---|
53 | #define __va_words __builtin_args_info (0) |
---|
54 | #define __va_fregno __builtin_args_info (1) |
---|
55 | #define __va_nargs __builtin_args_info (2) |
---|
56 | #define __va_orig_nargs __builtin_args_info (3) |
---|
57 | #define __va_varargs_offset __builtin_args_info (4) |
---|
58 | |
---|
59 | #define __va_start_common(AP, FAKE) \ |
---|
60 | __extension__ ({ \ |
---|
61 | register int __words = __va_words - FAKE; \ |
---|
62 | \ |
---|
63 | (AP)->gpr = (__words < 8) ? __words : 8; \ |
---|
64 | (AP)->fpr = __va_fregno - 33; \ |
---|
65 | (AP)->reg_save_area = (((char *) __builtin_frame_address (0)) \ |
---|
66 | + __va_varargs_offset); \ |
---|
67 | (AP)->overflow_arg_area = ((char *)__builtin_saveregs () \ |
---|
68 | + (((__words >= 8) ? __words - 8 : 0) \ |
---|
69 | * sizeof (long))); \ |
---|
70 | (void)0; \ |
---|
71 | }) |
---|
72 | |
---|
73 | #ifdef _STDARG_H /* stdarg.h support */ |
---|
74 | |
---|
75 | /* Calling __builtin_next_arg gives the proper error message if LASTARG is |
---|
76 | not indeed the last argument. */ |
---|
77 | #define va_start(AP,LASTARG) \ |
---|
78 | (__builtin_next_arg (LASTARG), __va_start_common (AP, 0)) |
---|
79 | |
---|
80 | #else /* varargs.h support */ |
---|
81 | |
---|
82 | #define va_start(AP) __va_start_common (AP, 1) |
---|
83 | #define va_alist __va_1st_arg |
---|
84 | #define va_dcl register int va_alist; ... |
---|
85 | |
---|
86 | #endif /* _STDARG_H */ |
---|
87 | |
---|
88 | #ifdef _SOFT_FLOAT |
---|
89 | #define __va_float_p(TYPE) 0 |
---|
90 | #else |
---|
91 | #define __va_float_p(TYPE) (__builtin_classify_type(*(TYPE *)0) == 8) |
---|
92 | #endif |
---|
93 | |
---|
94 | #define __va_aggregate_p(TYPE) (__builtin_classify_type(*(TYPE *)0) >= 12) |
---|
95 | #define __va_size(TYPE) ((sizeof(TYPE) + sizeof (long) - 1) / sizeof (long)) |
---|
96 | |
---|
97 | #define va_arg(AP,TYPE) \ |
---|
98 | __extension__ (*({ \ |
---|
99 | register TYPE *__ptr; \ |
---|
100 | \ |
---|
101 | if (__va_float_p (TYPE) && (AP)->fpr < 8) \ |
---|
102 | { \ |
---|
103 | __ptr = __VA_FP_REGSAVE (AP, TYPE); \ |
---|
104 | (AP)->fpr++; \ |
---|
105 | } \ |
---|
106 | \ |
---|
107 | else if (__va_aggregate_p (TYPE) && (AP)->gpr < 8) \ |
---|
108 | { \ |
---|
109 | __ptr = * __VA_GP_REGSAVE (AP, TYPE *); \ |
---|
110 | (AP)->gpr++; \ |
---|
111 | } \ |
---|
112 | \ |
---|
113 | else if (!__va_float_p (TYPE) && !__va_aggregate_p (TYPE) \ |
---|
114 | && (AP)->gpr + __va_size(TYPE) <= 8) \ |
---|
115 | { \ |
---|
116 | __ptr = __VA_GP_REGSAVE (AP, TYPE); \ |
---|
117 | (AP)->gpr += __va_size (TYPE); \ |
---|
118 | } \ |
---|
119 | \ |
---|
120 | else if (!__va_float_p (TYPE) && !__va_aggregate_p (TYPE) \ |
---|
121 | && (AP)->gpr < 8) \ |
---|
122 | { \ |
---|
123 | (AP)->gpr = 8; \ |
---|
124 | __ptr = (TYPE *) (void *) ((AP)->overflow_arg_area); \ |
---|
125 | (AP)->overflow_arg_area += __va_size (TYPE) * sizeof (long); \ |
---|
126 | } \ |
---|
127 | \ |
---|
128 | else if (__va_aggregate_p (TYPE)) \ |
---|
129 | { \ |
---|
130 | __ptr = * (TYPE **) (void *) ((AP)->overflow_arg_area); \ |
---|
131 | (AP)->overflow_arg_area += sizeof (TYPE *); \ |
---|
132 | } \ |
---|
133 | else \ |
---|
134 | { \ |
---|
135 | __ptr = (TYPE *) (void *) ((AP)->overflow_arg_area); \ |
---|
136 | (AP)->overflow_arg_area += __va_size (TYPE) * sizeof (long); \ |
---|
137 | } \ |
---|
138 | \ |
---|
139 | __ptr; \ |
---|
140 | })) |
---|
141 | |
---|
142 | #define va_end(AP) ((void)0) |
---|
143 | |
---|
144 | #endif /* defined (_STDARG_H) || defined (_VARARGS_H) */ |
---|