Annotation of gforth/engine/threaded.h, revision 1.1
1.1 ! anton 1: /* This file defines a number of threading schemes.
! 2:
! 3: Copyright (C) 1995, 1996 Free Software Foundation, Inc.
! 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
! 96: #endif
! 97:
! 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:
! 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)
! 186: # define INC_IP(const_inc) ({ip+=(const_inc);})
! 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
! 257: # define NEXT_P1
! 258: # define NEXT_P2 ({cfa=*ip++; goto **cfa;})
! 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
! 309: # define NEXT_P1
! 310: # define NEXT_P2 ({cfa=*ip++; goto **cfa;})
! 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 */
! 333: #else /* !defined(CISC_NEXT) || defined(LONG_LATENCY) */
! 334: # ifdef DIRECT_THREADED
! 335: # define NEXT1_P1
! 336: # define NEXT1_P2 ({goto *cfa;})
! 337: # else /* !DIRECT_THREADED */
! 338: # define NEXT1_P1 ({ca = *cfa;})
! 339: # define NEXT1_P2 ({goto *ca;})
! 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>