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