m88k.c

Go to the documentation of this file.
00001 /*
00002  * QuickThreads -- Threads-building toolkit.
00003  * Copyright (c) 1993 by David Keppel
00004  *
00005  * Permission to use, copy, modify and distribute this software and
00006  * its documentation for any purpose and without fee is hereby
00007  * granted, provided that the above copyright notice and this notice
00008  * appear in all copies.  This software is provided as a
00009  * proof-of-concept and for demonstration purposes; there is no
00010  * representation about the suitability of this software for any
00011  * purpose.
00012  */
00013 
00014 #include <stdarg.h>
00015 #include "qt.h"
00016 
00017 /* Varargs is harder on the m88k.  Parameters are saved on the stack as
00018    something like (stack grows down to low memory; low at bottom of
00019    picture):
00020 
00021     |  :
00022     | arg8      <-- va_list.__va_stk
00023     +---
00024     |  :
00025     +---
00026     | arg7
00027     |  :
00028     | iarg0     <-- va_list.__va_reg
00029     +---
00030     |  :
00031     | va_list { __va_arg, __va_stk, __va_reg }
00032     |  :
00033     +---
00034 
00035    Here, `va_list.__va_arg' is the number of word-size arguments
00036    that have already been skipped.  Doubles must be double-arligned.
00037 
00038    What this means for us is that the user's routine needs to be
00039    called with an arg list where some of the words in the `__va_stk'
00040    part of the parameter list have to be promoted to registers.
00041 
00042    BUG: doubleword register arguments must be double-aligned.  If
00043    something is passed as an even # arg and used as an odd # arg or
00044    vice-versa, the code in the called routine (in the new thread) that
00045    decides how to adjust the index will get it wrong, because it will
00046    be expect it to be, say, doubleword aligned and it will really be
00047    singleword aligned.
00048 
00049    I'm not sure you can solve this without knowing the types of all
00050    the arguments.  All in all, we never promised varargs would work
00051    reliably. */
00052 
00053 
00054 
00055 #define QUICKTHREADS_VADJ(sp)   (((char *)sp) - QUICKTHREADS_VSTKBASE)
00056 
00057 /* Always allocate at least enough space for 8 args; waste some space
00058    at the base of the stack to ensure the startup routine doesn't read
00059    off the end of the stack. */
00060 
00061 #define QUICKTHREADS_VARGS_MD0(sp, vabytes) \
00062    ((qt_t *)(((char *)(sp)) - 8*4 - QUICKTHREADS_STKROUNDUP(vabytes)))
00063 
00064 extern void qt_vstart(void);
00065 #define QUICKTHREADS_VARGS_MD1(sp)  (QUICKTHREADS_SPUT (sp, QUICKTHREADS_1, qt_vstart))
00066 
00067 
00068   struct qt_t *
00069 qt_vargs (struct qt_t *qsp, int nbytes, void *vargs,
00070       void *pt, qt_function_t *startup,
00071       qt_function_t *vuserf, qt_function_t *cleanup)
00072 {
00073   va_list ap;
00074   int i;
00075   int n;        /* Number of words into original arg list. */
00076   qt_word_t *sp;
00077   int *reg;     /* Where to read passed-in-reg args. */
00078   int *stk;     /* Where to read passed-on-stk args. */
00079 
00080   ap = *(va_list *)vargs;
00081   qsp = QUICKTHREADS_VARGS_MD0 (qsp, nbytes);
00082   sp = (qt_word_t *)qsp;
00083 
00084   reg = (ap.__va_arg < 8)
00085     ? &ap.__va_reg[ap.__va_arg]
00086     : 0;
00087   stk = &ap.__va_stk[8];
00088   n = ap.__va_arg;
00089   for (i=0; i<nbytes/sizeof(qt_word_t) && n<8; ++i,++n) {
00090     sp[i] = *reg++;
00091   }
00092   for (; i<nbytes/sizeof(qt_word_t); ++i) {
00093     sp[i] = *stk++;
00094   }
00095 
00096 #ifdef QUICKTHREADS_NDEF
00097   for (i=0; i<nbytes/sizeof(qt_word_t); ++i) {
00098     sp[i] = (n < 8)
00099       ? *reg++
00100       : *stk++;
00101     ++n;
00102   }
00103 #endif
00104 
00105   QUICKTHREADS_VARGS_MD1 (QUICKTHREADS_VADJ(sp));
00106   QUICKTHREADS_SPUT (QUICKTHREADS_VADJ(sp), QUICKTHREADS_VARGT_INDEX, pt);
00107   QUICKTHREADS_SPUT (QUICKTHREADS_VADJ(sp), QUICKTHREADS_VSTARTUP_INDEX, startup);
00108   QUICKTHREADS_SPUT (QUICKTHREADS_VADJ(sp), QUICKTHREADS_VUSERF_INDEX, vuserf);
00109   QUICKTHREADS_SPUT (QUICKTHREADS_VADJ(sp), QUICKTHREADS_VCLEANUP_INDEX, cleanup);
00110   return ((qt_t *)QUICKTHREADS_VADJ(sp));
00111 }

Generated on Wed Jan 21 15:32:10 2009 for SystemC by  doxygen 1.5.5