Fix `.go' compilation for $(builddir) != $(srcdir).
[bpt/guile.git] / libguile / vm-i-system.c
CommitLineData
53e28ed9 1/* Copyright (C) 2001,2008,2009 Free Software Foundation, Inc.
a98cef7e 2 *
53e28ed9
AW
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
a98cef7e 7 *
53e28ed9
AW
8 * This library 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 GNU
11 * Lesser General Public License for more details.
a98cef7e 12 *
53e28ed9
AW
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17
a98cef7e
KN
18
19/* This file is included in vm_engine.c */
20
a98cef7e
KN
21\f
22/*
23 * Basic operations
24 */
25
53e28ed9 26VM_DEFINE_INSTRUCTION (0, nop, "nop", 0, 0, 0)
a98cef7e
KN
27{
28 NEXT;
29}
30
53e28ed9 31VM_DEFINE_INSTRUCTION (1, halt, "halt", 0, 0, 0)
a98cef7e 32{
3d5ee0cd 33 vp->time += scm_c_get_internal_run_time () - start_time;
17e90c5e 34 HALT_HOOK ();
a222b0fa 35 nvalues = SCM_I_INUM (*sp--);
11ea1aba 36 NULLSTACK (1);
a222b0fa 37 if (nvalues == 1)
e06e857c 38 POP (finish_args);
a222b0fa
AW
39 else
40 {
41 POP_LIST (nvalues);
e06e857c 42 POP (finish_args);
877ffa3f 43 SYNC_REGISTER ();
e06e857c 44 finish_args = scm_values (finish_args);
a222b0fa
AW
45 }
46
1dc8f851 47 {
11ea1aba
AW
48 ASSERT (sp == stack_base);
49 ASSERT (stack_base == SCM_FRAME_UPPER_ADDRESS (fp) - 1);
1dc8f851
AW
50
51 /* Restore registers */
52 sp = SCM_FRAME_LOWER_ADDRESS (fp) - 1;
53 ip = NULL;
54 fp = SCM_FRAME_DYNAMIC_LINK (fp);
11ea1aba 55 NULLSTACK (stack_base - sp);
1dc8f851 56 }
e06e857c
AW
57
58 goto vm_done;
a98cef7e
KN
59}
60
53e28ed9 61VM_DEFINE_INSTRUCTION (2, break, "break", 0, 0, 0)
7a0d0cee
KN
62{
63 BREAK_HOOK ();
64 NEXT;
65}
66
131f7d6c 67VM_DEFINE_INSTRUCTION (3, drop, "drop", 0, 1, 0)
a98cef7e 68{
17e90c5e 69 DROP ();
a98cef7e
KN
70 NEXT;
71}
72
53e28ed9 73VM_DEFINE_INSTRUCTION (4, mark, "mark", 0, 0, 1)
cb4cca12
KN
74{
75 PUSH (SCM_UNDEFINED);
76 NEXT;
77}
78
53e28ed9 79VM_DEFINE_INSTRUCTION (5, dup, "dup", 0, 0, 1)
26403690 80{
f349065e
KN
81 SCM x = *sp;
82 PUSH (x);
26403690
KN
83 NEXT;
84}
85
17e90c5e
KN
86\f
87/*
88 * Object creation
89 */
a98cef7e 90
53e28ed9 91VM_DEFINE_INSTRUCTION (6, void, "void", 0, 0, 1)
a98cef7e 92{
17e90c5e 93 PUSH (SCM_UNSPECIFIED);
a98cef7e
KN
94 NEXT;
95}
96
53e28ed9 97VM_DEFINE_INSTRUCTION (7, make_true, "make-true", 0, 0, 1)
a98cef7e 98{
17e90c5e 99 PUSH (SCM_BOOL_T);
a98cef7e
KN
100 NEXT;
101}
102
53e28ed9 103VM_DEFINE_INSTRUCTION (8, make_false, "make-false", 0, 0, 1)
a98cef7e 104{
17e90c5e 105 PUSH (SCM_BOOL_F);
a98cef7e
KN
106 NEXT;
107}
108
53e28ed9 109VM_DEFINE_INSTRUCTION (9, make_eol, "make-eol", 0, 0, 1)
a98cef7e 110{
17e90c5e 111 PUSH (SCM_EOL);
a98cef7e
KN
112 NEXT;
113}
114
53e28ed9 115VM_DEFINE_INSTRUCTION (10, make_int8, "make-int8", 1, 0, 1)
a98cef7e 116{
2d80426a 117 PUSH (SCM_I_MAKINUM ((signed char) FETCH ()));
a98cef7e
KN
118 NEXT;
119}
120
53e28ed9 121VM_DEFINE_INSTRUCTION (11, make_int8_0, "make-int8:0", 0, 0, 1)
a98cef7e 122{
238e7a11 123 PUSH (SCM_INUM0);
a98cef7e
KN
124 NEXT;
125}
126
53e28ed9 127VM_DEFINE_INSTRUCTION (12, make_int8_1, "make-int8:1", 0, 0, 1)
a98cef7e 128{
238e7a11 129 PUSH (SCM_I_MAKINUM (1));
a98cef7e
KN
130 NEXT;
131}
132
53e28ed9 133VM_DEFINE_INSTRUCTION (13, make_int16, "make-int16", 2, 0, 1)
a98cef7e 134{
ea9b4b29
KN
135 int h = FETCH ();
136 int l = FETCH ();
2d80426a 137 PUSH (SCM_I_MAKINUM ((signed short) (h << 8) + l));
a98cef7e
KN
138 NEXT;
139}
140
53e28ed9 141VM_DEFINE_INSTRUCTION (14, make_char8, "make-char8", 1, 0, 1)
a98cef7e 142{
17e90c5e 143 PUSH (SCM_MAKE_CHAR (FETCH ()));
a98cef7e
KN
144 NEXT;
145}
146
53e28ed9 147VM_DEFINE_INSTRUCTION (15, list, "list", 2, -1, 1)
cb4cca12 148{
23b587b0
LC
149 unsigned h = FETCH ();
150 unsigned l = FETCH ();
151 unsigned len = ((h << 8) + l);
152 POP_LIST (len);
cb4cca12
KN
153 NEXT;
154}
155
53e28ed9 156VM_DEFINE_INSTRUCTION (16, vector, "vector", 2, -1, 1)
cb4cca12 157{
23b587b0
LC
158 unsigned h = FETCH ();
159 unsigned l = FETCH ();
160 unsigned len = ((h << 8) + l);
5338b62b
AW
161 SCM vect;
162
877ffa3f 163 SYNC_REGISTER ();
5338b62b
AW
164 sp++; sp -= len;
165 CHECK_UNDERFLOW ();
166 vect = scm_make_vector (scm_from_uint (len), SCM_BOOL_F);
167 memcpy (SCM_I_VECTOR_WELTS(vect), sp, sizeof(SCM) * len);
168 NULLSTACK (len);
169 *sp = vect;
170
cb4cca12
KN
171 NEXT;
172}
173
53e28ed9 174VM_DEFINE_INSTRUCTION (17, list_mark, "list-mark", 0, 0, 0)
cb4cca12
KN
175{
176 POP_LIST_MARK ();
177 NEXT;
178}
179
53e28ed9 180VM_DEFINE_INSTRUCTION (18, cons_mark, "cons-mark", 0, 0, 0)
2bd859c8
AW
181{
182 POP_CONS_MARK ();
183 NEXT;
184}
185
53e28ed9 186VM_DEFINE_INSTRUCTION (19, vector_mark, "vector-mark", 0, 0, 0)
cb4cca12
KN
187{
188 POP_LIST_MARK ();
877ffa3f 189 SYNC_REGISTER ();
cb4cca12
KN
190 *sp = scm_vector (*sp);
191 NEXT;
192}
193
53e28ed9 194VM_DEFINE_INSTRUCTION (20, list_break, "list-break", 0, 0, 0)
cb4cca12
KN
195{
196 SCM l;
197 POP (l);
fb10a008 198 PUSH_LIST (l, SCM_NULLP);
cb4cca12
KN
199 NEXT;
200}
201
a98cef7e
KN
202\f
203/*
17e90c5e 204 * Variable access
a98cef7e
KN
205 */
206
17e90c5e
KN
207#define OBJECT_REF(i) objects[i]
208#define OBJECT_SET(i,o) objects[i] = o
a98cef7e 209
af988bbf
KN
210#define LOCAL_REF(i) SCM_FRAME_VARIABLE (fp, i)
211#define LOCAL_SET(i,o) SCM_FRAME_VARIABLE (fp, i) = o
a98cef7e 212
2d80426a
LC
213/* For the variable operations, we _must_ obviously avoid function calls to
214 `scm_variable_ref ()', `scm_variable_bound_p ()' and friends which do
215 nothing more than the corresponding macros. */
216#define VARIABLE_REF(v) SCM_VARIABLE_REF (v)
217#define VARIABLE_SET(v,o) SCM_VARIABLE_SET (v, o)
218#define VARIABLE_BOUNDP(v) (VARIABLE_REF (v) != SCM_UNDEFINED)
a98cef7e 219
17e90c5e 220/* ref */
a98cef7e 221
53e28ed9 222VM_DEFINE_INSTRUCTION (21, object_ref, "object-ref", 1, 0, 1)
a98cef7e 223{
a52b2d3d 224 register unsigned objnum = FETCH ();
0b5f0e49
LC
225 CHECK_OBJECT (objnum);
226 PUSH (OBJECT_REF (objnum));
17e90c5e 227 NEXT;
a98cef7e
KN
228}
229
53e28ed9 230VM_DEFINE_INSTRUCTION (22, local_ref, "local-ref", 1, 0, 1)
a98cef7e 231{
17e90c5e
KN
232 PUSH (LOCAL_REF (FETCH ()));
233 NEXT;
a98cef7e
KN
234}
235
53e28ed9 236VM_DEFINE_INSTRUCTION (23, external_ref, "external-ref", 1, 0, 1)
a98cef7e 237{
17e90c5e
KN
238 unsigned int i;
239 SCM e = external;
240 for (i = FETCH (); i; i--)
2a63758b
KN
241 {
242 CHECK_EXTERNAL(e);
243 e = SCM_CDR (e);
244 }
245 CHECK_EXTERNAL(e);
17e90c5e 246 PUSH (SCM_CAR (e));
a98cef7e
KN
247 NEXT;
248}
249
53e28ed9 250VM_DEFINE_INSTRUCTION (24, variable_ref, "variable-ref", 0, 0, 1)
a98cef7e 251{
17e90c5e 252 SCM x = *sp;
238e7a11 253
2d80426a 254 if (!VARIABLE_BOUNDP (x))
17e90c5e 255 {
e06e857c
AW
256 finish_args = SCM_LIST1 (x);
257 /* Was: finish_args = SCM_LIST1 (SCM_CAR (x)); */
17e90c5e
KN
258 goto vm_error_unbound;
259 }
238e7a11
LC
260 else
261 {
2d80426a 262 SCM o = VARIABLE_REF (x);
238e7a11
LC
263 *sp = o;
264 }
265
a98cef7e
KN
266 NEXT;
267}
268
53e28ed9 269VM_DEFINE_INSTRUCTION (25, toplevel_ref, "toplevel-ref", 1, 0, 1)
9cc649b8 270{
6297d229 271 unsigned objnum = FETCH ();
fd358575 272 SCM what;
9cc649b8 273 CHECK_OBJECT (objnum);
fd358575 274 what = OBJECT_REF (objnum);
9cc649b8 275
fd358575 276 if (!SCM_VARIABLEP (what))
9cc649b8 277 {
d0168f3d 278 SYNC_REGISTER ();
fd358575 279 if (SCM_LIKELY (SCM_SYMBOLP (what)))
3aabb7b7 280 {
2fda0242 281 SCM mod;
fd358575 282 if (SCM_LIKELY (scm_module_system_booted_p
2fda0242 283 && scm_is_true ((mod = scm_program_module (program)))))
fd358575 284 /* might longjmp */
2fda0242 285 what = scm_module_lookup (mod, what);
fd358575
AW
286 else
287 what = scm_sym2var (what, SCM_BOOL_F, SCM_BOOL_F);
3aabb7b7
AW
288 }
289 else
290 {
fd358575
AW
291 SCM mod;
292 /* compilation of @ or @@
293 `what' is a three-element list: (MODNAME SYM INTERFACE?)
294 INTERFACE? is #t if we compiled @ or #f if we compiled @@
295 */
296 mod = scm_resolve_module (SCM_CAR (what));
297 if (scm_is_true (SCM_CADDR (what)))
298 mod = scm_module_public_interface (mod);
299 if (SCM_FALSEP (mod))
300 {
e06e857c 301 finish_args = SCM_LIST1 (mod);
fd358575
AW
302 goto vm_error_no_such_module;
303 }
304 /* might longjmp */
305 what = scm_module_lookup (mod, SCM_CADR (what));
3aabb7b7
AW
306 }
307
fd358575 308 if (!VARIABLE_BOUNDP (what))
9cc649b8 309 {
e06e857c 310 finish_args = SCM_LIST1 (what);
9cc649b8
AW
311 goto vm_error_unbound;
312 }
3aabb7b7 313
fd358575 314 OBJECT_SET (objnum, what);
9cc649b8
AW
315 }
316
fd358575 317 PUSH (VARIABLE_REF (what));
9cc649b8
AW
318 NEXT;
319}
320
17e90c5e
KN
321/* set */
322
53e28ed9 323VM_DEFINE_INSTRUCTION (26, local_set, "local-set", 1, 1, 0)
a98cef7e 324{
17e90c5e
KN
325 LOCAL_SET (FETCH (), *sp);
326 DROP ();
a98cef7e
KN
327 NEXT;
328}
329
53e28ed9 330VM_DEFINE_INSTRUCTION (27, external_set, "external-set", 1, 1, 0)
a98cef7e 331{
17e90c5e
KN
332 unsigned int i;
333 SCM e = external;
334 for (i = FETCH (); i; i--)
ac02b386
KN
335 {
336 CHECK_EXTERNAL(e);
337 e = SCM_CDR (e);
338 }
339 CHECK_EXTERNAL(e);
17e90c5e
KN
340 SCM_SETCAR (e, *sp);
341 DROP ();
a98cef7e
KN
342 NEXT;
343}
344
53e28ed9 345VM_DEFINE_INSTRUCTION (28, variable_set, "variable-set", 0, 1, 0)
a98cef7e 346{
2d80426a 347 VARIABLE_SET (sp[0], sp[-1]);
11ea1aba 348 DROPN (2);
a98cef7e
KN
349 NEXT;
350}
351
53e28ed9 352VM_DEFINE_INSTRUCTION (29, toplevel_set, "toplevel-set", 1, 1, 0)
9cc649b8 353{
6297d229 354 unsigned objnum = FETCH ();
fd358575 355 SCM what;
9cc649b8 356 CHECK_OBJECT (objnum);
fd358575 357 what = OBJECT_REF (objnum);
9cc649b8 358
fd358575 359 if (!SCM_VARIABLEP (what))
9cc649b8 360 {
6287726a 361 SYNC_BEFORE_GC ();
fd358575 362 if (SCM_LIKELY (SCM_SYMBOLP (what)))
3aabb7b7 363 {
2fda0242 364 SCM mod;
fd358575 365 if (SCM_LIKELY (scm_module_system_booted_p
2fda0242 366 && scm_is_true ((mod = scm_program_module (program)))))
fd358575 367 /* might longjmp */
2fda0242 368 what = scm_module_lookup (mod, what);
fd358575
AW
369 else
370 what = scm_sym2var (what, SCM_BOOL_F, SCM_BOOL_F);
3aabb7b7
AW
371 }
372 else
373 {
fd358575
AW
374 SCM mod;
375 /* compilation of @ or @@
376 `what' is a three-element list: (MODNAME SYM INTERFACE?)
377 INTERFACE? is #t if we compiled @ or #f if we compiled @@
378 */
379 mod = scm_resolve_module (SCM_CAR (what));
380 if (scm_is_true (SCM_CADDR (what)))
381 mod = scm_module_public_interface (mod);
382 if (SCM_FALSEP (mod))
383 {
e06e857c 384 finish_args = SCM_LIST1 (what);
fd358575
AW
385 goto vm_error_no_such_module;
386 }
387 /* might longjmp */
388 what = scm_module_lookup (mod, SCM_CADR (what));
3aabb7b7
AW
389 }
390
fd358575 391 OBJECT_SET (objnum, what);
9cc649b8
AW
392 }
393
fd358575 394 VARIABLE_SET (what, *sp);
9cc649b8
AW
395 DROP ();
396 NEXT;
397}
398
53e28ed9 399VM_DEFINE_INSTRUCTION (30, externals, "externals", 0, 0, 1)
3de80ed5
AW
400{
401 PUSH (external);
402 NEXT;
403}
404
a98cef7e
KN
405\f
406/*
407 * branch and jump
408 */
409
efbd5892
AW
410/* offset must be a signed short!!! */
411#define FETCH_OFFSET(offset) \
17e90c5e 412{ \
41f248a8
KN
413 int h = FETCH (); \
414 int l = FETCH (); \
efbd5892
AW
415 offset = (h << 8) + l; \
416}
417
418#define BR(p) \
419{ \
420 signed short offset; \
421 FETCH_OFFSET (offset); \
17e90c5e
KN
422 if (p) \
423 ip += offset; \
11ea1aba 424 NULLSTACK (1); \
17e90c5e
KN
425 DROP (); \
426 NEXT; \
427}
428
53e28ed9 429VM_DEFINE_INSTRUCTION (31, br, "br", 2, 0, 0)
41f248a8
KN
430{
431 int h = FETCH ();
432 int l = FETCH ();
433 ip += (signed short) (h << 8) + l;
434 NEXT;
435}
436
53e28ed9 437VM_DEFINE_INSTRUCTION (32, br_if, "br-if", 2, 0, 0)
a98cef7e 438{
17e90c5e 439 BR (!SCM_FALSEP (*sp));
a98cef7e
KN
440}
441
53e28ed9 442VM_DEFINE_INSTRUCTION (33, br_if_not, "br-if-not", 2, 0, 0)
a98cef7e 443{
17e90c5e 444 BR (SCM_FALSEP (*sp));
a98cef7e
KN
445}
446
53e28ed9 447VM_DEFINE_INSTRUCTION (34, br_if_eq, "br-if-eq", 2, 0, 0)
a98cef7e 448{
17e90c5e 449 BR (SCM_EQ_P (sp[0], sp--[1]));
a98cef7e
KN
450}
451
53e28ed9 452VM_DEFINE_INSTRUCTION (35, br_if_not_eq, "br-if-not-eq", 2, 0, 0)
a98cef7e 453{
17e90c5e
KN
454 BR (!SCM_EQ_P (sp[0], sp--[1]));
455}
456
53e28ed9 457VM_DEFINE_INSTRUCTION (36, br_if_null, "br-if-null", 2, 0, 0)
17e90c5e
KN
458{
459 BR (SCM_NULLP (*sp));
460}
461
53e28ed9 462VM_DEFINE_INSTRUCTION (37, br_if_not_null, "br-if-not-null", 2, 0, 0)
17e90c5e
KN
463{
464 BR (!SCM_NULLP (*sp));
a98cef7e
KN
465}
466
a98cef7e
KN
467\f
468/*
469 * Subprogram call
470 */
471
53e28ed9 472VM_DEFINE_INSTRUCTION (38, make_closure, "make-closure", 0, 1, 1)
a98cef7e 473{
3d5ee0cd 474 SYNC_BEFORE_GC ();
7edf2001
AW
475 SCM_NEWSMOB3 (*sp, scm_tc16_program, SCM_PROGRAM_OBJCODE (*sp),
476 SCM_PROGRAM_OBJTABLE (*sp), external);
17e90c5e 477 NEXT;
a98cef7e
KN
478}
479
53e28ed9 480VM_DEFINE_INSTRUCTION (39, call, "call", 1, -1, 1)
a98cef7e 481{
3616e9e9 482 SCM x;
17e90c5e 483 nargs = FETCH ();
a98cef7e
KN
484
485 vm_call:
c8b9df71
KN
486 x = sp[-nargs];
487
e311f5fa
AW
488 SYNC_REGISTER ();
489 SCM_TICK; /* allow interrupt here */
490
a98cef7e
KN
491 /*
492 * Subprogram call
493 */
3616e9e9 494 if (SCM_PROGRAM_P (x))
a98cef7e 495 {
3616e9e9 496 program = x;
499a4c07 497 CACHE_PROGRAM ();
17e90c5e
KN
498 INIT_ARGS ();
499 NEW_FRAME ();
17e90c5e
KN
500 ENTER_HOOK ();
501 APPLY_HOOK ();
a98cef7e
KN
502 NEXT;
503 }
d507b25f
AW
504#ifdef ENABLE_TRAMPOLINE
505 /* Seems to slow down the fibo test, dunno why */
a98cef7e 506 /*
659b4611
AW
507 * Subr call
508 */
509 switch (nargs)
510 {
511 case 0:
512 {
513 scm_t_trampoline_0 call = scm_trampoline_0 (x);
514 if (call)
515 {
516 SYNC_ALL ();
517 *sp = call (x);
518 NEXT;
519 }
520 break;
521 }
522 case 1:
523 {
524 scm_t_trampoline_1 call = scm_trampoline_1 (x);
525 if (call)
526 {
527 SCM arg1;
528 POP (arg1);
529 SYNC_ALL ();
530 *sp = call (x, arg1);
531 NEXT;
532 }
533 break;
534 }
535 case 2:
536 {
537 scm_t_trampoline_2 call = scm_trampoline_2 (x);
538 if (call)
539 {
540 SCM arg1, arg2;
541 POP (arg2);
542 POP (arg1);
543 SYNC_ALL ();
544 *sp = call (x, arg1, arg2);
545 NEXT;
546 }
547 break;
548 }
549 }
d507b25f 550#endif
659b4611
AW
551 /*
552 * Other interpreted or compiled call
a98cef7e 553 */
3616e9e9 554 if (!SCM_FALSEP (scm_procedure_p (x)))
a98cef7e 555 {
f41cb00c
LC
556 /* At this point, the stack contains the procedure and each one of its
557 arguments. */
17e90c5e 558 POP_LIST (nargs);
1865ad56 559 SYNC_REGISTER ();
887ce75a
AW
560 /* keep args on stack so they are marked */
561 sp[-1] = scm_apply (x, sp[0], SCM_EOL);
66db076a 562 NULLSTACK_FOR_NONLOCAL_EXIT ();
887ce75a 563 DROP ();
42906d74
AW
564 if (SCM_UNLIKELY (SCM_VALUESP (*sp)))
565 {
566 /* truncate values */
567 SCM values;
568 POP (values);
569 values = scm_struct_ref (values, SCM_INUM0);
570 if (scm_is_null (values))
571 goto vm_error_not_enough_values;
572 PUSH (SCM_CAR (values));
573 }
17e90c5e 574 NEXT;
a98cef7e
KN
575 }
576 /*
577 * Continuation call
578 */
3616e9e9 579 if (SCM_VM_CONT_P (x))
a98cef7e 580 {
fcd4901b 581 program = x;
f03c31db 582 vm_call_continuation:
a98cef7e 583 /* Check the number of arguments */
f03c31db 584 /* FIXME multiple args */
382693fe 585 if (nargs != 1)
fcd4901b 586 scm_wrong_num_args (program);
a98cef7e
KN
587
588 /* Reinstate the continuation */
17e90c5e 589 EXIT_HOOK ();
fcd4901b 590 reinstate_vm_cont (vp, program);
3d5ee0cd 591 CACHE_REGISTER ();
af988bbf 592 program = SCM_FRAME_PROGRAM (fp);
3616e9e9 593 CACHE_PROGRAM ();
a98cef7e
KN
594 NEXT;
595 }
596
66292535 597 program = x;
17e90c5e 598 goto vm_error_wrong_type_apply;
a98cef7e
KN
599}
600
53e28ed9 601VM_DEFINE_INSTRUCTION (40, goto_args, "goto/args", 1, -1, 1)
a98cef7e 602{
f41cb00c 603 register SCM x;
17e90c5e 604 nargs = FETCH ();
f03c31db 605 vm_goto_args:
3616e9e9 606 x = sp[-nargs];
17e90c5e 607
28a2f57b 608 SYNC_REGISTER ();
17e90c5e 609 SCM_TICK; /* allow interrupt here */
a98cef7e
KN
610
611 /*
17e90c5e 612 * Tail recursive call
a98cef7e 613 */
17e90c5e 614 if (SCM_EQ_P (x, program))
a98cef7e 615 {
f21dfea6 616 int i;
17e90c5e
KN
617
618 /* Move arguments */
f21dfea6
KN
619 INIT_ARGS ();
620 sp -= bp->nargs - 1;
621 for (i = 0; i < bp->nargs; i++)
622 LOCAL_SET (i, sp[i]);
f41cb00c
LC
623
624 /* Drop the first argument and the program itself. */
625 sp -= 2;
5e390de6
AW
626 NULLSTACK (bp->nargs + 1);
627
628 /* Freshen the externals */
53e28ed9 629 external = SCM_PROGRAM_EXTERNALS (x);
5e390de6
AW
630 for (i = 0; i < bp->nexts; i++)
631 CONS (external, SCM_UNDEFINED, external);
632 SCM_FRAME_DATA_ADDRESS (fp)[0] = external;
a98cef7e 633
f21dfea6 634 /* Call itself */
17e90c5e 635 ip = bp->base;
17e90c5e 636 APPLY_HOOK ();
a98cef7e
KN
637 NEXT;
638 }
28106f54 639
17e90c5e 640 /*
28106f54 641 * Tail call, but not to self -- reuse the frame, keeping the ra and dl
17e90c5e 642 */
3616e9e9 643 if (SCM_PROGRAM_P (x))
17e90c5e 644 {
28106f54
AW
645 SCM *data, *tail_args, *dl;
646 int i;
da320011 647 scm_byte_t *ra, *mvra;
11ea1aba
AW
648#ifdef VM_ENABLE_STACK_NULLING
649 SCM *old_sp;
650#endif
28106f54 651
17e90c5e 652 EXIT_HOOK ();
28106f54
AW
653
654 /* save registers */
655 tail_args = stack_base + 2;
656 ra = SCM_FRAME_RETURN_ADDRESS (fp);
da320011 657 mvra = SCM_FRAME_MV_RETURN_ADDRESS (fp);
28106f54
AW
658 dl = SCM_FRAME_DYNAMIC_LINK (fp);
659
660 /* switch programs */
11ea1aba 661 program = x;
28106f54
AW
662 CACHE_PROGRAM ();
663 INIT_ARGS ();
11ea1aba
AW
664 /* delay updating the frame so that if INIT_ARGS has to cons up a rest
665 arg, going into GC, the stack still makes sense */
666 fp[-1] = program;
28106f54
AW
667 nargs = bp->nargs;
668
11ea1aba
AW
669#ifdef VM_ENABLE_STACK_NULLING
670 old_sp = sp;
671 CHECK_STACK_LEAK ();
672#endif
673
28106f54
AW
674 /* new registers -- logically this would be better later, but let's make
675 sure we have space for the locals now */
676 data = SCM_FRAME_DATA_ADDRESS (fp);
677 ip = bp->base;
b1b942b7 678 stack_base = data + 3;
28106f54
AW
679 sp = stack_base;
680 CHECK_OVERFLOW ();
681
682 /* copy args, bottom-up */
683 for (i = 0; i < nargs; i++)
684 fp[i] = tail_args[i];
685
11ea1aba
AW
686 NULLSTACK (old_sp - sp);
687
28106f54
AW
688 /* init locals */
689 for (i = bp->nlocs; i; i--)
690 data[-i] = SCM_UNDEFINED;
691
28106f54 692 /* Set frame data */
b1b942b7
AW
693 data[3] = (SCM)ra;
694 data[2] = (SCM)mvra;
695 data[1] = (SCM)dl;
11ea1aba
AW
696
697 /* Postpone initializing external vars, because if the CONS causes a GC,
698 we want the stack marker to see the data array formatted as expected. */
699 data[0] = SCM_UNDEFINED;
53e28ed9 700 external = SCM_PROGRAM_EXTERNALS (fp[-1]);
11ea1aba
AW
701 for (i = 0; i < bp->nexts; i++)
702 CONS (external, SCM_UNDEFINED, external);
28106f54 703 data[0] = external;
11ea1aba 704
28106f54
AW
705 ENTER_HOOK ();
706 APPLY_HOOK ();
707 NEXT;
17e90c5e 708 }
d507b25f
AW
709#ifdef ENABLE_TRAMPOLINE
710 /* This seems to actually slow down the fibo test -- dunno why */
a98cef7e 711 /*
659b4611
AW
712 * Subr call
713 */
714 switch (nargs)
715 {
716 case 0:
717 {
718 scm_t_trampoline_0 call = scm_trampoline_0 (x);
719 if (call)
720 {
721 SYNC_ALL ();
722 *sp = call (x);
723 goto vm_return;
724 }
725 break;
726 }
727 case 1:
728 {
729 scm_t_trampoline_1 call = scm_trampoline_1 (x);
730 if (call)
731 {
732 SCM arg1;
733 POP (arg1);
734 SYNC_ALL ();
735 *sp = call (x, arg1);
736 goto vm_return;
737 }
738 break;
739 }
740 case 2:
741 {
742 scm_t_trampoline_2 call = scm_trampoline_2 (x);
743 if (call)
744 {
745 SCM arg1, arg2;
746 POP (arg2);
747 POP (arg1);
748 SYNC_ALL ();
749 *sp = call (x, arg1, arg2);
750 goto vm_return;
751 }
752 break;
753 }
754 }
d507b25f 755#endif
659b4611
AW
756
757 /*
758 * Other interpreted or compiled call
a98cef7e 759 */
3616e9e9 760 if (!SCM_FALSEP (scm_procedure_p (x)))
a98cef7e 761 {
17e90c5e 762 POP_LIST (nargs);
1865ad56 763 SYNC_REGISTER ();
887ce75a 764 sp[-1] = scm_apply (x, sp[0], SCM_EOL);
66db076a 765 NULLSTACK_FOR_NONLOCAL_EXIT ();
887ce75a 766 DROP ();
42906d74
AW
767 if (SCM_UNLIKELY (SCM_VALUESP (*sp)))
768 {
769 /* multiple values returned to continuation */
770 SCM values;
771 POP (values);
772 values = scm_struct_ref (values, SCM_INUM0);
773 nvalues = scm_ilength (values);
fb10a008 774 PUSH_LIST (values, SCM_NULLP);
42906d74
AW
775 goto vm_return_values;
776 }
a98cef7e
KN
777 goto vm_return;
778 }
fcd4901b
AW
779
780 program = x;
781
a98cef7e
KN
782 /*
783 * Continuation call
784 */
fcd4901b 785 if (SCM_VM_CONT_P (program))
f03c31db 786 goto vm_call_continuation;
a98cef7e 787
17e90c5e
KN
788 goto vm_error_wrong_type_apply;
789}
790
53e28ed9 791VM_DEFINE_INSTRUCTION (41, goto_nargs, "goto/nargs", 0, 0, 1)
efbd5892
AW
792{
793 SCM x;
794 POP (x);
795 nargs = scm_to_int (x);
d51406fe 796 /* FIXME: should truncate values? */
efbd5892
AW
797 goto vm_goto_args;
798}
799
53e28ed9 800VM_DEFINE_INSTRUCTION (42, call_nargs, "call/nargs", 0, 0, 1)
efbd5892
AW
801{
802 SCM x;
803 POP (x);
804 nargs = scm_to_int (x);
d51406fe 805 /* FIXME: should truncate values? */
efbd5892
AW
806 goto vm_call;
807}
808
53e28ed9 809VM_DEFINE_INSTRUCTION (43, mv_call, "mv-call", 3, -1, 1)
a222b0fa
AW
810{
811 SCM x;
efbd5892 812 signed short offset;
a222b0fa
AW
813
814 nargs = FETCH ();
efbd5892 815 FETCH_OFFSET (offset);
a222b0fa
AW
816
817 x = sp[-nargs];
818
819 /*
820 * Subprogram call
821 */
822 if (SCM_PROGRAM_P (x))
823 {
824 program = x;
825 CACHE_PROGRAM ();
826 INIT_ARGS ();
827 NEW_FRAME ();
b1b942b7 828 SCM_FRAME_DATA_ADDRESS (fp)[2] = (SCM)(SCM_FRAME_RETURN_ADDRESS (fp) + offset);
a222b0fa
AW
829 ENTER_HOOK ();
830 APPLY_HOOK ();
831 NEXT;
832 }
833 /*
834 * Other interpreted or compiled call
835 */
836 if (!SCM_FALSEP (scm_procedure_p (x)))
837 {
838 /* At this point, the stack contains the procedure and each one of its
839 arguments. */
a222b0fa 840 POP_LIST (nargs);
a222b0fa 841 SYNC_REGISTER ();
887ce75a 842 sp[-1] = scm_apply (x, sp[0], SCM_EOL);
66db076a 843 NULLSTACK_FOR_NONLOCAL_EXIT ();
887ce75a 844 DROP ();
a222b0fa
AW
845 if (SCM_VALUESP (*sp))
846 {
847 SCM values, len;
848 POP (values);
849 values = scm_struct_ref (values, SCM_INUM0);
850 len = scm_length (values);
fb10a008 851 PUSH_LIST (values, SCM_NULLP);
a222b0fa
AW
852 PUSH (len);
853 ip += offset;
854 }
855 NEXT;
856 }
857 /*
858 * Continuation call
859 */
860 if (SCM_VM_CONT_P (x))
861 {
862 program = x;
863 goto vm_call_continuation;
864 }
865
866 program = x;
867 goto vm_error_wrong_type_apply;
868}
869
53e28ed9 870VM_DEFINE_INSTRUCTION (44, apply, "apply", 1, -1, 1)
3616e9e9 871{
c8b9df71
KN
872 int len;
873 SCM ls;
874 POP (ls);
875
876 nargs = FETCH ();
9a8cc8e7 877 ASSERT (nargs >= 2);
c8b9df71
KN
878
879 len = scm_ilength (ls);
880 if (len < 0)
881 goto vm_error_wrong_type_arg;
882
fb10a008 883 PUSH_LIST (ls, SCM_NULL_OR_NIL_P);
c8b9df71
KN
884
885 nargs += len - 2;
886 goto vm_call;
3616e9e9
KN
887}
888
53e28ed9 889VM_DEFINE_INSTRUCTION (45, goto_apply, "goto/apply", 1, -1, 1)
f03c31db
AW
890{
891 int len;
892 SCM ls;
893 POP (ls);
894
895 nargs = FETCH ();
9a8cc8e7 896 ASSERT (nargs >= 2);
f03c31db
AW
897
898 len = scm_ilength (ls);
899 if (len < 0)
900 goto vm_error_wrong_type_arg;
901
fb10a008 902 PUSH_LIST (ls, SCM_NULL_OR_NIL_P);
f03c31db
AW
903
904 nargs += len - 2;
905 goto vm_goto_args;
906}
907
53e28ed9 908VM_DEFINE_INSTRUCTION (46, call_cc, "call/cc", 0, 1, 1)
17e90c5e 909{
76282387
AW
910 int first;
911 SCM proc, cont;
912 POP (proc);
913 SYNC_ALL ();
914 cont = scm_make_continuation (&first);
915 if (first)
916 {
917 PUSH (proc);
918 PUSH (cont);
919 nargs = 1;
920 goto vm_call;
921 }
11ea1aba
AW
922 ASSERT (sp == vp->sp);
923 ASSERT (fp == vp->fp);
76282387
AW
924 else if (SCM_VALUESP (cont))
925 {
926 /* multiple values returned to continuation */
927 SCM values;
928 values = scm_struct_ref (cont, SCM_INUM0);
929 if (SCM_NULLP (values))
9a8cc8e7 930 goto vm_error_no_values;
76282387
AW
931 /* non-tail context does not accept multiple values? */
932 PUSH (SCM_CAR (values));
933 NEXT;
934 }
935 else
936 {
937 PUSH (cont);
938 NEXT;
939 }
a98cef7e
KN
940}
941
53e28ed9 942VM_DEFINE_INSTRUCTION (47, goto_cc, "goto/cc", 0, 1, 1)
f03c31db 943{
76282387
AW
944 int first;
945 SCM proc, cont;
946 POP (proc);
947 SYNC_ALL ();
948 cont = scm_make_continuation (&first);
66db076a
AW
949 ASSERT (sp == vp->sp);
950 ASSERT (fp == vp->fp);
76282387
AW
951 if (first)
952 {
953 PUSH (proc);
954 PUSH (cont);
955 nargs = 1;
956 goto vm_goto_args;
957 }
958 else if (SCM_VALUESP (cont))
959 {
960 /* multiple values returned to continuation */
961 SCM values;
962 values = scm_struct_ref (cont, SCM_INUM0);
963 nvalues = scm_ilength (values);
fb10a008 964 PUSH_LIST (values, SCM_NULLP);
76282387
AW
965 goto vm_return_values;
966 }
967 else
968 {
969 PUSH (cont);
970 goto vm_return;
971 }
f03c31db
AW
972}
973
131f7d6c 974VM_DEFINE_INSTRUCTION (48, return, "return", 0, 1, 1)
a98cef7e 975{
a98cef7e 976 vm_return:
17e90c5e
KN
977 EXIT_HOOK ();
978 RETURN_HOOK ();
ef7e1868
AW
979 SYNC_REGISTER ();
980 SCM_TICK; /* allow interrupt here */
f13c269b
AW
981 {
982 SCM ret, *data;
983 data = SCM_FRAME_DATA_ADDRESS (fp);
984
985 POP (ret);
11ea1aba 986 ASSERT (sp == stack_base);
b1b942b7 987 ASSERT (stack_base == data + 3);
f13c269b
AW
988
989 /* Restore registers */
990 sp = SCM_FRAME_LOWER_ADDRESS (fp);
b1b942b7
AW
991 ip = SCM_FRAME_BYTE_CAST (data[3]);
992 fp = SCM_FRAME_STACK_CAST (data[1]);
11ea1aba
AW
993 {
994#ifdef VM_ENABLE_STACK_NULLING
995 int nullcount = stack_base - sp;
996#endif
997 stack_base = SCM_FRAME_UPPER_ADDRESS (fp) - 1;
998 NULLSTACK (nullcount);
999 }
f13c269b
AW
1000
1001 /* Set return value (sp is already pushed) */
1002 *sp = ret;
1003 }
17e90c5e 1004
15df3447 1005 /* Restore the last program */
af988bbf 1006 program = SCM_FRAME_PROGRAM (fp);
499a4c07 1007 CACHE_PROGRAM ();
af988bbf 1008 CACHE_EXTERNAL ();
7e4760e4 1009 CHECK_IP ();
a98cef7e
KN
1010 NEXT;
1011}
17e90c5e 1012
53e28ed9 1013VM_DEFINE_INSTRUCTION (49, return_values, "return/values", 1, -1, -1)
a222b0fa 1014{
ef24c01b
AW
1015 /* nvalues declared at top level, because for some reason gcc seems to think
1016 that perhaps it might be used without declaration. Fooey to that, I say. */
1017 SCM *data;
1018
1019 nvalues = FETCH ();
1020 vm_return_values:
a222b0fa
AW
1021 EXIT_HOOK ();
1022 RETURN_HOOK ();
ef24c01b
AW
1023
1024 data = SCM_FRAME_DATA_ADDRESS (fp);
b1b942b7 1025 ASSERT (stack_base == data + 3);
a222b0fa 1026
b1b942b7
AW
1027 /* data[2] is the mv return address */
1028 if (nvalues != 1 && data[2])
ef24c01b
AW
1029 {
1030 int i;
1031 /* Restore registers */
1032 sp = SCM_FRAME_LOWER_ADDRESS (fp) - 1;
b1b942b7
AW
1033 ip = SCM_FRAME_BYTE_CAST (data[2]); /* multiple value ra */
1034 fp = SCM_FRAME_STACK_CAST (data[1]);
a222b0fa 1035
ef24c01b
AW
1036 /* Push return values, and the number of values */
1037 for (i = 0; i < nvalues; i++)
1038 *++sp = stack_base[1+i];
1039 *++sp = SCM_I_MAKINUM (nvalues);
a222b0fa 1040
ef24c01b 1041 /* Finally set new stack_base */
11ea1aba 1042 NULLSTACK (stack_base - sp + nvalues + 1);
ef24c01b
AW
1043 stack_base = SCM_FRAME_UPPER_ADDRESS (fp) - 1;
1044 }
1045 else if (nvalues >= 1)
1046 {
1047 /* Multiple values for a single-valued continuation -- here's where I
1048 break with guile tradition and try and do something sensible. (Also,
1049 this block handles the single-valued return to an mv
1050 continuation.) */
1051 /* Restore registers */
1052 sp = SCM_FRAME_LOWER_ADDRESS (fp) - 1;
b1b942b7
AW
1053 ip = SCM_FRAME_BYTE_CAST (data[3]); /* single value ra */
1054 fp = SCM_FRAME_STACK_CAST (data[1]);
a222b0fa 1055
ef24c01b
AW
1056 /* Push first value */
1057 *++sp = stack_base[1];
a222b0fa 1058
ef24c01b 1059 /* Finally set new stack_base */
9b10d0bc 1060 NULLSTACK (stack_base - sp + nvalues + 1);
ef24c01b
AW
1061 stack_base = SCM_FRAME_UPPER_ADDRESS (fp) - 1;
1062 }
1063 else
1064 goto vm_error_no_values;
a222b0fa
AW
1065
1066 /* Restore the last program */
1067 program = SCM_FRAME_PROGRAM (fp);
1068 CACHE_PROGRAM ();
1069 CACHE_EXTERNAL ();
1070 CHECK_IP ();
1071 NEXT;
1072}
1073
53e28ed9 1074VM_DEFINE_INSTRUCTION (50, return_values_star, "return/values*", 1, -1, -1)
ef24c01b
AW
1075{
1076 SCM l;
1077
1078 nvalues = FETCH ();
11ea1aba 1079 ASSERT (nvalues >= 1);
ef24c01b
AW
1080
1081 nvalues--;
1082 POP (l);
1083 while (SCM_CONSP (l))
1084 {
1085 PUSH (SCM_CAR (l));
1086 l = SCM_CDR (l);
1087 nvalues++;
1088 }
fb10a008 1089 if (SCM_UNLIKELY (!SCM_NULL_OR_NIL_P (l))) {
e06e857c 1090 finish_args = scm_list_1 (l);
fb10a008
AW
1091 goto vm_error_improper_list;
1092 }
ef24c01b
AW
1093
1094 goto vm_return_values;
1095}
1096
53e28ed9 1097VM_DEFINE_INSTRUCTION (51, truncate_values, "truncate-values", 2, -1, -1)
d51406fe
AW
1098{
1099 SCM x;
1100 int nbinds, rest;
1101 POP (x);
1102 nvalues = scm_to_int (x);
1103 nbinds = FETCH ();
1104 rest = FETCH ();
1105
1106 if (rest)
1107 nbinds--;
1108
1109 if (nvalues < nbinds)
1110 goto vm_error_not_enough_values;
1111
1112 if (rest)
1113 POP_LIST (nvalues - nbinds);
1114 else
1115 DROPN (nvalues - nbinds);
1116
1117 NEXT;
1118}
1119
53e28ed9
AW
1120/*
1121(defun renumber-ops ()
1122 "start from top of buffer and renumber 'VM_DEFINE_FOO (\n' sequences"
1123 (interactive "")
1124 (save-excursion
1125 (let ((counter -1)) (goto-char (point-min))
1126 (while (re-search-forward "^VM_DEFINE_[^ ]+ (\\([^,]+\\)," (point-max) t)
1127 (replace-match
1128 (number-to-string (setq counter (1+ counter)))
1129 t t nil 1)))))
1130*/
17e90c5e
KN
1131/*
1132 Local Variables:
1133 c-file-style: "gnu"
1134 End:
1135*/