*** empty log message ***
[bpt/guile.git] / src / vm_system.c
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 \f
45 /*
46 * Basic operations
47 */
48
49 /* This must be the first instruction! */
50 VM_DEFINE_INSTRUCTION (nop, "nop", 0, 0, 0)
51 {
52 NEXT;
53 }
54
55 VM_DEFINE_INSTRUCTION (halt, "halt", 0, 0, 0)
56 {
57 SCM ret = *sp;
58 vp->time += scm_c_get_internal_run_time () - start_time;
59 HALT_HOOK ();
60 FREE_FRAME ();
61 SYNC_ALL ();
62 return ret;
63 }
64
65 VM_DEFINE_INSTRUCTION (drop, "drop", 0, 1, 0)
66 {
67 DROP ();
68 NEXT;
69 }
70
71 VM_DEFINE_INSTRUCTION (dup, "dup", 0, 0, 1)
72 {
73 PUSH (*sp);
74 NEXT;
75 }
76
77 \f
78 /*
79 * Object creation
80 */
81
82 VM_DEFINE_INSTRUCTION (void, "void", 0, 0, 1)
83 {
84 PUSH (SCM_UNSPECIFIED);
85 NEXT;
86 }
87
88 VM_DEFINE_INSTRUCTION (mark, "mark", 0, 0, 1)
89 {
90 PUSH (SCM_UNDEFINED);
91 NEXT;
92 }
93
94 VM_DEFINE_INSTRUCTION (make_true, "make-true", 0, 0, 1)
95 {
96 PUSH (SCM_BOOL_T);
97 NEXT;
98 }
99
100 VM_DEFINE_INSTRUCTION (make_false, "make-false", 0, 0, 1)
101 {
102 PUSH (SCM_BOOL_F);
103 NEXT;
104 }
105
106 VM_DEFINE_INSTRUCTION (make_eol, "make-eol", 0, 0, 1)
107 {
108 PUSH (SCM_EOL);
109 NEXT;
110 }
111
112 VM_DEFINE_INSTRUCTION (make_int8, "make-int8", 1, 0, 1)
113 {
114 PUSH (SCM_MAKINUM ((signed char) FETCH ()));
115 NEXT;
116 }
117
118 VM_DEFINE_INSTRUCTION (make_int8_0, "make-int8:0", 0, 0, 1)
119 {
120 PUSH (SCM_MAKINUM (0));
121 NEXT;
122 }
123
124 VM_DEFINE_INSTRUCTION (make_int8_1, "make-int8:1", 0, 0, 1)
125 {
126 PUSH (SCM_MAKINUM (1));
127 NEXT;
128 }
129
130 VM_DEFINE_INSTRUCTION (make_int16, "make-int16", 2, 0, 1)
131 {
132 int h = FETCH ();
133 int l = FETCH ();
134 PUSH (SCM_MAKINUM ((signed short) (h << 8) + l));
135 NEXT;
136 }
137
138 VM_DEFINE_INSTRUCTION (make_char8, "make-char8", 1, 0, 1)
139 {
140 PUSH (SCM_MAKE_CHAR (FETCH ()));
141 NEXT;
142 }
143
144 \f
145 /*
146 * Variable access
147 */
148
149 #define OBJECT_REF(i) objects[i]
150 #define OBJECT_SET(i,o) objects[i] = o
151
152 #define LOCAL_REF(i) SCM_VM_FRAME_VARIABLE (fp, i)
153 #define LOCAL_SET(i,o) SCM_VM_FRAME_VARIABLE (fp, i) = o
154
155 #define VARIABLE_REF(v) SCM_CDR (v)
156 #define VARIABLE_SET(v,o) SCM_SETCDR (v, o)
157
158 /* ref */
159
160 VM_DEFINE_INSTRUCTION (object_ref, "object-ref", 1, 0, 1)
161 {
162 PUSH (OBJECT_REF (FETCH ()));
163 NEXT;
164 }
165
166 VM_DEFINE_INSTRUCTION (local_ref, "local-ref", 1, 0, 1)
167 {
168 PUSH (LOCAL_REF (FETCH ()));
169 NEXT;
170 }
171
172 VM_DEFINE_INSTRUCTION (external_ref, "external-ref", 1, 0, 1)
173 {
174 unsigned int i;
175 SCM e = external;
176 for (i = FETCH (); i; i--)
177 e = SCM_CDR (e);
178 PUSH (SCM_CAR (e));
179 NEXT;
180 }
181
182 VM_DEFINE_INSTRUCTION (variable_ref, "variable-ref", 0, 0, 1)
183 {
184 SCM x = *sp;
185 SCM o = VARIABLE_REF (x);
186 if (SCM_UNBNDP (o))
187 {
188 /* Try autoload here */
189 err_args = SCM_LIST1 (SCM_CAR (x));
190 goto vm_error_unbound;
191 }
192 *sp = o;
193 NEXT;
194 }
195
196 /* set */
197
198 VM_DEFINE_INSTRUCTION (local_set, "local-set", 1, 1, 0)
199 {
200 LOCAL_SET (FETCH (), *sp);
201 DROP ();
202 NEXT;
203 }
204
205 VM_DEFINE_INSTRUCTION (external_set, "external-set", 1, 1, 0)
206 {
207 unsigned int i;
208 SCM e = external;
209 for (i = FETCH (); i; i--)
210 e = SCM_CDR (e);
211 SCM_SETCAR (e, *sp);
212 DROP ();
213 NEXT;
214 }
215
216 VM_DEFINE_INSTRUCTION (variable_set, "variable-set", 0, 1, 0)
217 {
218 VARIABLE_SET (sp[0], sp[1]);
219 sp += 2;
220 NEXT;
221 }
222
223 \f
224 /*
225 * branch and jump
226 */
227
228 #define BR(p) \
229 { \
230 signed char offset = FETCH (); \
231 if (p) \
232 ip += offset; \
233 DROP (); \
234 NEXT; \
235 }
236
237 VM_DEFINE_INSTRUCTION (br_if, "br-if", 1, 0, 0)
238 {
239 BR (!SCM_FALSEP (*sp));
240 }
241
242 VM_DEFINE_INSTRUCTION (br_if_not, "br-if-not", 1, 0, 0)
243 {
244 BR (SCM_FALSEP (*sp));
245 }
246
247 VM_DEFINE_INSTRUCTION (br_if_eq, "br-if-eq", 1, 0, 0)
248 {
249 BR (SCM_EQ_P (sp[0], sp--[1]));
250 }
251
252 VM_DEFINE_INSTRUCTION (br_if_not_eq, "br-if-not-eq", 1, 0, 0)
253 {
254 BR (!SCM_EQ_P (sp[0], sp--[1]));
255 }
256
257 VM_DEFINE_INSTRUCTION (br_if_null, "br-if-null", 1, 0, 0)
258 {
259 BR (SCM_NULLP (*sp));
260 }
261
262 VM_DEFINE_INSTRUCTION (br_if_not_null, "br-if-not-null", 1, 0, 0)
263 {
264 BR (!SCM_NULLP (*sp));
265 }
266
267 VM_DEFINE_INSTRUCTION (jump, "jump", 1, 0, 0)
268 {
269 ip += (signed char) FETCH ();
270 NEXT;
271 }
272
273 \f
274 /*
275 * Subprogram call
276 */
277
278 VM_DEFINE_INSTRUCTION (make_closure, "make-closure", 0, 1, 1)
279 {
280 SYNC_BEFORE_GC ();
281 *sp = scm_c_make_closure (*sp, external);
282 NEXT;
283 }
284
285 VM_DEFINE_INSTRUCTION (call, "call", 1, -1, 1)
286 {
287 POP (program);
288 nargs = FETCH ();
289
290 vm_call:
291 /*
292 * Subprogram call
293 */
294 if (SCM_PROGRAM_P (program))
295 {
296 int i;
297 vm_call_program:
298 CACHE_PROGRAM (program);
299 INIT_ARGS ();
300 NEW_FRAME ();
301
302 /* Init local variables */
303 for (i = 0; i < bp->nlocs; i++)
304 LOCAL_SET (i, SCM_UNDEFINED);
305
306 /* Create external variables */
307 for (i = 0; i < bp->nexts; i++)
308 CONS (external, SCM_UNDEFINED, external);
309
310 ENTER_HOOK ();
311 APPLY_HOOK ();
312 NEXT;
313 }
314 /*
315 * Function call
316 */
317 if (!SCM_FALSEP (scm_procedure_p (program)))
318 {
319 POP_LIST (nargs);
320 *sp = scm_apply (program, *sp, SCM_EOL);
321 program = SCM_VM_FRAME_PROGRAM (fp);
322 NEXT;
323 }
324 /*
325 * Continuation call
326 */
327 if (SCM_VM_CONT_P (program))
328 {
329 vm_call_cc:
330 /* Check the number of arguments */
331 if (nargs != 1)
332 scm_wrong_num_args (program);
333
334 /* Reinstate the continuation */
335 EXIT_HOOK ();
336 reinstate_vm_cont (vp, program);
337 CACHE_REGISTER ();
338 /* We don't need to set the return value here
339 because it is already on the top of the stack. */
340 NEXT;
341 }
342
343 goto vm_error_wrong_type_apply;
344 }
345
346 VM_DEFINE_INSTRUCTION (tail_call, "tail-call", 1, -1, 1)
347 {
348 SCM x;
349 POP (x);
350 nargs = FETCH ();
351
352 SCM_TICK; /* allow interrupt here */
353
354 /*
355 * Tail recursive call
356 */
357 if (SCM_EQ_P (x, program))
358 {
359 INIT_ARGS ();
360
361 /* Move arguments */
362 if (bp->nargs)
363 {
364 int i;
365 SCM *base = fp + bp->nlocs;
366 for (i = 0; i < bp->nargs; i++)
367 base[i] = sp[i];
368 }
369
370 ip = bp->base;
371 sp = SCM_VM_FRAME_LOWER_ADDRESS (fp);
372 APPLY_HOOK ();
373 NEXT;
374 }
375 program = x;
376 /*
377 * Proper tail call
378 */
379 if (SCM_PROGRAM_P (program))
380 {
381 int i;
382 SCM *base = sp;
383
384 /* Exit the current frame */
385 EXIT_HOOK ();
386 FREE_FRAME ();
387
388 /* Move arguments */
389 sp -= nargs;
390 for (i = 0; i < nargs; i++)
391 sp[i] = base[i];
392
393 /* Call the program */
394 goto vm_call_program;
395 }
396 /*
397 * Function call
398 */
399 if (!SCM_FALSEP (scm_procedure_p (program)))
400 {
401 POP_LIST (nargs);
402 *sp = scm_apply (program, *sp, SCM_EOL);
403 program = SCM_VM_FRAME_PROGRAM (fp);
404 goto vm_return;
405 }
406 /*
407 * Continuation call
408 */
409 if (SCM_VM_CONT_P (program))
410 goto vm_call_cc;
411
412 goto vm_error_wrong_type_apply;
413 }
414
415 VM_DEFINE_INSTRUCTION (call_cc, "call/cc", 1, 1, 1)
416 {
417 SYNC_BEFORE_GC ();
418 PUSH (capture_vm_cont (vp));
419 POP (program);
420 nargs = 1;
421 goto vm_call;
422 }
423
424 VM_DEFINE_INSTRUCTION (return, "return", 0, 0, 1)
425 {
426 SCM ret;
427 vm_return:
428 ret = *sp;
429 EXIT_HOOK ();
430 RETURN_HOOK ();
431 FREE_FRAME ();
432
433 /* Cache the last program */
434 program = SCM_VM_FRAME_PROGRAM (fp);
435 CACHE_PROGRAM (program);
436 PUSH (ret);
437 NEXT;
438 }
439
440 /*
441 Local Variables:
442 c-file-style: "gnu"
443 End:
444 */