Annotation of gforth/engine/threaded.h, revision 1.3
1.1 anton 1: /* This file defines a number of threading schemes.
2:
1.2 anton 3: Copyright (C) 1995, 1996,1997 Free Software Foundation, Inc.
1.1 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:
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:
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.
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:
92: */
93:
94: #ifndef GETCFA
95: # define CFA_NEXT
1.3 ! anton 96: /* a more appropriate name would be CFA_LIVE, i.e., cfa is live after NEXT */
1.1 anton 97: #endif
98:
99: #ifdef DOUBLY_INDIRECT
100: # define NEXT_P0 ({cfa=*ip;})
101: # define IP (ip)
1.3 ! anton 102: # define SET_IP(p) ({ip=(p); NEXT_P0;})
1.1 anton 103: # define NEXT_INST (cfa)
104: # define INC_IP(const_inc) ({cfa=IP[const_inc]; ip+=(const_inc);})
105: # define DEF_CA Label ca;
106: # define NEXT_P1 ({ip++; ca=**cfa;})
107: # define NEXT_P2 ({goto *ca;})
108: # define EXEC(XT) ({DEF_CA cfa=(XT); ca=**cfa; goto *ca;})
109: # define NEXT1_P1 ({ca = **cfa;})
110: # define NEXT1_P2 ({goto *ca;})
111:
112: #else /* !defined(DOUBLY_INDIRECT) */
113:
1.3 ! anton 114: #if defined(DIRECT_THREADED)
! 115:
! 116: /* note that the "cfa dead" versions only work if GETCFA exists and works */
! 117:
! 118: #if THREADING_SCHEME==1
! 119: #warning direct threading scheme 1: autoinc, long latency, cfa live
1.1 anton 120: # define NEXT_P0 ({cfa=*ip++;})
121: # define IP (ip-1)
1.3 ! anton 122: # define SET_IP(p) ({ip=(p); NEXT_P0;})
1.1 anton 123: # define NEXT_INST (cfa)
124: # define INC_IP(const_inc) ({cfa=IP[const_inc]; ip+=(const_inc);})
125: # define DEF_CA
126: # define NEXT_P1
127: # define NEXT_P2 ({goto *cfa;})
128: # define EXEC(XT) ({cfa=(XT); goto *cfa;})
129: #endif
130:
1.3 ! anton 131: #if THREADING_SCHEME==2
! 132: #warning direct threading scheme 2: autoinc, long latency, cfa dead
1.1 anton 133: # define NEXT_P0 (ip++)
134: # define IP (ip-1)
1.3 ! anton 135: # define SET_IP(p) ({ip=(p); NEXT_P0;})
1.1 anton 136: # define NEXT_INST (*(ip-1))
137: # define INC_IP(const_inc) ({ ip+=(const_inc);})
138: # define DEF_CA
139: # define NEXT_P1
140: # define NEXT_P2 ({goto **(ip-1);})
141: # define EXEC(XT) ({goto *(XT);})
142: #endif
143:
144:
1.3 ! anton 145: #if THREADING_SCHEME==3
! 146: #warning direct threading scheme 3: autoinc, low latency, cfa live
1.1 anton 147: # define NEXT_P0
148: # define IP (ip)
1.3 ! anton 149: # define SET_IP(p) ({ip=(p); NEXT_P0;})
1.1 anton 150: # define NEXT_INST (*ip)
151: # define INC_IP(const_inc) ({ip+=(const_inc);})
152: # define DEF_CA
153: # define NEXT_P1 ({cfa=*ip++;})
154: # define NEXT_P2 ({goto *cfa;})
155: # define EXEC(XT) ({cfa=(XT); goto *cfa;})
156: #endif
157:
1.3 ! anton 158: #if THREADING_SCHEME==4
! 159: #warning direct threading scheme 4: autoinc, low latency, cfa dead
1.1 anton 160: # define NEXT_P0
161: # define IP (ip)
1.3 ! anton 162: # define SET_IP(p) ({ip=(p); NEXT_P0;})
1.1 anton 163: # define NEXT_INST (*ip)
164: # define INC_IP(const_inc) ({ ip+=(const_inc);})
165: # define DEF_CA
166: # define NEXT_P1
167: # define NEXT_P2 ({goto **(ip++);})
168: # define EXEC(XT) ({goto *(XT);})
169: #endif
170:
1.3 ! anton 171: #if THREADING_SCHEME==5
! 172: #warning direct threading scheme 5: long latency, cfa live
1.1 anton 173: # define NEXT_P0 ({cfa=*ip;})
174: # define IP (ip)
1.3 ! anton 175: # define SET_IP(p) ({ip=(p); NEXT_P0;})
1.1 anton 176: # define NEXT_INST (cfa)
177: # define INC_IP(const_inc) ({cfa=IP[const_inc]; ip+=(const_inc);})
178: # define DEF_CA
179: # define NEXT_P1 (ip++)
180: # define NEXT_P2 ({goto *cfa;})
181: # define EXEC(XT) ({cfa=(XT); goto *cfa;})
182: #endif
183:
1.3 ! anton 184: #if THREADING_SCHEME==6
! 185: #warning direct threading scheme 6: long latency, cfa dead
1.1 anton 186: # define NEXT_P0
187: # define IP (ip)
1.3 ! anton 188: # define SET_IP(p) ({ip=(p); NEXT_P0;})
1.1 anton 189: # define NEXT_INST (*ip)
190: # define INC_IP(const_inc) ({ip+=(const_inc);})
191: # define DEF_CA
192: # define NEXT_P1 (ip++)
193: # define NEXT_P2 ({goto **(ip-1);})
194: # define EXEC(XT) ({goto *(XT);})
195: #endif
196:
197:
1.3 ! anton 198: #if THREADING_SCHEME==7
! 199: #warning direct threading scheme 7: low latency, cfa live
1.1 anton 200: # define NEXT_P0
201: # define IP (ip)
1.3 ! anton 202: # define SET_IP(p) ({ip=(p); NEXT_P0;})
1.1 anton 203: # define NEXT_INST (*ip)
204: # define INC_IP(const_inc) ({ip+=(const_inc);})
205: # define DEF_CA
206: # define NEXT_P1 ({cfa=*ip++;})
207: # define NEXT_P2 ({goto *cfa;})
208: # define EXEC(XT) ({cfa=(XT); goto *cfa;})
209: #endif
210:
1.3 ! anton 211: #if THREADING_SCHEME==8
! 212: #warning direct threading scheme 8: cfa dead, i386 hack
1.1 anton 213: # define NEXT_P0
214: # define IP (ip)
1.3 ! anton 215: # define SET_IP(p) ({ip=(p); NEXT_P0;})
1.1 anton 216: # define NEXT_INST (*IP)
217: # define INC_IP(const_inc) ({ ip+=(const_inc);})
218: # define DEF_CA
219: # define NEXT_P1 (ip++)
220: # define NEXT_P2 ({goto **(ip-1);})
221: # define EXEC(XT) ({goto *(XT);})
222: #endif
223:
1.3 ! anton 224: #if THREADING_SCHEME==9
! 225: #warning direct threading scheme 9: Power/PPC hack, long latency
! 226: /* Power uses a prepare-to-branch instruction, and the latency between
! 227: this inst and the branch is 5 cycles on a PPC604; so we utilize this
! 228: to do some prefetching in between */
! 229: # define NEXT_P0
! 230: # define IP ip
! 231: # define SET_IP(p) ({ip=(p); next_cfa=*ip; NEXT_P0;})
! 232: # define NEXT_INST (next_cfa)
! 233: # define INC_IP(const_inc) ({next_cfa=IP[const_inc]; ip+=(const_inc);})
! 234: # define DEF_CA Label ca;
! 235: # define NEXT_P1 ({ca=next_cfa; cfa=next_cfa; ip++; next_cfa=*ip;})
! 236: # define NEXT_P2 ({goto *ca;})
! 237: # define EXEC(XT) ({cfa=(XT); goto *cfa;})
! 238: # define MORE_VARS Xt next_cfa;
! 239: #endif
1.1 anton 240:
1.3 ! anton 241: #if THREADING_SCHEME==10
! 242: #warning direct threading scheme 10: plain (no attempt at scheduling)
! 243: # define NEXT_P0
! 244: # define IP (ip)
! 245: # define SET_IP(p) ({ip=(p); NEXT_P0;})
! 246: # define NEXT_INST (*ip)
! 247: # define INC_IP(const_inc) ({ip+=(const_inc);})
! 248: # define DEF_CA
! 249: # define NEXT_P1
! 250: # define NEXT_P2 ({cfa=*ip++; goto *cfa;})
! 251: # define EXEC(XT) ({cfa=(XT); goto *cfa;})
! 252: #endif
1.1 anton 253:
1.3 ! anton 254: /* direct threaded */
! 255: #else
1.1 anton 256: /* indirect THREADED */
257:
1.3 ! anton 258: #if THREADING_SCHEME==1
! 259: #warning indirect threading scheme 1: autoinc, long latency, cisc
1.1 anton 260: # define NEXT_P0 ({cfa=*ip++;})
261: # define IP (ip-1)
1.3 ! anton 262: # define SET_IP(p) ({ip=(p); NEXT_P0;})
1.1 anton 263: # define NEXT_INST (cfa)
264: # define INC_IP(const_inc) ({cfa=IP[const_inc]; ip+=(const_inc);})
265: # define DEF_CA
266: # define NEXT_P1
267: # define NEXT_P2 ({goto **cfa;})
268: # define EXEC(XT) ({cfa=(XT); goto **cfa;})
269: #endif
270:
1.3 ! anton 271: #if THREADING_SCHEME==2
! 272: #warning indirect threading scheme 2: autoinc, long latency
1.1 anton 273: # define NEXT_P0 ({cfa=*ip++;})
274: # define IP (ip-1)
1.3 ! anton 275: # define SET_IP(p) ({ip=(p); NEXT_P0;})
1.1 anton 276: # define NEXT_INST (cfa)
277: # define INC_IP(const_inc) ({cfa=IP[const_inc]; ip+=(const_inc);})
278: # define DEF_CA Label ca;
279: # define NEXT_P1 ({ca=*cfa;})
280: # define NEXT_P2 ({goto *ca;})
281: # define EXEC(XT) ({DEF_CA cfa=(XT); ca=*cfa; goto *ca;})
282: #endif
283:
284:
1.3 ! anton 285: #if THREADING_SCHEME==3
! 286: #warning indirect threading scheme 3: autoinc, low latency, cisc
1.1 anton 287: # define NEXT_P0
288: # define IP (ip)
1.3 ! anton 289: # define SET_IP(p) ({ip=(p); NEXT_P0;})
1.1 anton 290: # define NEXT_INST (*ip)
291: # define INC_IP(const_inc) ({ip+=(const_inc);})
292: # define DEF_CA
293: # define NEXT_P1
294: # define NEXT_P2 ({cfa=*ip++; goto **cfa;})
295: # define EXEC(XT) ({cfa=(XT); goto **cfa;})
296: #endif
297:
1.3 ! anton 298: #if THREADING_SCHEME==4
! 299: #warning indirect threading scheme 4: autoinc, low latency
1.1 anton 300: # define NEXT_P0 ({cfa=*ip++;})
301: # define IP (ip-1)
1.3 ! anton 302: # define SET_IP(p) ({ip=(p); NEXT_P0;})
1.1 anton 303: # define NEXT_INST (cfa)
304: # define INC_IP(const_inc) ({cfa=IP[const_inc]; ip+=(const_inc);})
305: # define DEF_CA Label ca;
306: # define NEXT_P1 ({ca=*cfa;})
307: # define NEXT_P2 ({goto *ca;})
308: # define EXEC(XT) ({DEF_CA cfa=(XT); ca=*cfa; goto *ca;})
309: #endif
310:
311:
1.3 ! anton 312: #if THREADING_SCHEME==5
! 313: #warning indirect threading scheme 5: long latency, cisc
1.1 anton 314: # define NEXT_P0 ({cfa=*ip;})
315: # define IP (ip)
1.3 ! anton 316: # define SET_IP(p) ({ip=(p); NEXT_P0;})
1.1 anton 317: # define NEXT_INST (cfa)
318: # define INC_IP(const_inc) ({cfa=IP[const_inc]; ip+=(const_inc);})
319: # define DEF_CA
320: # define NEXT_P1 (ip++)
321: # define NEXT_P2 ({goto **cfa;})
322: # define EXEC(XT) ({cfa=(XT); goto **cfa;})
323: #endif
324:
1.3 ! anton 325: #if THREADING_SCHEME==6
! 326: #warning indirect threading scheme 6: long latency
1.1 anton 327: # define NEXT_P0 ({cfa=*ip;})
328: # define IP (ip)
1.3 ! anton 329: # define SET_IP(p) ({ip=(p); NEXT_P0;})
1.1 anton 330: # define NEXT_INST (cfa)
331: # define INC_IP(const_inc) ({cfa=IP[const_inc]; ip+=(const_inc);})
332: # define DEF_CA Label ca;
333: # define NEXT_P1 ({ip++; ca=*cfa;})
334: # define NEXT_P2 ({goto *ca;})
335: # define EXEC(XT) ({DEF_CA cfa=(XT); ca=*cfa; goto *ca;})
336: #endif
337:
1.3 ! anton 338: #if THREADING_SCHEME==7
! 339: #warning indirect threading scheme 7: low latency
! 340: # define NEXT_P0 ({cfa=*ip;})
! 341: # define IP (ip)
! 342: # define SET_IP(p) ({ip=(p); NEXT_P0;})
! 343: # define NEXT_INST (cfa)
! 344: # define INC_IP(const_inc) ({cfa=IP[const_inc]; ip+=(const_inc);})
! 345: # define DEF_CA Label ca;
! 346: # define NEXT_P1 ({ip++; ca=*cfa;})
! 347: # define NEXT_P2 ({goto *ca;})
! 348: # define EXEC(XT) ({DEF_CA cfa=(XT); ca=*cfa; goto *ca;})
! 349: #endif
1.1 anton 350:
1.3 ! anton 351: #if THREADING_SCHEME==8
! 352: #warning indirect threading scheme 8: low latency,cisc
1.1 anton 353: # define NEXT_P0
354: # define IP (ip)
1.3 ! anton 355: # define SET_IP(p) ({ip=(p); NEXT_P0;})
1.1 anton 356: # define NEXT_INST (*ip)
357: # define INC_IP(const_inc) ({ip+=(const_inc);})
358: # define DEF_CA
359: # define NEXT_P1
360: # define NEXT_P2 ({cfa=*ip++; goto **cfa;})
361: # define EXEC(XT) ({cfa=(XT); goto **cfa;})
362: #endif
363:
1.3 ! anton 364: /* indirect threaded */
1.1 anton 365: #endif
366:
367: #endif /* !defined(DOUBLY_INDIRECT) */
368:
369: #define NEXT ({DEF_CA NEXT_P1; NEXT_P2;})
370:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>