diff options
Diffstat (limited to 'qt/md/m88k.c')
-rw-r--r-- | qt/md/m88k.c | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/qt/md/m88k.c b/qt/md/m88k.c new file mode 100644 index 000000000..9e3ae8ba8 --- /dev/null +++ b/qt/md/m88k.c @@ -0,0 +1,111 @@ +/* + * QuickThreads -- Threads-building toolkit. + * Copyright (c) 1993 by David Keppel + * + * Permission to use, copy, modify and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice and this notice + * appear in all copies. This software is provided as a + * proof-of-concept and for demonstration purposes; there is no + * representation about the suitability of this software for any + * purpose. + */ + +#include <stdarg.h> +#include "qt.h" + +/* Varargs is harder on the m88k. Parameters are saved on the stack as + something like (stack grows down to low memory; low at bottom of + picture): + + | : + | arg8 <-- va_list.__va_stk + +--- + | : + +--- + | arg7 + | : + | iarg0 <-- va_list.__va_reg + +--- + | : + | va_list { __va_arg, __va_stk, __va_reg } + | : + +--- + + Here, `va_list.__va_arg' is the number of word-size arguments + that have already been skipped. Doubles must be double-arligned. + + What this means for us is that the user's routine needs to be + called with an arg list where some of the words in the `__va_stk' + part of the parameter list have to be promoted to registers. + + BUG: doubleword register arguments must be double-aligned. If + something is passed as an even # arg and used as an odd # arg or + vice-versa, the code in the called routine (in the new thread) that + decides how to adjust the index will get it wrong, because it will + be expect it to be, say, doubleword aligned and it will really be + singleword aligned. + + I'm not sure you can solve this without knowing the types of all + the arguments. All in all, we never promised varargs would work + reliably. */ + + + +#define QT_VADJ(sp) (((char *)sp) - QT_VSTKBASE) + +/* Always allocate at least enough space for 8 args; waste some space + at the base of the stack to ensure the startup routine doesn't read + off the end of the stack. */ + +#define QT_VARGS_MD0(sp, vabytes) \ + ((qt_t *)(((char *)(sp)) - 8*4 - QT_STKROUNDUP(vabytes))) + +extern void qt_vstart(void); +#define QT_VARGS_MD1(sp) (QT_SPUT (sp, QT_1, qt_vstart)) + + + struct qt_t * +qt_vargs (struct qt_t *qsp, int nbytes, void *vargs, + void *pt, qt_function_t *startup, + qt_function_t *vuserf, qt_function_t *cleanup) +{ + va_list ap; + int i; + int n; /* Number of words into original arg list. */ + qt_word_t *sp; + int *reg; /* Where to read passed-in-reg args. */ + int *stk; /* Where to read passed-on-stk args. */ + + ap = *(va_list *)vargs; + qsp = QT_VARGS_MD0 (qsp, nbytes); + sp = (qt_word_t *)qsp; + + reg = (ap.__va_arg < 8) + ? &ap.__va_reg[ap.__va_arg] + : 0; + stk = &ap.__va_stk[8]; + n = ap.__va_arg; + for (i=0; i<nbytes/sizeof(qt_word_t) && n<8; ++i,++n) { + sp[i] = *reg++; + } + for (; i<nbytes/sizeof(qt_word_t); ++i) { + sp[i] = *stk++; + } + +#ifdef QT_NDEF + for (i=0; i<nbytes/sizeof(qt_word_t); ++i) { + sp[i] = (n < 8) + ? *reg++ + : *stk++; + ++n; + } +#endif + + QT_VARGS_MD1 (QT_VADJ(sp)); + QT_SPUT (QT_VADJ(sp), QT_VARGT_INDEX, pt); + QT_SPUT (QT_VADJ(sp), QT_VSTARTUP_INDEX, startup); + QT_SPUT (QT_VADJ(sp), QT_VUSERF_INDEX, vuserf); + QT_SPUT (QT_VADJ(sp), QT_VCLEANUP_INDEX, cleanup); + return ((qt_t *)QT_VADJ(sp)); +} |