summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/ginclude/va-pyr.h
blob: 5ad4ba9d763ef56e246b4024d87e0058c829e58f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/**
 *
 * 	Varargs for PYR/GNU CC
 *
 * WARNING -- WARNING -- DANGER
 *
 * The code in this file implements varargs for gcc on a pyr in
 * a way that is compatible with code compiled by the Pyramid Technology
 * C compiler.
 * As such, it depends strongly on the Pyramid conventions for
 * parameter passing.ct and independent implementation. 
 * These (somewhat bizarre) parameter-passing conventions are described
 * in the ``OSx Operating System Porting Guide''.
 * 
 * A quick summary is useful:
 * 12 of the 48 register-windowed regs available for
 * parameter passing.  Parameters of a function call that are eligible
 * to be passed in registers are assigned registers from TR0/PR0 onwards;
 * all other arguments are passed on the stack.
 * Structure and union parameters are *never* passed in registers,
 * even if they are small enough to fit.  They are always passed on
 * the stack.
 *
 * Double-sized parameters cannot be passed in TR11, because
 * TR12 is not used for passing parameters.  If, in the absence of this
 * rule, a double-sized param would have been passed in TR11,
 * that parameter is passed on the stack and no parameters are
 * passed in TR11.
 * 
 * It is only known to work for passing 32-bit integer quantities
 * (ie chars, shorts, ints/enums, longs), doubles, or pointers. 
 * Passing structures on a Pyramid via varargs is a loser.
 * Passing an object larger than 8 bytes on a pyramid via varargs may
 * also be a loser.
 * 
 */


/*
 *  pointer to next stack parameter in __va_buf[0]
 *  pointer to next parameter register in __va_buf[1]
 *  Count of registers seen at __va_buf[2]
 *  saved pr0..pr11 in __va_buf[3..14]
 *  # of calls to va_arg (debugging) at __va_buf[15]
 */

/* Define __gnuc_va_list.  */

#ifndef __GNUC_VA_LIST
#define __GNUC_VA_LIST

typedef void *__voidptr;
#if 1

typedef struct __va_regs {
      __voidptr __stackp,__regp,__count;
      __voidptr __pr0,__pr1,__pr2,__pr3,__pr4,__pr5,__pr6,__pr7,__pr8,__pr9,__pr10,__pr11;
  } __va_regs;

typedef __va_regs __va_buf;
#else

/* __va_buf[0] = address of next arg passed on the stack
   __va_buf[1] = address of next arg passed in a register
   __va_buf[2] = register-# of next arg passed in a register
 */
typedef __voidptr(*__va_buf);

#endif

typedef __va_buf __gnuc_va_list;

#endif /* not __GNUC_VA_LIST */

/* If this is for internal libc use, don't define anything but
   __gnuc_va_list.  */
#if defined (_STDARG_H) || defined (_VARARGS_H)

/* In GCC version 2, we want an ellipsis at the end of the declaration
   of the argument list.  GCC version 1 can't parse it.  */

#if __GNUC__ > 1
#define __va_ellipsis ...
#else
#define __va_ellipsis
#endif

#define va_alist \
  __va0,__va1,__va2,__va3,__va4,__va5,__va6,__va7,__va8,__va9,__va10,__va11, \
 __builtin_va_alist

/* The ... causes current_function_varargs to be set in cc1.  */
#define va_dcl __voidptr va_alist; __va_ellipsis


/* __asm ("rcsp %0" : "=r" ( _AP [0]));*/

#define va_start(_AP)  \
  _AP =  ((struct __va_regs) {						\
   &(_AP.__pr0), (void*)&__builtin_va_alist, (void*)0,			\
        __va0,__va1,__va2,__va3,__va4,__va5,				\
	__va6,__va7,__va8,__va9,__va10,__va11})


/* Avoid errors if compiling GCC v2 with GCC v1.  */
#if __GNUC__ == 1
#define __extension__
#endif

/* We cast to void * and then to TYPE * because this avoids
   a warning about increasing the alignment requirement.  */
#define va_arg(_AP, _MODE)	\
__extension__								\
(*({__voidptr *__ap = (__voidptr*)&_AP;					\
  register int __size = sizeof (_MODE);					\
  register int __onstack =						\
	  (__size > 8 || ( (int)(__ap[2]) > 11) ||			\
	    (__size==8 && (int)(__ap[2])==11));				\
  register int* __param_addr =  ((int*)((__ap) [__onstack]));		\
									\
  ((void *)__ap[__onstack])+=__size;					\
    if (__onstack==0 || (int)(__ap[2])==11)				\
      __ap[2]+= (__size >> 2);						\
  (( _MODE *) (void *) __param_addr);					\
}))

void va_end (__gnuc_va_list);		/* Defined in libgcc.a */
#define va_end(_X)	((void)0)

#endif /* defined (_STDARG_H) || defined (_VARARGS_H) */
OpenPOWER on IntegriCloud