1/*
2 * QuickThreads -- Threads-building toolkit.
3 * Copyright (c) 1993 by David Keppel
4 *
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
11 * purpose.
12 */
13
14#ifndef QUICKTHREADS_AXP_H
15#define QUICKTHREADS_AXP_H
16
17#define QUICKTHREADS_GROW_DOWN
18
19typedef unsigned long qt_word_t;
20
21
22/* Stack layout on the Alpha:
23
24   Integer:
25
26     Caller-save: r0..r8, r22..r25, r27..r29
27     argument/caller-save: r16..r21
28     callee-save: r9..r15
29     return pc *callee-save*: r26
30     stack pointer: r30
31     zero: r31
32
33   Floating-point:
34
35     Caller-save: f0..f1, f10..f15
36     argument/caller-save: f16..f21, f22..f30
37     callee-save: f2..f9
38     zero: f31
39
40   Non-varargs:
41
42   +---
43   | padding
44   | f9
45   | f8
46   | f7
47   | f6
48   | f5
49   | f4
50   | f3
51   | f2
52   | r26
53   +---
54   | padding
55   | r29
56   | r15
57   | r14
58   | r13
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
64   +---
65
66   Conventions for varargs startup:
67
68   |  :
69   | arg6
70   | iarg5
71   |  :
72   | iarg0
73   | farg5
74   |  :
75   | farg0
76   +---
77   | padding
78   | r29
79   | r15
80   | r14
81   | r13
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
87   +---
88
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. */
93
94
95/* Stack must be 16-byte aligned. */
96#define QUICKTHREADS_STKALIGN	(16)
97
98/* How much space is allocated to hold all the crud for
99   initialization: 7 registers times 8 bytes/register. */
100
101#define QUICKTHREADS_STKBASE	(10 * 8)
102#define QUICKTHREADS_VSTKBASE	QUICKTHREADS_STKBASE
103
104
105/* Offsets of various registers. */
106#define QUICKTHREADS_R26	0
107#define QUICKTHREADS_R9	1
108#define QUICKTHREADS_R10	2
109#define QUICKTHREADS_R11	3
110#define QUICKTHREADS_R12	4
111
112
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
117   functions.
118
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. */
124
125extern void qt_start(void);
126#define QUICKTHREADS_ARGS_MD(sp)	(QUICKTHREADS_SPUT (sp, QUICKTHREADS_R26, qt_start))
127
128
129/* The AXP uses a struct for `va_list', so pass a pointer to the
130   struct.  This may break some uses of `QUICKTHREADS_VARGS', but then we never
131   claimed it was totally portable. */
132
133typedef void (qt_function_t)(void);
134
135struct qt_t;
136struct va_list;
137extern 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);
142
143#define QUICKTHREADS_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));
147
148
149/* The *index* (positive offset) of where to put each value. */
150#define QUICKTHREADS_ONLY_INDEX	(QUICKTHREADS_R12)
151#define QUICKTHREADS_USER_INDEX	(QUICKTHREADS_R11)
152#define QUICKTHREADS_ARGT_INDEX	(QUICKTHREADS_R10)
153#define QUICKTHREADS_ARGU_INDEX	(QUICKTHREADS_R9)
154
155#define QUICKTHREADS_VCLEANUP_INDEX	(QUICKTHREADS_R10)
156#define QUICKTHREADS_VUSERF_INDEX		(QUICKTHREADS_R11)
157#define QUICKTHREADS_VSTARTUP_INDEX	(QUICKTHREADS_R12)
158#define QUICKTHREADS_VARGT_INDEX		(QUICKTHREADS_R9)
159
160#endif /* ndef QUICKTHREADS_AXP_H */
161