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