add vm-abort-continuation-hook, vm-restore-continuation-hook
[bpt/guile.git] / libguile / vm-i-system.c
CommitLineData
a5bbb22e 1/* Copyright (C) 2001,2008,2009,2010 Free Software Foundation, Inc.
a98cef7e 2 *
53e28ed9 3 * This library is free software; you can redistribute it and/or
53befeb7
NJ
4 * modify it under the terms of the GNU Lesser General Public License
5 * as published by the Free Software Foundation; either version 3 of
6 * the License, or (at your option) any later version.
a98cef7e 7 *
53befeb7
NJ
8 * This library is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
53e28ed9
AW
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
53befeb7
NJ
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16 * 02110-1301 USA
53e28ed9
AW
17 */
18
a98cef7e
KN
19
20/* This file is included in vm_engine.c */
21
a98cef7e
KN
22\f
23/*
24 * Basic operations
25 */
26
53e28ed9 27VM_DEFINE_INSTRUCTION (0, nop, "nop", 0, 0, 0)
a98cef7e
KN
28{
29 NEXT;
30}
31
53e28ed9 32VM_DEFINE_INSTRUCTION (1, halt, "halt", 0, 0, 0)
a98cef7e 33{
a222b0fa 34 nvalues = SCM_I_INUM (*sp--);
11ea1aba 35 NULLSTACK (1);
a222b0fa 36 if (nvalues == 1)
e06e857c 37 POP (finish_args);
a222b0fa
AW
38 else
39 {
40 POP_LIST (nvalues);
e06e857c 41 POP (finish_args);
877ffa3f 42 SYNC_REGISTER ();
e06e857c 43 finish_args = scm_values (finish_args);
a222b0fa
AW
44 }
45
1dc8f851 46 {
6c6a4439
AW
47#ifdef VM_ENABLE_STACK_NULLING
48 SCM *old_sp = sp;
49#endif
1dc8f851
AW
50
51 /* Restore registers */
52 sp = SCM_FRAME_LOWER_ADDRESS (fp) - 1;
6c6a4439
AW
53 /* Setting the ip here doesn't actually affect control flow, as the calling
54 code will restore its own registers, but it does help when walking the
55 stack */
56 ip = SCM_FRAME_RETURN_ADDRESS (fp);
1dc8f851 57 fp = SCM_FRAME_DYNAMIC_LINK (fp);
6c6a4439 58 NULLSTACK (old_sp - sp);
1dc8f851 59 }
e06e857c
AW
60
61 goto vm_done;
a98cef7e
KN
62}
63
131f7d6c 64VM_DEFINE_INSTRUCTION (3, drop, "drop", 0, 1, 0)
a98cef7e 65{
17e90c5e 66 DROP ();
a98cef7e
KN
67 NEXT;
68}
69
d94be25f 70VM_DEFINE_INSTRUCTION (4, dup, "dup", 0, 0, 1)
26403690 71{
f349065e
KN
72 SCM x = *sp;
73 PUSH (x);
26403690
KN
74 NEXT;
75}
76
17e90c5e
KN
77\f
78/*
79 * Object creation
80 */
a98cef7e 81
d94be25f 82VM_DEFINE_INSTRUCTION (5, void, "void", 0, 0, 1)
a98cef7e 83{
17e90c5e 84 PUSH (SCM_UNSPECIFIED);
a98cef7e
KN
85 NEXT;
86}
87
d94be25f 88VM_DEFINE_INSTRUCTION (6, make_true, "make-true", 0, 0, 1)
a98cef7e 89{
17e90c5e 90 PUSH (SCM_BOOL_T);
a98cef7e
KN
91 NEXT;
92}
93
d94be25f 94VM_DEFINE_INSTRUCTION (7, make_false, "make-false", 0, 0, 1)
a98cef7e 95{
17e90c5e 96 PUSH (SCM_BOOL_F);
a98cef7e
KN
97 NEXT;
98}
99
ff810079 100VM_DEFINE_INSTRUCTION (8, make_nil, "make-nil", 0, 0, 1)
4530432e
DK
101{
102 PUSH (SCM_ELISP_NIL);
103 NEXT;
104}
105
53e28ed9 106VM_DEFINE_INSTRUCTION (9, make_eol, "make-eol", 0, 0, 1)
a98cef7e 107{
17e90c5e 108 PUSH (SCM_EOL);
a98cef7e
KN
109 NEXT;
110}
111
53e28ed9 112VM_DEFINE_INSTRUCTION (10, make_int8, "make-int8", 1, 0, 1)
a98cef7e 113{
2d80426a 114 PUSH (SCM_I_MAKINUM ((signed char) FETCH ()));
a98cef7e
KN
115 NEXT;
116}
117
53e28ed9 118VM_DEFINE_INSTRUCTION (11, make_int8_0, "make-int8:0", 0, 0, 1)
a98cef7e 119{
238e7a11 120 PUSH (SCM_INUM0);
a98cef7e
KN
121 NEXT;
122}
123
53e28ed9 124VM_DEFINE_INSTRUCTION (12, make_int8_1, "make-int8:1", 0, 0, 1)
a98cef7e 125{
238e7a11 126 PUSH (SCM_I_MAKINUM (1));
a98cef7e
KN
127 NEXT;
128}
129
53e28ed9 130VM_DEFINE_INSTRUCTION (13, make_int16, "make-int16", 2, 0, 1)
a98cef7e 131{
ea9b4b29
KN
132 int h = FETCH ();
133 int l = FETCH ();
2d80426a 134 PUSH (SCM_I_MAKINUM ((signed short) (h << 8) + l));
a98cef7e
KN
135 NEXT;
136}
137
a5cfddd5 138VM_DEFINE_INSTRUCTION (14, make_int64, "make-int64", 8, 0, 1)
586cfdec
AW
139{
140 scm_t_uint64 v = 0;
141 v += FETCH ();
142 v <<= 8; v += FETCH ();
143 v <<= 8; v += FETCH ();
144 v <<= 8; v += FETCH ();
145 v <<= 8; v += FETCH ();
146 v <<= 8; v += FETCH ();
147 v <<= 8; v += FETCH ();
148 v <<= 8; v += FETCH ();
149 PUSH (scm_from_int64 ((scm_t_int64) v));
150 NEXT;
151}
152
a5cfddd5 153VM_DEFINE_INSTRUCTION (15, make_uint64, "make-uint64", 8, 0, 1)
586cfdec
AW
154{
155 scm_t_uint64 v = 0;
156 v += FETCH ();
157 v <<= 8; v += FETCH ();
158 v <<= 8; v += FETCH ();
159 v <<= 8; v += FETCH ();
160 v <<= 8; v += FETCH ();
161 v <<= 8; v += FETCH ();
162 v <<= 8; v += FETCH ();
163 v <<= 8; v += FETCH ();
164 PUSH (scm_from_uint64 (v));
165 NEXT;
166}
167
a5cfddd5 168VM_DEFINE_INSTRUCTION (16, make_char8, "make-char8", 1, 0, 1)
a98cef7e 169{
4c402b88
MG
170 scm_t_uint8 v = 0;
171 v = FETCH ();
172
173 PUSH (SCM_MAKE_CHAR (v));
174 /* Don't simplify this to PUSH (SCM_MAKE_CHAR (FETCH ())). The
175 contents of SCM_MAKE_CHAR may be evaluated more than once,
176 resulting in a double fetch. */
a98cef7e
KN
177 NEXT;
178}
179
ff810079 180VM_DEFINE_INSTRUCTION (17, make_char32, "make-char32", 4, 0, 1)
904a78f1
MG
181{
182 scm_t_wchar v = 0;
183 v += FETCH ();
184 v <<= 8; v += FETCH ();
185 v <<= 8; v += FETCH ();
186 v <<= 8; v += FETCH ();
187 PUSH (SCM_MAKE_CHAR (v));
188 NEXT;
189}
190
191
192
ff810079 193VM_DEFINE_INSTRUCTION (18, list, "list", 2, -1, 1)
cb4cca12 194{
23b587b0
LC
195 unsigned h = FETCH ();
196 unsigned l = FETCH ();
197 unsigned len = ((h << 8) + l);
198 POP_LIST (len);
cb4cca12
KN
199 NEXT;
200}
201
ff810079 202VM_DEFINE_INSTRUCTION (19, vector, "vector", 2, -1, 1)
cb4cca12 203{
23b587b0
LC
204 unsigned h = FETCH ();
205 unsigned l = FETCH ();
206 unsigned len = ((h << 8) + l);
5338b62b
AW
207 SCM vect;
208
877ffa3f 209 SYNC_REGISTER ();
5338b62b
AW
210 sp++; sp -= len;
211 CHECK_UNDERFLOW ();
212 vect = scm_make_vector (scm_from_uint (len), SCM_BOOL_F);
213 memcpy (SCM_I_VECTOR_WELTS(vect), sp, sizeof(SCM) * len);
214 NULLSTACK (len);
215 *sp = vect;
216
cb4cca12
KN
217 NEXT;
218}
219
a98cef7e
KN
220\f
221/*
17e90c5e 222 * Variable access
a98cef7e
KN
223 */
224
17e90c5e
KN
225#define OBJECT_REF(i) objects[i]
226#define OBJECT_SET(i,o) objects[i] = o
a98cef7e 227
af988bbf
KN
228#define LOCAL_REF(i) SCM_FRAME_VARIABLE (fp, i)
229#define LOCAL_SET(i,o) SCM_FRAME_VARIABLE (fp, i) = o
a98cef7e 230
2d80426a
LC
231/* For the variable operations, we _must_ obviously avoid function calls to
232 `scm_variable_ref ()', `scm_variable_bound_p ()' and friends which do
233 nothing more than the corresponding macros. */
234#define VARIABLE_REF(v) SCM_VARIABLE_REF (v)
235#define VARIABLE_SET(v,o) SCM_VARIABLE_SET (v, o)
236#define VARIABLE_BOUNDP(v) (VARIABLE_REF (v) != SCM_UNDEFINED)
a98cef7e 237
6f16379e 238#define FREE_VARIABLE_REF(i) SCM_PROGRAM_FREE_VARIABLE_REF (program, i)
8d90b356 239
17e90c5e 240/* ref */
a98cef7e 241
ff810079 242VM_DEFINE_INSTRUCTION (20, object_ref, "object-ref", 1, 0, 1)
a98cef7e 243{
a52b2d3d 244 register unsigned objnum = FETCH ();
0b5f0e49
LC
245 CHECK_OBJECT (objnum);
246 PUSH (OBJECT_REF (objnum));
17e90c5e 247 NEXT;
a98cef7e
KN
248}
249
a5cfddd5 250/* FIXME: necessary? elt 255 of the vector could be a vector... */
ff810079 251VM_DEFINE_INSTRUCTION (21, long_object_ref, "long-object-ref", 2, 0, 1)
a5cfddd5
AW
252{
253 unsigned int objnum = FETCH ();
254 objnum <<= 8;
255 objnum += FETCH ();
256 CHECK_OBJECT (objnum);
257 PUSH (OBJECT_REF (objnum));
258 NEXT;
259}
260
ff810079 261VM_DEFINE_INSTRUCTION (22, local_ref, "local-ref", 1, 0, 1)
a98cef7e 262{
17e90c5e 263 PUSH (LOCAL_REF (FETCH ()));
a1a482e0 264 ASSERT_BOUND (*sp);
17e90c5e 265 NEXT;
a98cef7e
KN
266}
267
ff810079 268VM_DEFINE_INSTRUCTION (23, long_local_ref, "long-local-ref", 2, 0, 1)
a98cef7e 269{
80545853
AW
270 unsigned int i = FETCH ();
271 i <<= 8;
272 i += FETCH ();
28b119ee 273 PUSH (LOCAL_REF (i));
a1a482e0 274 ASSERT_BOUND (*sp);
a98cef7e
KN
275 NEXT;
276}
277
e4257331 278VM_DEFINE_INSTRUCTION (24, local_bound, "local-bound?", 1, 0, 1)
3092a14d
AW
279{
280 if (LOCAL_REF (FETCH ()) == SCM_UNDEFINED)
281 PUSH (SCM_BOOL_F);
282 else
283 PUSH (SCM_BOOL_T);
284 NEXT;
285}
286
e4257331 287VM_DEFINE_INSTRUCTION (25, long_local_bound, "long-local-bound?", 2, 0, 1)
3092a14d
AW
288{
289 unsigned int i = FETCH ();
290 i <<= 8;
291 i += FETCH ();
292 if (LOCAL_REF (i) == SCM_UNDEFINED)
293 PUSH (SCM_BOOL_F);
294 else
295 PUSH (SCM_BOOL_T);
296 NEXT;
297}
298
e4257331 299VM_DEFINE_INSTRUCTION (26, variable_ref, "variable-ref", 0, 1, 1)
a98cef7e 300{
17e90c5e 301 SCM x = *sp;
238e7a11 302
1af77230 303 if (SCM_UNLIKELY (!VARIABLE_BOUNDP (x)))
17e90c5e 304 {
1af77230
LC
305 SCM var_name;
306
307 /* Attempt to provide the variable name in the error message. */
308 var_name = scm_module_reverse_lookup (scm_current_module (), x);
309 finish_args = scm_list_1 (scm_is_true (var_name) ? var_name : x);
17e90c5e
KN
310 goto vm_error_unbound;
311 }
238e7a11
LC
312 else
313 {
2d80426a 314 SCM o = VARIABLE_REF (x);
238e7a11
LC
315 *sp = o;
316 }
317
a98cef7e
KN
318 NEXT;
319}
320
05156612 321VM_DEFINE_INSTRUCTION (27, variable_bound, "variable-bound?", 0, 1, 1)
3092a14d
AW
322{
323 if (VARIABLE_BOUNDP (*sp))
324 *sp = SCM_BOOL_T;
325 else
326 *sp = SCM_BOOL_F;
327 NEXT;
328}
329
e4257331 330VM_DEFINE_INSTRUCTION (28, toplevel_ref, "toplevel-ref", 1, 0, 1)
9cc649b8 331{
6297d229 332 unsigned objnum = FETCH ();
fd358575 333 SCM what;
9cc649b8 334 CHECK_OBJECT (objnum);
fd358575 335 what = OBJECT_REF (objnum);
9cc649b8 336
fd358575 337 if (!SCM_VARIABLEP (what))
9cc649b8 338 {
d0168f3d 339 SYNC_REGISTER ();
b7393ea1 340 what = resolve_variable (what, scm_program_module (program));
fd358575 341 if (!VARIABLE_BOUNDP (what))
9cc649b8 342 {
da8b4747 343 finish_args = scm_list_1 (what);
9cc649b8
AW
344 goto vm_error_unbound;
345 }
fd358575 346 OBJECT_SET (objnum, what);
9cc649b8
AW
347 }
348
fd358575 349 PUSH (VARIABLE_REF (what));
9cc649b8
AW
350 NEXT;
351}
352
e4257331 353VM_DEFINE_INSTRUCTION (29, long_toplevel_ref, "long-toplevel-ref", 2, 0, 1)
a5cfddd5
AW
354{
355 SCM what;
356 unsigned int objnum = FETCH ();
357 objnum <<= 8;
358 objnum += FETCH ();
359 CHECK_OBJECT (objnum);
360 what = OBJECT_REF (objnum);
361
362 if (!SCM_VARIABLEP (what))
363 {
364 SYNC_REGISTER ();
365 what = resolve_variable (what, scm_program_module (program));
366 if (!VARIABLE_BOUNDP (what))
367 {
368 finish_args = scm_list_1 (what);
369 goto vm_error_unbound;
370 }
371 OBJECT_SET (objnum, what);
372 }
373
374 PUSH (VARIABLE_REF (what));
375 NEXT;
376}
377
17e90c5e
KN
378/* set */
379
e4257331 380VM_DEFINE_INSTRUCTION (30, local_set, "local-set", 1, 1, 0)
a98cef7e 381{
17e90c5e
KN
382 LOCAL_SET (FETCH (), *sp);
383 DROP ();
a98cef7e
KN
384 NEXT;
385}
386
e4257331 387VM_DEFINE_INSTRUCTION (31, long_local_set, "long-local-set", 2, 1, 0)
a98cef7e 388{
80545853
AW
389 unsigned int i = FETCH ();
390 i <<= 8;
391 i += FETCH ();
392 LOCAL_SET (i, *sp);
17e90c5e 393 DROP ();
a98cef7e
KN
394 NEXT;
395}
396
e4257331 397VM_DEFINE_INSTRUCTION (32, variable_set, "variable-set", 0, 2, 0)
a98cef7e 398{
2d80426a 399 VARIABLE_SET (sp[0], sp[-1]);
11ea1aba 400 DROPN (2);
a98cef7e
KN
401 NEXT;
402}
403
e4257331 404VM_DEFINE_INSTRUCTION (33, toplevel_set, "toplevel-set", 1, 1, 0)
9cc649b8 405{
6297d229 406 unsigned objnum = FETCH ();
fd358575 407 SCM what;
9cc649b8 408 CHECK_OBJECT (objnum);
fd358575 409 what = OBJECT_REF (objnum);
9cc649b8 410
fd358575 411 if (!SCM_VARIABLEP (what))
9cc649b8 412 {
6287726a 413 SYNC_BEFORE_GC ();
b7393ea1 414 what = resolve_variable (what, scm_program_module (program));
fd358575 415 OBJECT_SET (objnum, what);
9cc649b8
AW
416 }
417
fd358575 418 VARIABLE_SET (what, *sp);
9cc649b8
AW
419 DROP ();
420 NEXT;
421}
422
e4257331 423VM_DEFINE_INSTRUCTION (34, long_toplevel_set, "long-toplevel-set", 2, 1, 0)
a5cfddd5
AW
424{
425 SCM what;
426 unsigned int objnum = FETCH ();
427 objnum <<= 8;
428 objnum += FETCH ();
429 CHECK_OBJECT (objnum);
430 what = OBJECT_REF (objnum);
431
432 if (!SCM_VARIABLEP (what))
433 {
434 SYNC_BEFORE_GC ();
435 what = resolve_variable (what, scm_program_module (program));
436 OBJECT_SET (objnum, what);
437 }
438
439 VARIABLE_SET (what, *sp);
440 DROP ();
441 NEXT;
442}
443
a98cef7e
KN
444\f
445/*
446 * branch and jump
447 */
448
97fcf583 449/* offset must be at least 24 bits wide, and signed */
efbd5892 450#define FETCH_OFFSET(offset) \
17e90c5e 451{ \
97fcf583
AW
452 offset = FETCH () << 16; \
453 offset += FETCH () << 8; \
454 offset += FETCH (); \
455 offset -= (offset & (1<<23)) << 1; \
efbd5892
AW
456}
457
458#define BR(p) \
459{ \
97fcf583 460 scm_t_int32 offset; \
efbd5892 461 FETCH_OFFSET (offset); \
17e90c5e 462 if (p) \
97fcf583 463 ip += offset; \
5b09b37f
AW
464 if (offset < 0) \
465 VM_HANDLE_INTERRUPTS; \
11ea1aba 466 NULLSTACK (1); \
17e90c5e
KN
467 DROP (); \
468 NEXT; \
469}
470
e4257331 471VM_DEFINE_INSTRUCTION (35, br, "br", 3, 0, 0)
41f248a8 472{
97fcf583 473 scm_t_int32 offset;
e5dc27b8 474 FETCH_OFFSET (offset);
97fcf583 475 ip += offset;
5b09b37f
AW
476 if (offset < 0)
477 VM_HANDLE_INTERRUPTS;
41f248a8
KN
478 NEXT;
479}
480
e4257331 481VM_DEFINE_INSTRUCTION (36, br_if, "br-if", 3, 0, 0)
a98cef7e 482{
d38b431a 483 BR (scm_is_true (*sp));
a98cef7e
KN
484}
485
e4257331 486VM_DEFINE_INSTRUCTION (37, br_if_not, "br-if-not", 3, 0, 0)
a98cef7e 487{
d38b431a 488 BR (scm_is_false (*sp));
a98cef7e
KN
489}
490
e4257331 491VM_DEFINE_INSTRUCTION (38, br_if_eq, "br-if-eq", 3, 0, 0)
a98cef7e 492{
2c0f99a2 493 sp--; /* underflow? */
9bd48cb1 494 BR (scm_is_eq (sp[0], sp[1]));
a98cef7e
KN
495}
496
e4257331 497VM_DEFINE_INSTRUCTION (39, br_if_not_eq, "br-if-not-eq", 3, 0, 0)
a98cef7e 498{
2c0f99a2 499 sp--; /* underflow? */
9bd48cb1 500 BR (!scm_is_eq (sp[0], sp[1]));
17e90c5e
KN
501}
502
e4257331 503VM_DEFINE_INSTRUCTION (40, br_if_null, "br-if-null", 3, 0, 0)
17e90c5e 504{
2533f10b 505 BR (scm_is_null (*sp));
17e90c5e
KN
506}
507
e4257331 508VM_DEFINE_INSTRUCTION (41, br_if_not_null, "br-if-not-null", 3, 0, 0)
17e90c5e 509{
2533f10b 510 BR (!scm_is_null (*sp));
a98cef7e
KN
511}
512
a98cef7e
KN
513\f
514/*
515 * Subprogram call
516 */
517
e4257331 518VM_DEFINE_INSTRUCTION (42, br_if_nargs_ne, "br-if-nargs-ne", 5, 0, 0)
7e01997e
AW
519{
520 scm_t_ptrdiff n;
7f991c7d 521 scm_t_int32 offset;
7e01997e
AW
522 n = FETCH () << 8;
523 n += FETCH ();
7e01997e
AW
524 FETCH_OFFSET (offset);
525 if (sp - (fp - 1) != n)
526 ip += offset;
527 NEXT;
528}
529
e4257331 530VM_DEFINE_INSTRUCTION (43, br_if_nargs_lt, "br-if-nargs-lt", 5, 0, 0)
7e01997e
AW
531{
532 scm_t_ptrdiff n;
7f991c7d 533 scm_t_int32 offset;
7e01997e
AW
534 n = FETCH () << 8;
535 n += FETCH ();
7e01997e
AW
536 FETCH_OFFSET (offset);
537 if (sp - (fp - 1) < n)
538 ip += offset;
539 NEXT;
540}
541
e4257331 542VM_DEFINE_INSTRUCTION (44, br_if_nargs_gt, "br-if-nargs-gt", 5, 0, 0)
7e01997e
AW
543{
544 scm_t_ptrdiff n;
ff74e44e
AW
545 scm_t_int32 offset;
546
7e01997e
AW
547 n = FETCH () << 8;
548 n += FETCH ();
7e01997e
AW
549 FETCH_OFFSET (offset);
550 if (sp - (fp - 1) > n)
551 ip += offset;
552 NEXT;
553}
554
e4257331 555VM_DEFINE_INSTRUCTION (45, assert_nargs_ee, "assert-nargs-ee", 2, 0, 0)
1e2a8c26
AW
556{
557 scm_t_ptrdiff n;
558 n = FETCH () << 8;
559 n += FETCH ();
a6f15a1e 560 if (sp - (fp - 1) != n)
1e2a8c26 561 goto vm_error_wrong_num_args;
1e2a8c26
AW
562 NEXT;
563}
564
e4257331 565VM_DEFINE_INSTRUCTION (46, assert_nargs_ge, "assert-nargs-ge", 2, 0, 0)
1e2a8c26
AW
566{
567 scm_t_ptrdiff n;
568 n = FETCH () << 8;
569 n += FETCH ();
a6f15a1e 570 if (sp - (fp - 1) < n)
1e2a8c26 571 goto vm_error_wrong_num_args;
1e2a8c26
AW
572 NEXT;
573}
574
e4257331 575VM_DEFINE_INSTRUCTION (47, bind_optionals, "bind-optionals", 2, -1, -1)
7e01997e
AW
576{
577 scm_t_ptrdiff n;
578 n = FETCH () << 8;
579 n += FETCH ();
580 while (sp - (fp - 1) < n)
581 PUSH (SCM_UNDEFINED);
582 NEXT;
583}
584
e4257331 585VM_DEFINE_INSTRUCTION (48, bind_optionals_shuffle, "bind-optionals/shuffle", 6, -1, -1)
7e01997e
AW
586{
587 SCM *walk;
588 scm_t_ptrdiff nreq, nreq_and_opt, ntotal;
589 nreq = FETCH () << 8;
590 nreq += FETCH ();
591 nreq_and_opt = FETCH () << 8;
592 nreq_and_opt += FETCH ();
593 ntotal = FETCH () << 8;
594 ntotal += FETCH ();
595
596 /* look in optionals for first keyword or last positional */
597 /* starting after the last required positional arg */
3092a14d 598 walk = fp + nreq;
7e01997e
AW
599 while (/* while we have args */
600 walk <= sp
601 /* and we still have positionals to fill */
3092a14d 602 && walk - fp < nreq_and_opt
7e01997e
AW
603 /* and we haven't reached a keyword yet */
604 && !scm_is_keyword (*walk))
605 /* bind this optional arg (by leaving it in place) */
606 walk++;
607 /* now shuffle up, from walk to ntotal */
608 {
3092a14d 609 scm_t_ptrdiff nshuf = sp - walk + 1, i;
7e01997e
AW
610 sp = (fp - 1) + ntotal + nshuf;
611 CHECK_OVERFLOW ();
3092a14d
AW
612 for (i = 0; i < nshuf; i++)
613 sp[-i] = walk[nshuf-i-1];
7e01997e
AW
614 }
615 /* and fill optionals & keyword args with SCM_UNDEFINED */
3092a14d 616 while (walk <= (fp - 1) + ntotal)
7e01997e
AW
617 *walk++ = SCM_UNDEFINED;
618
619 NEXT;
620}
621
ff74e44e
AW
622/* Flags that determine whether other keywords are allowed, and whether a
623 rest argument is expected. These values must match those used by the
624 glil->assembly compiler. */
625#define F_ALLOW_OTHER_KEYS 1
626#define F_REST 2
627
e4257331 628VM_DEFINE_INSTRUCTION (49, bind_kwargs, "bind-kwargs", 5, 0, 0)
7e01997e
AW
629{
630 scm_t_uint16 idx;
631 scm_t_ptrdiff nkw;
ff74e44e 632 int kw_and_rest_flags;
7e01997e
AW
633 SCM kw;
634 idx = FETCH () << 8;
635 idx += FETCH ();
ff74e44e 636 /* XXX: We don't actually use NKW. */
7e01997e
AW
637 nkw = FETCH () << 8;
638 nkw += FETCH ();
ff74e44e 639 kw_and_rest_flags = FETCH ();
7e01997e 640
ff74e44e
AW
641 if (!(kw_and_rest_flags & F_REST)
642 && ((sp - (fp - 1) - nkw) % 2))
7e01997e
AW
643 goto vm_error_kwargs_length_not_even;
644
645 CHECK_OBJECT (idx);
646 kw = OBJECT_REF (idx);
ff74e44e
AW
647
648 /* Switch NKW to be a negative index below SP. */
649 for (nkw = -(sp - (fp - 1) - nkw) + 1; nkw < 0; nkw++)
7e01997e
AW
650 {
651 SCM walk;
ff74e44e
AW
652
653 if (scm_is_keyword (sp[nkw]))
654 {
655 for (walk = kw; scm_is_pair (walk); walk = SCM_CDR (walk))
656 {
657 if (scm_is_eq (SCM_CAAR (walk), sp[nkw]))
658 {
659 SCM si = SCM_CDAR (walk);
660 LOCAL_SET (SCM_I_INUMP (si) ? SCM_I_INUM (si) : scm_to_long (si),
661 sp[nkw + 1]);
662 break;
663 }
664 }
665 if (!(kw_and_rest_flags & F_ALLOW_OTHER_KEYS) && !scm_is_pair (walk))
666 goto vm_error_kwargs_unrecognized_keyword;
667
668 nkw++;
669 }
670 else if (!(kw_and_rest_flags & F_REST))
671 goto vm_error_kwargs_invalid_keyword;
7e01997e
AW
672 }
673
674 NEXT;
675}
676
ff74e44e
AW
677#undef F_ALLOW_OTHER_KEYS
678#undef F_REST
679
680
e4257331 681VM_DEFINE_INSTRUCTION (50, push_rest, "push-rest", 2, -1, -1)
1e2a8c26
AW
682{
683 scm_t_ptrdiff n;
a6f15a1e 684 SCM rest = SCM_EOL;
1e2a8c26
AW
685 n = FETCH () << 8;
686 n += FETCH ();
a6f15a1e 687 while (sp - (fp - 1) > n)
1e2a8c26
AW
688 /* No need to check for underflow. */
689 CONS (rest, *sp--, rest);
690 PUSH (rest);
1e2a8c26
AW
691 NEXT;
692}
693
e4257331 694VM_DEFINE_INSTRUCTION (51, bind_rest, "bind-rest", 4, -1, -1)
899d37a6
AW
695{
696 scm_t_ptrdiff n;
697 scm_t_uint32 i;
698 SCM rest = SCM_EOL;
699 n = FETCH () << 8;
700 n += FETCH ();
701 i = FETCH () << 8;
702 i += FETCH ();
703 while (sp - (fp - 1) > n)
704 /* No need to check for underflow. */
705 CONS (rest, *sp--, rest);
706 LOCAL_SET (i, rest);
707 NEXT;
708}
709
e4257331 710VM_DEFINE_INSTRUCTION (52, reserve_locals, "reserve-locals", 2, -1, -1)
b7946e9e 711{
258344b4 712 SCM *old_sp;
55d9bc94
AW
713 scm_t_int32 n;
714 n = FETCH () << 8;
715 n += FETCH ();
258344b4
AW
716 old_sp = sp;
717 sp = (fp - 1) + n;
718
719 if (old_sp < sp)
720 {
721 CHECK_OVERFLOW ();
722 while (old_sp < sp)
723 *++old_sp = SCM_UNDEFINED;
724 }
725 else
726 NULLSTACK (old_sp - sp);
727
55d9bc94
AW
728 NEXT;
729}
730
e4257331 731VM_DEFINE_INSTRUCTION (53, new_frame, "new-frame", 0, 0, 3)
b7946e9e 732{
6c6a4439
AW
733 /* NB: if you change this, see frames.c:vm-frame-num-locals */
734 /* and frames.h, vm-engine.c, etc of course */
b7946e9e
AW
735 PUSH ((SCM)fp); /* dynamic link */
736 PUSH (0); /* mvra */
737 PUSH (0); /* ra */
738 NEXT;
739}
740
e4257331 741VM_DEFINE_INSTRUCTION (54, call, "call", 1, -1, 1)
a98cef7e 742{
17e90c5e 743 nargs = FETCH ();
a98cef7e
KN
744
745 vm_call:
75c3ed28 746 program = sp[-nargs];
c8b9df71 747
e8c37772 748 VM_HANDLE_INTERRUPTS;
e311f5fa 749
75c3ed28 750 if (SCM_UNLIKELY (!SCM_PROGRAM_P (program)))
a98cef7e 751 {
75c3ed28 752 if (SCM_STRUCTP (program) && SCM_STRUCT_APPLICABLE_P (program))
42906d74 753 {
75c3ed28
AW
754 sp[-nargs] = SCM_STRUCT_PROCEDURE (program);
755 goto vm_call;
756 }
757 else if (SCM_NIMP (program) && SCM_TYP7 (program) == scm_tc7_smob
758 && SCM_SMOB_APPLICABLE_P (program))
759 {
760 SYNC_REGISTER ();
761 sp[-nargs] = scm_i_smob_apply_trampoline (program);
762 goto vm_call;
42906d74 763 }
23f276de 764 else
75c3ed28 765 goto vm_error_wrong_type_apply;
a98cef7e 766 }
a98cef7e 767
75c3ed28
AW
768 CACHE_PROGRAM ();
769 fp = sp - nargs + 1;
770 ASSERT (SCM_FRAME_RETURN_ADDRESS (fp) == 0);
771 ASSERT (SCM_FRAME_MV_RETURN_ADDRESS (fp) == 0);
772 SCM_FRAME_SET_RETURN_ADDRESS (fp, ip);
773 SCM_FRAME_SET_MV_RETURN_ADDRESS (fp, 0);
774 ip = SCM_C_OBJCODE_BASE (bp);
c45d4d77 775 PUSH_CONTINUATION_HOOK ();
75c3ed28
AW
776 APPLY_HOOK ();
777 NEXT;
a98cef7e
KN
778}
779
a5bbb22e 780VM_DEFINE_INSTRUCTION (55, tail_call, "tail-call", 1, -1, 1)
a98cef7e 781{
17e90c5e 782 nargs = FETCH ();
75c3ed28 783
a5bbb22e 784 vm_tail_call:
75c3ed28 785 program = sp[-nargs];
17e90c5e 786
e8c37772 787 VM_HANDLE_INTERRUPTS;
a98cef7e 788
75c3ed28
AW
789 if (SCM_UNLIKELY (!SCM_PROGRAM_P (program)))
790 {
791 if (SCM_STRUCTP (program) && SCM_STRUCT_APPLICABLE_P (program))
792 {
793 sp[-nargs] = SCM_STRUCT_PROCEDURE (program);
794 goto vm_tail_call;
795 }
796 else if (SCM_NIMP (program) && SCM_TYP7 (program) == scm_tc7_smob
797 && SCM_SMOB_APPLICABLE_P (program))
798 {
799 SYNC_REGISTER ();
800 sp[-nargs] = scm_i_smob_apply_trampoline (program);
801 goto vm_tail_call;
802 }
803 else
804 goto vm_error_wrong_type_apply;
805 }
806 else
17e90c5e 807 {
28106f54 808 int i;
11ea1aba 809#ifdef VM_ENABLE_STACK_NULLING
a6f15a1e
AW
810 SCM *old_sp = sp;
811 CHECK_STACK_LEAK ();
11ea1aba 812#endif
28106f54 813
28106f54 814 /* switch programs */
28106f54 815 CACHE_PROGRAM ();
a6f15a1e
AW
816 /* shuffle down the program and the arguments */
817 for (i = -1, sp = sp - nargs + 1; i < nargs; i++)
818 SCM_FRAME_STACK_ADDRESS (fp)[i] = sp[i];
11ea1aba 819
03e6c165 820 sp = fp + i - 1;
28106f54 821
11ea1aba
AW
822 NULLSTACK (old_sp - sp);
823
3dbbe28d 824 ip = SCM_C_OBJCODE_BASE (bp);
11ea1aba 825
28106f54
AW
826 APPLY_HOOK ();
827 NEXT;
17e90c5e 828 }
17e90c5e
KN
829}
830
827dc8dc 831VM_DEFINE_INSTRUCTION (56, subr_call, "subr-call", 1, -1, -1)
fd629322 832{
5b46a8c2 833 SCM pointer, ret;
fd629322 834 SCM (*subr)();
5b46a8c2 835
fd629322 836 nargs = FETCH ();
5b46a8c2 837 POP (pointer);
fd629322 838
5b46a8c2 839 subr = SCM_POINTER_VALUE (pointer);
fd629322
AW
840
841 VM_HANDLE_INTERRUPTS;
842 SYNC_REGISTER ();
843
844 switch (nargs)
845 {
846 case 0:
847 ret = subr ();
848 break;
849 case 1:
850 ret = subr (sp[0]);
851 break;
852 case 2:
853 ret = subr (sp[-1], sp[0]);
854 break;
855 case 3:
856 ret = subr (sp[-2], sp[-1], sp[0]);
857 break;
858 case 4:
859 ret = subr (sp[-3], sp[-2], sp[-1], sp[0]);
860 break;
861 case 5:
862 ret = subr (sp[-4], sp[-3], sp[-2], sp[-1], sp[0]);
863 break;
864 case 6:
865 ret = subr (sp[-5], sp[-4], sp[-3], sp[-2], sp[-1], sp[0]);
866 break;
867 case 7:
868 ret = subr (sp[-6], sp[-5], sp[-4], sp[-3], sp[-2], sp[-1], sp[0]);
869 break;
870 case 8:
871 ret = subr (sp[-7], sp[-6], sp[-5], sp[-4], sp[-3], sp[-2], sp[-1], sp[0]);
872 break;
873 case 9:
874 ret = subr (sp[-8], sp[-7], sp[-6], sp[-5], sp[-4], sp[-3], sp[-2], sp[-1], sp[0]);
875 break;
876 case 10:
877 ret = subr (sp[-9], sp[-8], sp[-7], sp[-6], sp[-5], sp[-4], sp[-3], sp[-2], sp[-1], sp[0]);
878 break;
879 default:
880 abort ();
881 }
882
883 NULLSTACK_FOR_NONLOCAL_EXIT ();
fd629322
AW
884
885 if (SCM_UNLIKELY (SCM_VALUESP (ret)))
886 {
887 /* multiple values returned to continuation */
888 ret = scm_struct_ref (ret, SCM_INUM0);
889 nvalues = scm_ilength (ret);
890 PUSH_LIST (ret, scm_is_null);
891 goto vm_return_values;
892 }
893 else
894 {
895 PUSH (ret);
896 goto vm_return;
897 }
898}
899
827dc8dc 900VM_DEFINE_INSTRUCTION (57, smob_call, "smob-call", 1, -1, -1)
75c3ed28
AW
901{
902 SCM smob, ret;
903 SCM (*subr)();
904 nargs = FETCH ();
905 POP (smob);
906
907 subr = SCM_SMOB_DESCRIPTOR (smob).apply;
908
909 VM_HANDLE_INTERRUPTS;
910 SYNC_REGISTER ();
911
912 switch (nargs)
913 {
914 case 0:
915 ret = subr (smob);
916 break;
917 case 1:
918 ret = subr (smob, sp[0]);
919 break;
920 case 2:
921 ret = subr (smob, sp[-1], sp[0]);
922 break;
923 case 3:
924 ret = subr (smob, sp[-2], sp[-1], sp[0]);
925 break;
926 default:
927 abort ();
928 }
929
930 NULLSTACK_FOR_NONLOCAL_EXIT ();
75c3ed28
AW
931
932 if (SCM_UNLIKELY (SCM_VALUESP (ret)))
933 {
934 /* multiple values returned to continuation */
935 ret = scm_struct_ref (ret, SCM_INUM0);
936 nvalues = scm_ilength (ret);
937 PUSH_LIST (ret, scm_is_null);
938 goto vm_return_values;
939 }
940 else
941 {
942 PUSH (ret);
943 goto vm_return;
944 }
945}
946
827dc8dc
AW
947VM_DEFINE_INSTRUCTION (58, foreign_call, "foreign-call", 1, -1, -1)
948{
949 SCM foreign, ret;
950 nargs = FETCH ();
951 POP (foreign);
952
953 VM_HANDLE_INTERRUPTS;
954 SYNC_REGISTER ();
955
4d9130a5 956 ret = scm_i_foreign_call (foreign, sp - nargs + 1);
827dc8dc
AW
957
958 NULLSTACK_FOR_NONLOCAL_EXIT ();
959
960 if (SCM_UNLIKELY (SCM_VALUESP (ret)))
961 {
962 /* multiple values returned to continuation */
963 ret = scm_struct_ref (ret, SCM_INUM0);
964 nvalues = scm_ilength (ret);
965 PUSH_LIST (ret, scm_is_null);
966 goto vm_return_values;
967 }
968 else
969 {
970 PUSH (ret);
971 goto vm_return;
972 }
973}
974
1d1cae0e
AW
975VM_DEFINE_INSTRUCTION (89, continuation_call, "continuation-call", 0, -1, 0)
976{
977 SCM contregs;
978 POP (contregs);
d8873dfe 979
f7cea645 980 SYNC_ALL ();
d8873dfe
AW
981 scm_i_check_continuation (contregs);
982 vm_return_to_continuation (scm_i_contregs_vm (contregs),
983 scm_i_contregs_vm_cont (contregs),
984 sp - (fp - 1), fp);
985 scm_i_reinstate_continuation (contregs);
986
1d1cae0e
AW
987 /* no NEXT */
988 abort ();
989}
990
cee1d22c
AW
991VM_DEFINE_INSTRUCTION (94, partial_cont_call, "partial-cont-call", 0, -1, 0)
992{
adbdfd6d 993 SCM vmcont, intwinds, prevwinds;
cee1d22c
AW
994 POP (intwinds);
995 POP (vmcont);
07801437 996 SYNC_REGISTER ();
b3950ad6
AW
997 if (SCM_UNLIKELY (!SCM_VM_CONT_REWINDABLE_P (vmcont)))
998 { finish_args = vmcont;
999 goto vm_error_continuation_not_rewindable;
1000 }
adbdfd6d
AW
1001 prevwinds = scm_i_dynwinds ();
1002 vm_reinstate_partial_continuation (vm, vmcont, intwinds, sp + 1 - fp, fp,
1003 vm_cookie);
1004
1005 /* Rewind prompt jmpbuffers, if any. */
1006 {
1007 SCM winds = scm_i_dynwinds ();
1008 for (; !scm_is_eq (winds, prevwinds); winds = scm_cdr (winds))
1009 if (SCM_PROMPT_P (scm_car (winds)) && SCM_PROMPT_SETJMP (scm_car (winds)))
1010 break;
1011 }
1012
07801437
AW
1013 CACHE_REGISTER ();
1014 program = SCM_FRAME_PROGRAM (fp);
1015 CACHE_PROGRAM ();
cee1d22c
AW
1016 NEXT;
1017}
1018
827dc8dc 1019VM_DEFINE_INSTRUCTION (59, tail_call_nargs, "tail-call/nargs", 0, 0, 1)
efbd5892
AW
1020{
1021 SCM x;
1022 POP (x);
1023 nargs = scm_to_int (x);
d51406fe 1024 /* FIXME: should truncate values? */
a5bbb22e 1025 goto vm_tail_call;
efbd5892
AW
1026}
1027
827dc8dc 1028VM_DEFINE_INSTRUCTION (60, call_nargs, "call/nargs", 0, 0, 1)
efbd5892
AW
1029{
1030 SCM x;
1031 POP (x);
1032 nargs = scm_to_int (x);
d51406fe 1033 /* FIXME: should truncate values? */
efbd5892
AW
1034 goto vm_call;
1035}
1036
827dc8dc 1037VM_DEFINE_INSTRUCTION (61, mv_call, "mv-call", 4, -1, 1)
a222b0fa 1038{
97fcf583 1039 scm_t_int32 offset;
e5dc27b8 1040 scm_t_uint8 *mvra;
a222b0fa
AW
1041
1042 nargs = FETCH ();
efbd5892 1043 FETCH_OFFSET (offset);
97fcf583 1044 mvra = ip + offset;
a222b0fa 1045
352c87d7 1046 vm_mv_call:
75c3ed28 1047 program = sp[-nargs];
a222b0fa 1048
7d94e4af
AW
1049 VM_HANDLE_INTERRUPTS;
1050
75c3ed28 1051 if (SCM_UNLIKELY (!SCM_PROGRAM_P (program)))
a222b0fa 1052 {
75c3ed28
AW
1053 if (SCM_STRUCTP (program) && SCM_STRUCT_APPLICABLE_P (program))
1054 {
1055 sp[-nargs] = SCM_STRUCT_PROCEDURE (program);
1056 goto vm_mv_call;
1057 }
1058 else if (SCM_NIMP (program) && SCM_TYP7 (program) == scm_tc7_smob
1059 && SCM_SMOB_APPLICABLE_P (program))
a222b0fa 1060 {
75c3ed28
AW
1061 SYNC_REGISTER ();
1062 sp[-nargs] = scm_i_smob_apply_trampoline (program);
1063 goto vm_mv_call;
a222b0fa 1064 }
cc8d1f5f 1065 else
75c3ed28 1066 goto vm_error_wrong_type_apply;
a222b0fa 1067 }
a222b0fa 1068
75c3ed28
AW
1069 CACHE_PROGRAM ();
1070 fp = sp - nargs + 1;
1071 ASSERT (SCM_FRAME_RETURN_ADDRESS (fp) == 0);
1072 ASSERT (SCM_FRAME_MV_RETURN_ADDRESS (fp) == 0);
1073 SCM_FRAME_SET_RETURN_ADDRESS (fp, ip);
1074 SCM_FRAME_SET_MV_RETURN_ADDRESS (fp, mvra);
1075 ip = SCM_C_OBJCODE_BASE (bp);
c45d4d77 1076 PUSH_CONTINUATION_HOOK ();
75c3ed28
AW
1077 APPLY_HOOK ();
1078 NEXT;
a222b0fa
AW
1079}
1080
827dc8dc 1081VM_DEFINE_INSTRUCTION (62, apply, "apply", 1, -1, 1)
3616e9e9 1082{
c8b9df71
KN
1083 int len;
1084 SCM ls;
1085 POP (ls);
1086
1087 nargs = FETCH ();
9a8cc8e7 1088 ASSERT (nargs >= 2);
c8b9df71
KN
1089
1090 len = scm_ilength (ls);
41e49280
AW
1091 if (SCM_UNLIKELY (len < 0))
1092 {
1093 finish_args = ls;
1094 goto vm_error_apply_to_non_list;
1095 }
c8b9df71 1096
fb10a008 1097 PUSH_LIST (ls, SCM_NULL_OR_NIL_P);
c8b9df71
KN
1098
1099 nargs += len - 2;
1100 goto vm_call;
3616e9e9
KN
1101}
1102
827dc8dc 1103VM_DEFINE_INSTRUCTION (63, tail_apply, "tail-apply", 1, -1, 1)
f03c31db
AW
1104{
1105 int len;
1106 SCM ls;
1107 POP (ls);
1108
1109 nargs = FETCH ();
9a8cc8e7 1110 ASSERT (nargs >= 2);
f03c31db
AW
1111
1112 len = scm_ilength (ls);
41e49280
AW
1113 if (SCM_UNLIKELY (len < 0))
1114 {
1115 finish_args = ls;
1116 goto vm_error_apply_to_non_list;
1117 }
f03c31db 1118
fb10a008 1119 PUSH_LIST (ls, SCM_NULL_OR_NIL_P);
f03c31db
AW
1120
1121 nargs += len - 2;
a5bbb22e 1122 goto vm_tail_call;
f03c31db
AW
1123}
1124
827dc8dc 1125VM_DEFINE_INSTRUCTION (64, call_cc, "call/cc", 0, 1, 1)
17e90c5e 1126{
76282387 1127 int first;
d8873dfe 1128 SCM proc, vm_cont, cont;
76282387
AW
1129 POP (proc);
1130 SYNC_ALL ();
cee1d22c 1131 vm_cont = scm_i_vm_capture_stack (vp->stack_base, fp, sp, ip, NULL, 0);
d8873dfe 1132 cont = scm_i_make_continuation (&first, vm, vm_cont);
76282387
AW
1133 if (first)
1134 {
b7946e9e
AW
1135 PUSH ((SCM)fp); /* dynamic link */
1136 PUSH (0); /* mvra */
1137 PUSH (0); /* ra */
76282387
AW
1138 PUSH (proc);
1139 PUSH (cont);
1140 nargs = 1;
1141 goto vm_call;
1142 }
d8873dfe 1143 else
76282387 1144 {
f3120251
AW
1145 /* Otherwise, the vm continuation was reinstated, and
1146 vm_return_to_continuation pushed on one value. We know only one
1147 value was returned because we are in value context -- the
1148 previous block jumped to vm_call, not vm_mv_call, after all.
1149
1150 So, pull our regs back down from the vp, and march on to the
1151 next instruction. */
d8873dfe
AW
1152 CACHE_REGISTER ();
1153 program = SCM_FRAME_PROGRAM (fp);
1154 CACHE_PROGRAM ();
f3120251 1155 RESTORE_CONTINUATION_HOOK ();
76282387
AW
1156 NEXT;
1157 }
a98cef7e
KN
1158}
1159
827dc8dc 1160VM_DEFINE_INSTRUCTION (65, tail_call_cc, "tail-call/cc", 0, 1, 1)
f03c31db 1161{
76282387 1162 int first;
d8873dfe 1163 SCM proc, vm_cont, cont;
76282387
AW
1164 POP (proc);
1165 SYNC_ALL ();
d8873dfe
AW
1166 /* In contrast to call/cc, tail-call/cc captures the continuation without the
1167 stack frame. */
cee1d22c
AW
1168 vm_cont = scm_i_vm_capture_stack (vp->stack_base,
1169 SCM_FRAME_DYNAMIC_LINK (fp),
1170 SCM_FRAME_LOWER_ADDRESS (fp) - 1,
1171 SCM_FRAME_RETURN_ADDRESS (fp),
1172 SCM_FRAME_MV_RETURN_ADDRESS (fp),
1173 0);
d8873dfe 1174 cont = scm_i_make_continuation (&first, vm, vm_cont);
76282387
AW
1175 if (first)
1176 {
1177 PUSH (proc);
1178 PUSH (cont);
1179 nargs = 1;
a5bbb22e 1180 goto vm_tail_call;
76282387 1181 }
76282387
AW
1182 else
1183 {
d8873dfe 1184 /* Otherwise, cache regs and NEXT, as above. Invoking the continuation
f3120251
AW
1185 does a return from the frame, either to the RA or
1186 MVRA. */
d8873dfe
AW
1187 CACHE_REGISTER ();
1188 program = SCM_FRAME_PROGRAM (fp);
1189 CACHE_PROGRAM ();
f3120251
AW
1190 /* Unfortunately we don't know whether we are at the RA, and thus
1191 have one value without an nvalues marker, or we are at the
1192 MVRA and thus have multiple values and the nvalues
1193 marker. Instead of adding heuristics here, we will let hook
1194 client code do that. */
1195 RESTORE_CONTINUATION_HOOK ();
d8873dfe 1196 NEXT;
76282387 1197 }
f03c31db
AW
1198}
1199
827dc8dc 1200VM_DEFINE_INSTRUCTION (66, return, "return", 0, 1, 1)
a98cef7e 1201{
a98cef7e 1202 vm_return:
c45d4d77 1203 POP_CONTINUATION_HOOK (1);
e8c37772
AW
1204
1205 VM_HANDLE_INTERRUPTS;
1206
f13c269b 1207 {
03e6c165 1208 SCM ret;
f13c269b
AW
1209
1210 POP (ret);
6c6a4439
AW
1211
1212#ifdef VM_ENABLE_STACK_NULLING
1213 SCM *old_sp = sp;
1214#endif
f13c269b
AW
1215
1216 /* Restore registers */
1217 sp = SCM_FRAME_LOWER_ADDRESS (fp);
03e6c165
AW
1218 ip = SCM_FRAME_RETURN_ADDRESS (fp);
1219 fp = SCM_FRAME_DYNAMIC_LINK (fp);
6c6a4439 1220
11ea1aba 1221#ifdef VM_ENABLE_STACK_NULLING
6c6a4439 1222 NULLSTACK (old_sp - sp);
11ea1aba 1223#endif
f13c269b
AW
1224
1225 /* Set return value (sp is already pushed) */
1226 *sp = ret;
1227 }
17e90c5e 1228
15df3447 1229 /* Restore the last program */
af988bbf 1230 program = SCM_FRAME_PROGRAM (fp);
499a4c07 1231 CACHE_PROGRAM ();
7e4760e4 1232 CHECK_IP ();
a98cef7e
KN
1233 NEXT;
1234}
17e90c5e 1235
827dc8dc 1236VM_DEFINE_INSTRUCTION (67, return_values, "return/values", 1, -1, -1)
a222b0fa 1237{
ef24c01b
AW
1238 /* nvalues declared at top level, because for some reason gcc seems to think
1239 that perhaps it might be used without declaration. Fooey to that, I say. */
ef24c01b
AW
1240 nvalues = FETCH ();
1241 vm_return_values:
c45d4d77 1242 POP_CONTINUATION_HOOK (nvalues);
ef24c01b 1243
7d94e4af
AW
1244 VM_HANDLE_INTERRUPTS;
1245
03e6c165 1246 if (nvalues != 1 && SCM_FRAME_MV_RETURN_ADDRESS (fp))
ef24c01b 1247 {
6c6a4439
AW
1248 /* A multiply-valued continuation */
1249 SCM *vals = sp - nvalues;
ef24c01b
AW
1250 int i;
1251 /* Restore registers */
1252 sp = SCM_FRAME_LOWER_ADDRESS (fp) - 1;
03e6c165
AW
1253 ip = SCM_FRAME_MV_RETURN_ADDRESS (fp);
1254 fp = SCM_FRAME_DYNAMIC_LINK (fp);
a222b0fa 1255
ef24c01b
AW
1256 /* Push return values, and the number of values */
1257 for (i = 0; i < nvalues; i++)
6c6a4439 1258 *++sp = vals[i+1];
ef24c01b 1259 *++sp = SCM_I_MAKINUM (nvalues);
a222b0fa 1260
6c6a4439
AW
1261 /* Finally null the end of the stack */
1262 NULLSTACK (vals + nvalues - sp);
ef24c01b
AW
1263 }
1264 else if (nvalues >= 1)
1265 {
1266 /* Multiple values for a single-valued continuation -- here's where I
1267 break with guile tradition and try and do something sensible. (Also,
1268 this block handles the single-valued return to an mv
1269 continuation.) */
6c6a4439 1270 SCM *vals = sp - nvalues;
ef24c01b
AW
1271 /* Restore registers */
1272 sp = SCM_FRAME_LOWER_ADDRESS (fp) - 1;
03e6c165
AW
1273 ip = SCM_FRAME_RETURN_ADDRESS (fp);
1274 fp = SCM_FRAME_DYNAMIC_LINK (fp);
a222b0fa 1275
ef24c01b 1276 /* Push first value */
6c6a4439 1277 *++sp = vals[1];
a222b0fa 1278
6c6a4439
AW
1279 /* Finally null the end of the stack */
1280 NULLSTACK (vals + nvalues - sp);
ef24c01b
AW
1281 }
1282 else
1283 goto vm_error_no_values;
a222b0fa
AW
1284
1285 /* Restore the last program */
1286 program = SCM_FRAME_PROGRAM (fp);
1287 CACHE_PROGRAM ();
a222b0fa
AW
1288 CHECK_IP ();
1289 NEXT;
1290}
1291
827dc8dc 1292VM_DEFINE_INSTRUCTION (68, return_values_star, "return/values*", 1, -1, -1)
ef24c01b
AW
1293{
1294 SCM l;
1295
1296 nvalues = FETCH ();
11ea1aba 1297 ASSERT (nvalues >= 1);
ef24c01b
AW
1298
1299 nvalues--;
1300 POP (l);
9bd48cb1 1301 while (scm_is_pair (l))
ef24c01b
AW
1302 {
1303 PUSH (SCM_CAR (l));
1304 l = SCM_CDR (l);
1305 nvalues++;
1306 }
fb10a008 1307 if (SCM_UNLIKELY (!SCM_NULL_OR_NIL_P (l))) {
e06e857c 1308 finish_args = scm_list_1 (l);
fb10a008
AW
1309 goto vm_error_improper_list;
1310 }
ef24c01b
AW
1311
1312 goto vm_return_values;
1313}
1314
2d9260d1
AW
1315VM_DEFINE_INSTRUCTION (88, return_nvalues, "return/nvalues", 0, 1, -1)
1316{
1317 SCM n;
1318 POP (n);
1319 nvalues = scm_to_int (n);
1320 ASSERT (nvalues >= 0);
1321 goto vm_return_values;
1322}
1323
827dc8dc 1324VM_DEFINE_INSTRUCTION (69, truncate_values, "truncate-values", 2, -1, -1)
d51406fe
AW
1325{
1326 SCM x;
1327 int nbinds, rest;
1328 POP (x);
1329 nvalues = scm_to_int (x);
1330 nbinds = FETCH ();
1331 rest = FETCH ();
1332
1333 if (rest)
1334 nbinds--;
1335
1336 if (nvalues < nbinds)
1337 goto vm_error_not_enough_values;
1338
1339 if (rest)
1340 POP_LIST (nvalues - nbinds);
1341 else
1342 DROPN (nvalues - nbinds);
1343
1344 NEXT;
1345}
1346
827dc8dc 1347VM_DEFINE_INSTRUCTION (70, box, "box", 1, 1, 0)
a9b0f876 1348{
8d90b356
AW
1349 SCM val;
1350 POP (val);
1351 SYNC_BEFORE_GC ();
1352 LOCAL_SET (FETCH (), scm_cell (scm_tc7_variable, SCM_UNPACK (val)));
a9b0f876
AW
1353 NEXT;
1354}
1355
8d90b356
AW
1356/* for letrec:
1357 (let ((a *undef*) (b *undef*) ...)
1358 (set! a (lambda () (b ...)))
1359 ...)
1360 */
827dc8dc 1361VM_DEFINE_INSTRUCTION (71, empty_box, "empty-box", 1, 0, 0)
a9b0f876 1362{
8d90b356
AW
1363 SYNC_BEFORE_GC ();
1364 LOCAL_SET (FETCH (),
1365 scm_cell (scm_tc7_variable, SCM_UNPACK (SCM_UNDEFINED)));
1366 NEXT;
1367}
a9b0f876 1368
827dc8dc 1369VM_DEFINE_INSTRUCTION (72, local_boxed_ref, "local-boxed-ref", 1, 0, 1)
8d90b356
AW
1370{
1371 SCM v = LOCAL_REF (FETCH ());
1372 ASSERT_BOUND_VARIABLE (v);
1373 PUSH (VARIABLE_REF (v));
1374 NEXT;
1375}
a9b0f876 1376
827dc8dc 1377VM_DEFINE_INSTRUCTION (73, local_boxed_set, "local-boxed-set", 1, 1, 0)
8d90b356
AW
1378{
1379 SCM v, val;
1380 v = LOCAL_REF (FETCH ());
1381 POP (val);
1382 ASSERT_VARIABLE (v);
1383 VARIABLE_SET (v, val);
a9b0f876
AW
1384 NEXT;
1385}
1386
827dc8dc 1387VM_DEFINE_INSTRUCTION (74, free_ref, "free-ref", 1, 0, 1)
a9b0f876 1388{
8d90b356
AW
1389 scm_t_uint8 idx = FETCH ();
1390
57ab0671
AW
1391 CHECK_FREE_VARIABLE (idx);
1392 PUSH (FREE_VARIABLE_REF (idx));
8d90b356
AW
1393 NEXT;
1394}
a9b0f876 1395
57ab0671 1396/* no free-set -- if a var is assigned, it should be in a box */
a9b0f876 1397
827dc8dc 1398VM_DEFINE_INSTRUCTION (75, free_boxed_ref, "free-boxed-ref", 1, 0, 1)
8d90b356
AW
1399{
1400 SCM v;
1401 scm_t_uint8 idx = FETCH ();
57ab0671
AW
1402 CHECK_FREE_VARIABLE (idx);
1403 v = FREE_VARIABLE_REF (idx);
8d90b356
AW
1404 ASSERT_BOUND_VARIABLE (v);
1405 PUSH (VARIABLE_REF (v));
1406 NEXT;
1407}
1408
827dc8dc 1409VM_DEFINE_INSTRUCTION (76, free_boxed_set, "free-boxed-set", 1, 1, 0)
8d90b356
AW
1410{
1411 SCM v, val;
1412 scm_t_uint8 idx = FETCH ();
1413 POP (val);
57ab0671
AW
1414 CHECK_FREE_VARIABLE (idx);
1415 v = FREE_VARIABLE_REF (idx);
8d90b356
AW
1416 ASSERT_BOUND_VARIABLE (v);
1417 VARIABLE_SET (v, val);
1418 NEXT;
1419}
1420
827dc8dc 1421VM_DEFINE_INSTRUCTION (77, make_closure, "make-closure", 2, -1, 1)
8d90b356 1422{
6f16379e
AW
1423 size_t n, len;
1424 SCM closure;
1425
1426 len = FETCH ();
1427 len <<= 8;
1428 len += FETCH ();
8d90b356 1429 SYNC_BEFORE_GC ();
6f16379e
AW
1430 closure = scm_words (scm_tc7_program | (len<<16), len + 3);
1431 SCM_SET_CELL_OBJECT_1 (closure, SCM_PROGRAM_OBJCODE (sp[-len]));
1432 SCM_SET_CELL_OBJECT_2 (closure, SCM_PROGRAM_OBJTABLE (sp[-len]));
1433 sp[-len] = closure;
1434 for (n = 0; n < len; n++)
1435 SCM_PROGRAM_FREE_VARIABLE_SET (closure, n, sp[-len + 1 + n]);
1436 DROPN (len);
a9b0f876
AW
1437 NEXT;
1438}
1439
827dc8dc 1440VM_DEFINE_INSTRUCTION (78, make_variable, "make-variable", 0, 0, 1)
80545853
AW
1441{
1442 SYNC_BEFORE_GC ();
1443 /* fixme underflow */
1444 PUSH (scm_cell (scm_tc7_variable, SCM_UNPACK (SCM_UNDEFINED)));
1445 NEXT;
1446}
1447
827dc8dc 1448VM_DEFINE_INSTRUCTION (79, fix_closure, "fix-closure", 2, -1, 0)
c21c89b1 1449{
6f16379e 1450 SCM x;
c21c89b1 1451 unsigned int i = FETCH ();
6f16379e 1452 size_t n, len;
c21c89b1
AW
1453 i <<= 8;
1454 i += FETCH ();
c21c89b1
AW
1455 /* FIXME CHECK_LOCAL (i) */
1456 x = LOCAL_REF (i);
1457 /* FIXME ASSERT_PROGRAM (x); */
6f16379e
AW
1458 len = SCM_PROGRAM_NUM_FREE_VARIABLES (x);
1459 for (n = 0; n < len; n++)
1460 SCM_PROGRAM_FREE_VARIABLE_SET (x, n, sp[-len + 1 + n]);
1461 DROPN (len);
c21c89b1
AW
1462 NEXT;
1463}
1464
827dc8dc 1465VM_DEFINE_INSTRUCTION (80, define, "define", 0, 0, 2)
94ff26b9
AW
1466{
1467 SCM sym, val;
1468 POP (sym);
1469 POP (val);
1470 SYNC_REGISTER ();
1471 VARIABLE_SET (scm_sym2var (sym, scm_current_module_lookup_closure (),
1472 SCM_BOOL_T),
1473 val);
1474 NEXT;
1475}
1476
827dc8dc 1477VM_DEFINE_INSTRUCTION (81, make_keyword, "make-keyword", 0, 1, 1)
94ff26b9
AW
1478{
1479 CHECK_UNDERFLOW ();
1480 SYNC_REGISTER ();
1481 *sp = scm_symbol_to_keyword (*sp);
1482 NEXT;
1483}
1484
827dc8dc 1485VM_DEFINE_INSTRUCTION (82, make_symbol, "make-symbol", 0, 1, 1)
94ff26b9
AW
1486{
1487 CHECK_UNDERFLOW ();
1488 SYNC_REGISTER ();
1489 *sp = scm_string_to_symbol (*sp);
1490 NEXT;
1491}
1492
ea6b18e8 1493VM_DEFINE_INSTRUCTION (83, prompt, "prompt", 4, 2, 0)
4f66bcde
AW
1494{
1495 scm_t_int32 offset;
ea6b18e8 1496 scm_t_uint8 escape_only_p;
747022e4 1497 SCM k, prompt;
4f66bcde 1498
4f66bcde
AW
1499 escape_only_p = FETCH ();
1500 FETCH_OFFSET (offset);
4f66bcde
AW
1501 POP (k);
1502
1503 SYNC_REGISTER ();
d2964315 1504 /* Push the prompt onto the dynamic stack. */
adbdfd6d
AW
1505 prompt = scm_c_make_prompt (k, fp, sp, ip + offset, escape_only_p, vm_cookie,
1506 scm_i_dynwinds ());
1507 scm_i_set_dynwinds (scm_cons (prompt, SCM_PROMPT_DYNWINDS (prompt)));
adaf86ec 1508 if (SCM_PROMPT_SETJMP (prompt))
4f66bcde
AW
1509 {
1510 /* The prompt exited nonlocally. Cache the regs back from the vp, and go
ea6b18e8 1511 to the handler.
d2964315
AW
1512
1513 Note, at this point, we must assume that any variable local to
1514 vm_engine that can be assigned *has* been assigned. So we need to pull
1515 all our state back from the ip/fp/sp.
ea6b18e8 1516 */
d2964315
AW
1517 CACHE_REGISTER ();
1518 program = SCM_FRAME_PROGRAM (fp);
1519 CACHE_PROGRAM ();
f3120251
AW
1520 /* The stack contains the values returned to this prompt, along
1521 with a number-of-values marker -- like an MV return. */
1522 ABORT_CONTINUATION_HOOK ();
4f66bcde
AW
1523 NEXT;
1524 }
1525
1526 /* Otherwise setjmp returned for the first time, so we go to execute the
1527 prompt's body. */
1528 NEXT;
1529}
1530
1531VM_DEFINE_INSTRUCTION (85, wind, "wind", 0, 2, 0)
1532{
1533 SCM wind, unwind;
1534 POP (unwind);
1535 POP (wind);
1536 SYNC_REGISTER ();
1537 /* Push wind and unwind procedures onto the dynamic stack. Note that neither
1538 are actually called; the compiler should emit calls to wind and unwind for
1539 the normal dynamic-wind control flow. */
1540 if (SCM_UNLIKELY (scm_is_false (scm_thunk_p (wind))))
1541 {
1542 finish_args = wind;
1543 goto vm_error_not_a_thunk;
1544 }
1545 if (SCM_UNLIKELY (scm_is_false (scm_thunk_p (unwind))))
1546 {
1547 finish_args = unwind;
1548 goto vm_error_not_a_thunk;
1549 }
1550 scm_i_set_dynwinds (scm_cons (scm_cons (wind, unwind), scm_i_dynwinds ()));
1551 NEXT;
1552}
1553
6e84cb95 1554VM_DEFINE_INSTRUCTION (86, abort, "abort", 1, -1, -1)
4f66bcde
AW
1555{
1556 unsigned n = FETCH ();
4f66bcde 1557 SYNC_REGISTER ();
2d026f04 1558 if (sp - n - 2 <= SCM_FRAME_UPPER_ADDRESS (fp))
eaefabee 1559 goto vm_error_stack_underflow;
cee1d22c 1560 vm_abort (vm, n, vm_cookie);
6e84cb95 1561 /* vm_abort should not return */
4f66bcde
AW
1562 abort ();
1563}
1564
1565VM_DEFINE_INSTRUCTION (87, unwind, "unwind", 0, 0, 0)
1566{
1567 /* A normal exit from the dynamic extent of an expression. Pop the top entry
1568 off of the dynamic stack. */
1569 scm_i_set_dynwinds (scm_cdr (scm_i_dynwinds ()));
1570 NEXT;
1571}
1572
e084b27e
AW
1573VM_DEFINE_INSTRUCTION (90, wind_fluids, "wind-fluids", 1, -1, 0)
1574{
1575 unsigned n = FETCH ();
1576 SCM wf;
1577
1578 if (sp - 2*n < SCM_FRAME_UPPER_ADDRESS (fp))
1579 goto vm_error_stack_underflow;
1580
f7cea645 1581 SYNC_REGISTER ();
e084b27e 1582 wf = scm_i_make_with_fluids (n, sp + 1 - 2*n, sp + 1 - n);
26e6f99f 1583 scm_i_swap_with_fluids (wf, dynstate);
e084b27e
AW
1584 scm_i_set_dynwinds (scm_cons (wf, scm_i_dynwinds ()));
1585 NEXT;
1586}
1587
1588VM_DEFINE_INSTRUCTION (91, unwind_fluids, "unwind-fluids", 0, 0, 0)
1589{
1590 SCM wf;
1591 wf = scm_car (scm_i_dynwinds ());
1592 scm_i_set_dynwinds (scm_cdr (scm_i_dynwinds ()));
26e6f99f 1593 scm_i_swap_with_fluids (wf, dynstate);
e084b27e
AW
1594 NEXT;
1595}
4f66bcde 1596
1e7a0337
AW
1597VM_DEFINE_INSTRUCTION (92, fluid_ref, "fluid-ref", 0, 1, 1)
1598{
1599 size_t num;
1600 SCM fluids;
1601
1602 CHECK_UNDERFLOW ();
1603 fluids = SCM_I_DYNAMIC_STATE_FLUIDS (dynstate);
6f8d7b12 1604 if (SCM_UNLIKELY (!SCM_FLUID_P (*sp))
1e7a0337
AW
1605 || ((num = SCM_I_FLUID_NUM (*sp)) >= SCM_SIMPLE_VECTOR_LENGTH (fluids)))
1606 {
1607 /* Punt dynstate expansion and error handling to the C proc. */
1608 SYNC_REGISTER ();
1609 *sp = scm_fluid_ref (*sp);
1610 }
1611 else
1612 *sp = SCM_SIMPLE_VECTOR_REF (fluids, num);
1613
1614 NEXT;
1615}
1616
1617VM_DEFINE_INSTRUCTION (93, fluid_set, "fluid-set", 0, 2, 0)
1618{
1619 size_t num;
1620 SCM val, fluid, fluids;
1621
1622 POP (val);
1623 POP (fluid);
1624 fluids = SCM_I_DYNAMIC_STATE_FLUIDS (dynstate);
6f8d7b12 1625 if (SCM_UNLIKELY (!SCM_FLUID_P (fluid))
1e7a0337
AW
1626 || ((num = SCM_I_FLUID_NUM (fluid)) >= SCM_SIMPLE_VECTOR_LENGTH (fluids)))
1627 {
1628 /* Punt dynstate expansion and error handling to the C proc. */
1629 SYNC_REGISTER ();
1630 scm_fluid_set_x (fluid, val);
1631 }
1632 else
1633 SCM_SIMPLE_VECTOR_SET (fluids, num, val);
1634
1635 NEXT;
1636}
1637
de45d8ee
AW
1638VM_DEFINE_INSTRUCTION (95, assert_nargs_ee_locals, "assert-nargs-ee/locals", 1, 0, 0)
1639{
1640 scm_t_ptrdiff n;
1641 SCM *old_sp;
1642
1643 /* nargs = n & 0x7, nlocs = nargs + (n >> 3) */
1644 n = FETCH ();
1645
1646 if (SCM_UNLIKELY (sp - (fp - 1) != (n & 0x7)))
1647 goto vm_error_wrong_num_args;
1648
1649 old_sp = sp;
1650 sp += (n >> 3);
1651 CHECK_OVERFLOW ();
1652 while (old_sp < sp)
1653 *++old_sp = SCM_UNDEFINED;
1654
1655 NEXT;
1656}
1657
8d90b356 1658
53e28ed9
AW
1659/*
1660(defun renumber-ops ()
1661 "start from top of buffer and renumber 'VM_DEFINE_FOO (\n' sequences"
1662 (interactive "")
1663 (save-excursion
1664 (let ((counter -1)) (goto-char (point-min))
1665 (while (re-search-forward "^VM_DEFINE_[^ ]+ (\\([^,]+\\)," (point-max) t)
1666 (replace-match
1667 (number-to-string (setq counter (1+ counter)))
1668 t t nil 1)))))
ff810079 1669(renumber-ops)
53e28ed9 1670*/
17e90c5e
KN
1671/*
1672 Local Variables:
1673 c-file-style: "gnu"
1674 End:
1675*/