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