112027Sjungma@eit.uni-kl.de/*
212027Sjungma@eit.uni-kl.de * QuickThreads -- Threads-building toolkit.
312027Sjungma@eit.uni-kl.de * Copyright (c) 1993 by David Keppel
412027Sjungma@eit.uni-kl.de *
512027Sjungma@eit.uni-kl.de * Permission to use, copy, modify and distribute this software and
612027Sjungma@eit.uni-kl.de * its documentation for any purpose and without fee is hereby
712027Sjungma@eit.uni-kl.de * granted, provided that the above copyright notice and this notice
812027Sjungma@eit.uni-kl.de * appear in all copies.  This software is provided as a
912027Sjungma@eit.uni-kl.de * proof-of-concept and for demonstration purposes; there is no
1012027Sjungma@eit.uni-kl.de * representation about the suitability of this software for any
1112027Sjungma@eit.uni-kl.de * purpose.
1212027Sjungma@eit.uni-kl.de */
1312027Sjungma@eit.uni-kl.de
1412027Sjungma@eit.uni-kl.de#include <stdarg.h>
1512027Sjungma@eit.uni-kl.de#include "qt.h"
1612027Sjungma@eit.uni-kl.de
1712027Sjungma@eit.uni-kl.de
1812027Sjungma@eit.uni-kl.de/* Varargs is harder on the AXP.  Parameters are saved on the stack as
1912027Sjungma@eit.uni-kl.de   something like (stack grows down to low memory; low at bottom of
2012027Sjungma@eit.uni-kl.de   picture):
2112027Sjungma@eit.uni-kl.de
2212027Sjungma@eit.uni-kl.de	|  :
2312027Sjungma@eit.uni-kl.de	| arg6
2412027Sjungma@eit.uni-kl.de	+---
2512027Sjungma@eit.uni-kl.de	| iarg5
2612027Sjungma@eit.uni-kl.de	|  :
2712027Sjungma@eit.uni-kl.de	| iarg3		<-- va_list._a0 + va_list._offset
2812027Sjungma@eit.uni-kl.de	|  :
2912027Sjungma@eit.uni-kl.de	| iarg0		<-- va_list._a0
3012027Sjungma@eit.uni-kl.de	+---
3112027Sjungma@eit.uni-kl.de	| farg5
3212027Sjungma@eit.uni-kl.de	|  :
3312027Sjungma@eit.uni-kl.de	| farg0
3412027Sjungma@eit.uni-kl.de	+---
3512027Sjungma@eit.uni-kl.de
3612027Sjungma@eit.uni-kl.de   When some of the arguments have known type, there is no need to
3712027Sjungma@eit.uni-kl.de   save all of them in the struct.  So, for example, if the routine is
3812027Sjungma@eit.uni-kl.de   called
3912027Sjungma@eit.uni-kl.de
4012027Sjungma@eit.uni-kl.de	zork (int a0, float a1, int a2, ...)
4112027Sjungma@eit.uni-kl.de	{
4212027Sjungma@eit.uni-kl.de	  va_list ap;
4312027Sjungma@eit.uni-kl.de	  va_start (ap, a2);
4412027Sjungma@eit.uni-kl.de	  qt_vargs (... &ap ...);
4512027Sjungma@eit.uni-kl.de	}
4612027Sjungma@eit.uni-kl.de
4712027Sjungma@eit.uni-kl.de   then offset is set to 3 * 8 (8 === sizeof machine word) = 24.
4812027Sjungma@eit.uni-kl.de
4912027Sjungma@eit.uni-kl.de   What this means for us is that the user's routine needs to be
5012027Sjungma@eit.uni-kl.de   called with an arg list where some of the words in the `any type'
5112027Sjungma@eit.uni-kl.de   parameter list have to be split and moved up in to the int/fp
5212027Sjungma@eit.uni-kl.de   region.
5312027Sjungma@eit.uni-kl.de
5412027Sjungma@eit.uni-kl.de   Ways in which this can fail:
5512027Sjungma@eit.uni-kl.de    - The user might not know the size of the pushed arguments anyway.
5612027Sjungma@eit.uni-kl.de    - Structures have funny promotion rules.
5712027Sjungma@eit.uni-kl.de    - Probably lots of other things.
5812027Sjungma@eit.uni-kl.de
5912027Sjungma@eit.uni-kl.de   All in all, we never promised varargs would work reliably. */
6012027Sjungma@eit.uni-kl.de
6112027Sjungma@eit.uni-kl.de
6212027Sjungma@eit.uni-kl.de
6312027Sjungma@eit.uni-kl.de#define QUICKTHREADS_VADJ(sp)	(((char *)sp) - QUICKTHREADS_VSTKBASE)
6412027Sjungma@eit.uni-kl.de
6512027Sjungma@eit.uni-kl.de#define QUICKTHREADS_VARGS_MD0(sp, vabytes) \
6612027Sjungma@eit.uni-kl.de   ((qt_t *)(((char *)(sp)) - 6*2*8 - QUICKTHREADS_STKROUNDUP(vabytes)))
6712027Sjungma@eit.uni-kl.de
6812027Sjungma@eit.uni-kl.deextern void qt_vstart(void);
6912027Sjungma@eit.uni-kl.de#define QUICKTHREADS_VARGS_MD1(sp)	(QUICKTHREADS_SPUT (sp, QUICKTHREADS_R26, qt_vstart))
7012027Sjungma@eit.uni-kl.de
7112027Sjungma@eit.uni-kl.de
7212027Sjungma@eit.uni-kl.de/* Different machines use different implementations for varargs.
7312027Sjungma@eit.uni-kl.de   Unfortunately, the code below ``looks in to'' the varargs
7412027Sjungma@eit.uni-kl.de   structure, `va_list', and thus depends on the conventions.
7512027Sjungma@eit.uni-kl.de   The following #defines try to deal with it but don't catch
7612027Sjungma@eit.uni-kl.de   everything. */
7712027Sjungma@eit.uni-kl.de
7812027Sjungma@eit.uni-kl.de#ifdef __GNUC__
7912027Sjungma@eit.uni-kl.de#define _a0		__base
8012027Sjungma@eit.uni-kl.de#define _offset		__offset
8112027Sjungma@eit.uni-kl.de#else
8212027Sjungma@eit.uni-kl.de#ifdef __OSF1__
8312027Sjungma@eit.uni-kl.de#define _a0		a0
8412027Sjungma@eit.uni-kl.de#define _offset		offset
8512027Sjungma@eit.uni-kl.de#endif
8612027Sjungma@eit.uni-kl.de#endif /* def __GNUC__ */
8712027Sjungma@eit.uni-kl.de
8812027Sjungma@eit.uni-kl.de
8912027Sjungma@eit.uni-kl.de  struct qt_t *
9012027Sjungma@eit.uni-kl.deqt_vargs (struct qt_t *qsp, int nbytes, struct va_list *vargs,
9112027Sjungma@eit.uni-kl.de	  void *pt, qt_function_t *startup,
9212027Sjungma@eit.uni-kl.de	  qt_function_t *vuserf, qt_function_t *cleanup)
9312027Sjungma@eit.uni-kl.de{
9412027Sjungma@eit.uni-kl.de  va_list ap;
9512027Sjungma@eit.uni-kl.de  int i;
9612027Sjungma@eit.uni-kl.de  int max;		/* Maximum *words* of args to copy. */
9712027Sjungma@eit.uni-kl.de  int tmove;		/* *Words* of args moved typed->typed. */
9812027Sjungma@eit.uni-kl.de  qt_word_t *sp;
9912027Sjungma@eit.uni-kl.de
10012027Sjungma@eit.uni-kl.de  ap = *(va_list *)vargs;
10112027Sjungma@eit.uni-kl.de  qsp = QUICKTHREADS_VARGS_MD0 (qsp, nbytes);
10212027Sjungma@eit.uni-kl.de  sp = (qt_word_t *)qsp;
10312027Sjungma@eit.uni-kl.de
10412027Sjungma@eit.uni-kl.de  tmove = 6 - ap._offset/sizeof(qt_word_t);
10512027Sjungma@eit.uni-kl.de
10612027Sjungma@eit.uni-kl.de  /* Copy from one typed area to the other. */
10712027Sjungma@eit.uni-kl.de  for (i=0; i<tmove; ++i) {
10812027Sjungma@eit.uni-kl.de    /* Integer args: */
10912027Sjungma@eit.uni-kl.de    sp[i+6] = ((qt_word_t *)(ap._a0 + ap._offset))[i];
11012027Sjungma@eit.uni-kl.de    /* Fp args: */
11112027Sjungma@eit.uni-kl.de    sp[i] = ((qt_word_t *)(ap._a0 + ap._offset))[i-6];
11212027Sjungma@eit.uni-kl.de  }
11312027Sjungma@eit.uni-kl.de
11412027Sjungma@eit.uni-kl.de  max = nbytes/sizeof(qt_word_t);
11512027Sjungma@eit.uni-kl.de
11612027Sjungma@eit.uni-kl.de  /* Copy from the untyped area to the typed area.  Split each arg.
11712027Sjungma@eit.uni-kl.de     in to integer and floating-point save areas. */
11812027Sjungma@eit.uni-kl.de  for (; i<6 && i<max; ++i) {
11912027Sjungma@eit.uni-kl.de    sp[i] = sp[i+6] = ((qt_word_t *)(ap._a0 + ap._offset))[i];
12012027Sjungma@eit.uni-kl.de  }
12112027Sjungma@eit.uni-kl.de
12212027Sjungma@eit.uni-kl.de  /* Copy from the untyped area to the other untyped area. */
12312027Sjungma@eit.uni-kl.de  for (; i<max; ++i) {
12412027Sjungma@eit.uni-kl.de    sp[i+6] = ((qt_word_t *)(ap._a0 + ap._offset))[i];
12512027Sjungma@eit.uni-kl.de  }
12612027Sjungma@eit.uni-kl.de
12712027Sjungma@eit.uni-kl.de  QUICKTHREADS_VARGS_MD1 (QUICKTHREADS_VADJ(sp));
12812027Sjungma@eit.uni-kl.de  QUICKTHREADS_SPUT (QUICKTHREADS_VADJ(sp), QUICKTHREADS_VARGT_INDEX, pt);
12912027Sjungma@eit.uni-kl.de  QUICKTHREADS_SPUT (QUICKTHREADS_VADJ(sp), QUICKTHREADS_VSTARTUP_INDEX, startup);
13012027Sjungma@eit.uni-kl.de  QUICKTHREADS_SPUT (QUICKTHREADS_VADJ(sp), QUICKTHREADS_VUSERF_INDEX, vuserf);
13112027Sjungma@eit.uni-kl.de  QUICKTHREADS_SPUT (QUICKTHREADS_VADJ(sp), QUICKTHREADS_VCLEANUP_INDEX, cleanup);
13212027Sjungma@eit.uni-kl.de  return ((qt_t *)QUICKTHREADS_VADJ(sp));
13312027Sjungma@eit.uni-kl.de}
134