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