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
19 typedef unsigned long qt_word_t;
22 /* Stack layout on the Alpha:
26 Caller-save: r0..r8, r22..r25, r27..r29
27 argument/caller-save: r16..r21
29 return pc *callee-save*: r26
35 Caller-save: f0..f1, f10..f15
36 argument/caller-save: f16..f21, f22..f30
59 | r12 on startup === `only'
60 | r11 on startup === `userf'
61 | r10 on startup === `qt'
62 | r9 on startup === `qu'
63 | r26 on startup === qt_start <--- qt.sp
66 Conventions for varargs startup:
82 | r12 on startup === `startup'
83 | r11 on startup === `vuserf'
84 | r10 on startup === `cleanup'
85 | r9 on startup === `qt'
86 | r26 on startup === qt_vstart <--- qt.sp
89 Note: this is a pretty cheap/sleazy way to get things going,
90 but ``there must be a better way.'' For instance, some varargs
91 parameters could be loaded in to integer registers, or the return
92 address could be stored on top of the stack. */
95 /* Stack must be 16-byte aligned. */
96 #define QT_STKALIGN (16)
98 /* How much space is allocated to hold all the crud for
99 initialization: 7 registers times 8 bytes/register. */
101 #define QT_STKBASE (10 * 8)
102 #define QT_VSTKBASE QT_STKBASE
105 /* Offsets of various registers. */
113 /* When a never-before-run thread is restored, the return pc points
114 to a fragment of code that starts the thread running. For
115 non-vargs functions, it just calls the client's `only' function.
116 For varargs functions, it calls the startup, user, and cleanup
119 The varargs startup routine always reads 12 8-byte arguments from
120 the stack. If fewer argumets were pushed, the startup routine
121 would read off the top of the stack. To prevent errors we always
122 allocate enough space. When there are fewer args, the preallocated
123 words are simply wasted. */
125 extern void qt_start(void);
126 #define QT_ARGS_MD(sp) (QT_SPUT (sp, QT_R26, qt_start))
129 /* The AXP uses a struct for `va_list', so pass a pointer to the
130 struct. This may break some uses of `QT_VARGS', but then we never
131 claimed it was totally portable. */
133 typedef void (qt_function_t)(void);
137 extern struct qt_t *qt_vargs (struct qt_t *sp, int nbytes,
138 struct va_list *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, (struct va_list *)(&(vargs)), pt, \
145 (qt_function_t *) startup, (qt_function_t *)vuserf, \
146 (qt_function_t *)cleanup));
149 /* The *index* (positive offset) of where to put each value. */
150 #define QT_ONLY_INDEX (QT_R12)
151 #define QT_USER_INDEX (QT_R11)
152 #define QT_ARGT_INDEX (QT_R10)
153 #define QT_ARGU_INDEX (QT_R9)
155 #define QT_VCLEANUP_INDEX (QT_R10)
156 #define QT_VUSERF_INDEX (QT_R11)
157 #define QT_VSTARTUP_INDEX (QT_R12)
158 #define QT_VARGT_INDEX (QT_R9)
160 #endif /* ndef QT_AXP_H */