diff options
author | Richard Henderson <rth@gcc.gnu.org> | 1999-07-20 17:26:00 -0700 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 1999-07-20 17:26:00 -0700 |
commit | 4cc833b7a82f38982f5e709fd7ae368c9ead5016 (patch) | |
tree | 0ebaa8fa73357ac49f1fcc4fdc21804f89cd70f7 /gcc/ginclude | |
parent | 7705e9db01267c127d2b9f9a33b5218546898ef6 (diff) | |
download | gcc-4cc833b7a82f38982f5e709fd7ae368c9ead5016.zip gcc-4cc833b7a82f38982f5e709fd7ae368c9ead5016.tar.gz gcc-4cc833b7a82f38982f5e709fd7ae368c9ead5016.tar.bz2 |
rs6000.h (struct rs6000_args): Add sysv_gregno.
* rs6000.h (struct rs6000_args): Add sysv_gregno.
* rs6000.c (init_cumulative_args): Init sysv_gregno.
(function_arg_boundary): Align DFmode.
(function_arg_advance): Restructure for ABI_V4; use sysv_gregno
to get fp reg and stack overflow correct.
(function_arg): Likewise.
(function_arg_pass_by_reference): True for TFmode for ABI_V4.
(setup_incoming_varargs): Restructure for ABI_V4; use
function_arg_advance to skip final named argument.
(expand_builtin_saveregs): Properly unskip the last integer arg
when doing varargs. Adjust overflow location calculation.
* ginclude/va-ppc.h (struct __va_list_tag): Make gpr and fpr
explicitly unsigned.
(__VA_FP_REGSAVE): Use new OFS argument instead of AP->fpr directly.
(__VA_GP_REGSAVE): Similarly.
(__va_longlong_p): Delete.
(__va_arg_type_violation): New declaration.
(va_arg): Restructure. Flag promotion errors. Align double.
TFmode passed by reference.
* rs6000.md (movdi_32+1): Use GEN_INT after arithmetic
in the HOST_BITS_PER_WIDE_INT > 32 case.
From-SVN: r28199
Diffstat (limited to 'gcc/ginclude')
-rw-r--r-- | gcc/ginclude/va-ppc.h | 157 |
1 files changed, 100 insertions, 57 deletions
diff --git a/gcc/ginclude/va-ppc.h b/gcc/ginclude/va-ppc.h index 6d81497..0c79d5f 100644 --- a/gcc/ginclude/va-ppc.h +++ b/gcc/ginclude/va-ppc.h @@ -17,10 +17,10 @@ /* Note that the names in this structure are in the user's namespace, but that the V.4 abi explicitly states that these names should be used. */ typedef struct __va_list_tag { - char gpr; /* index into the array of 8 GPRs stored in the + unsigned char gpr; /* index into the array of 8 GPRs stored in the register save area gpr=0 corresponds to r3, gpr=1 to r4, etc. */ - char fpr; /* index into the array of 8 FPRs stored in the + unsigned char fpr; /* index into the array of 8 FPRs stored in the register save area fpr=0 corresponds to f1, fpr=1 to f2, etc. */ char *overflow_arg_area; /* location on stack that holds the next @@ -51,13 +51,13 @@ typedef struct { /* Macros to access the register save area */ /* We cast to void * and then to TYPE * because this avoids a warning about increasing the alignment requirement. */ -#define __VA_FP_REGSAVE(AP,TYPE) \ +#define __VA_FP_REGSAVE(AP,OFS,TYPE) \ ((TYPE *) (void *) (&(((__va_regsave_t *) \ - (AP)->reg_save_area)->__fp_save[(int)(AP)->fpr]))) + (AP)->reg_save_area)->__fp_save[OFS]))) -#define __VA_GP_REGSAVE(AP,TYPE) \ +#define __VA_GP_REGSAVE(AP,OFS,TYPE) \ ((TYPE *) (void *) (&(((__va_regsave_t *) \ - (AP)->reg_save_area)->__gp_save[(int)(AP)->gpr]))) + (AP)->reg_save_area)->__gp_save[OFS]))) /* Common code for va_start for both varargs and stdarg. We allow all the work to be done by __builtin_saveregs. It returns a pointer to @@ -88,60 +88,103 @@ typedef struct { #define __va_float_p(TYPE) (__builtin_classify_type(*(TYPE *)0) == 8) #endif -#define __va_longlong_p(TYPE) \ - ((__builtin_classify_type(*(TYPE *)0) == 1) && (sizeof(TYPE) == 8)) - #define __va_aggregate_p(TYPE) (__builtin_classify_type(*(TYPE *)0) >= 12) #define __va_size(TYPE) ((sizeof(TYPE) + sizeof (long) - 1) / sizeof (long)) -#define va_arg(AP,TYPE) \ -__extension__ (*({ \ - register TYPE *__ptr; \ - \ - if (__va_float_p (TYPE) && (AP)->fpr < 8) \ - { \ - __ptr = __VA_FP_REGSAVE (AP, TYPE); \ - (AP)->fpr++; \ - } \ - \ - else if (__va_aggregate_p (TYPE) && (AP)->gpr < 8) \ - { \ - __ptr = * __VA_GP_REGSAVE (AP, TYPE *); \ - (AP)->gpr++; \ - } \ - \ - else if (!__va_float_p (TYPE) && !__va_aggregate_p (TYPE) \ - && (AP)->gpr + __va_size(TYPE) <= 8 \ - && (!__va_longlong_p(TYPE) \ - || (AP)->gpr + __va_size(TYPE) <= 8)) \ - { \ - if (__va_longlong_p(TYPE) && ((AP)->gpr & 1) != 0) \ - (AP)->gpr++; \ - \ - __ptr = __VA_GP_REGSAVE (AP, TYPE); \ - (AP)->gpr += __va_size (TYPE); \ - } \ - \ - else if (!__va_float_p (TYPE) && !__va_aggregate_p (TYPE) \ - && (AP)->gpr < 8) \ - { \ - (AP)->gpr = 8; \ - __ptr = (TYPE *) (void *) (__va_overflow(AP)); \ - __va_overflow(AP) += __va_size (TYPE) * sizeof (long); \ - } \ - \ - else if (__va_aggregate_p (TYPE)) \ - { \ - __ptr = * (TYPE **) (void *) (__va_overflow(AP)); \ - __va_overflow(AP) += sizeof (TYPE *); \ - } \ - else \ - { \ - __ptr = (TYPE *) (void *) (__va_overflow(AP)); \ - __va_overflow(AP) += __va_size (TYPE) * sizeof (long); \ - } \ - \ - __ptr; \ +/* This symbol isn't defined. It is used to flag type promotion violations + at link time. We can only do this when optimizing. Use __builtin_trap + instead of abort so that we don't require a prototype for abort. */ + +#ifdef __OPTIMIZE__ +extern void __va_arg_type_violation(void) __attribute__((__noreturn__)); +#else +#define __va_arg_type_violation() __builtin_trap() +#endif + +#define va_arg(AP,TYPE) \ +__extension__ (*({ \ + register TYPE *__ptr; \ + \ + if (__va_float_p (TYPE) && sizeof (TYPE) < 16) \ + { \ + unsigned char __fpr = (AP)->fpr; \ + if (__fpr < 8) \ + { \ + __ptr = __VA_FP_REGSAVE (AP, __fpr, TYPE); \ + (AP)->fpr = __fpr + 1; \ + } \ + else if (sizeof (TYPE) == 8) \ + { \ + unsigned long __addr = (unsigned long) (__va_overflow (AP)); \ + __ptr = (TYPE *)((__addr + 7) & -8); \ + __va_overflow (AP) = (char *)(__ptr + 1); \ + } \ + else \ + { \ + /* float is promoted to double. */ \ + __va_arg_type_violation (); \ + } \ + } \ + \ + /* Aggregates and long doubles are passed by reference. */ \ + else if (__va_aggregate_p (TYPE) || __va_float_p (TYPE)) \ + { \ + unsigned char __gpr = (AP)->gpr; \ + if (__gpr < 8) \ + { \ + __ptr = * __VA_GP_REGSAVE (AP, __gpr, TYPE *); \ + (AP)->gpr = __gpr + 1; \ + } \ + else \ + { \ + TYPE **__pptr = (TYPE **) (__va_overflow (AP)); \ + __ptr = * __pptr; \ + __va_overflow (AP) = (char *) (__pptr + 1); \ + } \ + } \ + \ + /* Only integrals remaining. */ \ + else \ + { \ + /* longlong is aligned. */ \ + if (sizeof (TYPE) == 8) \ + { \ + unsigned char __gpr = (AP)->gpr; \ + if (__gpr < 7) \ + { \ + __gpr += __gpr & 1; \ + __ptr = __VA_GP_REGSAVE (AP, __gpr, TYPE); \ + (AP)->gpr = __gpr + 2; \ + } \ + else \ + { \ + unsigned long __addr = (unsigned long) (__va_overflow (AP)); \ + __ptr = (TYPE *)((__addr + 7) & -8); \ + (AP)->gpr = 8; \ + __va_overflow (AP) = (char *)(__ptr + 1); \ + } \ + } \ + else if (sizeof (TYPE) == 4) \ + { \ + unsigned char __gpr = (AP)->gpr; \ + if (__gpr < 8) \ + { \ + __ptr = __VA_GP_REGSAVE (AP, __gpr, TYPE); \ + (AP)->gpr = __gpr + 1; \ + } \ + else \ + { \ + __ptr = (TYPE *) __va_overflow (AP); \ + __va_overflow (AP) = (char *)(__ptr + 1); \ + } \ + } \ + else \ + { \ + /* Everything else was promoted to int. */ \ + __va_arg_type_violation (); \ + } \ + } \ + __ptr; \ })) #define va_end(AP) ((void)0) |