|
|
1.1 root 1: /**
2: *
3: * Varargs for PYR/GNU CC
4: *
5: * WARNING -- WARNING -- DANGER
6: *
7: * The code in this file implements varargs for gcc on a pyr in
8: * a way that is compatible with code compiled by the Pyramid Technology
9: * C compiler.
10: * As such, it depends strongly on the Pyramid conventions for
11: * parameter passing.ct and independent implementation.
12: * These (somewhat bizarre) parameter-passing conventions are described
13: * in the ``OSx Operating System Porting Guide''.
14: *
15: * A quick summary is useful:
16: * 12 of the 48 register-windowed regs available for
17: * parameter passing. Parameters of a function call that are eligible
18: * to be passed in registers are assigned registers from TR0/PR0 onwards;
19: * all other arguments are passed on the stack.
20: * Structure and union parameters are *never* passed in registers,
21: * even if they are small enough to fit. They are always passed on
22: * the stack.
23: *
24: * Double-sized parameters cannot be passed in TR11, because
25: * TR12 is not used for passing parameters. If, in the absence of this
26: * rule, a double-sized param would have been passed in TR11,
27: * that parameter is passed on the stack and no parameters are
28: * passed in TR11.
29: *
30: * It is only known to work for passing 32-bit integer quantities
31: * (ie chars, shorts, ints/enums, longs), doubles, or pointers.
32: * Passing structures on a Pyramid via varargs is a loser.
33: * Passing an object larger than 8 bytes on a pyramid via varargs may
34: * also be a loser.
35: *
36: */
37:
38:
39: /*
40: * pointer to next stack parameter in __va_buf[0]
41: * pointer to next parameter register in __va_buf[1]
42: * Count of registers seen at __va_buf[2]
43: * saved pr0..pr11 in __va_buf[3..14]
44: * # of calls to va_arg (debugging) at __va_buf[15]
45: */
46:
47: /* Define __gnuc_va_list. */
48:
49: #ifndef __GNUC_VA_LIST
50: #define __GNUC_VA_LIST
51:
52: typedef void *__voidptr;
53: #if 1
54:
55: typedef struct __va_regs {
56: __voidptr __stackp,__regp,__count;
57: __voidptr __pr0,__pr1,__pr2,__pr3,__pr4,__pr5,__pr6,__pr7,__pr8,__pr9,__pr10,__pr11;
58: } __va_regs;
59:
60: typedef __va_regs __va_buf;
61: #else
62:
63: /* __va_buf[0] = address of next arg passed on the stack
64: __va_buf[1] = address of next arg passed in a register
65: __va_buf[2] = register-# of next arg passed in a register
66: */
67: typedef __voidptr(*__va_buf);
68:
69: #endif
70:
71: typedef __va_buf __gnuc_va_list;
72:
73: #endif /* not __GNUC_VA_LIST */
74:
75: /* If this is for internal libc use, don't define anything but
76: __gnuc_va_list. */
77: #if defined (_STDARG_H) || defined (_VARARGS_H)
78:
79: /* In GCC version 2, we want an ellipsis at the end of the declaration
80: of the argument list. GCC version 1 can't parse it. */
81:
82: #if __GNUC__ > 1
83: #define __va_ellipsis ...
84: #else
85: #define __va_ellipsis
86: #endif
87:
88: #define va_alist \
89: __va0,__va1,__va2,__va3,__va4,__va5,__va6,__va7,__va8,__va9,__va10,__va11, \
90: __builtin_va_alist
91:
92: /* The ... causes current_function_varargs to be set in cc1. */
93: #define va_dcl __voidptr va_alist; __va_ellipsis
94:
95:
96: /* __asm ("rcsp %0" : "=r" ( _AP [0]));*/
97:
98: #define va_start(_AP) \
99: _AP = ((struct __va_regs) { \
100: &(_AP.__pr0), (void*)&__builtin_va_alist, (void*)0, \
101: __va0,__va1,__va2,__va3,__va4,__va5, \
102: __va6,__va7,__va8,__va9,__va10,__va11})
103:
104:
105: /* Avoid errors if compiling GCC v2 with GCC v1. */
106: #if __GNUC__ == 1
107: #define __extension__
108: #endif
109:
110: /* We cast to void * and then to TYPE * because this avoids
111: a warning about increasing the alignment requirement. */
112: #define va_arg(_AP, _MODE) \
113: __extension__ \
114: ({__voidptr *__ap = (__voidptr*)&_AP; \
115: register int __size = sizeof (_MODE); \
116: register int __onstack = \
117: (__size > 8 || ( (int)(__ap[2]) > 11) || \
118: (__size==8 && (int)(__ap[2])==11)); \
119: register int* __param_addr = ((int*)((__ap) [__onstack])); \
120: \
121: ((void *)__ap[__onstack])+=__size; \
122: if (__onstack==0 || (int)(__ap[2])==11) \
123: __ap[2]+= (__size >> 2); \
124: *(( _MODE *) (void *) __param_addr); \
125: })
126:
127: void va_end (__gnuc_va_list); /* Defined in libgcc.a */
128: #define va_end(_X)
129:
130: #endif /* defined (_STDARG_H) || defined (_VARARGS_H) */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.