|
|
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 indepenent implementation.
12: * These (somewhat bizarre) paramter-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: typedef void *_voidptr;
48: #if 1
49:
50: typedef struct _va_regs {
51: _voidptr __stackp,__regp,__count;
52: _voidptr _pr0,_pr1,_pr2,_pr3,_pr4,_pr5,_pr6,_pr7,_pr8,_pr9,_pr10,_pr11;
53: } _va_regs;
54:
55: typedef _va_regs _va_buf;
56: #else
57:
58: /* _va_buf[0] = address of next arg passed on the stack
59: _va_buf[1] = address of next arg passed in a register
60: _va_buf[2] = register-# of next arg passed in a register
61: */
62: typedef _voidptr(*_va_buf);
63:
64: #endif
65:
66: #define va_alist \
67: _va0,_va1,_va2,_va3,_va4,_va5,_va6,_va7,_va8,_va9,_va10,_va11, \
68: __builtin_va_alist
69:
70: #define va_dcl _voidptr va_alist;
71:
72: #define va_list _va_buf
73:
74:
75: /* __asm ("rcsp %0" : "=r" ( _AP [0]));*/
76:
77: #define va_start(_AP) \
78: { _AP = ((struct _va_regs) { \
79: &(_AP._pr0), (void*)&__builtin_va_alist, (void*)0, \
80: _va0,_va1,_va2,_va3,_va4,_va5, \
81: _va6,_va7,_va8,_va9,_va10,_va11})
82:
83:
84:
85:
86: #define va_arg(_AP, _MODE) \
87: ({_voidptr *_ap = (_voidptr*)&_AP; \
88: register int _size = sizeof (_MODE); \
89: register int _onstack = \
90: (_size > 8 || ( (int)(_ap[2]) > 11) || \
91: (_size==8 && (int)(_ap[2])==11)); \
92: register int* _param_addr = ((int*)((_ap) [_onstack])); \
93: \
94: ((void *)_ap[_onstack])+=_size; \
95: if (_onstack==0 || (int)(_ap[2])==11) \
96: _ap[2]+= (_size >> 2); \
97: *(( _MODE *)_param_addr); \
98: })
99:
100: #define va_end(_X) }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.