]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Forgot to commit last night.
authorJeff Law <law@gcc.gnu.org>
Wed, 26 Nov 1997 21:22:08 +0000 (14:22 -0700)
committerJeff Law <law@gcc.gnu.org>
Wed, 26 Nov 1997 21:22:08 +0000 (14:22 -0700)
From-SVN: r16757

gcc/ginclude/va-sh.h

index 4bae1e0dcd222e8e60e5734e0cbb4ca7ab58d40c..f1671c7b0b6c0abc146063b895fb6cd4f03383bf 100644 (file)
@@ -23,9 +23,6 @@ typedef struct {
 
 typedef void *__gnuc_va_list;
 
-#define __va_rounded_size(TYPE)  \
-  (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int))
-
 #endif /* ! SH3E */
 
 #endif /* __GNUC_VA_LIST */
@@ -116,104 +113,83 @@ enum __va_type_classes {
 #endif
 #define va_end(pvar)   ((void)0)
 
+#ifdef __LITTLE_ENDIAN__
+#define __LITTLE_ENDIAN_P 1
+#else
+#define __LITTLE_ENDIAN_P 0
+#endif
+
+#define __SCALAR_TYPE(TYPE)                                    \
+  ((TYPE) == __integer_type_class                              \
+   || (TYPE) == __char_type_class                              \
+   || (TYPE) == __enumeral_type_class)
+
 /* RECORD_TYPE args passed using the C calling convention are
    passed by invisible reference.  ??? RECORD_TYPE args passed
    in the stack are made to be word-aligned; for an aggregate that is
    not word-aligned, we advance the pointer to the first non-reg slot.  */
 
+  /* When this is a smaller-than-int integer, using
+     auto-increment in the promoted (SImode) is fastest;
+     however, there is no way to express that is C.  Therefore,
+     we use an asm.
+     We want the MEM_IN_STRUCT_P bit set in the emitted RTL, therefore we
+     use unions even when it would otherwise be unnecessary.  */
+
+#define __va_arg_sh1(AP, TYPE) __extension__                           \
+__extension__                                                          \
+({(sizeof (TYPE) == 1                                                  \
+   ? ({union {TYPE t; char c;} __t;                                    \
+       asm(""                                                          \
+          : "=r" (__t.c)                                               \
+          : "0" ((((union { int i, j; } *) (AP))++)->i));              \
+       __t.t;})                                                                \
+   : sizeof (TYPE) == 2                                                        \
+   ? ({union {TYPE t; short s;} __t;                                   \
+       asm(""                                                          \
+          : "=r" (__t.s)                                               \
+          : "0" ((((union { int i, j; } *) (AP))++)->i));              \
+       __t.t;})                                                                \
+   : sizeof (TYPE) >= 4 || __LITTLE_ENDIAN_P                           \
+   ? (((union { TYPE t; int i;} *) (AP))++)->t                         \
+   : ((union {TYPE t;TYPE u;}*) ((char *)++(int *)(AP) - sizeof (TYPE)))->t);})
+
 #ifdef __SH3E__
 
-#ifdef __LITTLE_ENDIAN__
+#define __PASS_AS_FLOAT(TYPE_CLASS,SIZE) \
+  (TYPE_CLASS == __real_type_class && SIZE == 4)
 
 #define va_arg(pvar,TYPE)                                      \
 __extension__                                                  \
-(*({int __type = __builtin_classify_type (* (TYPE *) 0);       \
-  void * __result;                                             \
-  if (__type == __real_type_class && sizeof(TYPE) == 4)                \
-                                               /* float? */    \
+({int __type = __builtin_classify_type (* (TYPE *) 0);         \
+  void * __result_p;                                           \
+  if (__PASS_AS_FLOAT (__type, sizeof(TYPE)))                  \
     {                                                          \
-      __va_freg *__r;                                          \
       if (pvar.__va_next_fp < pvar.__va_next_fp_limit)         \
-       __r = (__va_freg *) pvar.__va_next_fp++;                \
-      else                                                     \
-       __r = (__va_freg *) pvar.__va_next_stack++;             \
-      __result = (char *) __r;                                 \
-    }                                                          \
-  else                                                         \
-    {                                                          \
-      __va_greg *_r;                                           \
-      if (pvar.__va_next_o + ((sizeof (TYPE) + 3) / 4)         \
-         <= pvar.__va_next_o_limit)                            \
        {                                                       \
-         _r = pvar.__va_next_o;                                \
-         pvar.__va_next_o += (sizeof (TYPE) + 3) / 4;          \
+         __result_p = &pvar.__va_next_fp;                      \
        }                                                       \
       else                                                     \
-       {                                                       \
-         _r = pvar.__va_next_stack;                            \
-         pvar.__va_next_stack += (sizeof (TYPE) + 3) / 4;      \
-       }                                                       \
-      __result = (char *) _r;                                  \
-    }                                                          \
-  (TYPE *) __result;}))
-
-#else /* ! __LITTLE_ENDIAN__ */
-
-#define va_arg(pvar,TYPE)                                      \
-__extension__                                                  \
-(*({int __type = __builtin_classify_type (* (TYPE *) 0);       \
-  void * __result;                                             \
-  if (__type == __real_type_class && sizeof(TYPE) == 4)                \
-                                               /* float? */    \
-    {                                                          \
-      __va_freg *__r;                                          \
-      if (pvar.__va_next_fp < pvar.__va_next_fp_limit)         \
-       __r = (__va_freg *) pvar.__va_next_fp++;                \
-      else                                                     \
-       __r = (__va_freg *) pvar.__va_next_stack++;             \
-      __result = (char *) __r;                                 \
+       __result_p = &pvar.__va_next_stack;                     \
     }                                                          \
   else                                                         \
     {                                                          \
-      __va_greg *_r;                                           \
       if (pvar.__va_next_o + ((sizeof (TYPE) + 3) / 4)         \
          <= pvar.__va_next_o_limit)                            \
-       {                                                       \
-         pvar.__va_next_o += (sizeof (TYPE) + 3) / 4;          \
-         _r = pvar.__va_next_o;                                \
-       }                                                       \
+       __result_p = &pvar.__va_next_o;                         \
       else                                                     \
        {                                                       \
-         pvar.__va_next_stack += (sizeof (TYPE) + 3) / 4;      \
-         _r = pvar.__va_next_stack;                            \
+         if (sizeof (TYPE) > 4)                                \
+           pvar.__va_next_o = pvar.__va_next_o_limit;          \
+                                                               \
+         __result_p = &pvar.__va_next_stack;                   \
        }                                                       \
-      __result = ((char *) _r                                  \
-                 - (sizeof (TYPE) < 4 ? sizeof (TYPE)          \
-                    : ((sizeof (TYPE) + 3) / 4) * 4));         \
     }                                                          \
-  (TYPE *) __result;}))
-
-#endif /* __LITTLE_ENDIAN__ */
+  __va_arg_sh1(*(void **)__result_p, TYPE);})
 
 #else /* ! SH3E */
 
-#ifdef __LITTLE_ENDIAN__
-
-/* This is for little-endian machines; small args are padded upward.  */
-#define va_arg(AP, TYPE)                                               \
- (AP = (__gnuc_va_list) ((char *) (AP) + __va_rounded_size (TYPE)),    \
-  *((TYPE *) (void *) ((char *) (AP) - __va_rounded_size (TYPE))))
-
-#else /* ! __LITTLE_ENDIAN__ */
-
-/* This is for big-endian machines; small args are padded downward.  */
-#define va_arg(AP, TYPE)                                               \
- (AP = (__gnuc_va_list) ((char *) (AP) + __va_rounded_size (TYPE)),    \
-  *((TYPE *) (void *) ((char *) (AP)                                   \
-                      - ((sizeof (TYPE) < __va_rounded_size (char)     \
-                          ? sizeof (TYPE) : __va_rounded_size (TYPE))))))
-
-#endif /* __LITTLE_ENDIAN__ */
+#define va_arg(AP, TYPE) __va_arg_sh1((AP), TYPE)
 
 #endif /* SH3E */