*** empty log message ***
[bpt/guile.git] / src / vm_engine.h
CommitLineData
a98cef7e
KN
1/* Copyright (C) 2000 Free Software Foundation, Inc.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2, or (at your option)
6 * any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; see the file COPYING. If not, write to
15 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
16 * Boston, MA 02111-1307 USA
17 *
18 * As a special exception, the Free Software Foundation gives permission
19 * for additional uses of the text contained in its release of GUILE.
20 *
21 * The exception is that, if you link the GUILE library with other files
22 * to produce an executable, this does not by itself cause the
23 * resulting executable to be covered by the GNU General Public License.
24 * Your use of that executable is in no way restricted on account of
25 * linking the GUILE library code into it.
26 *
27 * This exception does not however invalidate any other reasons why
28 * the executable file might be covered by the GNU General Public License.
29 *
30 * This exception applies only to the code released by the
31 * Free Software Foundation under the name GUILE. If you copy
32 * code from other Free Software Foundation releases into a copy of
33 * GUILE, as the General Public License permits, the exception does
34 * not apply to the code that you add in this way. To avoid misleading
35 * anyone as to the status of such modified files, you must delete
36 * this exception notice from them.
37 *
38 * If you write modifications of your own for GUILE, it is your choice
39 * whether to permit this exception to apply to your modifications.
40 * If you do not wish that, delete this exception notice. */
41
42/* This file is included in vm_engine.c */
43
44/*
3d5ee0cd 45 * Options
a98cef7e
KN
46 */
47
3d5ee0cd
KN
48#define VM_USE_HOOKS 1 /* Various hooks */
49#define VM_USE_CLOCK 1 /* Bogoclock */
a98cef7e
KN
50
51\f
52/*
17e90c5e 53 * Registers
a98cef7e
KN
54 */
55
17e90c5e 56/* Register optimization. [ stolen from librep/src/lispmach.h,v 1.3 ]
9df03fd0 57
17e90c5e
KN
58 Some compilers underestimate the use of the local variables representing
59 the abstract machine registers, and don't put them in hardware registers,
60 which slows down the interpreter considerably.
61 For GCC, I have hand-assigned hardware registers for several architectures.
62*/
9df03fd0 63
17e90c5e
KN
64#ifdef __GNUC__
65#ifdef __mips__
66#define IP_REG asm("$16")
67#define SP_REG asm("$17")
68#define FP_REG asm("$18")
69#endif
70#ifdef __sparc__
71#define IP_REG asm("%l0")
72#define SP_REG asm("%l1")
73#define FP_REG asm("%l2")
74#endif
75#ifdef __alpha__
76#ifdef __CRAY__
77#define IP_REG asm("r9")
78#define SP_REG asm("r10")
79#define FP_REG asm("r11")
9df03fd0 80#else
17e90c5e
KN
81#define IP_REG asm("$9")
82#define SP_REG asm("$10")
83#define FP_REG asm("$11")
84#endif
85#endif
86#ifdef __i386__
87#define IP_REG asm("%esi")
88#define SP_REG asm("%edi")
89#define FP_REG
90#endif
91#if defined(PPC) || defined(_POWER) || defined(_IBMR2)
92#define IP_REG asm("26")
93#define SP_REG asm("27")
94#define FP_REG asm("28")
95#endif
96#ifdef __hppa__
97#define IP_REG asm("%r18")
98#define SP_REG asm("%r17")
99#define FP_REG asm("%r16")
100#endif
101#ifdef __mc68000__
102#define IP_REG asm("a5")
103#define SP_REG asm("a4")
104#define FP_REG
105#endif
106#ifdef __arm__
107#define IP_REG asm("r9")
108#define SP_REG asm("r8")
109#define FP_REG asm("r7")
110#endif
9df03fd0
KN
111#endif
112
113\f
a98cef7e 114/*
3d5ee0cd 115 * Cache/Sync
a98cef7e
KN
116 */
117
3d5ee0cd 118#define CACHE_REGISTER() \
17e90c5e 119{ \
3d5ee0cd
KN
120 ip = vp->ip; \
121 sp = vp->sp; \
122 fp = vp->fp; \
17e90c5e 123}
a98cef7e 124
3d5ee0cd 125#define SYNC_REGISTER() \
a98cef7e 126{ \
3d5ee0cd
KN
127 vp->ip = ip; \
128 vp->sp = sp; \
129 vp->fp = fp; \
a98cef7e
KN
130}
131
499a4c07 132#define CACHE_PROGRAM() \
a98cef7e 133{ \
3d5ee0cd 134 bp = SCM_PROGRAM_DATA (program); \
41f248a8
KN
135 objects = SCM_VELTS (bp->objs); \
136}
137
138#define CACHE_EXTERNAL() \
139{ \
140 external = fp[bp->nargs + bp->nlocs]; \
141}
142
143#define SYNC_EXTERNAL() \
144{ \
145 fp[bp->nargs + bp->nlocs] = external; \
a98cef7e
KN
146}
147
3d5ee0cd
KN
148#define SYNC_BEFORE_GC() \
149{ \
150 SYNC_REGISTER (); \
17e90c5e 151}
a98cef7e 152
17e90c5e 153#define SYNC_ALL() \
a98cef7e 154{ \
3d5ee0cd 155 SYNC_REGISTER (); \
a98cef7e
KN
156}
157
a98cef7e 158\f
3d5ee0cd
KN
159/*
160 * Hooks
161 */
162
163#undef RUN_HOOK
164#if VM_USE_HOOKS
165#define RUN_HOOK(h) \
166{ \
167 if (!SCM_FALSEP (h)) \
168 { \
169 SYNC_BEFORE_GC (); \
170 scm_c_run_hook (h, hook_args); \
171 } \
172}
173#else
174#define RUN_HOOK(h)
175#endif
176
177#define BOOT_HOOK() RUN_HOOK (vp->hooks[SCM_VM_BOOT_HOOK])
178#define HALT_HOOK() RUN_HOOK (vp->hooks[SCM_VM_HALT_HOOK])
179#define NEXT_HOOK() RUN_HOOK (vp->hooks[SCM_VM_NEXT_HOOK])
180#define ENTER_HOOK() RUN_HOOK (vp->hooks[SCM_VM_ENTER_HOOK])
181#define APPLY_HOOK() RUN_HOOK (vp->hooks[SCM_VM_APPLY_HOOK])
182#define EXIT_HOOK() RUN_HOOK (vp->hooks[SCM_VM_EXIT_HOOK])
183#define RETURN_HOOK() RUN_HOOK (vp->hooks[SCM_VM_RETURN_HOOK])
184
185\f
a98cef7e
KN
186/*
187 * Stack operation
188 */
189
17e90c5e 190#define CHECK_OVERFLOW() \
3616e9e9 191 if (sp > stack_limit) \
17e90c5e
KN
192 goto vm_error_stack_overflow
193
194#define CHECK_UNDERFLOW() \
3616e9e9 195 if (sp < stack_base) \
17e90c5e 196 goto vm_error_stack_underflow
a98cef7e 197
3616e9e9
KN
198#define PUSH(x) do { sp++; CHECK_OVERFLOW (); *sp = x; } while (0)
199#define DROP() do { CHECK_UNDERFLOW (); sp--; } while (0)
17e90c5e
KN
200#define POP(x) do { x = *sp; DROP (); } while (0)
201
202#define CONS(x,y,z) \
a98cef7e 203{ \
17e90c5e 204 SCM cell; \
3d5ee0cd 205 SYNC_BEFORE_GC (); \
17e90c5e
KN
206 SCM_NEWCELL (cell); \
207 SCM_SET_CELL_OBJECT_0 (cell, y); \
208 SCM_SET_CELL_OBJECT_1 (cell, z); \
209 x = cell; \
a98cef7e
KN
210}
211
17e90c5e
KN
212#define POP_LIST(n) \
213do { \
214 int i; \
215 SCM l = SCM_EOL; \
3616e9e9
KN
216 sp -= n; \
217 for (i = n; i; i--) \
17e90c5e 218 CONS (l, sp[i], l); \
3616e9e9 219 PUSH (l); \
17e90c5e
KN
220} while (0)
221
a98cef7e
KN
222\f
223/*
17e90c5e 224 * Instruction operation
a98cef7e
KN
225 */
226
17e90c5e 227#define FETCH() (*ip++)
17e90c5e
KN
228#define FETCH_LENGTH(len) do { ip = vm_fetch_length (ip, &len); } while (0)
229
230#undef CLOCK
231#if VM_USE_CLOCK
3d5ee0cd 232#define CLOCK(n) vp->clock += n
a98cef7e 233#else
17e90c5e 234#define CLOCK(n)
a98cef7e
KN
235#endif
236
17e90c5e
KN
237#undef NEXT_JUMP
238#ifdef HAVE_LABELS_AS_VALUES
239#define NEXT_JUMP() goto *jump_table[FETCH ()]
240#else
241#define NEXT_JUMP() goto vm_start
242#endif
243
244#define NEXT \
245{ \
246 CLOCK (1); \
17e90c5e
KN
247 NEXT_HOOK (); \
248 NEXT_JUMP (); \
a98cef7e
KN
249}
250
251\f
252/*
17e90c5e 253 * Function support
a98cef7e
KN
254 */
255
17e90c5e 256#define ARGS1(a1) SCM a1 = sp[0];
3616e9e9
KN
257#define ARGS2(a1,a2) SCM a1 = sp[-1], a2 = sp[0]; sp--;
258#define ARGS3(a1,a2,a3) SCM a1 = sp[-2], a2 = sp[-1], a3 = sp[0]; sp -= 2;
17e90c5e 259#define ARGSN(an) int an = FETCH ();
a98cef7e 260
a80be762 261#define RETURN(x) do { *sp = x; NEXT; } while (0)
a98cef7e 262
17e90c5e
KN
263\f
264/*
265 * Frame allocation
266 */
267
17e90c5e
KN
268#define INIT_ARGS() \
269{ \
270 if (bp->nrest) \
271 { \
5315b862 272 int n = nargs - (bp->nargs - 1); \
17e90c5e
KN
273 if (n < 0) \
274 goto vm_error_wrong_num_args; \
275 POP_LIST (n); \
276 } \
277 else \
278 { \
279 if (nargs != bp->nargs) \
280 goto vm_error_wrong_num_args; \
281 } \
282}
283
3616e9e9
KN
284/* See vm.h for the layout of stack frames */
285
286#define NEW_FRAME() \
287{ \
731f329c
KN
288 SCM ra = SCM_VM_MAKE_BYTE_ADDRESS (ip); \
289 SCM dl = SCM_VM_MAKE_STACK_ADDRESS (fp); \
3616e9e9
KN
290 ip = bp->base; \
291 fp = sp - bp->nargs + 1; \
41f248a8 292 sp = sp + bp->nlocs + 3; \
3616e9e9 293 CHECK_OVERFLOW (); \
41f248a8
KN
294 sp[0] = ra; \
295 sp[-1] = dl; \
296 sp[-2] = bp->external; \
3616e9e9
KN
297}
298
299#define FREE_FRAME() \
300{ \
301 SCM *new_sp = fp - 2; \
302 sp = fp + bp->nargs + bp->nlocs; \
41f248a8 303 ip = SCM_VM_BYTE_ADDRESS (sp[2]); \
3616e9e9
KN
304 fp = SCM_VM_STACK_ADDRESS (sp[1]); \
305 sp = new_sp; \
306}
307
17e90c5e
KN
308/*
309 Local Variables:
310 c-file-style: "gnu"
311 End:
312*/