diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2004-06-09 23:08:20 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2004-06-09 23:08:20 +0000 |
commit | f2e19766833f6503536e96fbba85318691aeac27 (patch) | |
tree | 7322f414428b8c488c8a0a8f5003b9a36641827f /sys/arch/m88k/include | |
parent | ae372ca4eeb4d3eb205c0ac60b5dc8d946965d35 (diff) |
Among other tricky (or nice, depending upon your involvment) features,
the 88Open ABI allows arguments to be passed through registers, then on
the stack, the through registers, then on the stack again, with some
function signatures.
Unfortunately, gcc has not been designed with this possibility in mind,
and does not handle this situation optimally (since no sane architecture
does this anyway) and will reserve stack storage for the second set of
in-registers parameters.
Fixing this is quite non-trivial (trust me on this), so in the meantime
keep at wasting space stack, but teach varargs about this so that it can
compensate correctly.
Diffstat (limited to 'sys/arch/m88k/include')
-rw-r--r-- | sys/arch/m88k/include/va-m88k.h | 9 |
1 files changed, 7 insertions, 2 deletions
diff --git a/sys/arch/m88k/include/va-m88k.h b/sys/arch/m88k/include/va-m88k.h index ff418f05ecd..0303d9184c6 100644 --- a/sys/arch/m88k/include/va-m88k.h +++ b/sys/arch/m88k/include/va-m88k.h @@ -1,4 +1,4 @@ -/* $OpenBSD: va-m88k.h,v 1.3 2004/06/07 20:44:18 miod Exp $ */ +/* $OpenBSD: va-m88k.h,v 1.4 2004/06/09 23:08:19 miod Exp $ */ /* Define __gnuc_va_list. */ @@ -9,6 +9,7 @@ typedef struct __va_list_tag { unsigned int __va_arg; /* argument number */ unsigned int *__va_stk; /* start of args passed on stack */ unsigned int *__va_reg; /* start of args passed in regs */ + unsigned int __va_tomfoolery; /* do we need to eat stack for regs */ } __va_list[1], __gnuc_va_list[1]; #endif /* not __GNUC_VA_LIST */ @@ -23,6 +24,7 @@ __extension__ ({ \ __builtin_memcpy ((AP), __builtin_saveregs (), sizeof(__gnuc_va_list)); \ if ((AP)->__va_arg > 8) \ (AP)->__va_stk += ((AP)->__va_arg - 8); \ + (AP)->__va_tomfoolery = 0; \ }) #ifdef _STDARG_H /* stdarg.h support */ @@ -65,13 +67,16 @@ __extension__(*({ \ if ((AP)->__va_arg <= 8 && __va_reg_p(TYPE)) { \ __ptr = (TYPE *) (void *) ((AP)->__va_reg + \ (AP)->__va_arg - __va_size(TYPE)); \ + if ((AP)->__va_tomfoolery) \ + (AP)->__va_stk += __va_size(TYPE); \ } else { \ if (((unsigned int)((AP)->__va_stk) & 4) != 0 && \ __alignof__(*(TYPE *)0) > 4) { \ (AP)->__va_stk++; \ -} \ + } \ __ptr = (TYPE *) (AP)->__va_stk; \ (AP)->__va_stk += __va_size(TYPE); \ + (AP)->__va_tomfoolery = 1; \ } \ __ptr; \ })) |