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