version 1.1, 1997/05/21 20:40:12
|
version 1.41, 2010/04/05 22:17:56
|
Line 1
|
Line 1
|
/* This file defines a number of threading schemes. |
/* This file defines a number of threading schemes. |
|
|
Copyright (C) 1995, 1996 Free Software Foundation, Inc. |
Copyright (C) 1995, 1996,1997,1999,2003,2004,2005,2007,2008 Free Software Foundation, Inc. |
|
|
This file is part of Gforth. |
This file is part of Gforth. |
|
|
Gforth is free software; you can redistribute it and/or |
Gforth is free software; you can redistribute it and/or |
modify it under the terms of the GNU General Public License |
modify it under the terms of the GNU General Public License |
as published by the Free Software Foundation; either version 2 |
as published by the Free Software Foundation, either version 3 |
of the License, or (at your option) any later version. |
of the License, or (at your option) any later version. |
|
|
This program is distributed in the hope that it will be useful, |
This program is distributed in the hope that it will be useful, |
Line 15
|
Line 15
|
GNU General Public License for more details. |
GNU General Public License for more details. |
|
|
You should have received a copy of the GNU General Public License |
You should have received a copy of the GNU General Public License |
along with this program; if not, write to the Free Software |
along with this program; if not, see http://www.gnu.org/licenses/. |
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|
|
|
|
|
This files defines macros for threading. Many sets of macros are |
This files defines macros for threading. Many sets of macros are |
Line 91
|
Line 90
|
|
|
*/ |
*/ |
|
|
#ifndef GETCFA |
#if !defined(GCC_PR15242_WORKAROUND) |
# define CFA_NEXT |
#if __GNUC__ == 3 |
|
/* various gcc-3.x version have problems (including PR15242) that are |
|
solved with this workaround */ |
|
#define GCC_PR15242_WORKAROUND 1 |
|
#else |
|
/* other gcc versions are better off without the workaround for |
|
primitives that are not relocatable */ |
|
#define GCC_PR15242_WORKAROUND 0 |
#endif |
#endif |
|
|
#ifdef DOUBLY_INDIRECT |
|
# define NEXT_P0 ({cfa=*ip;}) |
|
# define IP (ip) |
|
# define NEXT_INST (cfa) |
|
# define INC_IP(const_inc) ({cfa=IP[const_inc]; ip+=(const_inc);}) |
|
# define DEF_CA Label ca; |
|
# define NEXT_P1 ({ip++; ca=**cfa;}) |
|
# define NEXT_P2 ({goto *ca;}) |
|
# define EXEC(XT) ({DEF_CA cfa=(XT); ca=**cfa; goto *ca;}) |
|
# define NEXT1_P1 ({ca = **cfa;}) |
|
# define NEXT1_P2 ({goto *ca;}) |
|
|
|
#else /* !defined(DOUBLY_INDIRECT) */ |
|
|
|
#if defined(DIRECT_THREADED) && defined(AUTO_INCREMENT)\ |
|
&& defined(LONG_LATENCY) && defined(CFA_NEXT) |
|
#warning scheme 1 |
|
# define NEXT_P0 ({cfa=*ip++;}) |
|
# define IP (ip-1) |
|
# define NEXT_INST (cfa) |
|
# define INC_IP(const_inc) ({cfa=IP[const_inc]; ip+=(const_inc);}) |
|
# define DEF_CA |
|
# define NEXT_P1 |
|
# define NEXT_P2 ({goto *cfa;}) |
|
# define EXEC(XT) ({cfa=(XT); goto *cfa;}) |
|
#endif |
#endif |
|
|
#if defined(DIRECT_THREADED) && defined(AUTO_INCREMENT)\ |
#if GCC_PR15242_WORKAROUND |
&& defined(LONG_LATENCY) && !defined(CFA_NEXT) |
#define DO_GOTO goto before_goto |
#warning scheme 2 |
#else |
# define NEXT_P0 (ip++) |
#define DO_GOTO goto *real_ca |
# define IP (ip-1) |
#endif |
# define NEXT_INST (*(ip-1)) |
|
# define INC_IP(const_inc) ({ ip+=(const_inc);}) |
#ifndef GOTO_ALIGN |
# define DEF_CA |
#define GOTO_ALIGN |
# define NEXT_P1 |
#endif |
# define NEXT_P2 ({goto **(ip-1);}) |
|
# define EXEC(XT) ({goto *(XT);}) |
#define GOTO(target) do {(real_ca=(target));} while(0) |
#endif |
#define NEXT_P2 do {NEXT_P1_5; DO_GOTO;} while(0) |
|
#define EXEC(XT) do { real_ca=EXEC1(XT); DO_GOTO;} while (0) |
|
#define VM_JUMP(target) do {GOTO(target);} while (0) |
|
#define NEXT do {DEF_CA NEXT_P1; NEXT_P2;} while(0) |
|
#define FIRST_NEXT_P2 NEXT_P1_5; GOTO_ALIGN; \ |
|
before_goto: goto *real_ca; after_goto: |
|
#define FIRST_NEXT do {DEF_CA NEXT_P1; FIRST_NEXT_P2;} while(0) |
|
#define IPTOS NEXT_INST |
|
|
|
|
#if defined(DIRECT_THREADED) && defined(AUTO_INCREMENT)\ |
#ifdef DOUBLY_INDIRECT |
&& !defined(LONG_LATENCY) && defined(CFA_NEXT) |
# ifndef DEBUG_DITC |
#warning scheme 3 |
# define DEBUG_DITC 0 |
# define NEXT_P0 |
# endif |
# define IP (ip) |
/* define to 1 if you want to check consistency */ |
# define NEXT_INST (*ip) |
# define NEXT_P0 do {cfa1=cfa; cfa=*ip;} while(0) |
# define INC_IP(const_inc) ({ip+=(const_inc);}) |
# define CFA cfa1 |
# define DEF_CA |
# define MORE_VARS Xt cfa1; |
# define NEXT_P1 ({cfa=*ip++;}) |
# define IP (ip) |
# define NEXT_P2 ({goto *cfa;}) |
# define SET_IP(p) do {ip=(p); cfa=*ip;} while(0) |
# define EXEC(XT) ({cfa=(XT); goto *cfa;}) |
# define NEXT_INST (cfa) |
#endif |
# define INC_IP(const_inc) do {cfa=IP[const_inc]; ip+=(const_inc);} while(0) |
|
# define DEF_CA Label MAYBE_UNUSED ca; |
#if defined(DIRECT_THREADED) && defined(AUTO_INCREMENT)\ |
# define NEXT_P1 do {\ |
&& !defined(LONG_LATENCY) && !defined(CFA_NEXT) |
if (DEBUG_DITC && (cfa<=vm_prims+DOER_MAX || cfa>=vm_prims+npriminfos)) \ |
#warning scheme 4 |
fprintf(stderr,"NEXT encountered prim %p at ip=%p\n", cfa, ip); \ |
# define NEXT_P0 |
ip++;} while(0) |
# define IP (ip) |
# define NEXT_P1_5 do {ca=**cfa; GOTO(ca);} while(0) |
# define NEXT_INST (*ip) |
# define EXEC1(XT) ({DEF_CA cfa=(XT);\ |
# define INC_IP(const_inc) ({ ip+=(const_inc);}) |
if (DEBUG_DITC && (cfa>vm_prims+DOER_MAX && cfa<vm_prims+npriminfos)) \ |
# define DEF_CA |
fprintf(stderr,"EXEC encountered xt %p at ip=%p, vm_prims=%p, xts=%p\n", cfa, ip, vm_prims, xts); \ |
# define NEXT_P1 |
ca=**cfa; ca;}) |
# define NEXT_P2 ({goto **(ip++);}) |
|
# define EXEC(XT) ({goto *(XT);}) |
#elif defined(NO_IP) |
#endif |
|
|
#define NEXT_P0 |
/* without autoincrement */ |
# define CFA cfa |
|
#define SET_IP(target) assert(0) |
|
#define INC_IP(n) ((void)0) |
|
#define DEF_CA |
|
#define NEXT_P1 |
|
#define NEXT_P1_5 do {goto *next_code;} while(0) |
|
/* set next_code to the return address before performing EXEC */ |
|
/* original: */ |
|
/* #define EXEC1(XT) do {cfa=(XT); goto **cfa;} while(0) */ |
|
/* fake, to make syntax check work */ |
|
#define EXEC1(XT) ({cfa=(XT); *cfa;}) |
|
|
|
#else /* !defined(DOUBLY_INDIRECT) && !defined(NO_IP) */ |
|
|
|
#if defined(DIRECT_THREADED) |
|
|
|
/* This lets the compiler know that cfa is dead before; we place it at |
|
"goto *"s that perform direct threaded dispatch (i.e., not EXECUTE |
|
etc.), and thus do not reach doers, which would use cfa; the only |
|
way to a doer is through EXECUTE etc., which set the cfa |
|
themselves. |
|
|
|
Some of these direct threaded schemes use "cfa" to hold the code |
|
address in normal direct threaded code. Of course we cannot use |
|
KILLS there. |
|
|
#if defined(DIRECT_THREADED) && !defined(AUTO_INCREMENT)\ |
KILLS works by having an empty asm instruction, and claiming to the |
&& defined(LONG_LATENCY) && defined(CFA_NEXT) |
compiler that it writes to cfa. |
#warning scheme 5 |
|
# define NEXT_P0 ({cfa=*ip;}) |
|
# define IP (ip) |
|
# define NEXT_INST (cfa) |
|
# define INC_IP(const_inc) ({cfa=IP[const_inc]; ip+=(const_inc);}) |
|
# define DEF_CA |
|
# define NEXT_P1 (ip++) |
|
# define NEXT_P2 ({goto *cfa;}) |
|
# define EXEC(XT) ({cfa=(XT); goto *cfa;}) |
|
#endif |
|
|
|
#if defined(DIRECT_THREADED) && !defined(AUTO_INCREMENT)\ |
KILLS is optional. You can write |
&& defined(LONG_LATENCY) && !defined(CFA_NEXT) |
|
#warning scheme 6 |
|
# define NEXT_P0 |
|
# define IP (ip) |
|
# define NEXT_INST (*ip) |
|
# define INC_IP(const_inc) ({ip+=(const_inc);}) |
|
# define DEF_CA |
|
# define NEXT_P1 (ip++) |
|
# define NEXT_P2 ({goto **(ip-1);}) |
|
# define EXEC(XT) ({goto *(XT);}) |
|
#endif |
|
|
|
|
#define KILLS |
|
|
#if defined(DIRECT_THREADED) && !defined(AUTO_INCREMENT)\ |
and lose just a little performance. |
&& !defined(LONG_LATENCY) && defined(CFA_NEXT) |
*/ |
#warning scheme 7 |
#define KILLS asm("":"=X"(cfa)); |
# define NEXT_P0 |
|
# define IP (ip) |
|
# define NEXT_INST (*ip) |
|
# define INC_IP(const_inc) ({ip+=(const_inc);}) |
|
# define DEF_CA |
|
# define NEXT_P1 ({cfa=*ip++;}) |
|
# define NEXT_P2 ({goto *cfa;}) |
|
# define EXEC(XT) ({cfa=(XT); goto *cfa;}) |
|
#endif |
|
|
|
#if defined(DIRECT_THREADED) && !defined(AUTO_INCREMENT)\ |
/* #warning direct threading scheme 8: cfa dead, i386 hack */ |
&& !defined(LONG_LATENCY) && !defined(CFA_NEXT) |
|
#warning scheme 8 |
|
# define NEXT_P0 |
# define NEXT_P0 |
|
# define CFA cfa |
# define IP (ip) |
# define IP (ip) |
|
# define SET_IP(p) do {ip=(p); NEXT_P0;} while(0) |
# define NEXT_INST (*IP) |
# define NEXT_INST (*IP) |
# define INC_IP(const_inc) ({ ip+=(const_inc);}) |
# define INC_IP(const_inc) do { ip+=(const_inc);} while(0) |
# define DEF_CA |
# define DEF_CA |
# define NEXT_P1 (ip++) |
# define NEXT_P1 (ip++) |
# define NEXT_P2 ({goto **(ip-1);}) |
# define NEXT_P1_5 do {KILLS GOTO(*(ip-1));} while(0) |
# define EXEC(XT) ({goto *(XT);}) |
# define EXEC1(XT) ({cfa=(XT); *cfa;}) |
#endif |
|
|
|
/* common settings for direct THREADED */ |
|
|
|
|
|
|
/* direct threaded */ |
|
#else |
/* indirect THREADED */ |
/* indirect THREADED */ |
|
|
#if !defined(DIRECT_THREADED) && defined(AUTO_INCREMENT)\ |
/* #warning indirect threading scheme 8: low latency,cisc */ |
&& defined(LONG_LATENCY) && defined(CISC_NEXT) |
|
# define NEXT_P0 ({cfa=*ip++;}) |
|
# define IP (ip-1) |
|
# define NEXT_INST (cfa) |
|
# define INC_IP(const_inc) ({cfa=IP[const_inc]; ip+=(const_inc);}) |
|
# define DEF_CA |
|
# define NEXT_P1 |
|
# define NEXT_P2 ({goto **cfa;}) |
|
# define EXEC(XT) ({cfa=(XT); goto **cfa;}) |
|
#endif |
|
|
|
#if !defined(DIRECT_THREADED) && defined(AUTO_INCREMENT)\ |
|
&& defined(LONG_LATENCY) && !defined(CISC_NEXT) |
|
# define NEXT_P0 ({cfa=*ip++;}) |
|
# define IP (ip-1) |
|
# define NEXT_INST (cfa) |
|
# define INC_IP(const_inc) ({cfa=IP[const_inc]; ip+=(const_inc);}) |
|
# define DEF_CA Label ca; |
|
# define NEXT_P1 ({ca=*cfa;}) |
|
# define NEXT_P2 ({goto *ca;}) |
|
# define EXEC(XT) ({DEF_CA cfa=(XT); ca=*cfa; goto *ca;}) |
|
#endif |
|
|
|
|
|
#if !defined(DIRECT_THREADED) && defined(AUTO_INCREMENT)\ |
|
&& !defined(LONG_LATENCY) && defined(CISC_NEXT) |
|
# define NEXT_P0 |
|
# define IP (ip) |
|
# define NEXT_INST (*ip) |
|
# define INC_IP(const_inc) ({ip+=(const_inc);}) |
|
# define DEF_CA |
|
# define NEXT_P1 |
|
# define NEXT_P2 ({cfa=*ip++; goto **cfa;}) |
|
# define EXEC(XT) ({cfa=(XT); goto **cfa;}) |
|
#endif |
|
|
|
#if !defined(DIRECT_THREADED) && defined(AUTO_INCREMENT)\ |
|
&& !defined(LONG_LATENCY) && !defined(CISC_NEXT) |
|
# define NEXT_P0 ({cfa=*ip++;}) |
|
# define IP (ip-1) |
|
# define NEXT_INST (cfa) |
|
# define INC_IP(const_inc) ({cfa=IP[const_inc]; ip+=(const_inc);}) |
|
# define DEF_CA Label ca; |
|
# define NEXT_P1 ({ca=*cfa;}) |
|
# define NEXT_P2 ({goto *ca;}) |
|
# define EXEC(XT) ({DEF_CA cfa=(XT); ca=*cfa; goto *ca;}) |
|
#endif |
|
|
|
|
|
/* without autoincrement */ |
|
|
|
#if !defined(DIRECT_THREADED) && !defined(AUTO_INCREMENT)\ |
|
&& defined(LONG_LATENCY) && defined(CISC_NEXT) |
|
# define NEXT_P0 ({cfa=*ip;}) |
|
# define IP (ip) |
|
# define NEXT_INST (cfa) |
|
# define INC_IP(const_inc) ({cfa=IP[const_inc]; ip+=(const_inc);}) |
|
# define DEF_CA |
|
# define NEXT_P1 (ip++) |
|
# define NEXT_P2 ({goto **cfa;}) |
|
# define EXEC(XT) ({cfa=(XT); goto **cfa;}) |
|
#endif |
|
|
|
#if !defined(DIRECT_THREADED) && !defined(AUTO_INCREMENT)\ |
|
&& defined(LONG_LATENCY) && !defined(CISC_NEXT) |
|
# define NEXT_P0 ({cfa=*ip;}) |
|
# define IP (ip) |
|
# define NEXT_INST (cfa) |
|
# define INC_IP(const_inc) ({cfa=IP[const_inc]; ip+=(const_inc);}) |
|
# define DEF_CA Label ca; |
|
# define NEXT_P1 ({ip++; ca=*cfa;}) |
|
# define NEXT_P2 ({goto *ca;}) |
|
# define EXEC(XT) ({DEF_CA cfa=(XT); ca=*cfa; goto *ca;}) |
|
#endif |
|
|
|
|
|
#if !defined(DIRECT_THREADED) && !defined(AUTO_INCREMENT)\ |
|
&& !defined(LONG_LATENCY) && defined(CISC_NEXT) |
|
# define NEXT_P0 |
# define NEXT_P0 |
|
# define CFA cfa |
# define IP (ip) |
# define IP (ip) |
|
# define SET_IP(p) do {ip=(p); NEXT_P0;} while(0) |
# define NEXT_INST (*ip) |
# define NEXT_INST (*ip) |
# define INC_IP(const_inc) ({ip+=(const_inc);}) |
# define INC_IP(const_inc) do {ip+=(const_inc);} while(0) |
# define DEF_CA |
# define DEF_CA |
# define NEXT_P1 |
# define NEXT_P1 |
# define NEXT_P2 ({cfa=*ip++; goto **cfa;}) |
# define NEXT_P1_5 do {cfa=*ip++; GOTO(*cfa);} while(0) |
# define EXEC(XT) ({cfa=(XT); goto **cfa;}) |
# define EXEC1(XT) ({cfa=(XT); *cfa;}) |
#endif |
|
|
|
#if !defined(DIRECT_THREADED) && !defined(AUTO_INCREMENT)\ |
/* indirect threaded */ |
&& !defined(LONG_LATENCY) && !defined(CISC_NEXT) |
|
# define NEXT_P0 ({cfa=*ip;}) |
|
# define IP (ip) |
|
# define NEXT_INST (cfa) |
|
# define INC_IP(const_inc) ({cfa=IP[const_inc]; ip+=(const_inc);}) |
|
# define DEF_CA Label ca; |
|
# define NEXT_P1 ({ip++; ca=*cfa;}) |
|
# define NEXT_P2 ({goto *ca;}) |
|
# define EXEC(XT) ({DEF_CA cfa=(XT); ca=*cfa; goto *ca;}) |
|
#endif |
#endif |
|
|
#if defined(CISC_NEXT) && !defined(LONG_LATENCY) |
#endif /* !defined(DOUBLY_INDIRECT) && !defined(NO_IP) */ |
# define NEXT1_P1 |
|
# ifdef DIRECT_THREADED |
|
# define NEXT1_P2 ({goto *cfa;}) |
|
# else |
|
# define NEXT1_P2 ({goto **cfa;}) |
|
# endif /* DIRECT_THREADED */ |
|
#else /* !defined(CISC_NEXT) || defined(LONG_LATENCY) */ |
|
# ifdef DIRECT_THREADED |
|
# define NEXT1_P1 |
|
# define NEXT1_P2 ({goto *cfa;}) |
|
# else /* !DIRECT_THREADED */ |
|
# define NEXT1_P1 ({ca = *cfa;}) |
|
# define NEXT1_P2 ({goto *ca;}) |
|
# endif /* !DIRECT_THREADED */ |
|
#endif /* !defined(CISC_NEXT) || defined(LONG_LATENCY) */ |
|
|
|
#endif /* !defined(DOUBLY_INDIRECT) */ |
|
|
|
#define NEXT ({DEF_CA NEXT_P1; NEXT_P2;}) |
|
|
|