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_386_H
15#define QUICKTHREADS_386_H
16
17typedef unsigned long qt_word_t;
18
19/* Thread's initial stack layout on the i386:
20
21   non-varargs:
22
23   +---
24   | arg[2]	=== `userf' on startup
25   | arg[1]	=== `pt' on startup
26   | arg[0]	=== `pu' on startup
27   +---
28   | ret pc === qt_error
29   +---
30   | ret pc	=== `only' on startup
31   +---
32   | %ebp
33   | %esi
34   | %edi
35   | %ebx				<--- qt_t.sp
36   +---
37
38   When a non-varargs thread is started, it ``returns'' directly to
39   the client's `only' function.
40
41   varargs:
42
43   +---
44   | arg[n-1]
45   | ..
46   | arg[0]
47   +---
48   | ret pc	=== `qt_vstart'
49   +---
50   | %ebp	=== `startup'
51   | %esi	=== `cleanup'
52   | %edi	=== `pt'
53   | %ebx	=== `vuserf'		<--- qt_t.sp
54   +---
55
56   When a varargs thread is started, it ``returns'' to the `qt_vstart'
57   startup code.  The startup code calls the appropriate functions. */
58
59
60/* What to do to start a varargs thread running. */
61extern void qt_vstart (void);
62
63
64/* Hold 4 saved regs plus two return pcs (qt_error, qt_start) plus
65   three args. */
66#define QUICKTHREADS_STKBASE	(13 * 4)
67
68/* Hold 4 saved regs plus one return pc (qt_vstart). */
69#define QUICKTHREADS_VSTKBASE	(5 * 4)
70
71
72/* Stack must be 16-byte aligned at function call instr. (SSE data support) */
73#define QUICKTHREADS_STKALIGN	(16)
74
75
76/* Where to place various arguments. */
77#define QUICKTHREADS_ONLY_INDEX	(QUICKTHREADS_PC)
78#define QUICKTHREADS_USER_INDEX	(QUICKTHREADS_ARG2)
79#define QUICKTHREADS_ARGT_INDEX	(QUICKTHREADS_ARG1)
80#define QUICKTHREADS_ARGU_INDEX	(QUICKTHREADS_ARG0)
81
82#define QUICKTHREADS_VSTARTUP_INDEX	(QUICKTHREADS_EBP)
83#define QUICKTHREADS_VUSERF_INDEX		(QUICKTHREADS_EBX)
84#define QUICKTHREADS_VCLEANUP_INDEX	(QUICKTHREADS_ESI)
85#define QUICKTHREADS_VARGT_INDEX		(QUICKTHREADS_EDI)
86
87
88#define QUICKTHREADS_EBX        0
89#define QUICKTHREADS_EDI        1
90#define QUICKTHREADS_ESI        2
91#define QUICKTHREADS_EBP        3
92#define QUICKTHREADS_POP0       4
93#define QUICKTHREADS_POP1       5
94#define QUICKTHREADS_POP2       6
95#define QUICKTHREADS_PC         7
96/* The following are defined only for non-varargs. */
97#define QUICKTHREADS_POPE       8
98#define QUICKTHREADS_ARG0       9
99#define QUICKTHREADS_ARG1      10
100#define QUICKTHREADS_ARG2      11
101#define QUICKTHREADS_RPC       12
102
103
104/* Stack grows down.  The top of the stack is the first thing to
105   pop off (preincrement, postdecrement). */
106#define QUICKTHREADS_GROW_DOWN
107
108extern void qt_error (void);
109
110/* For correct 16-byte stack alignment (auto-relocatable functions) */
111extern void qt_tramp (void);
112extern void qt_align (void);
113
114/* Push on the error return address and the alignment/trampoline functions. */
115#define QUICKTHREADS_ARGS_MD(sto) \
116  (QUICKTHREADS_SPUT (sto, QUICKTHREADS_POP0, qt_align), \
117   QUICKTHREADS_SPUT (sto, QUICKTHREADS_POP1, qt_align), \
118   QUICKTHREADS_SPUT (sto, QUICKTHREADS_POP2, qt_align), \
119   QUICKTHREADS_SPUT (sto, QUICKTHREADS_POPE, qt_tramp), \
120   QUICKTHREADS_SPUT (sto, QUICKTHREADS_RPC, qt_error))
121
122
123/* When varargs are pushed, allocate space for all the args. */
124#define QUICKTHREADS_VARGS_MD0(sto, nbytes) \
125  ((qt_t *)(((char *)(sto)) - QUICKTHREADS_STKROUNDUP(nbytes)))
126
127#define QUICKTHREADS_VARGS_MD1(sto) \
128  (QUICKTHREADS_SPUT (sto, QUICKTHREADS_PC, qt_vstart))
129
130#define QUICKTHREADS_VARGS_DEFAULT
131
132#endif /* QUICKTHREADS_386_H */
133