summaryrefslogtreecommitdiffstats
path: root/gcc/ginclude/va-sh.h
diff options
context:
space:
mode:
authoramylaar <amylaar@138bc75d-0d04-0410-961f-82ee72b054a4>1997-11-08 19:54:57 +0000
committeramylaar <amylaar@138bc75d-0d04-0410-961f-82ee72b054a4>1997-11-08 19:54:57 +0000
commit8ded07523c6750b3f48740eb99a3b66cbd2f05fa (patch)
tree59f0428e343ff462a9ba43cace6b8429cdaa9063 /gcc/ginclude/va-sh.h
parent3058915fac5f3a2fb61c9fc20134c7a5d2e4ad1b (diff)
downloadppe42-gcc-8ded07523c6750b3f48740eb99a3b66cbd2f05fa.tar.gz
ppe42-gcc-8ded07523c6750b3f48740eb99a3b66cbd2f05fa.zip
Sync SH port with FSF; enable regmove for SH.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@16371 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ginclude/va-sh.h')
-rw-r--r--gcc/ginclude/va-sh.h124
1 files changed, 50 insertions, 74 deletions
diff --git a/gcc/ginclude/va-sh.h b/gcc/ginclude/va-sh.h
index 4bae1e0dcd2..f1671c7b0b6 100644
--- a/gcc/ginclude/va-sh.h
+++ b/gcc/ginclude/va-sh.h
@@ -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 */
OpenPOWER on IntegriCloud