Annotation of gforth/vmgen-ex2/engine.c, revision 1.7
1.1 anton 1: /* vm interpreter wrapper
2:
1.6 anton 3: Copyright (C) 2001,2002 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., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
20: */
21:
22: #include "mini.h"
23:
24: #define USE_spTOS 1
25:
26: #ifdef USE_spTOS
27: #define IF_spTOS(x) x
28: #else
29: #define IF_spTOS(x)
30: #endif
31:
32: #ifdef VM_DEBUG
33: #define NAME(_x) if (vm_debug) {fprintf(vm_out, "%p: %-20s, ", ip-1, _x); fprintf(vm_out,"fp=%p, sp=%p", fp, sp);}
34: #else
35: #define NAME(_x)
36: #endif
37:
38: /* different threading schemes for different architectures; the sparse
39: numbering is there for historical reasons */
40:
41: /* here you select the threading scheme; I have only set this up for
42: 386 and generic, because I don't know what preprocessor macros to
1.5 anton 43: test for (Gforth uses config.guess instead). Anyway, it's probably
44: best to build them all and select the fastest instead of hardwiring
45: a specific scheme for an architecture. E.g., scheme 8 is fastest
46: for Gforth "make bench" on a 486, whereas scheme 5 is fastest for
47: "mini fib.mini" on an Athlon */
1.1 anton 48: #ifndef THREADING_SCHEME
49: #define THREADING_SCHEME 5
50: #endif /* defined(THREADING_SCHEME) */
51:
1.2 anton 52: #ifdef __GNUC__
1.1 anton 53: #if THREADING_SCHEME==1
54: /* direct threading scheme 1: autoinc, long latency (HPPA, Sharc) */
55: # define NEXT_P0 ({cfa=*ip++;})
56: # define IP (ip-1)
57: # define SET_IP(p) ({ip=(p); NEXT_P0;})
58: # define NEXT_INST (cfa)
59: # define INC_IP(const_inc) ({cfa=IP[const_inc]; ip+=(const_inc);})
60: # define DEF_CA
61: # define NEXT_P1
1.5 anton 62: # define NEXT_P2 ({goto *(cfa.inst);})
1.1 anton 63: #endif
64:
65: #if THREADING_SCHEME==3
66: /* direct threading scheme 3: autoinc, low latency (68K) */
67: # define NEXT_P0
68: # define IP (ip)
69: # define SET_IP(p) ({ip=(p); NEXT_P0;})
70: # define NEXT_INST (*ip)
71: # define INC_IP(const_inc) ({ip+=(const_inc);})
72: # define DEF_CA
73: # define NEXT_P1 ({cfa=*ip++;})
1.5 anton 74: # define NEXT_P2 ({goto *(cfa.inst);})
1.1 anton 75: #endif
76:
77: #if THREADING_SCHEME==5
78: /* direct threading scheme 5: early fetching (Alpha, MIPS) */
79: # define CFA_NEXT
80: # define NEXT_P0 ({cfa=*ip;})
1.5 anton 81: # define IP (ip)
1.1 anton 82: # define SET_IP(p) ({ip=(Inst *)(p); NEXT_P0;})
1.5 anton 83: # define NEXT_INST (cfa)
1.1 anton 84: # define INC_IP(const_inc) ({cfa=ip[const_inc]; ip+=(const_inc);})
85: # define DEF_CA
86: # define NEXT_P1 (ip++)
1.5 anton 87: # define NEXT_P2 ({goto *(cfa.inst);})
1.1 anton 88: #endif
89:
90: #if THREADING_SCHEME==8
91: /* direct threading scheme 8: i386 hack */
92: # define NEXT_P0
93: # define IP (ip)
94: # define SET_IP(p) ({ip=(p); NEXT_P0;})
95: # define NEXT_INST (*IP)
96: # define INC_IP(const_inc) ({ ip+=(const_inc);})
97: # define DEF_CA
98: # define NEXT_P1 (ip++)
99: # define NEXT_P2 ({goto *((*(ip-1)).inst);})
100: #endif
101:
102: #if THREADING_SCHEME==9
103: /* direct threading scheme 9: prefetching (for PowerPC) */
104: /* note that the "cfa=next_cfa;" occurs only in NEXT_P1, because this
105: works out better with the capabilities of gcc to introduce and
106: schedule the mtctr instruction. */
107: # define NEXT_P0
108: # define IP ip
109: # define SET_IP(p) ({ip=(p); next_cfa=*ip; NEXT_P0;})
110: # define NEXT_INST (next_cfa)
111: # define INC_IP(const_inc) ({next_cfa=IP[const_inc]; ip+=(const_inc);})
112: # define DEF_CA
113: # define NEXT_P1 ({cfa=next_cfa; ip++; next_cfa=*ip;})
1.5 anton 114: # define NEXT_P2 ({goto *(cfa.inst);})
115: # define MORE_VARS Cell next_cfa;
1.1 anton 116: #endif
117:
118: #if THREADING_SCHEME==10
119: /* direct threading scheme 10: plain (no attempt at scheduling) */
120: # define NEXT_P0
121: # define IP (ip)
122: # define SET_IP(p) ({ip=(p); NEXT_P0;})
123: # define NEXT_INST (*ip)
124: # define INC_IP(const_inc) ({ip+=(const_inc);})
125: # define DEF_CA
126: # define NEXT_P1
1.5 anton 127: # define NEXT_P2 ({cfa=*ip++; goto *(cfa.inst);})
1.1 anton 128: #endif
129:
130:
131: #define NEXT ({DEF_CA NEXT_P1; NEXT_P2;})
1.5 anton 132: #define IPTOS ((NEXT_INST))
1.1 anton 133:
1.2 anton 134: #define INST_ADDR(name) (Label)&&I_##name
1.4 anton 135: #define LABEL(name) I_##name:
1.2 anton 136: #else /* !defined(__GNUC__) */
137: /* use switch dispatch */
138: #define DEF_CA
139: #define NEXT_P0
140: #define NEXT_P1
141: #define NEXT_P2 goto next_inst;
142: #define SET_IP(p) (ip=(p))
143: #define IP ip
144: #define NEXT_INST (*ip)
145: #define INC_IP(const_inc) (ip+=(const_inc))
146: #define IPTOS NEXT_INST
147: #define INST_ADDR(name) I_##name
1.4 anton 148: #define LABEL(name) case I_##name:
1.2 anton 149:
150: #endif /* !defined(__GNUC__) */
1.4 anton 151:
152: #define LABEL2(x)
1.2 anton 153:
1.1 anton 154: #ifdef VM_PROFILING
155: #define SUPER_END vm_count_block(IP)
156: #else
157: #define SUPER_END
158: #endif
159:
1.2 anton 160: #ifndef __GNUC__
161: enum {
162: #include "mini-labels.i"
163: };
164: #endif
1.1 anton 165:
1.7 ! anton 166: #if defined(__GNUC__) && ((__GNUC__==2 && defined(__GNUC_MINOR__) && __GNUC_MINOR__>=7)||(__GNUC__>2))
! 167: #define MAYBE_UNUSED __attribute__((unused))
! 168: #else
! 169: #define MAYBE_UNUSED
! 170: #endif
! 171:
1.1 anton 172: /* the return type can be anything you want it to */
173: long engine(Cell *ip0, Cell *sp, char *fp)
174: {
175: /* VM registers (you may want to use gcc's "Explicit Reg Vars" here) */
176: Cell * ip;
1.5 anton 177: Cell cfa;
1.1 anton 178: #ifdef USE_spTOS
179: Cell spTOS;
180: #else
181: #define spTOS (sp[0])
182: #endif
183: static Label labels[] = {
184: #include "mini-labels.i"
185: };
186: #ifdef MORE_VARS
187: MORE_VARS
188: #endif
189:
190: if (vm_debug)
191: fprintf(vm_out,"entering engine(%p,%p,%p)\n",ip0,sp,fp);
192: if (ip0 == NULL) {
193: vm_prim = labels;
194: return 0;
195: }
196:
197: /* I don't have a clue where these things come from,
198: but I've put them in macros.h for the moment */
199: IF_spTOS(spTOS = sp[0]);
200:
201: SET_IP(ip0);
202: SUPER_END; /* count the BB starting at ip0 */
1.2 anton 203:
204: #ifdef __GNUC__
1.1 anton 205: NEXT;
206: #include "mini-vm.i"
1.2 anton 207: #else
208: next_inst:
209: switch((*ip++).inst) {
210: #include "mini-vm.i"
211: default:
212: fprintf(stderr,"unknown instruction %d at %p\n", ip[-1], ip-1);
213: exit(1);
214: }
215: #endif
1.1 anton 216: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>