2 * QuickThreads -- Threads-building toolkit.
3 * Copyright (c) 1993 by David Keppel
5 * Permission to use, copy, modify and distribute this software and
6 * its documentation for any purpose and without fee is hereby
7 * granted, provided that the above copyright notice and this notice
8 * appear in all copies. This software is provided as a
9 * proof-of-concept and for demonstration purposes; there is no
10 * representation about the suitability of this software for any
17 typedef unsigned long qt_word_t;
21 /* Stack layout on the mips:
23 Callee-save registers are: $16-$23, $30; $f20-$f30.
24 Also save $31, return pc.
29 | r30 (fp) on startup === 0
38 | r17 on startup === `only'
39 | r16 on startup === `userf'
40 | r15 on startup === `pt'
41 | r14 on startup === `pu'
42 | r1 on startup === `qt_start'
47 | ... (8 regs worth === 32 bytes of homing area)
51 Conventions for varargs:
65 | r17 on startup === `startup'
66 | r16 on startup === `vuserf'
67 | r15 on startup === `pt'
68 | r14 on startup === `cleanup'
69 | r1 on startup === `qt_vstart'
74 | ... (8 regs worth === 32 bytes of homing area)
81 /* Stack must be doubleword aligned. */
82 #define QT_STKALIGN (16) /* Doubleword aligned. */
84 /* How much space is allocated to hold all the crud for
85 initialization: saved registers plus padding to keep the stack
86 aligned plus 8 words of padding to use as a `homing area' (for
87 r2-r9) when calling helper functions on the stack of the (not yet
88 started) thread. The varargs save area is small because it gets
89 overlapped with the top of the parameter list. In case the
90 parameter list is less than 8 args, QT_ARGS_MD0 adds some dead
91 space at the top of the stack. */
93 #define QT_STKBASE (16*4 + 8*4)
94 #define QT_VSTKBASE (8*4 + 8*4)
97 /* Index of various registers. */
106 /* When a never-before-run thread is restored, the return pc points
107 to a fragment of code that starts the thread running. For
108 non-vargs functions, it sets up arguments and calls the client's
109 `only' function. For varargs functions, the startup code calls the
110 startup, user, and cleanup functions.
112 For non-varargs functions, we set the frame pointer to 0 to
113 null-terminate the call chain.
115 For varargs functions, the frame pointer register is used to hold
116 one of the arguments, so that all arguments can be laid out in
117 memory by the conventional `qt_vargs' varargs initialization
120 The varargs startup routine always reads 8 words of arguments from
121 the stack. If there are less than 8 words of arguments, then the
122 arg list could call off the top of the stack. To prevent fall-off,
123 always allocate 8 words. */
125 extern void qt_start(void);
126 #define QT_ARGS_MD(sp) \
127 (QT_SPUT (sp, QT_1, qt_start), \
128 QT_SPUT (sp, QT_30, 0))
131 /* The m88k uses a struct for `va_list', so pass a pointer to the
134 typedef void (qt_function_t)(void);
137 extern struct qt_t *qt_vargs (struct qt_t *sp, int nbytes,
138 void *vargs, void *pt,
139 qt_function_t *startup,
140 qt_function_t *vuserf,
141 qt_function_t *cleanup);
143 #define QT_VARGS(sp, nbytes, vargs, pt, startup, vuserf, cleanup) \
144 (qt_vargs (sp, nbytes, &(vargs), pt, (qt_function_t *)startup, \
145 (qt_function_t *)vuserf, (qt_function_t *)cleanup))
148 /* The *index* (positive offset) of where to put each value. */
149 #define QT_ONLY_INDEX (QT_17)
150 #define QT_USER_INDEX (QT_16)
151 #define QT_ARGT_INDEX (QT_15)
152 #define QT_ARGU_INDEX (QT_14)
154 #define QT_VCLEANUP_INDEX (QT_14)
155 #define QT_VUSERF_INDEX (QT_16)
156 #define QT_VSTARTUP_INDEX (QT_17)
157 #define QT_VARGT_INDEX (QT_15)
159 #endif /* ndef QT_M88K_H */