|
|
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.