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