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