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