m88k.c revision 12027
14486Sbinkertn@umich.edu/*
24486Sbinkertn@umich.edu * QuickThreads -- Threads-building toolkit.
34486Sbinkertn@umich.edu * Copyright (c) 1993 by David Keppel
44486Sbinkertn@umich.edu *
54486Sbinkertn@umich.edu * Permission to use, copy, modify and distribute this software and
64486Sbinkertn@umich.edu * its documentation for any purpose and without fee is hereby
74486Sbinkertn@umich.edu * granted, provided that the above copyright notice and this notice
84486Sbinkertn@umich.edu * appear in all copies.  This software is provided as a
94486Sbinkertn@umich.edu * proof-of-concept and for demonstration purposes; there is no
104486Sbinkertn@umich.edu * representation about the suitability of this software for any
114486Sbinkertn@umich.edu * purpose.
124486Sbinkertn@umich.edu */
134486Sbinkertn@umich.edu
144486Sbinkertn@umich.edu#include <stdarg.h>
154486Sbinkertn@umich.edu#include "qt.h"
164486Sbinkertn@umich.edu
174486Sbinkertn@umich.edu/* Varargs is harder on the m88k.  Parameters are saved on the stack as
184486Sbinkertn@umich.edu   something like (stack grows down to low memory; low at bottom of
194486Sbinkertn@umich.edu   picture):
204486Sbinkertn@umich.edu
214486Sbinkertn@umich.edu	|  :
224486Sbinkertn@umich.edu	| arg8		<-- va_list.__va_stk
234486Sbinkertn@umich.edu	+---
244486Sbinkertn@umich.edu	|  :
254486Sbinkertn@umich.edu	+---
264486Sbinkertn@umich.edu	| arg7
274486Sbinkertn@umich.edu	|  :
284486Sbinkertn@umich.edu	| iarg0		<-- va_list.__va_reg
293102SN/A	+---
303102SN/A	|  :
313102SN/A	| va_list { __va_arg, __va_stk, __va_reg }
322667SN/A	|  :
332998SN/A	+---
343584SN/A
352667SN/A   Here, `va_list.__va_arg' is the number of word-size arguments
364486Sbinkertn@umich.edu   that have already been skipped.  Doubles must be double-arligned.
374486Sbinkertn@umich.edu
384486Sbinkertn@umich.edu   What this means for us is that the user's routine needs to be
394486Sbinkertn@umich.edu   called with an arg list where some of the words in the `__va_stk'
404486Sbinkertn@umich.edu   part of the parameter list have to be promoted to registers.
414486Sbinkertn@umich.edu
424486Sbinkertn@umich.edu   BUG: doubleword register arguments must be double-aligned.  If
431692SN/A   something is passed as an even # arg and used as an odd # arg or
441366SN/A   vice-versa, the code in the called routine (in the new thread) that
451310SN/A   decides how to adjust the index will get it wrong, because it will
461310SN/A   be expect it to be, say, doubleword aligned and it will really be
472901SN/A   singleword aligned.
483170SN/A
493170SN/A   I'm not sure you can solve this without knowing the types of all
501530SN/A   the arguments.  All in all, we never promised varargs would work
513620SN/A   reliably. */
523617SN/A
533617SN/A
543617SN/A
553617SN/A#define QUICKTHREADS_VADJ(sp)	(((char *)sp) - QUICKTHREADS_VSTKBASE)
563617SN/A
573584SN/A/* Always allocate at least enough space for 8 args; waste some space
583584SN/A   at the base of the stack to ensure the startup routine doesn't read
593584SN/A   off the end of the stack. */
603584SN/A
613584SN/A#define QUICKTHREADS_VARGS_MD0(sp, vabytes) \
623584SN/A   ((qt_t *)(((char *)(sp)) - 8*4 - QUICKTHREADS_STKROUNDUP(vabytes)))
633584SN/A
643584SN/Aextern void qt_vstart(void);
653584SN/A#define QUICKTHREADS_VARGS_MD1(sp)	(QUICKTHREADS_SPUT (sp, QUICKTHREADS_1, qt_vstart))
661445SN/A
671445SN/A
681310SN/A  struct qt_t *
691310SN/Aqt_vargs (struct qt_t *qsp, int nbytes, void *vargs,
701310SN/A	  void *pt, qt_function_t *startup,
711310SN/A	  qt_function_t *vuserf, qt_function_t *cleanup)
721310SN/A{
731310SN/A  va_list ap;
741310SN/A  int i;
751310SN/A  int n;		/* Number of words into original arg list. */
761310SN/A  qt_word_t *sp;
773878SN/A  int *reg;		/* Where to read passed-in-reg args. */
783878SN/A  int *stk;		/* Where to read passed-on-stk args. */
791310SN/A
801369SN/A  ap = *(va_list *)vargs;
811310SN/A  qsp = QUICKTHREADS_VARGS_MD0 (qsp, nbytes);
821634SN/A  sp = (qt_word_t *)qsp;
834167SN/A
844167SN/A  reg = (ap.__va_arg < 8)
852998SN/A    ? &ap.__va_reg[ap.__va_arg]
862998SN/A    : 0;
872998SN/A  stk = &ap.__va_stk[8];
882998SN/A  n = ap.__va_arg;
892998SN/A  for (i=0; i<nbytes/sizeof(qt_word_t) && n<8; ++i,++n) {
902998SN/A    sp[i] = *reg++;
912998SN/A  }
922998SN/A  for (; i<nbytes/sizeof(qt_word_t); ++i) {
932998SN/A    sp[i] = *stk++;
942998SN/A  }
952998SN/A
962998SN/A#ifdef QUICKTHREADS_NDEF
972998SN/A  for (i=0; i<nbytes/sizeof(qt_word_t); ++i) {
982998SN/A    sp[i] = (n < 8)
992998SN/A      ? *reg++
1002998SN/A      : *stk++;
1012998SN/A    ++n;
1022998SN/A  }
1032998SN/A#endif
1042998SN/A
1053017SN/A  QUICKTHREADS_VARGS_MD1 (QUICKTHREADS_VADJ(sp));
1062998SN/A  QUICKTHREADS_SPUT (QUICKTHREADS_VADJ(sp), QUICKTHREADS_VARGT_INDEX, pt);
107  QUICKTHREADS_SPUT (QUICKTHREADS_VADJ(sp), QUICKTHREADS_VSTARTUP_INDEX, startup);
108  QUICKTHREADS_SPUT (QUICKTHREADS_VADJ(sp), QUICKTHREADS_VUSERF_INDEX, vuserf);
109  QUICKTHREADS_SPUT (QUICKTHREADS_VADJ(sp), QUICKTHREADS_VCLEANUP_INDEX, cleanup);
110  return ((qt_t *)QUICKTHREADS_VADJ(sp));
111}
112