Initial revision
authorRichard Kenner <kenner@gcc.gnu.org>
Fri, 14 Aug 1992 19:32:10 +0000 (15:32 -0400)
committerRichard Kenner <kenner@gcc.gnu.org>
Fri, 14 Aug 1992 19:32:10 +0000 (15:32 -0400)
From-SVN: r1838

gcc/ginclude/va-alpha.h [new file with mode: 0644]

diff --git a/gcc/ginclude/va-alpha.h b/gcc/ginclude/va-alpha.h
new file mode 100644 (file)
index 0000000..37de689
--- /dev/null
@@ -0,0 +1,186 @@
+/* GNU C varargs and stdargs support for the DEC Alpha.  */
+
+/* Note:  We must use the name __builtin_savregs.  GCC attaches special
+   significance to that name.  In particular, regardless of where in a
+   function __builtin_saveregs is called, GCC moves the call up to the
+   very start of the function.  */
+
+/* Define __gnuc_va_list.  */
+
+#ifndef __GNUC_VA_LIST
+#define __GNUC_VA_LIST
+
+typedef struct {
+  long __va_arg;               /* Current argument number. */
+  long *__va_stack;            /* Start of arguments on stack */
+  long *__va_iregs;            /* Integer parameter registers ($16-$21) */
+  long *__va_fregs;            /* FP parameter registers ($f16-$f21) */
+} __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)
+
+#define va_list __gnuc_va_list
+#define _VA_LIST
+#define _VA_LIST_
+
+#if !defined(_STDARG_H)
+
+/* varargs support */
+#define va_alist __builtin_va_alist
+#define va_dcl
+#define va_start(pvar) ((pvar) = * (__gnuc_va_list *) __builtin_saveregs ())
+
+#else /* STDARG.H */
+
+/* ANSI alternative.  */
+
+#define va_start(pvar, firstarg)  \
+  ((pvar) = *(__gnuc_va_list *) __builtin_saveregs ())
+
+#endif /* _STDARG_H */
+
+#define va_end(__va)
+
+/* Values returned by __builtin_classify_type.  */
+
+enum {
+  __no_type_class = -1,
+  __void_type_class,
+  __integer_type_class,
+  __char_type_class,
+  __enumeral_type_class,
+  __boolean_type_class,
+  __pointer_type_class,
+  __reference_type_class,
+  __offset_type_class,
+  __real_type_class,
+  __complex_type_class,
+  __function_type_class,
+  __method_type_class,
+  __record_type_class,
+  __union_type_class,
+  __array_type_class,
+  __string_type_class,
+  __set_type_class,
+  __file_type_class,
+  __lang_type_class
+};
+
+/* Note that parameters are always aligned at least to a word boundary
+   (when passed) regardless of what GCC's __alignof__ operator says.  */
+
+/* Avoid errors if compiling GCC v2 with GCC v1.  */
+#if __GNUC__ == 1
+#define __extension__
+#endif
+
+/* Get the rounded number of words of a type.  */
+
+#define __va_nwords(__type)  \
+  ((sizeof (__type) + sizeof (long) - 1) / sizeof (long))
+
+#define va_arg(__va, __type)                                           \
+__extension__                                                          \
+(* (__type *)                                                          \
+ ({                                                                    \
+  register void *__rv;  /* result value */                             \
+  switch (__builtin_classify_type (* (__type *) 0))                    \
+    {                                                                  \
+    case __real_type_class:                                            \
+                                                                       \
+      /* Get a pointer to the value.  If we want a float instead of    \
+        a double, we have to make one and point to it instead.  */     \
+                                                                       \
+      __rv = (void *) & (__va.__va_arg < 6                             \
+                        ? __va.__va_fregs[__va.__va_arg]               \
+                        : __va.__va_stack[__va.__va_arg - 6]);         \
+                                                                       \
+      if (sizeof (__type) == sizeof (float))                           \
+       {                                                               \
+         float __rf = * ((double *) __rv);                             \
+                                                                       \
+         __rv = (void *) &__rf;                                        \
+       }                                                               \
+                                                                       \
+      break;                                                           \
+                                                                       \
+    case __void_type_class:                                            \
+    case __integer_type_class:                                         \
+    case __char_type_class:                                            \
+    case __enumeral_type_class:                                                \
+    case __boolean_type_class:                                         \
+    case __pointer_type_class:                                         \
+    case __reference_type_class:                                       \
+    case __offset_type_class:                                          \
+    case __record_type_class:                                          \
+    case __union_type_class:                                           \
+                                                                       \
+      /* Force this on the stack if it's alignment isn't right.  */    \
+                                                                       \
+      if (__va.__va_arg < 6)                                           \
+       switch (sizeof (__type))                                        \
+         {                                                             \
+         case sizeof (char):                                           \
+           break;                                                      \
+         case sizeof (short):                                          \
+           if (__alignof__ (__type) < sizeof (short))                  \
+             __va.__va_arg = 6;                                        \
+           break;                                                      \
+         case 3:                                                       \
+         case sizeof (int):                                            \
+           if (__alignof__ (__type) < sizeof (int))                    \
+             __va.__va_arg = 6;                                        \
+           break;                                                      \
+         default:                                                      \
+           if (__alignof__ (__type) < sizeof (long))                   \
+             __va.__va_arg = 6;                                        \
+           break;                                                      \
+         }                                                             \
+                                                                       \
+      /* If this object is only one word long, just get it.  If it is   \
+        longer, we need to worry about the possibility that it is      \
+        passed both in registers and in memory.  */                    \
+                                                                       \
+      if (sizeof (__type) <= sizeof (long)                             \
+         || __va.__va_arg >= 6                                 \
+         || __va.__va_arg + __va_nwords (__type) < 6)                  \
+       __rv = (void *) & (__va.__va_arg < 6                            \
+                          ? __va.__va_iregs[__va.__va_arg]             \
+                          : __va.__va_stack[__va.__va_arg - 6]);       \
+      else                                                             \
+       {                                                               \
+         long __obj[__va_nwords (__type)];                             \
+         int __i;                                                      \
+                                                                       \
+         for (__i = 0; __i < __va_nwords (__type); __i++)              \
+           __obj[__i] = (__va.__va_arg < 6                             \
+                         ? __va.__va_iregs[__va.__va_arg]              \
+                         : __va.__va_stack[__va.__va_arg - 6]);        \
+                                                                       \
+         __rv = (void *) &__obj[0];                                    \
+       }                                                               \
+      break;                                                           \
+                                                                       \
+    case __complex_type_class:                                         \
+    case __function_type_class:                                                \
+    case __method_type_class:                                          \
+    case __array_type_class:                                           \
+    case __string_type_class:                                          \
+    case __set_type_class:                                             \
+    case __file_type_class:                                            \
+    case __lang_type_class:                                            \
+    case __no_type_class:                                              \
+    default:                                                           \
+       abort ();                                                       \
+    }                                                                  \
+                                                                       \
+  __va.__va_arg += __va_nwords (__type);                               \
+                                                                       \
+  __rv;                                                                        \
+}))
+
+#endif /* defined (_STDARG_H) || defined (_VARARGS_H) */
+