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) ((void)0) 129 130 #endif /* defined (_STDARG_H) || defined (_VARARGS_H) */ 131