Annotation of gforth/threading.h, revision 1.5
1.1 pazsan 1: /* This file defines a number of threading schemes.
1.2 anton 2:
1.4 anton 3: Copyright (C) 1995, 1996 Free Software Foundation, Inc.
1.2 anton 4:
5: This file is part of Gforth.
6:
7: Gforth is free software; you can redistribute it and/or
8: modify it under the terms of the GNU General Public License
9: as published by the Free Software Foundation; either version 2
10: of the License, or (at your option) any later version.
11:
12: This program is distributed in the hope that it will be useful,
13: but WITHOUT ANY WARRANTY; without even the implied warranty of
14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15: GNU General Public License for more details.
16:
17: You should have received a copy of the GNU General Public License
18: along with this program; if not, write to the Free Software
19: Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20:
21:
1.4 anton 22: This files defines macros for threading. Many sets of macros are
23: defined. Functionally they have only one difference: Some implement
24: direct threading, some indirect threading. The other differences are
25: just variations to help GCC generate faster code for various
26: machines.
27:
28: (Well, to tell the truth, there actually is another functional
29: difference in some pathological cases: e.g., a '!' stores into the
30: cell where the next executed word comes from; or, the next word
31: executed comes from the top-of-stack. These differences are one of
32: the reasons why GCC cannot produce the right variation by itself. We
33: chose disallowing such practices and using the added implementation
34: freedom to achieve a significant speedup, because these practices
35: are not common in Forth (I have never heard of or seen anyone using
36: them), and it is easy to circumvent problems: A control flow change
37: will flush any prefetched words; you may want to do a "0
38: drop" before that to write back the top-of-stack cache.)
39:
40: These macro sets are used in the following ways: After translation
41: to C a typical primitive looks like
42:
43: ...
44: {
45: DEF_CA
46: other declarations
47: NEXT_P0;
48: main part of the primitive
49: NEXT_P1;
50: store results to stack
51: NEXT_P2;
52: }
53:
54: DEF_CA and all the NEXT_P* together must implement NEXT; In the main
55: part the instruction pointer can be read with IP, changed with
56: INC_IP(const_inc), and the cell right behind the presently executing
57: word (i.e. the value of *IP) is accessed with NEXT_INST.
58:
59: If a primitive does not fall through the main part, it has to do the
60: rest by itself. If it changes ip, it has to redo NEXT_P0 (perhaps we
61: should define a macro SET_IP).
62:
63: Some primitives (execute, dodefer) do not end with NEXT, but with
64: EXEC(.). If NEXT_P0 has been called earlier, it has to perform
65: "ip=IP;" to ensure that ip has the right value (NEXT_P0 may change
66: it).
67:
68: Finally, there is NEXT1_P1 and NEXT1_P2, which are parts of EXEC
69: (EXEC(XT) could be defined as "cfa=XT; NEXT1_P1; NEXT1_P2;" (is this
70: true?)) and are used for making docol faster.
71:
72: We can define the ways in which these macros are used with a regular
73: expression:
74:
75: For a primitive
76:
77: DEF_CA NEXT_P0 ( IP | INC_IP | NEXT_INST | ip=...; NEXT_P0 ) * ( NEXT_P1 NEXT_P2 | EXEC(...) )
78:
79: For a run-time routine, e.g., docol:
80: PFA1(cfa) ( NEXT_P0 NEXT | cfa=...; NEXT1_P1; NEXT1_P2 | EXEC(...) )
81:
82: This comment does not yet describe all the dependences that the
83: macros have to satisfy.
84:
1.2 anton 85: To organize the former ifdef chaos, each path is separated
86: This gives a quite impressive number of paths, but you clearly
87: find things that go together.
1.4 anton 88:
89: It should be possible to organize the whole thing in a way that
90: contains less redundancy and allows a simpler description.
91:
1.2 anton 92: */
1.1 pazsan 93:
94: #ifndef GETCFA
95: # define CFA_NEXT
96: #endif
97:
1.5 ! anton 98: #ifdef DOUBLY_INDIRECT
! 99: # define NEXT_P0 ({cfa=*ip;})
! 100: # define IP (ip)
! 101: # define NEXT_INST (cfa)
! 102: # define INC_IP(const_inc) ({cfa=IP[const_inc]; ip+=(const_inc);})
! 103: # define DEF_CA Label ca;
! 104: # define NEXT_P1 ({ip++; ca=**cfa;})
! 105: # define NEXT_P2 ({goto *ca;})
! 106: # define EXEC(XT) ({DEF_CA cfa=(XT); ca=**cfa; goto *ca;})
! 107: # define NEXT1_P1 ({ca = **cfa;})
! 108: # define NEXT1_P2 ({goto *ca;})
! 109:
! 110: #else /* !defined(DOUBLY_INDIRECT) */
! 111:
1.1 pazsan 112: #if defined(DIRECT_THREADED) && defined(AUTO_INCREMENT)\
113: && defined(LONG_LATENCY) && defined(CFA_NEXT)
114: #warning scheme 1
115: # define NEXT_P0 ({cfa=*ip++;})
116: # define IP (ip-1)
117: # define NEXT_INST (cfa)
118: # define INC_IP(const_inc) ({cfa=IP[const_inc]; ip+=(const_inc);})
119: # define DEF_CA
120: # define NEXT_P1
121: # define NEXT_P2 ({goto *cfa;})
122: # define EXEC(XT) ({cfa=(XT); goto *cfa;})
123: #endif
124:
125: #if defined(DIRECT_THREADED) && defined(AUTO_INCREMENT)\
126: && defined(LONG_LATENCY) && !defined(CFA_NEXT)
127: #warning scheme 2
128: # define NEXT_P0 (ip++)
129: # define IP (ip-1)
130: # define NEXT_INST (*(ip-1))
131: # define INC_IP(const_inc) ({ ip+=(const_inc);})
132: # define DEF_CA
133: # define NEXT_P1
134: # define NEXT_P2 ({goto **(ip-1);})
135: # define EXEC(XT) ({goto *(XT);})
136: #endif
137:
138:
139: #if defined(DIRECT_THREADED) && defined(AUTO_INCREMENT)\
140: && !defined(LONG_LATENCY) && defined(CFA_NEXT)
141: #warning scheme 3
142: # define NEXT_P0
143: # define IP (ip)
144: # define NEXT_INST (*ip)
145: # define INC_IP(const_inc) ({ip+=(const_inc);})
146: # define DEF_CA
147: # define NEXT_P1 ({cfa=*ip++;})
148: # define NEXT_P2 ({goto *cfa;})
149: # define EXEC(XT) ({cfa=(XT); goto *cfa;})
150: #endif
151:
152: #if defined(DIRECT_THREADED) && defined(AUTO_INCREMENT)\
153: && !defined(LONG_LATENCY) && !defined(CFA_NEXT)
154: #warning scheme 4
155: # define NEXT_P0
156: # define IP (ip)
157: # define NEXT_INST (*ip)
158: # define INC_IP(const_inc) ({ ip+=(const_inc);})
159: # define DEF_CA
160: # define NEXT_P1
161: # define NEXT_P2 ({goto **(ip++);})
162: # define EXEC(XT) ({goto *(XT);})
163: #endif
164:
165: /* without autoincrement */
166:
167: #if defined(DIRECT_THREADED) && !defined(AUTO_INCREMENT)\
168: && defined(LONG_LATENCY) && defined(CFA_NEXT)
169: #warning scheme 5
170: # define NEXT_P0 ({cfa=*ip;})
171: # define IP (ip)
172: # define NEXT_INST (cfa)
173: # define INC_IP(const_inc) ({cfa=IP[const_inc]; ip+=(const_inc);})
174: # define DEF_CA
175: # define NEXT_P1 (ip++)
176: # define NEXT_P2 ({goto *cfa;})
177: # define EXEC(XT) ({cfa=(XT); goto *cfa;})
178: #endif
179:
180: #if defined(DIRECT_THREADED) && !defined(AUTO_INCREMENT)\
181: && defined(LONG_LATENCY) && !defined(CFA_NEXT)
182: #warning scheme 6
183: # define NEXT_P0
184: # define IP (ip)
185: # define NEXT_INST (*ip)
1.2 anton 186: # define INC_IP(const_inc) ({ip+=(const_inc);})
1.1 pazsan 187: # define DEF_CA
188: # define NEXT_P1 (ip++)
189: # define NEXT_P2 ({goto **(ip-1);})
190: # define EXEC(XT) ({goto *(XT);})
191: #endif
192:
193:
194: #if defined(DIRECT_THREADED) && !defined(AUTO_INCREMENT)\
195: && !defined(LONG_LATENCY) && defined(CFA_NEXT)
196: #warning scheme 7
197: # define NEXT_P0
198: # define IP (ip)
199: # define NEXT_INST (*ip)
200: # define INC_IP(const_inc) ({ip+=(const_inc);})
201: # define DEF_CA
202: # define NEXT_P1 ({cfa=*ip++;})
203: # define NEXT_P2 ({goto *cfa;})
204: # define EXEC(XT) ({cfa=(XT); goto *cfa;})
205: #endif
206:
207: #if defined(DIRECT_THREADED) && !defined(AUTO_INCREMENT)\
208: && !defined(LONG_LATENCY) && !defined(CFA_NEXT)
209: #warning scheme 8
210: # define NEXT_P0
211: # define IP (ip)
212: # define NEXT_INST (*IP)
213: # define INC_IP(const_inc) ({ ip+=(const_inc);})
214: # define DEF_CA
215: # define NEXT_P1 (ip++)
216: # define NEXT_P2 ({goto **(ip-1);})
217: # define EXEC(XT) ({goto *(XT);})
218: #endif
219:
220: /* common settings for direct THREADED */
221:
222:
223: /* indirect THREADED */
224:
225: #if !defined(DIRECT_THREADED) && defined(AUTO_INCREMENT)\
226: && defined(LONG_LATENCY) && defined(CISC_NEXT)
227: # define NEXT_P0 ({cfa=*ip++;})
228: # define IP (ip-1)
229: # define NEXT_INST (cfa)
230: # define INC_IP(const_inc) ({cfa=IP[const_inc]; ip+=(const_inc);})
231: # define DEF_CA
232: # define NEXT_P1
233: # define NEXT_P2 ({goto **cfa;})
234: # define EXEC(XT) ({cfa=(XT); goto **cfa;})
235: #endif
236:
237: #if !defined(DIRECT_THREADED) && defined(AUTO_INCREMENT)\
238: && defined(LONG_LATENCY) && !defined(CISC_NEXT)
239: # define NEXT_P0 ({cfa=*ip++;})
240: # define IP (ip-1)
241: # define NEXT_INST (cfa)
242: # define INC_IP(const_inc) ({cfa=IP[const_inc]; ip+=(const_inc);})
243: # define DEF_CA Label ca;
244: # define NEXT_P1 ({ca=*cfa;})
245: # define NEXT_P2 ({goto *ca;})
246: # define EXEC(XT) ({DEF_CA cfa=(XT); ca=*cfa; goto *ca;})
247: #endif
248:
249:
250: #if !defined(DIRECT_THREADED) && defined(AUTO_INCREMENT)\
251: && !defined(LONG_LATENCY) && defined(CISC_NEXT)
252: # define NEXT_P0
253: # define IP (ip)
254: # define NEXT_INST (*ip)
255: # define INC_IP(const_inc) ({ip+=(const_inc);})
256: # define DEF_CA
1.3 pazsan 257: # define NEXT_P1
258: # define NEXT_P2 ({cfa=*ip++; goto **cfa;})
1.1 pazsan 259: # define EXEC(XT) ({cfa=(XT); goto **cfa;})
260: #endif
261:
262: #if !defined(DIRECT_THREADED) && defined(AUTO_INCREMENT)\
263: && !defined(LONG_LATENCY) && !defined(CISC_NEXT)
264: # define NEXT_P0 ({cfa=*ip++;})
265: # define IP (ip-1)
266: # define NEXT_INST (cfa)
267: # define INC_IP(const_inc) ({cfa=IP[const_inc]; ip+=(const_inc);})
268: # define DEF_CA Label ca;
269: # define NEXT_P1 ({ca=*cfa;})
270: # define NEXT_P2 ({goto *ca;})
271: # define EXEC(XT) ({DEF_CA cfa=(XT); ca=*cfa; goto *ca;})
272: #endif
273:
274:
275: /* without autoincrement */
276:
277: #if !defined(DIRECT_THREADED) && !defined(AUTO_INCREMENT)\
278: && defined(LONG_LATENCY) && defined(CISC_NEXT)
279: # define NEXT_P0 ({cfa=*ip;})
280: # define IP (ip)
281: # define NEXT_INST (cfa)
282: # define INC_IP(const_inc) ({cfa=IP[const_inc]; ip+=(const_inc);})
283: # define DEF_CA
284: # define NEXT_P1 (ip++)
285: # define NEXT_P2 ({goto **cfa;})
286: # define EXEC(XT) ({cfa=(XT); goto **cfa;})
287: #endif
288:
289: #if !defined(DIRECT_THREADED) && !defined(AUTO_INCREMENT)\
290: && defined(LONG_LATENCY) && !defined(CISC_NEXT)
291: # define NEXT_P0 ({cfa=*ip;})
292: # define IP (ip)
293: # define NEXT_INST (cfa)
294: # define INC_IP(const_inc) ({cfa=IP[const_inc]; ip+=(const_inc);})
295: # define DEF_CA Label ca;
296: # define NEXT_P1 ({ip++; ca=*cfa;})
297: # define NEXT_P2 ({goto *ca;})
298: # define EXEC(XT) ({DEF_CA cfa=(XT); ca=*cfa; goto *ca;})
299: #endif
300:
301:
302: #if !defined(DIRECT_THREADED) && !defined(AUTO_INCREMENT)\
303: && !defined(LONG_LATENCY) && defined(CISC_NEXT)
304: # define NEXT_P0
305: # define IP (ip)
306: # define NEXT_INST (*ip)
307: # define INC_IP(const_inc) ({ip+=(const_inc);})
308: # define DEF_CA
1.3 pazsan 309: # define NEXT_P1
310: # define NEXT_P2 ({cfa=*ip++; goto **cfa;})
1.1 pazsan 311: # define EXEC(XT) ({cfa=(XT); goto **cfa;})
312: #endif
313:
314: #if !defined(DIRECT_THREADED) && !defined(AUTO_INCREMENT)\
315: && !defined(LONG_LATENCY) && !defined(CISC_NEXT)
316: # define NEXT_P0 ({cfa=*ip;})
317: # define IP (ip)
318: # define NEXT_INST (cfa)
319: # define INC_IP(const_inc) ({cfa=IP[const_inc]; ip+=(const_inc);})
320: # define DEF_CA Label ca;
321: # define NEXT_P1 ({ip++; ca=*cfa;})
322: # define NEXT_P2 ({goto *ca;})
323: # define EXEC(XT) ({DEF_CA cfa=(XT); ca=*cfa; goto *ca;})
324: #endif
325:
326: #if defined(CISC_NEXT) && !defined(LONG_LATENCY)
327: # define NEXT1_P1
328: # ifdef DIRECT_THREADED
329: # define NEXT1_P2 ({goto *cfa;})
330: # else
331: # define NEXT1_P2 ({goto **cfa;})
332: # endif /* DIRECT_THREADED */
1.5 ! anton 333: #else /* !defined(CISC_NEXT) || defined(LONG_LATENCY) */
1.1 pazsan 334: # ifdef DIRECT_THREADED
335: # define NEXT1_P1
336: # define NEXT1_P2 ({goto *cfa;})
1.5 ! anton 337: # else /* !DIRECT_THREADED */
1.1 pazsan 338: # define NEXT1_P1 ({ca = *cfa;})
339: # define NEXT1_P2 ({goto *ca;})
1.5 ! anton 340: # endif /* !DIRECT_THREADED */
! 341: #endif /* !defined(CISC_NEXT) || defined(LONG_LATENCY) */
! 342:
! 343: #endif /* !defined(DOUBLY_INDIRECT) */
! 344:
! 345: #define NEXT ({DEF_CA NEXT_P1; NEXT_P2;})
! 346:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>