axp.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 
00018 /* Varargs is harder on the AXP.  Parameters are saved on the stack as
00019    something like (stack grows down to low memory; low at bottom of
00020    picture):
00021 
00022     |  :
00023     | arg6
00024     +---
00025     | iarg5
00026     |  :
00027     | iarg3     <-- va_list._a0 + va_list._offset
00028     |  :
00029     | iarg0     <-- va_list._a0
00030     +---
00031     | farg5
00032     |  :
00033     | farg0
00034     +---
00035 
00036    When some of the arguments have known type, there is no need to
00037    save all of them in the struct.  So, for example, if the routine is
00038    called
00039 
00040     zork (int a0, float a1, int a2, ...)
00041     {
00042       va_list ap;
00043       va_start (ap, a2);
00044       qt_vargs (... &ap ...);
00045     }
00046 
00047    then offset is set to 3 * 8 (8 === sizeof machine word) = 24.
00048 
00049    What this means for us is that the user's routine needs to be
00050    called with an arg list where some of the words in the `any type'
00051    parameter list have to be split and moved up in to the int/fp
00052    region.
00053 
00054    Ways in which this can fail:
00055     - The user might not know the size of the pushed arguments anyway.
00056     - Structures have funny promotion rules.
00057     - Probably lots of other things.
00058 
00059    All in all, we never promised varargs would work reliably. */
00060 
00061 
00062 
00063 #define QUICKTHREADS_VADJ(sp)   (((char *)sp) - QUICKTHREADS_VSTKBASE)
00064 
00065 #define QUICKTHREADS_VARGS_MD0(sp, vabytes) \
00066    ((qt_t *)(((char *)(sp)) - 6*2*8 - QUICKTHREADS_STKROUNDUP(vabytes)))
00067 
00068 extern void qt_vstart(void);
00069 #define QUICKTHREADS_VARGS_MD1(sp)  (QUICKTHREADS_SPUT (sp, QUICKTHREADS_R26, qt_vstart))
00070 
00071 
00072 /* Different machines use different implementations for varargs.
00073    Unfortunately, the code below ``looks in to'' the varargs
00074    structure, `va_list', and thus depends on the conventions.
00075    The following #defines try to deal with it but don't catch
00076    everything. */
00077 
00078 #ifdef __GNUC__
00079 #define _a0     __base
00080 #define _offset     __offset
00081 #else
00082 #ifdef __OSF1__
00083 #define _a0     a0
00084 #define _offset     offset
00085 #endif
00086 #endif /* def __GNUC__ */
00087 
00088 
00089   struct qt_t *
00090 qt_vargs (struct qt_t *qsp, int nbytes, struct va_list *vargs,
00091       void *pt, qt_function_t *startup,
00092       qt_function_t *vuserf, qt_function_t *cleanup)
00093 {
00094   va_list ap;
00095   int i;
00096   int max;      /* Maximum *words* of args to copy. */
00097   int tmove;        /* *Words* of args moved typed->typed. */
00098   qt_word_t *sp;
00099 
00100   ap = *(va_list *)vargs;
00101   qsp = QUICKTHREADS_VARGS_MD0 (qsp, nbytes);
00102   sp = (qt_word_t *)qsp;
00103 
00104   tmove = 6 - ap._offset/sizeof(qt_word_t);
00105 
00106   /* Copy from one typed area to the other. */
00107   for (i=0; i<tmove; ++i) {
00108     /* Integer args: */
00109     sp[i+6] = ((qt_word_t *)(ap._a0 + ap._offset))[i];
00110     /* Fp args: */
00111     sp[i] = ((qt_word_t *)(ap._a0 + ap._offset))[i-6];
00112   }
00113 
00114   max = nbytes/sizeof(qt_word_t);
00115 
00116   /* Copy from the untyped area to the typed area.  Split each arg.
00117      in to integer and floating-point save areas. */
00118   for (; i<6 && i<max; ++i) {
00119     sp[i] = sp[i+6] = ((qt_word_t *)(ap._a0 + ap._offset))[i];
00120   }
00121 
00122   /* Copy from the untyped area to the other untyped area. */
00123   for (; i<max; ++i) {
00124     sp[i+6] = ((qt_word_t *)(ap._a0 + ap._offset))[i];
00125   }
00126 
00127   QUICKTHREADS_VARGS_MD1 (QUICKTHREADS_VADJ(sp));
00128   QUICKTHREADS_SPUT (QUICKTHREADS_VADJ(sp), QUICKTHREADS_VARGT_INDEX, pt);
00129   QUICKTHREADS_SPUT (QUICKTHREADS_VADJ(sp), QUICKTHREADS_VSTARTUP_INDEX, startup);
00130   QUICKTHREADS_SPUT (QUICKTHREADS_VADJ(sp), QUICKTHREADS_VUSERF_INDEX, vuserf);
00131   QUICKTHREADS_SPUT (QUICKTHREADS_VADJ(sp), QUICKTHREADS_VCLEANUP_INDEX, cleanup);
00132   return ((qt_t *)QUICKTHREADS_VADJ(sp));
00133 }

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