1 /* Copyright (C) 2001, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
3 * This library is free software; you can redistribute it and/or
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.
8 * This library is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 /* This file is included in vm.c multiple times. */
22 #define UNPACK_8_8_8(op,a,b,c) \
25 a = (op >> 8) & 0xff; \
26 b = (op >> 16) & 0xff; \
31 #define UNPACK_8_16(op,a,b) \
34 a = (op >> 8) & 0xff; \
39 #define UNPACK_16_8(op,a,b) \
42 a = (op >> 8) & 0xffff; \
47 #define UNPACK_12_12(op,a,b) \
50 a = (op >> 8) & 0xfff; \
55 #define UNPACK_24(op,a) \
63 #if (VM_ENGINE == SCM_VM_REGULAR_ENGINE)
64 # define VM_USE_HOOKS 0 /* Various hooks */
65 #elif (VM_ENGINE == SCM_VM_DEBUG_ENGINE)
66 # define VM_USE_HOOKS 1
68 # error unknown debug engine VM_ENGINE
71 /* Assign some registers by hand. There used to be a bigger list here,
72 but it was never tested, and in the case of x86-32, was a source of
73 compilation failures. It can be revived if it's useful, but my naive
74 hope is that simply annotating the locals with "register" will be a
75 sufficient hint to the compiler. */
77 # if defined __x86_64__
78 /* GCC 4.6 chooses %rbp for IP_REG and %rbx for SP_REG, which works
79 well. Tell it to keep the jump table in a r12, which is
81 # define JT_REG asm ("r12")
95 #define VM_ASSERT(condition, handler) \
97 if (SCM_UNLIKELY (!(condition))) \
104 #ifdef VM_ENABLE_ASSERTIONS
105 # define ASSERT(condition) VM_ASSERT (condition, abort())
107 # define ASSERT(condition)
111 #define RUN_HOOK(h, args, n) \
113 if (SCM_UNLIKELY (vp->trace_level > 0)) \
116 vm_dispatch_hook (vm, h, args, n); \
120 #define RUN_HOOK(h, args, n)
122 #define RUN_HOOK0(h) RUN_HOOK(h, NULL, 0)
124 #define APPLY_HOOK() \
125 RUN_HOOK0 (SCM_VM_APPLY_HOOK)
126 #define PUSH_CONTINUATION_HOOK() \
127 RUN_HOOK0 (SCM_VM_PUSH_CONTINUATION_HOOK)
128 #define POP_CONTINUATION_HOOK(old_fp) \
129 RUN_HOOK (SCM_VM_POP_CONTINUATION_HOOK, \
130 &SCM_FRAME_LOCAL (old_fp, 1), \
131 SCM_FRAME_NUM_LOCALS (old_fp, vp->sp) - 1)
132 #define NEXT_HOOK() \
133 RUN_HOOK0 (SCM_VM_NEXT_HOOK)
134 #define ABORT_CONTINUATION_HOOK() \
135 RUN_HOOK (SCM_VM_ABORT_CONTINUATION_HOOK, \
137 FRAME_LOCALS_COUNT () - 1)
138 #define RESTORE_CONTINUATION_HOOK() \
139 RUN_HOOK0 (SCM_VM_RESTORE_CONTINUATION_HOOK)
141 #define VM_HANDLE_INTERRUPTS \
142 SCM_ASYNC_TICK_WITH_CODE (current_thread, SYNC_REGISTER ())
147 This is Guile's new virtual machine. When I say "new", I mean
148 relative to the current virtual machine. At some point it will
149 become "the" virtual machine, and we'll delete this paragraph. As
150 such, the rest of the comments speak as if there's only one VM.
151 In difference from the old VM, local 0 is the procedure, and the
152 first argument is local 1. At some point in the future we should
153 change the fp to point to the procedure and not to local 1.
159 /* The VM has three state bits: the instruction pointer (IP), the frame
160 pointer (FP), and the top-of-stack pointer (SP). We cache the first
161 two of these in machine registers, local to the VM, because they are
162 used extensively by the VM. As the SP is used more by code outside
163 the VM than by the VM itself, we don't bother caching it locally.
165 Since the FP changes infrequently, relative to the IP, we keep vp->fp
166 in sync with the local FP. This would be a big lose for the IP,
167 though, so instead of updating vp->ip all the time, we call SYNC_IP
168 whenever we would need to know the IP of the top frame. In practice,
169 we need to SYNC_IP whenever we call out of the VM to a function that
170 would like to walk the stack, perhaps as the result of an
176 #define SYNC_REGISTER() \
178 #define SYNC_BEFORE_GC() /* Only SP and FP needed to trace GC */
179 #define SYNC_ALL() /* FP already saved */ \
182 #define CHECK_OVERFLOW(sp) \
184 if (SCM_UNLIKELY ((sp) >= stack_limit)) \
185 vm_error_stack_overflow (vp); \
188 /* Reserve stack space for a frame. Will check that there is sufficient
189 stack space for N locals, including the procedure. Invoke after
190 preparing the new frame and setting the fp and ip. */
191 #define ALLOC_FRAME(n) \
193 SCM *new_sp = vp->sp = LOCAL_ADDRESS (n - 1); \
194 CHECK_OVERFLOW (new_sp); \
197 /* Reset the current frame to hold N locals. Used when we know that no
198 stack expansion is needed. */
199 #define RESET_FRAME(n) \
201 vp->sp = LOCAL_ADDRESS (n - 1); \
204 /* Compute the number of locals in the frame. At a call, this is equal
205 to the number of actual arguments when a function is first called,
206 plus one for the function. */
207 #define FRAME_LOCALS_COUNT_FROM(slot) \
208 (vp->sp + 1 - LOCAL_ADDRESS (slot))
209 #define FRAME_LOCALS_COUNT() \
210 FRAME_LOCALS_COUNT_FROM (0)
212 /* Restore registers after returning from a frame. */
213 #define RESTORE_FRAME() \
218 #define CACHE_REGISTER() \
220 ip = (scm_t_uint32 *) vp->ip; \
224 #ifdef HAVE_LABELS_AS_VALUES
225 # define BEGIN_DISPATCH_SWITCH /* */
226 # define END_DISPATCH_SWITCH /* */
233 goto *jump_table[op & 0xff]; \
236 # define VM_DEFINE_OP(opcode, tag, name, meta) \
239 # define BEGIN_DISPATCH_SWITCH \
245 # define END_DISPATCH_SWITCH \
247 goto vm_error_bad_instruction; \
256 # define VM_DEFINE_OP(opcode, tag, name, meta) \
261 #define LOCAL_ADDRESS(i) (&SCM_FRAME_LOCAL (fp, i))
262 #define LOCAL_REF(i) SCM_FRAME_LOCAL (fp, i)
263 #define LOCAL_SET(i,o) SCM_FRAME_LOCAL (fp, i) = o
265 #define VARIABLE_REF(v) SCM_VARIABLE_REF (v)
266 #define VARIABLE_SET(v,o) SCM_VARIABLE_SET (v, o)
267 #define VARIABLE_BOUNDP(v) (!scm_is_eq (VARIABLE_REF (v), SCM_UNDEFINED))
269 #define RETURN_ONE_VALUE(ret) \
273 VM_HANDLE_INTERRUPTS; \
274 ip = SCM_FRAME_RETURN_ADDRESS (fp); \
275 fp = vp->fp = SCM_FRAME_DYNAMIC_LINK (fp); \
277 old_fp[-1] = SCM_BOOL_F; \
278 old_fp[-2] = SCM_BOOL_F; \
280 SCM_FRAME_LOCAL (old_fp, 1) = val; \
281 vp->sp = &SCM_FRAME_LOCAL (old_fp, 1); \
282 POP_CONTINUATION_HOOK (old_fp); \
286 /* While we could generate the list-unrolling code here, it's fine for
287 now to just tail-call (apply values vals). */
288 #define RETURN_VALUE_LIST(vals_) \
291 VM_HANDLE_INTERRUPTS; \
292 fp[0] = vm_builtin_apply; \
293 fp[1] = vm_builtin_values; \
296 ip = (scm_t_uint32 *) vm_builtin_apply_code; \
297 goto op_tail_apply; \
300 #define BR_NARGS(rel) \
301 scm_t_uint32 expected; \
302 UNPACK_24 (op, expected); \
303 if (FRAME_LOCALS_COUNT() rel expected) \
305 scm_t_int32 offset = ip[1]; \
306 offset >>= 8; /* Sign-extending shift. */ \
311 #define BR_UNARY(x, exp) \
314 UNPACK_24 (op, test); \
315 x = LOCAL_REF (test); \
316 if ((ip[1] & 0x1) ? !(exp) : (exp)) \
318 scm_t_int32 offset = ip[1]; \
319 offset >>= 8; /* Sign-extending shift. */ \
321 VM_HANDLE_INTERRUPTS; \
326 #define BR_BINARY(x, y, exp) \
329 UNPACK_12_12 (op, a, b); \
332 if ((ip[1] & 0x1) ? !(exp) : (exp)) \
334 scm_t_int32 offset = ip[1]; \
335 offset >>= 8; /* Sign-extending shift. */ \
337 VM_HANDLE_INTERRUPTS; \
342 #define BR_ARITHMETIC(crel,srel) \
346 UNPACK_12_12 (op, a, b); \
349 if (SCM_I_INUMP (x) && SCM_I_INUMP (y)) \
351 scm_t_signed_bits x_bits = SCM_UNPACK (x); \
352 scm_t_signed_bits y_bits = SCM_UNPACK (y); \
353 if ((ip[1] & 0x1) ? !(x_bits crel y_bits) : (x_bits crel y_bits)) \
355 scm_t_int32 offset = ip[1]; \
356 offset >>= 8; /* Sign-extending shift. */ \
358 VM_HANDLE_INTERRUPTS; \
368 if ((ip[1] & 0x1) ? scm_is_false (res) : scm_is_true (res)) \
370 scm_t_int32 offset = ip[1]; \
371 offset >>= 8; /* Sign-extending shift. */ \
373 VM_HANDLE_INTERRUPTS; \
381 scm_t_uint16 dst, src; \
383 UNPACK_12_12 (op, dst, src); \
385 #define ARGS2(a1, a2) \
386 scm_t_uint8 dst, src1, src2; \
388 UNPACK_8_8_8 (op, dst, src1, src2); \
389 a1 = LOCAL_REF (src1); \
390 a2 = LOCAL_REF (src2)
392 do { LOCAL_SET (dst, x); NEXT (1); } while (0)
394 /* The maximum/minimum tagged integers. */
396 ((scm_t_signed_bits) SCM_UNPACK (SCM_I_MAKINUM (SCM_MOST_POSITIVE_FIXNUM)))
398 ((scm_t_signed_bits) SCM_UNPACK (SCM_I_MAKINUM (SCM_MOST_NEGATIVE_FIXNUM)))
400 ((scm_t_signed_bits) SCM_UNPACK (SCM_INUM1) \
401 - (scm_t_signed_bits) SCM_UNPACK (SCM_INUM0))
403 #define BINARY_INTEGER_OP(CFUNC,SFUNC) \
406 if (SCM_I_INUMP (x) && SCM_I_INUMP (y)) \
408 scm_t_int64 n = SCM_I_INUM (x) CFUNC SCM_I_INUM (y); \
409 if (SCM_FIXABLE (n)) \
410 RETURN (SCM_I_MAKINUM (n)); \
413 RETURN (SFUNC (x, y)); \
416 #define VM_VALIDATE_PAIR(x, proc) \
417 VM_ASSERT (scm_is_pair (x), vm_error_not_a_pair (proc, x))
419 #define VM_VALIDATE_STRUCT(obj, proc) \
420 VM_ASSERT (SCM_STRUCTP (obj), vm_error_not_a_pair (proc, obj))
422 #define VM_VALIDATE_BYTEVECTOR(x, proc) \
423 VM_ASSERT (SCM_BYTEVECTOR_P (x), vm_error_not_a_bytevector (proc, x))
425 /* Return true (non-zero) if PTR has suitable alignment for TYPE. */
426 #define ALIGNED_P(ptr, type) \
427 ((scm_t_uintptr) (ptr) % alignof_type (type) == 0)
430 RTL_VM_NAME (SCM vm
, SCM program
, SCM
*argv
, size_t nargs_
)
432 /* Instruction pointer: A pointer to the opcode that is currently
434 register scm_t_uint32
*ip IP_REG
;
436 /* Frame pointer: A pointer into the stack, off of which we index
437 arguments and local variables. Pushed at function calls, popped on
439 register SCM
*fp FP_REG
;
441 /* Current opcode: A cache of *ip. */
442 register scm_t_uint32 op
;
444 /* Cached variables. */
445 struct scm_vm
*vp
= SCM_VM_DATA (vm
);
446 SCM
*stack_limit
= vp
->stack_limit
; /* stack limit address */
447 scm_i_thread
*current_thread
= SCM_I_CURRENT_THREAD
;
448 scm_i_jmp_buf registers
; /* used for prompts */
450 #ifdef HAVE_LABELS_AS_VALUES
451 static const void **jump_table_pointer
= NULL
;
452 register const void **jump_table JT_REG
;
454 if (SCM_UNLIKELY (!jump_table_pointer
))
457 jump_table_pointer
= malloc (SCM_VM_NUM_INSTRUCTIONS
* sizeof (void*));
458 for (i
= 0; i
< SCM_VM_NUM_INSTRUCTIONS
; i
++)
459 jump_table_pointer
[i
] = &&vm_error_bad_instruction
;
460 #define INIT(opcode, tag, name, meta) jump_table_pointer[opcode] = &&op_##tag;
461 FOR_EACH_VM_OPERATION(INIT
);
465 /* Attempt to keep JUMP_TABLE_POINTER in a register. This saves one
466 load instruction at each instruction dispatch. */
467 jump_table
= jump_table_pointer
;
470 if (SCM_I_SETJMP (registers
))
472 /* Non-local return. The values are on the stack, on a new frame
473 set up to call `values' to return the values to the handler.
474 Cache the VM registers back from the vp, and dispatch to the
477 Note, at this point, we must assume that any variable local to
478 vm_engine that can be assigned *has* been assigned. So we need
479 to pull all our state back from the ip/fp/sp.
482 ABORT_CONTINUATION_HOOK ();
486 /* Load previous VM registers. */
489 VM_HANDLE_INTERRUPTS
;
495 /* Check that we have enough space: 3 words for the boot
496 continuation, 3 + nargs for the procedure application, and 3 for
497 setting up a new frame. */
499 CHECK_OVERFLOW (vp
->sp
+ 3 + 3 + nargs_
+ 3);
501 /* Since it's possible to receive the arguments on the stack itself,
502 and indeed the regular VM invokes us that way, shuffle up the
506 for (i
= nargs_
- 1; i
>= 0; i
--)
507 base
[6 + i
] = argv
[i
];
510 /* Initial frame, saving previous fp and ip, with the boot
512 base
[0] = SCM_PACK (fp
); /* dynamic link */
513 base
[1] = SCM_PACK (ip
); /* ra */
514 base
[2] = vm_boot_continuation
;
516 ip
= (scm_t_uint32
*) vm_boot_continuation_code
;
518 /* MV-call frame, function & arguments */
519 base
[3] = SCM_PACK (fp
); /* dynamic link */
520 base
[4] = SCM_PACK (ip
); /* ra */
522 fp
= vp
->fp
= &base
[5];
523 RESET_FRAME (nargs_
+ 1);
527 while (!SCM_PROGRAM_P (SCM_FRAME_PROGRAM (fp
)))
529 SCM proc
= SCM_FRAME_PROGRAM (fp
);
531 if (SCM_STRUCTP (proc
) && SCM_STRUCT_APPLICABLE_P (proc
))
533 LOCAL_SET (0, SCM_STRUCT_PROCEDURE (proc
));
536 if (SCM_HAS_TYP7 (proc
, scm_tc7_smob
) && SCM_SMOB_APPLICABLE_P (proc
))
538 scm_t_uint32 n
= FRAME_LOCALS_COUNT();
540 /* Shuffle args up. */
543 LOCAL_SET (n
+ 1, LOCAL_REF (n
));
545 LOCAL_SET (0, SCM_SMOB_DESCRIPTOR (proc
).apply_trampoline
);
550 vm_error_wrong_type_apply (proc
);
554 ip
= SCM_PROGRAM_CODE (SCM_FRAME_PROGRAM (fp
));
557 BEGIN_DISPATCH_SWITCH
;
568 * Bring the VM to a halt, returning all the values from the stack.
570 VM_DEFINE_OP (0, halt
, "halt", OP1 (U8_X24
))
572 /* Boot closure in r0, empty frame in r1/r2, proc in r3, values from r4. */
574 scm_t_uint32 nvals
= FRAME_LOCALS_COUNT_FROM (4);
584 for (n
= nvals
; n
> 0; n
--)
585 ret
= scm_cons (LOCAL_REF (4 + n
- 1), ret
);
586 ret
= scm_values (ret
);
589 vp
->ip
= SCM_FRAME_RETURN_ADDRESS (fp
);
590 vp
->sp
= SCM_FRAME_PREVIOUS_SP (fp
);
591 vp
->fp
= SCM_FRAME_DYNAMIC_LINK (fp
);
596 /* call proc:24 _:8 nlocals:24
598 * Call a procedure. PROC is the local corresponding to a procedure.
599 * The three values below PROC will be overwritten by the saved call
600 * frame data. The new frame will have space for NLOCALS locals: one
601 * for the procedure, and the rest for the arguments which should
602 * already have been pushed on.
604 * When the call returns, execution proceeds with the next
605 * instruction. There may be any number of values on the return
606 * stack; the precise number can be had by subtracting the address of
607 * PROC from the post-call SP.
609 VM_DEFINE_OP (1, call
, "call", OP2 (U8_U24
, X8_U24
))
611 scm_t_uint32 proc
, nlocals
;
614 UNPACK_24 (op
, proc
);
615 UNPACK_24 (ip
[1], nlocals
);
617 VM_HANDLE_INTERRUPTS
;
619 fp
= vp
->fp
= old_fp
+ proc
;
620 SCM_FRAME_SET_DYNAMIC_LINK (fp
, old_fp
);
621 SCM_FRAME_SET_RETURN_ADDRESS (fp
, ip
+ 2);
623 RESET_FRAME (nlocals
);
625 PUSH_CONTINUATION_HOOK ();
628 if (SCM_UNLIKELY (!SCM_PROGRAM_P (SCM_FRAME_PROGRAM (fp
))))
631 ip
= SCM_PROGRAM_CODE (SCM_FRAME_PROGRAM (fp
));
635 /* tail-call nlocals:24
637 * Tail-call a procedure. Requires that the procedure and all of the
638 * arguments have already been shuffled into position. Will reset the
641 VM_DEFINE_OP (2, tail_call
, "tail-call", OP1 (U8_U24
))
643 scm_t_uint32 nlocals
;
645 UNPACK_24 (op
, nlocals
);
647 VM_HANDLE_INTERRUPTS
;
649 RESET_FRAME (nlocals
);
653 if (SCM_UNLIKELY (!SCM_PROGRAM_P (SCM_FRAME_PROGRAM (fp
))))
656 ip
= SCM_PROGRAM_CODE (SCM_FRAME_PROGRAM (fp
));
660 /* tail-call/shuffle from:24
662 * Tail-call a procedure. The procedure should already be set to slot
663 * 0. The rest of the args are taken from the frame, starting at
664 * FROM, shuffled down to start at slot 0. This is part of the
665 * implementation of the call-with-values builtin.
667 VM_DEFINE_OP (3, tail_call_shuffle
, "tail-call/shuffle", OP1 (U8_U24
))
669 scm_t_uint32 n
, from
, nlocals
;
671 UNPACK_24 (op
, from
);
673 VM_HANDLE_INTERRUPTS
;
675 VM_ASSERT (from
> 0, abort ());
676 nlocals
= FRAME_LOCALS_COUNT ();
678 for (n
= 0; from
+ n
< nlocals
; n
++)
679 LOCAL_SET (n
+ 1, LOCAL_REF (from
+ n
));
685 if (SCM_UNLIKELY (!SCM_PROGRAM_P (SCM_FRAME_PROGRAM (fp
))))
688 ip
= SCM_PROGRAM_CODE (SCM_FRAME_PROGRAM (fp
));
692 /* receive dst:12 proc:12 _:8 nlocals:24
694 * Receive a single return value from a call whose procedure was in
695 * PROC, asserting that the call actually returned at least one
696 * value. Afterwards, resets the frame to NLOCALS locals.
698 VM_DEFINE_OP (4, receive
, "receive", OP2 (U8_U12_U12
, X8_U24
) | OP_DST
)
700 scm_t_uint16 dst
, proc
;
701 scm_t_uint32 nlocals
;
702 UNPACK_12_12 (op
, dst
, proc
);
703 UNPACK_24 (ip
[1], nlocals
);
704 VM_ASSERT (FRAME_LOCALS_COUNT () > proc
+ 1, vm_error_no_values ());
705 LOCAL_SET (dst
, LOCAL_REF (proc
+ 1));
706 RESET_FRAME (nlocals
);
710 /* receive-values proc:24 allow-extra?:1 _:7 nvalues:24
712 * Receive a return of multiple values from a call whose procedure was
713 * in PROC. If fewer than NVALUES values were returned, signal an
714 * error. Unless ALLOW-EXTRA? is true, require that the number of
715 * return values equals NVALUES exactly. After receive-values has
716 * run, the values can be copied down via `mov'.
718 VM_DEFINE_OP (5, receive_values
, "receive-values", OP2 (U8_U24
, B1_X7_U24
))
720 scm_t_uint32 proc
, nvalues
;
721 UNPACK_24 (op
, proc
);
722 UNPACK_24 (ip
[1], nvalues
);
724 VM_ASSERT (FRAME_LOCALS_COUNT () > proc
+ nvalues
,
725 vm_error_not_enough_values ());
727 VM_ASSERT (FRAME_LOCALS_COUNT () == proc
+ 1 + nvalues
,
728 vm_error_wrong_number_of_values (nvalues
));
736 VM_DEFINE_OP (6, return, "return", OP1 (U8_U24
))
740 RETURN_ONE_VALUE (LOCAL_REF (src
));
743 /* return-values _:24
745 * Return a number of values from a call frame. This opcode
746 * corresponds to an application of `values' in tail position. As
747 * with tail calls, we expect that the values have already been
748 * shuffled down to a contiguous array starting at slot 1.
749 * We also expect the frame has already been reset.
751 VM_DEFINE_OP (7, return_values
, "return-values", OP1 (U8_X24
))
755 VM_HANDLE_INTERRUPTS
;
756 ip
= SCM_FRAME_RETURN_ADDRESS (fp
);
757 fp
= vp
->fp
= SCM_FRAME_DYNAMIC_LINK (fp
);
759 /* Clear stack frame. */
760 old_fp
[-1] = SCM_BOOL_F
;
761 old_fp
[-2] = SCM_BOOL_F
;
763 POP_CONTINUATION_HOOK (old_fp
);
772 * Specialized call stubs
775 /* subr-call ptr-idx:24
777 * Call a subr, passing all locals in this frame as arguments. Fetch
778 * the foreign pointer from PTR-IDX, a free variable. Return from the
779 * calling frame. This instruction is part of the trampolines
780 * created in gsubr.c, and is not generated by the compiler.
782 VM_DEFINE_OP (8, subr_call
, "subr-call", OP1 (U8_U24
))
784 scm_t_uint32 ptr_idx
;
788 UNPACK_24 (op
, ptr_idx
);
790 pointer
= SCM_PROGRAM_FREE_VARIABLE_REF (LOCAL_REF (0), ptr_idx
);
791 subr
= SCM_POINTER_VALUE (pointer
);
793 VM_HANDLE_INTERRUPTS
;
796 switch (FRAME_LOCALS_COUNT_FROM (1))
805 ret
= subr (fp
[1], fp
[2]);
808 ret
= subr (fp
[1], fp
[2], fp
[3]);
811 ret
= subr (fp
[1], fp
[2], fp
[3], fp
[4]);
814 ret
= subr (fp
[1], fp
[2], fp
[3], fp
[4], fp
[5]);
817 ret
= subr (fp
[1], fp
[2], fp
[3], fp
[4], fp
[5], fp
[6]);
820 ret
= subr (fp
[1], fp
[2], fp
[3], fp
[4], fp
[5], fp
[6], fp
[7]);
823 ret
= subr (fp
[1], fp
[2], fp
[3], fp
[4], fp
[5], fp
[6], fp
[7], fp
[8]);
826 ret
= subr (fp
[1], fp
[2], fp
[3], fp
[4], fp
[5], fp
[6], fp
[7], fp
[8], fp
[9]);
829 ret
= subr (fp
[1], fp
[2], fp
[3], fp
[4], fp
[5], fp
[6], fp
[7], fp
[8], fp
[9], fp
[10]);
835 // NULLSTACK_FOR_NONLOCAL_EXIT ();
837 if (SCM_UNLIKELY (SCM_VALUESP (ret
)))
838 /* multiple values returned to continuation */
839 RETURN_VALUE_LIST (scm_struct_ref (ret
, SCM_INUM0
));
841 RETURN_ONE_VALUE (ret
);
844 /* foreign-call cif-idx:12 ptr-idx:12
846 * Call a foreign function. Fetch the CIF and foreign pointer from
847 * CIF-IDX and PTR-IDX, both free variables. Return from the calling
848 * frame. Arguments are taken from the stack. This instruction is
849 * part of the trampolines created by the FFI, and is not generated by
852 VM_DEFINE_OP (9, foreign_call
, "foreign-call", OP1 (U8_U12_U12
))
854 scm_t_uint16 cif_idx
, ptr_idx
;
855 SCM closure
, cif
, pointer
, ret
;
857 UNPACK_12_12 (op
, cif_idx
, ptr_idx
);
859 closure
= LOCAL_REF (0);
860 cif
= SCM_PROGRAM_FREE_VARIABLE_REF (closure
, cif_idx
);
861 pointer
= SCM_PROGRAM_FREE_VARIABLE_REF (closure
, ptr_idx
);
864 VM_HANDLE_INTERRUPTS
;
866 // FIXME: separate args
867 ret
= scm_i_foreign_call (scm_cons (cif
, pointer
), LOCAL_ADDRESS (1));
869 // NULLSTACK_FOR_NONLOCAL_EXIT ();
871 if (SCM_UNLIKELY (SCM_VALUESP (ret
)))
872 /* multiple values returned to continuation */
873 RETURN_VALUE_LIST (scm_struct_ref (ret
, SCM_INUM0
));
875 RETURN_ONE_VALUE (ret
);
878 /* continuation-call contregs:24
880 * Return to a continuation, nonlocally. The arguments to the
881 * continuation are taken from the stack. CONTREGS is a free variable
882 * containing the reified continuation. This instruction is part of
883 * the implementation of undelimited continuations, and is not
884 * generated by the compiler.
886 VM_DEFINE_OP (10, continuation_call
, "continuation-call", OP1 (U8_U24
))
889 scm_t_uint32 contregs_idx
;
891 UNPACK_24 (op
, contregs_idx
);
894 SCM_PROGRAM_FREE_VARIABLE_REF (LOCAL_REF (0), contregs_idx
);
897 scm_i_check_continuation (contregs
);
898 vm_return_to_continuation (scm_i_contregs_vm (contregs
),
899 scm_i_contregs_vm_cont (contregs
),
900 FRAME_LOCALS_COUNT_FROM (1),
902 scm_i_reinstate_continuation (contregs
);
908 /* compose-continuation cont:24
910 * Compose a partial continution with the current continuation. The
911 * arguments to the continuation are taken from the stack. CONT is a
912 * free variable containing the reified continuation. This
913 * instruction is part of the implementation of partial continuations,
914 * and is not generated by the compiler.
916 VM_DEFINE_OP (11, compose_continuation
, "compose-continuation", OP1 (U8_U24
))
919 scm_t_uint32 cont_idx
;
921 UNPACK_24 (op
, cont_idx
);
922 vmcont
= SCM_PROGRAM_FREE_VARIABLE_REF (LOCAL_REF (0), cont_idx
);
925 VM_ASSERT (SCM_VM_CONT_REWINDABLE_P (vmcont
),
926 vm_error_continuation_not_rewindable (vmcont
));
927 vm_reinstate_partial_continuation (vm
, vmcont
, FRAME_LOCALS_COUNT_FROM (1),
929 ¤t_thread
->dynstack
,
937 * Tail-apply the procedure in local slot 0 to the rest of the
938 * arguments. This instruction is part of the implementation of
939 * `apply', and is not generated by the compiler.
941 VM_DEFINE_OP (12, tail_apply
, "tail-apply", OP1 (U8_X24
))
943 int i
, list_idx
, list_len
, nlocals
;
946 VM_HANDLE_INTERRUPTS
;
948 nlocals
= FRAME_LOCALS_COUNT ();
949 // At a minimum, there should be apply, f, and the list.
950 VM_ASSERT (nlocals
>= 3, abort ());
951 list_idx
= nlocals
- 1;
952 list
= LOCAL_REF (list_idx
);
953 list_len
= scm_ilength (list
);
955 VM_ASSERT (list_len
>= 0, vm_error_apply_to_non_list (list
));
957 nlocals
= nlocals
- 2 + list_len
;
958 ALLOC_FRAME (nlocals
);
960 for (i
= 1; i
< list_idx
; i
++)
961 LOCAL_SET (i
- 1, LOCAL_REF (i
));
963 /* Null out these slots, just in case there are less than 2 elements
965 LOCAL_SET (list_idx
- 1, SCM_UNDEFINED
);
966 LOCAL_SET (list_idx
, SCM_UNDEFINED
);
968 for (i
= 0; i
< list_len
; i
++, list
= SCM_CDR (list
))
969 LOCAL_SET (list_idx
- 1 + i
, SCM_CAR (list
));
973 if (SCM_UNLIKELY (!SCM_PROGRAM_P (SCM_FRAME_PROGRAM (fp
))))
976 ip
= SCM_PROGRAM_CODE (SCM_FRAME_PROGRAM (fp
));
982 * Capture the current continuation, and tail-apply the procedure in
983 * local slot 1 to it. This instruction is part of the implementation
984 * of `call/cc', and is not generated by the compiler.
986 VM_DEFINE_OP (13, call_cc
, "call/cc", OP1 (U8_X24
))
989 scm_t_dynstack
*dynstack
;
992 VM_HANDLE_INTERRUPTS
;
995 dynstack
= scm_dynstack_capture_all (¤t_thread
->dynstack
);
996 vm_cont
= scm_i_vm_capture_stack (vp
->stack_base
,
997 SCM_FRAME_DYNAMIC_LINK (fp
),
998 SCM_FRAME_PREVIOUS_SP (fp
),
999 SCM_FRAME_RETURN_ADDRESS (fp
),
1002 /* FIXME: Seems silly to capture the registers here, when they are
1003 already captured in the registers local, which here we are
1004 copying out to the heap; and likewise, the setjmp(®isters)
1005 code already has the non-local return handler. But oh
1007 cont
= scm_i_make_continuation (&first
, vm
, vm_cont
);
1011 LOCAL_SET (0, LOCAL_REF (1));
1012 LOCAL_SET (1, cont
);
1017 if (SCM_UNLIKELY (!SCM_PROGRAM_P (SCM_FRAME_PROGRAM (fp
))))
1020 ip
= SCM_PROGRAM_CODE (SCM_FRAME_PROGRAM (fp
));
1026 ABORT_CONTINUATION_HOOK ();
1033 * Abort to a prompt handler. The tag is expected in r1, and the rest
1034 * of the values in the frame are returned to the prompt handler.
1035 * This corresponds to a tail application of abort-to-prompt.
1037 VM_DEFINE_OP (14, abort
, "abort", OP1 (U8_X24
))
1039 scm_t_uint32 nlocals
= FRAME_LOCALS_COUNT ();
1041 ASSERT (nlocals
>= 2);
1042 /* FIXME: Really we should capture the caller's registers. Until
1043 then, manually advance the IP so that when the prompt resumes,
1044 it continues with the next instruction. */
1047 vm_abort (vm
, LOCAL_REF (1), nlocals
- 2, LOCAL_ADDRESS (2),
1048 SCM_EOL
, LOCAL_ADDRESS (0), ®isters
);
1050 /* vm_abort should not return */
1054 /* builtin-ref dst:12 idx:12
1056 * Load a builtin stub by index into DST.
1058 VM_DEFINE_OP (15, builtin_ref
, "builtin-ref", OP1 (U8_U12_U12
) | OP_DST
)
1060 scm_t_uint16 dst
, idx
;
1062 UNPACK_12_12 (op
, dst
, idx
);
1063 LOCAL_SET (dst
, scm_vm_builtin_ref (idx
));
1072 * Function prologues
1075 /* br-if-nargs-ne expected:24 _:8 offset:24
1076 * br-if-nargs-lt expected:24 _:8 offset:24
1077 * br-if-nargs-gt expected:24 _:8 offset:24
1079 * If the number of actual arguments is not equal, less than, or greater
1080 * than EXPECTED, respectively, add OFFSET, a signed 24-bit number, to
1081 * the current instruction pointer.
1083 VM_DEFINE_OP (16, br_if_nargs_ne
, "br-if-nargs-ne", OP2 (U8_U24
, X8_L24
))
1087 VM_DEFINE_OP (17, br_if_nargs_lt
, "br-if-nargs-lt", OP2 (U8_U24
, X8_L24
))
1091 VM_DEFINE_OP (18, br_if_nargs_gt
, "br-if-nargs-gt", OP2 (U8_U24
, X8_L24
))
1096 /* assert-nargs-ee expected:24
1097 * assert-nargs-ge expected:24
1098 * assert-nargs-le expected:24
1100 * If the number of actual arguments is not ==, >=, or <= EXPECTED,
1101 * respectively, signal an error.
1103 VM_DEFINE_OP (19, assert_nargs_ee
, "assert-nargs-ee", OP1 (U8_U24
))
1105 scm_t_uint32 expected
;
1106 UNPACK_24 (op
, expected
);
1107 VM_ASSERT (FRAME_LOCALS_COUNT () == expected
,
1108 vm_error_wrong_num_args (SCM_FRAME_PROGRAM (fp
)));
1111 VM_DEFINE_OP (20, assert_nargs_ge
, "assert-nargs-ge", OP1 (U8_U24
))
1113 scm_t_uint32 expected
;
1114 UNPACK_24 (op
, expected
);
1115 VM_ASSERT (FRAME_LOCALS_COUNT () >= expected
,
1116 vm_error_wrong_num_args (SCM_FRAME_PROGRAM (fp
)));
1119 VM_DEFINE_OP (21, assert_nargs_le
, "assert-nargs-le", OP1 (U8_U24
))
1121 scm_t_uint32 expected
;
1122 UNPACK_24 (op
, expected
);
1123 VM_ASSERT (FRAME_LOCALS_COUNT () <= expected
,
1124 vm_error_wrong_num_args (SCM_FRAME_PROGRAM (fp
)));
1128 /* alloc-frame nlocals:24
1130 * Ensure that there is space on the stack for NLOCALS local variables,
1131 * setting them all to SCM_UNDEFINED, except those nargs values that
1132 * were passed as arguments and procedure.
1134 VM_DEFINE_OP (22, alloc_frame
, "alloc-frame", OP1 (U8_U24
))
1136 scm_t_uint32 nlocals
, nargs
;
1137 UNPACK_24 (op
, nlocals
);
1139 nargs
= FRAME_LOCALS_COUNT ();
1140 ALLOC_FRAME (nlocals
);
1141 while (nlocals
-- > nargs
)
1142 LOCAL_SET (nlocals
, SCM_UNDEFINED
);
1147 /* reset-frame nlocals:24
1149 * Like alloc-frame, but doesn't check that the stack is big enough.
1150 * Used to reset the frame size to something less than the size that
1151 * was previously set via alloc-frame.
1153 VM_DEFINE_OP (23, reset_frame
, "reset-frame", OP1 (U8_U24
))
1155 scm_t_uint32 nlocals
;
1156 UNPACK_24 (op
, nlocals
);
1157 RESET_FRAME (nlocals
);
1161 /* assert-nargs-ee/locals expected:12 nlocals:12
1163 * Equivalent to a sequence of assert-nargs-ee and reserve-locals. The
1164 * number of locals reserved is EXPECTED + NLOCALS.
1166 VM_DEFINE_OP (24, assert_nargs_ee_locals
, "assert-nargs-ee/locals", OP1 (U8_U12_U12
))
1168 scm_t_uint16 expected
, nlocals
;
1169 UNPACK_12_12 (op
, expected
, nlocals
);
1170 VM_ASSERT (FRAME_LOCALS_COUNT () == expected
,
1171 vm_error_wrong_num_args (SCM_FRAME_PROGRAM (fp
)));
1172 ALLOC_FRAME (expected
+ nlocals
);
1174 LOCAL_SET (expected
+ nlocals
, SCM_UNDEFINED
);
1179 /* br-if-npos-gt nreq:24 _:8 npos:24 _:8 offset:24
1181 * Find the first positional argument after NREQ. If it is greater
1182 * than NPOS, jump to OFFSET.
1184 * This instruction is only emitted for functions with multiple
1185 * clauses, and an earlier clause has keywords and no rest arguments.
1186 * See "Case-lambda" in the manual, for more on how case-lambda
1187 * chooses the clause to apply.
1189 VM_DEFINE_OP (25, br_if_npos_gt
, "br-if-npos-gt", OP3 (U8_U24
, X8_U24
, X8_L24
))
1191 scm_t_uint32 nreq
, npos
;
1193 UNPACK_24 (op
, nreq
);
1194 UNPACK_24 (ip
[1], npos
);
1196 /* We can only have too many positionals if there are more
1197 arguments than NPOS. */
1198 if (FRAME_LOCALS_COUNT() > npos
)
1201 for (n
= nreq
; n
< npos
; n
++)
1202 if (scm_is_keyword (LOCAL_REF (n
)))
1204 if (n
== npos
&& !scm_is_keyword (LOCAL_REF (n
)))
1206 scm_t_int32 offset
= ip
[2];
1207 offset
>>= 8; /* Sign-extending shift. */
1214 /* bind-kwargs nreq:24 allow-other-keys:1 has-rest:1 _:6 nreq-and-opt:24
1215 * _:8 ntotal:24 kw-offset:32
1217 * Find the last positional argument, and shuffle all the rest above
1218 * NTOTAL. Initialize the intervening locals to SCM_UNDEFINED. Then
1219 * load the constant at KW-OFFSET words from the current IP, and use it
1220 * to bind keyword arguments. If HAS-REST, collect all shuffled
1221 * arguments into a list, and store it in NREQ-AND-OPT. Finally, clear
1222 * the arguments that we shuffled up.
1224 * A macro-mega-instruction.
1226 VM_DEFINE_OP (26, bind_kwargs
, "bind-kwargs", OP4 (U8_U24
, U8_U24
, X8_U24
, N32
))
1228 scm_t_uint32 nreq
, nreq_and_opt
, ntotal
, npositional
, nkw
, n
, nargs
;
1229 scm_t_int32 kw_offset
;
1232 char allow_other_keys
, has_rest
;
1234 UNPACK_24 (op
, nreq
);
1235 allow_other_keys
= ip
[1] & 0x1;
1236 has_rest
= ip
[1] & 0x2;
1237 UNPACK_24 (ip
[1], nreq_and_opt
);
1238 UNPACK_24 (ip
[2], ntotal
);
1240 kw_bits
= (scm_t_bits
) (ip
+ kw_offset
);
1241 VM_ASSERT (!(kw_bits
& 0x7), abort());
1242 kw
= SCM_PACK (kw_bits
);
1244 nargs
= FRAME_LOCALS_COUNT ();
1246 /* look in optionals for first keyword or last positional */
1247 /* starting after the last required positional arg */
1249 while (/* while we have args */
1251 /* and we still have positionals to fill */
1252 && npositional
< nreq_and_opt
1253 /* and we haven't reached a keyword yet */
1254 && !scm_is_keyword (LOCAL_REF (npositional
)))
1255 /* bind this optional arg (by leaving it in place) */
1257 nkw
= nargs
- npositional
;
1258 /* shuffle non-positional arguments above ntotal */
1259 ALLOC_FRAME (ntotal
+ nkw
);
1262 LOCAL_SET (ntotal
+ n
, LOCAL_REF (npositional
+ n
));
1263 /* and fill optionals & keyword args with SCM_UNDEFINED */
1266 LOCAL_SET (n
++, SCM_UNDEFINED
);
1268 VM_ASSERT (has_rest
|| (nkw
% 2) == 0,
1269 vm_error_kwargs_length_not_even (SCM_FRAME_PROGRAM (fp
)));
1271 /* Now bind keywords, in the order given. */
1272 for (n
= 0; n
< nkw
; n
++)
1273 if (scm_is_keyword (LOCAL_REF (ntotal
+ n
)))
1276 for (walk
= kw
; scm_is_pair (walk
); walk
= SCM_CDR (walk
))
1277 if (scm_is_eq (SCM_CAAR (walk
), LOCAL_REF (ntotal
+ n
)))
1279 SCM si
= SCM_CDAR (walk
);
1280 LOCAL_SET (SCM_I_INUMP (si
) ? SCM_I_INUM (si
) : scm_to_uint32 (si
),
1281 LOCAL_REF (ntotal
+ n
+ 1));
1284 VM_ASSERT (scm_is_pair (walk
) || allow_other_keys
,
1285 vm_error_kwargs_unrecognized_keyword (SCM_FRAME_PROGRAM (fp
),
1286 LOCAL_REF (ntotal
+ n
)));
1290 VM_ASSERT (has_rest
, vm_error_kwargs_invalid_keyword (SCM_FRAME_PROGRAM (fp
),
1291 LOCAL_REF (ntotal
+ n
)));
1298 rest
= scm_cons (LOCAL_REF (ntotal
+ n
), rest
);
1299 LOCAL_SET (nreq_and_opt
, rest
);
1302 RESET_FRAME (ntotal
);
1309 * Collect any arguments at or above DST into a list, and store that
1312 VM_DEFINE_OP (27, bind_rest
, "bind-rest", OP1 (U8_U24
) | OP_DST
)
1314 scm_t_uint32 dst
, nargs
;
1317 UNPACK_24 (op
, dst
);
1318 nargs
= FRAME_LOCALS_COUNT ();
1322 ALLOC_FRAME (dst
+ 1);
1324 LOCAL_SET (nargs
++, SCM_UNDEFINED
);
1328 while (nargs
-- > dst
)
1330 rest
= scm_cons (LOCAL_REF (nargs
), rest
);
1331 LOCAL_SET (nargs
, SCM_UNDEFINED
);
1334 RESET_FRAME (dst
+ 1);
1337 LOCAL_SET (dst
, rest
);
1346 * Branching instructions
1351 * Add OFFSET, a signed 24-bit number, to the current instruction
1354 VM_DEFINE_OP (28, br
, "br", OP1 (U8_L24
))
1356 scm_t_int32 offset
= op
;
1357 offset
>>= 8; /* Sign-extending shift. */
1361 /* br-if-true test:24 invert:1 _:7 offset:24
1363 * If the value in TEST is true for the purposes of Scheme, add
1364 * OFFSET, a signed 24-bit number, to the current instruction pointer.
1366 VM_DEFINE_OP (29, br_if_true
, "br-if-true", OP2 (U8_U24
, B1_X7_L24
))
1368 BR_UNARY (x
, scm_is_true (x
));
1371 /* br-if-null test:24 invert:1 _:7 offset:24
1373 * If the value in TEST is the end-of-list or Lisp nil, add OFFSET, a
1374 * signed 24-bit number, to the current instruction pointer.
1376 VM_DEFINE_OP (30, br_if_null
, "br-if-null", OP2 (U8_U24
, B1_X7_L24
))
1378 BR_UNARY (x
, scm_is_null (x
));
1381 /* br-if-nil test:24 invert:1 _:7 offset:24
1383 * If the value in TEST is false to Lisp, add OFFSET, a signed 24-bit
1384 * number, to the current instruction pointer.
1386 VM_DEFINE_OP (31, br_if_nil
, "br-if-nil", OP2 (U8_U24
, B1_X7_L24
))
1388 BR_UNARY (x
, scm_is_lisp_false (x
));
1391 /* br-if-pair test:24 invert:1 _:7 offset:24
1393 * If the value in TEST is a pair, add OFFSET, a signed 24-bit number,
1394 * to the current instruction pointer.
1396 VM_DEFINE_OP (32, br_if_pair
, "br-if-pair", OP2 (U8_U24
, B1_X7_L24
))
1398 BR_UNARY (x
, scm_is_pair (x
));
1401 /* br-if-struct test:24 invert:1 _:7 offset:24
1403 * If the value in TEST is a struct, add OFFSET, a signed 24-bit
1404 * number, to the current instruction pointer.
1406 VM_DEFINE_OP (33, br_if_struct
, "br-if-struct", OP2 (U8_U24
, B1_X7_L24
))
1408 BR_UNARY (x
, SCM_STRUCTP (x
));
1411 /* br-if-char test:24 invert:1 _:7 offset:24
1413 * If the value in TEST is a char, add OFFSET, a signed 24-bit number,
1414 * to the current instruction pointer.
1416 VM_DEFINE_OP (34, br_if_char
, "br-if-char", OP2 (U8_U24
, B1_X7_L24
))
1418 BR_UNARY (x
, SCM_CHARP (x
));
1421 /* br-if-tc7 test:24 invert:1 tc7:7 offset:24
1423 * If the value in TEST has the TC7 given in the second word, add
1424 * OFFSET, a signed 24-bit number, to the current instruction pointer.
1426 VM_DEFINE_OP (35, br_if_tc7
, "br-if-tc7", OP2 (U8_U24
, B1_U7_L24
))
1428 BR_UNARY (x
, SCM_HAS_TYP7 (x
, (ip
[1] >> 1) & 0x7f));
1431 /* br-if-eq a:12 b:12 invert:1 _:7 offset:24
1433 * If the value in A is eq? to the value in B, add OFFSET, a signed
1434 * 24-bit number, to the current instruction pointer.
1436 VM_DEFINE_OP (36, br_if_eq
, "br-if-eq", OP2 (U8_U12_U12
, B1_X7_L24
))
1438 BR_BINARY (x
, y
, scm_is_eq (x
, y
));
1441 /* br-if-eqv a:12 b:12 invert:1 _:7 offset:24
1443 * If the value in A is eqv? to the value in B, add OFFSET, a signed
1444 * 24-bit number, to the current instruction pointer.
1446 VM_DEFINE_OP (37, br_if_eqv
, "br-if-eqv", OP2 (U8_U12_U12
, B1_X7_L24
))
1450 || (SCM_NIMP (x
) && SCM_NIMP (y
)
1451 && scm_is_true (scm_eqv_p (x
, y
))));
1454 // FIXME: remove, have compiler inline eqv test instead
1455 /* br-if-equal a:12 b:12 invert:1 _:7 offset:24
1457 * If the value in A is equal? to the value in B, add OFFSET, a signed
1458 * 24-bit number, to the current instruction pointer.
1460 // FIXME: should sync_ip before calling out?
1461 VM_DEFINE_OP (38, br_if_equal
, "br-if-equal", OP2 (U8_U12_U12
, B1_X7_L24
))
1465 || (SCM_NIMP (x
) && SCM_NIMP (y
)
1466 && scm_is_true (scm_equal_p (x
, y
))));
1469 /* br-if-= a:12 b:12 invert:1 _:7 offset:24
1471 * If the value in A is = to the value in B, add OFFSET, a signed
1472 * 24-bit number, to the current instruction pointer.
1474 VM_DEFINE_OP (39, br_if_ee
, "br-if-=", OP2 (U8_U12_U12
, B1_X7_L24
))
1476 BR_ARITHMETIC (==, scm_num_eq_p
);
1479 /* br-if-< a:12 b:12 _:8 offset:24
1481 * If the value in A is < to the value in B, add OFFSET, a signed
1482 * 24-bit number, to the current instruction pointer.
1484 VM_DEFINE_OP (40, br_if_lt
, "br-if-<", OP2 (U8_U12_U12
, B1_X7_L24
))
1486 BR_ARITHMETIC (<, scm_less_p
);
1489 /* br-if-<= a:12 b:12 _:8 offset:24
1491 * If the value in A is <= to the value in B, add OFFSET, a signed
1492 * 24-bit number, to the current instruction pointer.
1494 VM_DEFINE_OP (41, br_if_le
, "br-if-<=", OP2 (U8_U12_U12
, B1_X7_L24
))
1496 BR_ARITHMETIC (<=, scm_leq_p
);
1503 * Lexical binding instructions
1506 /* mov dst:12 src:12
1508 * Copy a value from one local slot to another.
1510 VM_DEFINE_OP (42, mov
, "mov", OP1 (U8_U12_U12
) | OP_DST
)
1515 UNPACK_12_12 (op
, dst
, src
);
1516 LOCAL_SET (dst
, LOCAL_REF (src
));
1521 /* long-mov dst:24 _:8 src:24
1523 * Copy a value from one local slot to another.
1525 VM_DEFINE_OP (43, long_mov
, "long-mov", OP2 (U8_U24
, X8_U24
) | OP_DST
)
1530 UNPACK_24 (op
, dst
);
1531 UNPACK_24 (ip
[1], src
);
1532 LOCAL_SET (dst
, LOCAL_REF (src
));
1537 /* box dst:12 src:12
1539 * Create a new variable holding SRC, and place it in DST.
1541 VM_DEFINE_OP (44, box
, "box", OP1 (U8_U12_U12
) | OP_DST
)
1543 scm_t_uint16 dst
, src
;
1544 UNPACK_12_12 (op
, dst
, src
);
1545 LOCAL_SET (dst
, scm_cell (scm_tc7_variable
, SCM_UNPACK (LOCAL_REF (src
))));
1549 /* box-ref dst:12 src:12
1551 * Unpack the variable at SRC into DST, asserting that the variable is
1554 VM_DEFINE_OP (45, box_ref
, "box-ref", OP1 (U8_U12_U12
) | OP_DST
)
1556 scm_t_uint16 dst
, src
;
1558 UNPACK_12_12 (op
, dst
, src
);
1559 var
= LOCAL_REF (src
);
1560 VM_ASSERT (SCM_VARIABLEP (var
),
1561 vm_error_not_a_variable ("variable-ref", var
));
1562 VM_ASSERT (VARIABLE_BOUNDP (var
),
1563 vm_error_unbound (SCM_FRAME_PROGRAM (fp
), var
));
1564 LOCAL_SET (dst
, VARIABLE_REF (var
));
1568 /* box-set! dst:12 src:12
1570 * Set the contents of the variable at DST to SET.
1572 VM_DEFINE_OP (46, box_set
, "box-set!", OP1 (U8_U12_U12
))
1574 scm_t_uint16 dst
, src
;
1576 UNPACK_12_12 (op
, dst
, src
);
1577 var
= LOCAL_REF (dst
);
1578 VM_ASSERT (SCM_VARIABLEP (var
),
1579 vm_error_not_a_variable ("variable-set!", var
));
1580 VARIABLE_SET (var
, LOCAL_REF (src
));
1584 /* make-closure dst:24 offset:32 _:8 nfree:24
1586 * Make a new closure, and write it to DST. The code for the closure
1587 * will be found at OFFSET words from the current IP. OFFSET is a
1588 * signed 32-bit integer. Space for NFREE free variables will be
1591 VM_DEFINE_OP (47, make_closure
, "make-closure", OP3 (U8_U24
, L32
, X8_U24
) | OP_DST
)
1593 scm_t_uint32 dst
, nfree
, n
;
1597 UNPACK_24 (op
, dst
);
1599 UNPACK_24 (ip
[2], nfree
);
1601 // FIXME: Assert range of nfree?
1602 closure
= scm_words (scm_tc7_program
| (nfree
<< 16), nfree
+ 2);
1603 SCM_SET_CELL_WORD_1 (closure
, ip
+ offset
);
1604 // FIXME: Elide these initializations?
1605 for (n
= 0; n
< nfree
; n
++)
1606 SCM_PROGRAM_FREE_VARIABLE_SET (closure
, n
, SCM_BOOL_F
);
1607 LOCAL_SET (dst
, closure
);
1611 /* free-ref dst:12 src:12 _:8 idx:24
1613 * Load free variable IDX from the closure SRC into local slot DST.
1615 VM_DEFINE_OP (48, free_ref
, "free-ref", OP2 (U8_U12_U12
, X8_U24
) | OP_DST
)
1617 scm_t_uint16 dst
, src
;
1619 UNPACK_12_12 (op
, dst
, src
);
1620 UNPACK_24 (ip
[1], idx
);
1621 /* CHECK_FREE_VARIABLE (src); */
1622 LOCAL_SET (dst
, SCM_PROGRAM_FREE_VARIABLE_REF (LOCAL_REF (src
), idx
));
1626 /* free-set! dst:12 src:12 _8 idx:24
1628 * Set free variable IDX from the closure DST to SRC.
1630 VM_DEFINE_OP (49, free_set
, "free-set!", OP2 (U8_U12_U12
, X8_U24
))
1632 scm_t_uint16 dst
, src
;
1634 UNPACK_12_12 (op
, dst
, src
);
1635 UNPACK_24 (ip
[1], idx
);
1636 /* CHECK_FREE_VARIABLE (src); */
1637 SCM_PROGRAM_FREE_VARIABLE_SET (LOCAL_REF (dst
), idx
, LOCAL_REF (src
));
1645 * Immediates and statically allocated non-immediates
1648 /* make-short-immediate dst:8 low-bits:16
1650 * Make an immediate whose low bits are LOW-BITS, and whose top bits are
1653 VM_DEFINE_OP (50, make_short_immediate
, "make-short-immediate", OP1 (U8_U8_I16
) | OP_DST
)
1658 UNPACK_8_16 (op
, dst
, val
);
1659 LOCAL_SET (dst
, SCM_PACK (val
));
1663 /* make-long-immediate dst:24 low-bits:32
1665 * Make an immediate whose low bits are LOW-BITS, and whose top bits are
1668 VM_DEFINE_OP (51, make_long_immediate
, "make-long-immediate", OP2 (U8_U24
, I32
))
1673 UNPACK_24 (op
, dst
);
1675 LOCAL_SET (dst
, SCM_PACK (val
));
1679 /* make-long-long-immediate dst:24 high-bits:32 low-bits:32
1681 * Make an immediate with HIGH-BITS and LOW-BITS.
1683 VM_DEFINE_OP (52, make_long_long_immediate
, "make-long-long-immediate", OP3 (U8_U24
, A32
, B32
) | OP_DST
)
1688 UNPACK_24 (op
, dst
);
1689 #if SIZEOF_SCM_T_BITS > 4
1694 ASSERT (ip
[1] == 0);
1697 LOCAL_SET (dst
, SCM_PACK (val
));
1701 /* make-non-immediate dst:24 offset:32
1703 * Load a pointer to statically allocated memory into DST. The
1704 * object's memory is will be found OFFSET 32-bit words away from the
1705 * current instruction pointer. OFFSET is a signed value. The
1706 * intention here is that the compiler would produce an object file
1707 * containing the words of a non-immediate object, and this
1708 * instruction creates a pointer to that memory, effectively
1709 * resurrecting that object.
1711 * Whether the object is mutable or immutable depends on where it was
1712 * allocated by the compiler, and loaded by the loader.
1714 VM_DEFINE_OP (53, make_non_immediate
, "make-non-immediate", OP2 (U8_U24
, N32
) | OP_DST
)
1719 scm_t_bits unpacked
;
1721 UNPACK_24 (op
, dst
);
1724 unpacked
= (scm_t_bits
) loc
;
1726 VM_ASSERT (!(unpacked
& 0x7), abort());
1728 LOCAL_SET (dst
, SCM_PACK (unpacked
));
1733 /* static-ref dst:24 offset:32
1735 * Load a SCM value into DST. The SCM value will be fetched from
1736 * memory, OFFSET 32-bit words away from the current instruction
1737 * pointer. OFFSET is a signed value.
1739 * The intention is for this instruction to be used to load constants
1740 * that the compiler is unable to statically allocate, like symbols.
1741 * These values would be initialized when the object file loads.
1743 VM_DEFINE_OP (54, static_ref
, "static-ref", OP2 (U8_U24
, S32
))
1748 scm_t_uintptr loc_bits
;
1750 UNPACK_24 (op
, dst
);
1753 loc_bits
= (scm_t_uintptr
) loc
;
1754 VM_ASSERT (ALIGNED_P (loc
, SCM
), abort());
1756 LOCAL_SET (dst
, *((SCM
*) loc_bits
));
1761 /* static-set! src:24 offset:32
1763 * Store a SCM value into memory, OFFSET 32-bit words away from the
1764 * current instruction pointer. OFFSET is a signed value.
1766 VM_DEFINE_OP (55, static_set
, "static-set!", OP2 (U8_U24
, LO32
))
1772 UNPACK_24 (op
, src
);
1775 VM_ASSERT (ALIGNED_P (loc
, SCM
), abort());
1777 *((SCM
*) loc
) = LOCAL_REF (src
);
1782 /* static-patch! _:24 dst-offset:32 src-offset:32
1784 * Patch a pointer at DST-OFFSET to point to SRC-OFFSET. Both offsets
1785 * are signed 32-bit values, indicating a memory address as a number
1786 * of 32-bit words away from the current instruction pointer.
1788 VM_DEFINE_OP (56, static_patch
, "static-patch!", OP3 (U8_X24
, LO32
, L32
))
1790 scm_t_int32 dst_offset
, src_offset
;
1797 dst_loc
= (void **) (ip
+ dst_offset
);
1798 src
= ip
+ src_offset
;
1799 VM_ASSERT (ALIGNED_P (dst_loc
, void*), abort());
1809 * Mutable top-level bindings
1812 /* There are three slightly different ways to resolve toplevel
1815 1. A toplevel reference outside of a function. These need to be
1816 looked up when the expression is evaluated -- no later, and no
1817 before. They are looked up relative to the module that is
1818 current when the expression is evaluated. For example:
1822 The "resolve" instruction resolves the variable (box), and then
1823 access is via box-ref or box-set!.
1825 2. A toplevel reference inside a function. These are looked up
1826 relative to the module that was current when the function was
1827 defined. Unlike code at the toplevel, which is usually run only
1828 once, these bindings benefit from memoized lookup, in which the
1829 variable resulting from the lookup is cached in the function.
1831 (lambda () (if (foo) a b))
1833 The toplevel-box instruction is equivalent to "resolve", but
1834 caches the resulting variable in statically allocated memory.
1836 3. A reference to an identifier with respect to a particular
1837 module. This can happen for primitive references, and
1838 references residualized by macro expansions. These can always
1839 be cached. Use module-box for these.
1842 /* current-module dst:24
1844 * Store the current module in DST.
1846 VM_DEFINE_OP (57, current_module
, "current-module", OP1 (U8_U24
) | OP_DST
)
1850 UNPACK_24 (op
, dst
);
1853 LOCAL_SET (dst
, scm_current_module ());
1858 /* resolve dst:24 bound?:1 _:7 sym:24
1860 * Resolve SYM in the current module, and place the resulting variable
1863 VM_DEFINE_OP (58, resolve
, "resolve", OP2 (U8_U24
, B1_X7_U24
) | OP_DST
)
1869 UNPACK_24 (op
, dst
);
1870 UNPACK_24 (ip
[1], sym
);
1873 var
= scm_lookup (LOCAL_REF (sym
));
1875 VM_ASSERT (VARIABLE_BOUNDP (var
),
1876 vm_error_unbound (fp
[0], LOCAL_REF (sym
)));
1877 LOCAL_SET (dst
, var
);
1882 /* define! sym:12 val:12
1884 * Look up a binding for SYM in the current module, creating it if
1885 * necessary. Set its value to VAL.
1887 VM_DEFINE_OP (59, define
, "define!", OP1 (U8_U12_U12
))
1889 scm_t_uint16 sym
, val
;
1890 UNPACK_12_12 (op
, sym
, val
);
1892 scm_define (LOCAL_REF (sym
), LOCAL_REF (val
));
1896 /* toplevel-box dst:24 var-offset:32 mod-offset:32 sym-offset:32 bound?:1 _:31
1898 * Load a SCM value. The SCM value will be fetched from memory,
1899 * VAR-OFFSET 32-bit words away from the current instruction pointer.
1900 * VAR-OFFSET is a signed value. Up to here, toplevel-box is like
1903 * Then, if the loaded value is a variable, it is placed in DST, and control
1906 * Otherwise, we have to resolve the variable. In that case we load
1907 * the module from MOD-OFFSET, just as we loaded the variable.
1908 * Usually the module gets set when the closure is created. The name
1909 * is an offset to a symbol.
1911 * We use the module and the symbol to resolve the variable, placing it in
1912 * DST, and caching the resolved variable so that we will hit the cache next
1915 VM_DEFINE_OP (60, toplevel_box
, "toplevel-box", OP5 (U8_U24
, S32
, S32
, N32
, B1_X31
) | OP_DST
)
1918 scm_t_int32 var_offset
;
1919 scm_t_uint32
* var_loc_u32
;
1923 UNPACK_24 (op
, dst
);
1925 var_loc_u32
= ip
+ var_offset
;
1926 VM_ASSERT (ALIGNED_P (var_loc_u32
, SCM
), abort());
1927 var_loc
= (SCM
*) var_loc_u32
;
1930 if (SCM_UNLIKELY (!SCM_VARIABLEP (var
)))
1933 scm_t_int32 mod_offset
= ip
[2]; /* signed */
1934 scm_t_int32 sym_offset
= ip
[3]; /* signed */
1935 scm_t_uint32
*mod_loc
= ip
+ mod_offset
;
1936 scm_t_uint32
*sym_loc
= ip
+ sym_offset
;
1940 VM_ASSERT (ALIGNED_P (mod_loc
, SCM
), abort());
1941 VM_ASSERT (ALIGNED_P (sym_loc
, SCM
), abort());
1943 mod
= *((SCM
*) mod_loc
);
1944 sym
= *((SCM
*) sym_loc
);
1946 /* If the toplevel scope was captured before modules were
1947 booted, use the root module. */
1948 if (scm_is_false (mod
))
1949 mod
= scm_the_root_module ();
1951 var
= scm_module_lookup (mod
, sym
);
1953 VM_ASSERT (VARIABLE_BOUNDP (var
), vm_error_unbound (fp
[0], sym
));
1958 LOCAL_SET (dst
, var
);
1962 /* module-box dst:24 var-offset:32 mod-offset:32 sym-offset:32 bound?:1 _:31
1964 * Like toplevel-box, except MOD-OFFSET points at the name of a module
1965 * instead of the module itself.
1967 VM_DEFINE_OP (61, module_box
, "module-box", OP5 (U8_U24
, S32
, N32
, N32
, B1_X31
) | OP_DST
)
1970 scm_t_int32 var_offset
;
1971 scm_t_uint32
* var_loc_u32
;
1975 UNPACK_24 (op
, dst
);
1977 var_loc_u32
= ip
+ var_offset
;
1978 VM_ASSERT (ALIGNED_P (var_loc_u32
, SCM
), abort());
1979 var_loc
= (SCM
*) var_loc_u32
;
1982 if (SCM_UNLIKELY (!SCM_VARIABLEP (var
)))
1985 scm_t_int32 modname_offset
= ip
[2]; /* signed */
1986 scm_t_int32 sym_offset
= ip
[3]; /* signed */
1987 scm_t_uint32
*modname_words
= ip
+ modname_offset
;
1988 scm_t_uint32
*sym_loc
= ip
+ sym_offset
;
1992 VM_ASSERT (!(((scm_t_uintptr
) modname_words
) & 0x7), abort());
1993 VM_ASSERT (ALIGNED_P (sym_loc
, SCM
), abort());
1995 modname
= SCM_PACK ((scm_t_bits
) modname_words
);
1996 sym
= *((SCM
*) sym_loc
);
1998 if (!scm_module_system_booted_p
)
2000 #ifdef VM_ENABLE_PARANOID_ASSERTIONS
2003 scm_equal_p (modname
,
2004 scm_list_2 (SCM_BOOL_T
,
2005 scm_from_utf8_symbol ("guile"))));
2007 var
= scm_lookup (sym
);
2009 else if (scm_is_true (SCM_CAR (modname
)))
2010 var
= scm_public_lookup (SCM_CDR (modname
), sym
);
2012 var
= scm_private_lookup (SCM_CDR (modname
), sym
);
2015 VM_ASSERT (VARIABLE_BOUNDP (var
), vm_error_unbound (fp
[0], sym
));
2020 LOCAL_SET (dst
, var
);
2027 * The dynamic environment
2030 /* prompt tag:24 escape-only?:1 _:7 proc-slot:24 _:8 handler-offset:24
2032 * Push a new prompt on the dynamic stack, with a tag from TAG and a
2033 * handler at HANDLER-OFFSET words from the current IP. The handler
2034 * will expect a multiple-value return as if from a call with the
2035 * procedure at PROC-SLOT.
2037 VM_DEFINE_OP (62, prompt
, "prompt", OP3 (U8_U24
, B1_X7_U24
, X8_L24
))
2039 scm_t_uint32 tag
, proc_slot
;
2041 scm_t_uint8 escape_only_p
;
2042 scm_t_dynstack_prompt_flags flags
;
2044 UNPACK_24 (op
, tag
);
2045 escape_only_p
= ip
[1] & 0x1;
2046 UNPACK_24 (ip
[1], proc_slot
);
2048 offset
>>= 8; /* Sign extension */
2050 /* Push the prompt onto the dynamic stack. */
2051 flags
= escape_only_p
? SCM_F_DYNSTACK_PROMPT_ESCAPE_ONLY
: 0;
2052 scm_dynstack_push_prompt (¤t_thread
->dynstack
, flags
,
2055 LOCAL_ADDRESS (proc_slot
),
2061 /* wind winder:12 unwinder:12
2063 * Push wind and unwind procedures onto the dynamic stack. Note that
2064 * neither are actually called; the compiler should emit calls to wind
2065 * and unwind for the normal dynamic-wind control flow. Also note that
2066 * the compiler should have inserted checks that they wind and unwind
2067 * procs are thunks, if it could not prove that to be the case.
2069 VM_DEFINE_OP (63, wind
, "wind", OP1 (U8_U12_U12
))
2071 scm_t_uint16 winder
, unwinder
;
2072 UNPACK_12_12 (op
, winder
, unwinder
);
2073 scm_dynstack_push_dynwind (¤t_thread
->dynstack
,
2074 LOCAL_REF (winder
), LOCAL_REF (unwinder
));
2080 * A normal exit from the dynamic extent of an expression. Pop the top
2081 * entry off of the dynamic stack.
2083 VM_DEFINE_OP (64, unwind
, "unwind", OP1 (U8_X24
))
2085 scm_dynstack_pop (¤t_thread
->dynstack
);
2089 /* push-fluid fluid:12 value:12
2091 * Dynamically bind N fluids to values. The fluids are expected to be
2092 * allocated in a continguous range on the stack, starting from
2093 * FLUID-BASE. The values do not have this restriction.
2095 VM_DEFINE_OP (65, push_fluid
, "push-fluid", OP1 (U8_U12_U12
))
2097 scm_t_uint32 fluid
, value
;
2099 UNPACK_12_12 (op
, fluid
, value
);
2101 scm_dynstack_push_fluid (¤t_thread
->dynstack
,
2102 LOCAL_REF (fluid
), LOCAL_REF (value
),
2103 current_thread
->dynamic_state
);
2109 * Leave the dynamic extent of a with-fluids expression, restoring the
2110 * fluids to their previous values.
2112 VM_DEFINE_OP (66, pop_fluid
, "pop-fluid", OP1 (U8_X24
))
2114 /* This function must not allocate. */
2115 scm_dynstack_unwind_fluid (¤t_thread
->dynstack
,
2116 current_thread
->dynamic_state
);
2120 /* fluid-ref dst:12 src:12
2122 * Reference the fluid in SRC, and place the value in DST.
2124 VM_DEFINE_OP (67, fluid_ref
, "fluid-ref", OP1 (U8_U12_U12
) | OP_DST
)
2126 scm_t_uint16 dst
, src
;
2130 UNPACK_12_12 (op
, dst
, src
);
2131 fluid
= LOCAL_REF (src
);
2132 fluids
= SCM_I_DYNAMIC_STATE_FLUIDS (current_thread
->dynamic_state
);
2133 if (SCM_UNLIKELY (!SCM_FLUID_P (fluid
))
2134 || ((num
= SCM_I_FLUID_NUM (fluid
)) >= SCM_SIMPLE_VECTOR_LENGTH (fluids
)))
2136 /* Punt dynstate expansion and error handling to the C proc. */
2138 LOCAL_SET (dst
, scm_fluid_ref (fluid
));
2142 SCM val
= SCM_SIMPLE_VECTOR_REF (fluids
, num
);
2143 if (scm_is_eq (val
, SCM_UNDEFINED
))
2144 val
= SCM_I_FLUID_DEFAULT (fluid
);
2145 VM_ASSERT (!scm_is_eq (val
, SCM_UNDEFINED
),
2146 vm_error_unbound_fluid (program
, fluid
));
2147 LOCAL_SET (dst
, val
);
2153 /* fluid-set fluid:12 val:12
2155 * Set the value of the fluid in DST to the value in SRC.
2157 VM_DEFINE_OP (68, fluid_set
, "fluid-set", OP1 (U8_U12_U12
))
2163 UNPACK_12_12 (op
, a
, b
);
2164 fluid
= LOCAL_REF (a
);
2165 fluids
= SCM_I_DYNAMIC_STATE_FLUIDS (current_thread
->dynamic_state
);
2166 if (SCM_UNLIKELY (!SCM_FLUID_P (fluid
))
2167 || ((num
= SCM_I_FLUID_NUM (fluid
)) >= SCM_SIMPLE_VECTOR_LENGTH (fluids
)))
2169 /* Punt dynstate expansion and error handling to the C proc. */
2171 scm_fluid_set_x (fluid
, LOCAL_REF (b
));
2174 SCM_SIMPLE_VECTOR_SET (fluids
, num
, LOCAL_REF (b
));
2183 * Strings, symbols, and keywords
2186 /* string-length dst:12 src:12
2188 * Store the length of the string in SRC in DST.
2190 VM_DEFINE_OP (69, string_length
, "string-length", OP1 (U8_U12_U12
) | OP_DST
)
2193 if (SCM_LIKELY (scm_is_string (str
)))
2194 RETURN (SCM_I_MAKINUM (scm_i_string_length (str
)));
2198 RETURN (scm_string_length (str
));
2202 /* string-ref dst:8 src:8 idx:8
2204 * Fetch the character at position IDX in the string in SRC, and store
2207 VM_DEFINE_OP (70, string_ref
, "string-ref", OP1 (U8_U8_U8_U8
) | OP_DST
)
2209 scm_t_signed_bits i
= 0;
2211 if (SCM_LIKELY (scm_is_string (str
)
2212 && SCM_I_INUMP (idx
)
2213 && ((i
= SCM_I_INUM (idx
)) >= 0)
2214 && i
< scm_i_string_length (str
)))
2215 RETURN (SCM_MAKE_CHAR (scm_i_string_ref (str
, i
)));
2219 RETURN (scm_string_ref (str
, idx
));
2223 /* No string-set! instruction, as there is no good fast path there. */
2225 /* string-to-number dst:12 src:12
2227 * Parse a string in SRC to a number, and store in DST.
2229 VM_DEFINE_OP (71, string_to_number
, "string->number", OP1 (U8_U12_U12
) | OP_DST
)
2231 scm_t_uint16 dst
, src
;
2233 UNPACK_12_12 (op
, dst
, src
);
2236 scm_string_to_number (LOCAL_REF (src
),
2237 SCM_UNDEFINED
/* radix = 10 */));
2241 /* string-to-symbol dst:12 src:12
2243 * Parse a string in SRC to a symbol, and store in DST.
2245 VM_DEFINE_OP (72, string_to_symbol
, "string->symbol", OP1 (U8_U12_U12
) | OP_DST
)
2247 scm_t_uint16 dst
, src
;
2249 UNPACK_12_12 (op
, dst
, src
);
2251 LOCAL_SET (dst
, scm_string_to_symbol (LOCAL_REF (src
)));
2255 /* symbol->keyword dst:12 src:12
2257 * Make a keyword from the symbol in SRC, and store it in DST.
2259 VM_DEFINE_OP (73, symbol_to_keyword
, "symbol->keyword", OP1 (U8_U12_U12
) | OP_DST
)
2261 scm_t_uint16 dst
, src
;
2262 UNPACK_12_12 (op
, dst
, src
);
2264 LOCAL_SET (dst
, scm_symbol_to_keyword (LOCAL_REF (src
)));
2274 /* cons dst:8 car:8 cdr:8
2276 * Cons CAR and CDR, and store the result in DST.
2278 VM_DEFINE_OP (74, cons
, "cons", OP1 (U8_U8_U8_U8
) | OP_DST
)
2281 RETURN (scm_cons (x
, y
));
2284 /* car dst:12 src:12
2286 * Place the car of SRC in DST.
2288 VM_DEFINE_OP (75, car
, "car", OP1 (U8_U12_U12
) | OP_DST
)
2291 VM_VALIDATE_PAIR (x
, "car");
2292 RETURN (SCM_CAR (x
));
2295 /* cdr dst:12 src:12
2297 * Place the cdr of SRC in DST.
2299 VM_DEFINE_OP (76, cdr
, "cdr", OP1 (U8_U12_U12
) | OP_DST
)
2302 VM_VALIDATE_PAIR (x
, "cdr");
2303 RETURN (SCM_CDR (x
));
2306 /* set-car! pair:12 car:12
2308 * Set the car of DST to SRC.
2310 VM_DEFINE_OP (77, set_car
, "set-car!", OP1 (U8_U12_U12
))
2314 UNPACK_12_12 (op
, a
, b
);
2317 VM_VALIDATE_PAIR (x
, "set-car!");
2322 /* set-cdr! pair:12 cdr:12
2324 * Set the cdr of DST to SRC.
2326 VM_DEFINE_OP (78, set_cdr
, "set-cdr!", OP1 (U8_U12_U12
))
2330 UNPACK_12_12 (op
, a
, b
);
2333 VM_VALIDATE_PAIR (x
, "set-car!");
2342 * Numeric operations
2345 /* add dst:8 a:8 b:8
2347 * Add A to B, and place the result in DST.
2349 VM_DEFINE_OP (79, add
, "add", OP1 (U8_U8_U8_U8
) | OP_DST
)
2351 BINARY_INTEGER_OP (+, scm_sum
);
2354 /* add1 dst:12 src:12
2356 * Add 1 to the value in SRC, and place the result in DST.
2358 VM_DEFINE_OP (80, add1
, "add1", OP1 (U8_U12_U12
) | OP_DST
)
2362 /* Check for overflow. We must avoid overflow in the signed
2363 addition below, even if X is not an inum. */
2364 if (SCM_LIKELY ((scm_t_signed_bits
) SCM_UNPACK (x
) <= INUM_MAX
- INUM_STEP
))
2368 /* Add 1 to the integer without untagging. */
2369 result
= SCM_PACK ((scm_t_signed_bits
) SCM_UNPACK (x
) + INUM_STEP
);
2371 if (SCM_LIKELY (SCM_I_INUMP (result
)))
2376 RETURN (scm_sum (x
, SCM_I_MAKINUM (1)));
2379 /* sub dst:8 a:8 b:8
2381 * Subtract B from A, and place the result in DST.
2383 VM_DEFINE_OP (81, sub
, "sub", OP1 (U8_U8_U8_U8
) | OP_DST
)
2385 BINARY_INTEGER_OP (-, scm_difference
);
2388 /* sub1 dst:12 src:12
2390 * Subtract 1 from SRC, and place the result in DST.
2392 VM_DEFINE_OP (82, sub1
, "sub1", OP1 (U8_U12_U12
) | OP_DST
)
2396 /* Check for overflow. We must avoid overflow in the signed
2397 subtraction below, even if X is not an inum. */
2398 if (SCM_LIKELY ((scm_t_signed_bits
) SCM_UNPACK (x
) >= INUM_MIN
+ INUM_STEP
))
2402 /* Substract 1 from the integer without untagging. */
2403 result
= SCM_PACK ((scm_t_signed_bits
) SCM_UNPACK (x
) - INUM_STEP
);
2405 if (SCM_LIKELY (SCM_I_INUMP (result
)))
2410 RETURN (scm_difference (x
, SCM_I_MAKINUM (1)));
2413 /* mul dst:8 a:8 b:8
2415 * Multiply A and B, and place the result in DST.
2417 VM_DEFINE_OP (83, mul
, "mul", OP1 (U8_U8_U8_U8
) | OP_DST
)
2421 RETURN (scm_product (x
, y
));
2424 /* div dst:8 a:8 b:8
2426 * Divide A by B, and place the result in DST.
2428 VM_DEFINE_OP (84, div
, "div", OP1 (U8_U8_U8_U8
) | OP_DST
)
2432 RETURN (scm_divide (x
, y
));
2435 /* quo dst:8 a:8 b:8
2437 * Divide A by B, and place the quotient in DST.
2439 VM_DEFINE_OP (85, quo
, "quo", OP1 (U8_U8_U8_U8
) | OP_DST
)
2443 RETURN (scm_quotient (x
, y
));
2446 /* rem dst:8 a:8 b:8
2448 * Divide A by B, and place the remainder in DST.
2450 VM_DEFINE_OP (86, rem
, "rem", OP1 (U8_U8_U8_U8
) | OP_DST
)
2454 RETURN (scm_remainder (x
, y
));
2457 /* mod dst:8 a:8 b:8
2459 * Place the modulo of A by B in DST.
2461 VM_DEFINE_OP (87, mod
, "mod", OP1 (U8_U8_U8_U8
) | OP_DST
)
2465 RETURN (scm_modulo (x
, y
));
2468 /* ash dst:8 a:8 b:8
2470 * Shift A arithmetically by B bits, and place the result in DST.
2472 VM_DEFINE_OP (88, ash
, "ash", OP1 (U8_U8_U8_U8
) | OP_DST
)
2475 if (SCM_I_INUMP (x
) && SCM_I_INUMP (y
))
2477 if (SCM_I_INUM (y
) < 0)
2478 /* Right shift, will be a fixnum. */
2479 RETURN (SCM_I_MAKINUM
2480 (SCM_SRS (SCM_I_INUM (x
),
2481 (-SCM_I_INUM (y
) <= SCM_I_FIXNUM_BIT
-1)
2482 ? -SCM_I_INUM (y
) : SCM_I_FIXNUM_BIT
-1)));
2484 /* Left shift. See comments in scm_ash. */
2486 scm_t_signed_bits nn
, bits_to_shift
;
2488 nn
= SCM_I_INUM (x
);
2489 bits_to_shift
= SCM_I_INUM (y
);
2491 if (bits_to_shift
< SCM_I_FIXNUM_BIT
-1
2493 (SCM_SRS (nn
, (SCM_I_FIXNUM_BIT
-1 - bits_to_shift
)) + 1)
2495 RETURN (SCM_I_MAKINUM (nn
<< bits_to_shift
));
2501 RETURN (scm_ash (x
, y
));
2504 /* logand dst:8 a:8 b:8
2506 * Place the bitwise AND of A and B into DST.
2508 VM_DEFINE_OP (89, logand
, "logand", OP1 (U8_U8_U8_U8
) | OP_DST
)
2511 if (SCM_I_INUMP (x
) && SCM_I_INUMP (y
))
2512 /* Compute bitwise AND without untagging */
2513 RETURN (SCM_PACK (SCM_UNPACK (x
) & SCM_UNPACK (y
)));
2515 RETURN (scm_logand (x
, y
));
2518 /* logior dst:8 a:8 b:8
2520 * Place the bitwise inclusive OR of A with B in DST.
2522 VM_DEFINE_OP (90, logior
, "logior", OP1 (U8_U8_U8_U8
) | OP_DST
)
2525 if (SCM_I_INUMP (x
) && SCM_I_INUMP (y
))
2526 /* Compute bitwise OR without untagging */
2527 RETURN (SCM_PACK (SCM_UNPACK (x
) | SCM_UNPACK (y
)));
2529 RETURN (scm_logior (x
, y
));
2532 /* logxor dst:8 a:8 b:8
2534 * Place the bitwise exclusive OR of A with B in DST.
2536 VM_DEFINE_OP (91, logxor
, "logxor", OP1 (U8_U8_U8_U8
) | OP_DST
)
2539 if (SCM_I_INUMP (x
) && SCM_I_INUMP (y
))
2540 RETURN (SCM_I_MAKINUM (SCM_I_INUM (x
) ^ SCM_I_INUM (y
)));
2542 RETURN (scm_logxor (x
, y
));
2545 /* make-vector/immediate dst:8 length:8 init:8
2547 * Make a short vector of known size and write it to DST. The vector
2548 * will have space for LENGTH slots, an immediate value. They will be
2549 * filled with the value in slot INIT.
2551 VM_DEFINE_OP (92, make_vector_immediate
, "make-vector/immediate", OP1 (U8_U8_U8_U8
) | OP_DST
)
2553 scm_t_uint8 dst
, init
;
2554 scm_t_int32 length
, n
;
2557 UNPACK_8_8_8 (op
, dst
, length
, init
);
2559 val
= LOCAL_REF (init
);
2560 vector
= scm_words (scm_tc7_vector
| (length
<< 8), length
+ 1);
2561 for (n
= 0; n
< length
; n
++)
2562 SCM_SIMPLE_VECTOR_SET (vector
, n
, val
);
2563 LOCAL_SET (dst
, vector
);
2567 /* vector-length dst:12 src:12
2569 * Store the length of the vector in SRC in DST.
2571 VM_DEFINE_OP (93, vector_length
, "vector-length", OP1 (U8_U12_U12
) | OP_DST
)
2574 if (SCM_LIKELY (SCM_I_IS_VECTOR (vect
)))
2575 RETURN (SCM_I_MAKINUM (SCM_I_VECTOR_LENGTH (vect
)));
2579 RETURN (scm_vector_length (vect
));
2583 /* vector-ref dst:8 src:8 idx:8
2585 * Fetch the item at position IDX in the vector in SRC, and store it
2588 VM_DEFINE_OP (94, vector_ref
, "vector-ref", OP1 (U8_U8_U8_U8
) | OP_DST
)
2590 scm_t_signed_bits i
= 0;
2592 if (SCM_LIKELY (SCM_I_IS_NONWEAK_VECTOR (vect
)
2593 && SCM_I_INUMP (idx
)
2594 && ((i
= SCM_I_INUM (idx
)) >= 0)
2595 && i
< SCM_I_VECTOR_LENGTH (vect
)))
2596 RETURN (SCM_I_VECTOR_ELTS (vect
)[i
]);
2600 RETURN (scm_vector_ref (vect
, idx
));
2604 /* vector-ref/immediate dst:8 src:8 idx:8
2606 * Fill DST with the item IDX elements into the vector at SRC. Useful
2607 * for building data types using vectors.
2609 VM_DEFINE_OP (95, vector_ref_immediate
, "vector-ref/immediate", OP1 (U8_U8_U8_U8
) | OP_DST
)
2611 scm_t_uint8 dst
, src
, idx
;
2614 UNPACK_8_8_8 (op
, dst
, src
, idx
);
2615 v
= LOCAL_REF (src
);
2616 if (SCM_LIKELY (SCM_I_IS_NONWEAK_VECTOR (v
)
2617 && idx
< SCM_I_VECTOR_LENGTH (v
)))
2618 LOCAL_SET (dst
, SCM_I_VECTOR_ELTS (LOCAL_REF (src
))[idx
]);
2620 LOCAL_SET (dst
, scm_c_vector_ref (v
, idx
));
2624 /* vector-set! dst:8 idx:8 src:8
2626 * Store SRC into the vector DST at index IDX.
2628 VM_DEFINE_OP (96, vector_set
, "vector-set!", OP1 (U8_U8_U8_U8
))
2630 scm_t_uint8 dst
, idx_var
, src
;
2632 scm_t_signed_bits i
= 0;
2634 UNPACK_8_8_8 (op
, dst
, idx_var
, src
);
2635 vect
= LOCAL_REF (dst
);
2636 idx
= LOCAL_REF (idx_var
);
2637 val
= LOCAL_REF (src
);
2639 if (SCM_LIKELY (SCM_I_IS_NONWEAK_VECTOR (vect
)
2640 && SCM_I_INUMP (idx
)
2641 && ((i
= SCM_I_INUM (idx
)) >= 0)
2642 && i
< SCM_I_VECTOR_LENGTH (vect
)))
2643 SCM_I_VECTOR_WELTS (vect
)[i
] = val
;
2647 scm_vector_set_x (vect
, idx
, val
);
2652 /* vector-set!/immediate dst:8 idx:8 src:8
2654 * Store SRC into the vector DST at index IDX. Here IDX is an
2657 VM_DEFINE_OP (97, vector_set_immediate
, "vector-set!/immediate", OP1 (U8_U8_U8_U8
))
2659 scm_t_uint8 dst
, idx
, src
;
2662 UNPACK_8_8_8 (op
, dst
, idx
, src
);
2663 vect
= LOCAL_REF (dst
);
2664 val
= LOCAL_REF (src
);
2666 if (SCM_LIKELY (SCM_I_IS_NONWEAK_VECTOR (vect
)
2667 && idx
< SCM_I_VECTOR_LENGTH (vect
)))
2668 SCM_I_VECTOR_WELTS (vect
)[idx
] = val
;
2672 scm_vector_set_x (vect
, scm_from_uint8 (idx
), val
);
2684 /* struct-vtable dst:12 src:12
2686 * Store the vtable of SRC into DST.
2688 VM_DEFINE_OP (98, struct_vtable
, "struct-vtable", OP1 (U8_U12_U12
) | OP_DST
)
2691 VM_VALIDATE_STRUCT (obj
, "struct_vtable");
2692 RETURN (SCM_STRUCT_VTABLE (obj
));
2695 /* allocate-struct/immediate dst:8 vtable:8 nfields:8
2697 * Allocate a new struct with VTABLE, and place it in DST. The struct
2698 * will be constructed with space for NFIELDS fields, which should
2699 * correspond to the field count of the VTABLE.
2701 VM_DEFINE_OP (99, allocate_struct_immediate
, "allocate-struct/immediate", OP1 (U8_U8_U8_U8
) | OP_DST
)
2703 scm_t_uint8 dst
, vtable
, nfields
;
2706 UNPACK_8_8_8 (op
, dst
, vtable
, nfields
);
2709 ret
= scm_allocate_struct (LOCAL_REF (vtable
), SCM_I_MAKINUM (nfields
));
2710 LOCAL_SET (dst
, ret
);
2715 /* struct-ref/immediate dst:8 src:8 idx:8
2717 * Fetch the item at slot IDX in the struct in SRC, and store it
2718 * in DST. IDX is an immediate unsigned 8-bit value.
2720 VM_DEFINE_OP (100, struct_ref_immediate
, "struct-ref/immediate", OP1 (U8_U8_U8_U8
) | OP_DST
)
2722 scm_t_uint8 dst
, src
, idx
;
2725 UNPACK_8_8_8 (op
, dst
, src
, idx
);
2727 obj
= LOCAL_REF (src
);
2729 if (SCM_LIKELY (SCM_STRUCTP (obj
)
2730 && SCM_STRUCT_VTABLE_FLAG_IS_SET (obj
,
2731 SCM_VTABLE_FLAG_SIMPLE
)
2732 && idx
< SCM_STRUCT_DATA_REF (SCM_STRUCT_VTABLE (obj
),
2733 scm_vtable_index_size
)))
2734 RETURN (SCM_STRUCT_SLOT_REF (obj
, idx
));
2737 RETURN (scm_struct_ref (obj
, SCM_I_MAKINUM (idx
)));
2740 /* struct-set!/immediate dst:8 idx:8 src:8
2742 * Store SRC into the struct DST at slot IDX. IDX is an immediate
2743 * unsigned 8-bit value.
2745 VM_DEFINE_OP (101, struct_set_immediate
, "struct-set!/immediate", OP1 (U8_U8_U8_U8
))
2747 scm_t_uint8 dst
, idx
, src
;
2750 UNPACK_8_8_8 (op
, dst
, idx
, src
);
2752 obj
= LOCAL_REF (dst
);
2753 val
= LOCAL_REF (src
);
2755 if (SCM_LIKELY (SCM_STRUCTP (obj
)
2756 && SCM_STRUCT_VTABLE_FLAG_IS_SET (obj
,
2757 SCM_VTABLE_FLAG_SIMPLE
)
2758 && SCM_STRUCT_VTABLE_FLAG_IS_SET (obj
,
2759 SCM_VTABLE_FLAG_SIMPLE_RW
)
2760 && idx
< SCM_STRUCT_DATA_REF (SCM_STRUCT_VTABLE (obj
),
2761 scm_vtable_index_size
)))
2763 SCM_STRUCT_SLOT_SET (obj
, idx
, val
);
2768 scm_struct_set_x (obj
, SCM_I_MAKINUM (idx
), val
);
2772 /* class-of dst:12 type:12
2774 * Store the vtable of SRC into DST.
2776 VM_DEFINE_OP (102, class_of
, "class-of", OP1 (U8_U12_U12
) | OP_DST
)
2779 if (SCM_INSTANCEP (obj
))
2780 RETURN (SCM_CLASS_OF (obj
));
2782 RETURN (scm_class_of (obj
));
2785 /* slot-ref dst:8 src:8 idx:8
2787 * Fetch the item at slot IDX in the struct in SRC, and store it in
2788 * DST. Unlike struct-ref, IDX is an 8-bit immediate value, not an
2789 * index into the stack.
2791 VM_DEFINE_OP (103, slot_ref
, "slot-ref", OP1 (U8_U8_U8_U8
) | OP_DST
)
2793 scm_t_uint8 dst
, src
, idx
;
2794 UNPACK_8_8_8 (op
, dst
, src
, idx
);
2796 SCM_PACK (SCM_STRUCT_DATA (LOCAL_REF (src
))[idx
]));
2800 /* slot-set! dst:8 idx:8 src:8
2802 * Store SRC into slot IDX of the struct in DST. Unlike struct-set!,
2803 * IDX is an 8-bit immediate value, not an index into the stack.
2805 VM_DEFINE_OP (104, slot_set
, "slot-set!", OP1 (U8_U8_U8_U8
))
2807 scm_t_uint8 dst
, idx
, src
;
2808 UNPACK_8_8_8 (op
, dst
, idx
, src
);
2809 SCM_STRUCT_DATA (LOCAL_REF (dst
))[idx
] = SCM_UNPACK (LOCAL_REF (src
));
2817 * Arrays, packed uniform arrays, and bytevectors.
2820 /* load-typed-array dst:8 type:8 shape:8 offset:32 len:32
2822 * Load the contiguous typed array located at OFFSET 32-bit words away
2823 * from the instruction pointer, and store into DST. LEN is a byte
2824 * length. OFFSET is signed.
2826 VM_DEFINE_OP (105, load_typed_array
, "load-typed-array", OP3 (U8_U8_U8_U8
, N32
, U32
) | OP_DST
)
2828 scm_t_uint8 dst
, type
, shape
;
2832 UNPACK_8_8_8 (op
, dst
, type
, shape
);
2836 LOCAL_SET (dst
, scm_from_contiguous_typed_array (LOCAL_REF (type
),
2842 /* make-array dst:12 type:12 _:8 fill:12 bounds:12
2844 * Make a new array with TYPE, FILL, and BOUNDS, storing it in DST.
2846 VM_DEFINE_OP (106, make_array
, "make-array", OP2 (U8_U12_U12
, X8_U12_U12
) | OP_DST
)
2848 scm_t_uint16 dst
, type
, fill
, bounds
;
2849 UNPACK_12_12 (op
, dst
, type
);
2850 UNPACK_12_12 (ip
[1], fill
, bounds
);
2852 LOCAL_SET (dst
, scm_make_typed_array (LOCAL_REF (type
), LOCAL_REF (fill
),
2853 LOCAL_REF (bounds
)));
2857 /* bv-u8-ref dst:8 src:8 idx:8
2858 * bv-s8-ref dst:8 src:8 idx:8
2859 * bv-u16-ref dst:8 src:8 idx:8
2860 * bv-s16-ref dst:8 src:8 idx:8
2861 * bv-u32-ref dst:8 src:8 idx:8
2862 * bv-s32-ref dst:8 src:8 idx:8
2863 * bv-u64-ref dst:8 src:8 idx:8
2864 * bv-s64-ref dst:8 src:8 idx:8
2865 * bv-f32-ref dst:8 src:8 idx:8
2866 * bv-f64-ref dst:8 src:8 idx:8
2868 * Fetch the item at byte offset IDX in the bytevector SRC, and store
2869 * it in DST. All accesses use native endianness.
2871 #define BV_FIXABLE_INT_REF(stem, fn_stem, type, size) \
2873 scm_t_signed_bits i; \
2874 const scm_t_ ## type *int_ptr; \
2877 VM_VALIDATE_BYTEVECTOR (bv, "bv-" #stem "-ref"); \
2878 i = SCM_I_INUM (idx); \
2879 int_ptr = (scm_t_ ## type *) (SCM_BYTEVECTOR_CONTENTS (bv) + i); \
2881 if (SCM_LIKELY (SCM_I_INUMP (idx) \
2883 && (i + size <= SCM_BYTEVECTOR_LENGTH (bv)) \
2884 && (ALIGNED_P (int_ptr, scm_t_ ## type)))) \
2885 RETURN (SCM_I_MAKINUM (*int_ptr)); \
2889 RETURN (scm_bytevector_ ## fn_stem ## _ref (bv, idx)); \
2893 #define BV_INT_REF(stem, type, size) \
2895 scm_t_signed_bits i; \
2896 const scm_t_ ## type *int_ptr; \
2899 VM_VALIDATE_BYTEVECTOR (bv, "bv-" #stem "-ref"); \
2900 i = SCM_I_INUM (idx); \
2901 int_ptr = (scm_t_ ## type *) (SCM_BYTEVECTOR_CONTENTS (bv) + i); \
2903 if (SCM_LIKELY (SCM_I_INUMP (idx) \
2905 && (i + size <= SCM_BYTEVECTOR_LENGTH (bv)) \
2906 && (ALIGNED_P (int_ptr, scm_t_ ## type)))) \
2908 scm_t_ ## type x = *int_ptr; \
2909 if (SCM_FIXABLE (x)) \
2910 RETURN (SCM_I_MAKINUM (x)); \
2914 RETURN (scm_from_ ## type (x)); \
2920 RETURN (scm_bytevector_ ## stem ## _native_ref (bv, idx)); \
2924 #define BV_FLOAT_REF(stem, fn_stem, type, size) \
2926 scm_t_signed_bits i; \
2927 const type *float_ptr; \
2930 VM_VALIDATE_BYTEVECTOR (bv, "bv-" #stem "-ref"); \
2931 i = SCM_I_INUM (idx); \
2932 float_ptr = (type *) (SCM_BYTEVECTOR_CONTENTS (bv) + i); \
2935 if (SCM_LIKELY (SCM_I_INUMP (idx) \
2937 && (i + size <= SCM_BYTEVECTOR_LENGTH (bv)) \
2938 && (ALIGNED_P (float_ptr, type)))) \
2939 RETURN (scm_from_double (*float_ptr)); \
2941 RETURN (scm_bytevector_ ## fn_stem ## _native_ref (bv, idx)); \
2944 VM_DEFINE_OP (107, bv_u8_ref
, "bv-u8-ref", OP1 (U8_U8_U8_U8
) | OP_DST
)
2945 BV_FIXABLE_INT_REF (u8
, u8
, uint8
, 1);
2947 VM_DEFINE_OP (108, bv_s8_ref
, "bv-s8-ref", OP1 (U8_U8_U8_U8
) | OP_DST
)
2948 BV_FIXABLE_INT_REF (s8
, s8
, int8
, 1);
2950 VM_DEFINE_OP (109, bv_u16_ref
, "bv-u16-ref", OP1 (U8_U8_U8_U8
) | OP_DST
)
2951 BV_FIXABLE_INT_REF (u16
, u16_native
, uint16
, 2);
2953 VM_DEFINE_OP (110, bv_s16_ref
, "bv-s16-ref", OP1 (U8_U8_U8_U8
) | OP_DST
)
2954 BV_FIXABLE_INT_REF (s16
, s16_native
, int16
, 2);
2956 VM_DEFINE_OP (111, bv_u32_ref
, "bv-u32-ref", OP1 (U8_U8_U8_U8
) | OP_DST
)
2957 #if SIZEOF_VOID_P > 4
2958 BV_FIXABLE_INT_REF (u32
, u32_native
, uint32
, 4);
2960 BV_INT_REF (u32
, uint32
, 4);
2963 VM_DEFINE_OP (112, bv_s32_ref
, "bv-s32-ref", OP1 (U8_U8_U8_U8
) | OP_DST
)
2964 #if SIZEOF_VOID_P > 4
2965 BV_FIXABLE_INT_REF (s32
, s32_native
, int32
, 4);
2967 BV_INT_REF (s32
, int32
, 4);
2970 VM_DEFINE_OP (113, bv_u64_ref
, "bv-u64-ref", OP1 (U8_U8_U8_U8
) | OP_DST
)
2971 BV_INT_REF (u64
, uint64
, 8);
2973 VM_DEFINE_OP (114, bv_s64_ref
, "bv-s64-ref", OP1 (U8_U8_U8_U8
) | OP_DST
)
2974 BV_INT_REF (s64
, int64
, 8);
2976 VM_DEFINE_OP (115, bv_f32_ref
, "bv-f32-ref", OP1 (U8_U8_U8_U8
) | OP_DST
)
2977 BV_FLOAT_REF (f32
, ieee_single
, float, 4);
2979 VM_DEFINE_OP (116, bv_f64_ref
, "bv-f64-ref", OP1 (U8_U8_U8_U8
) | OP_DST
)
2980 BV_FLOAT_REF (f64
, ieee_double
, double, 8);
2982 /* bv-u8-set! dst:8 idx:8 src:8
2983 * bv-s8-set! dst:8 idx:8 src:8
2984 * bv-u16-set! dst:8 idx:8 src:8
2985 * bv-s16-set! dst:8 idx:8 src:8
2986 * bv-u32-set! dst:8 idx:8 src:8
2987 * bv-s32-set! dst:8 idx:8 src:8
2988 * bv-u64-set! dst:8 idx:8 src:8
2989 * bv-s64-set! dst:8 idx:8 src:8
2990 * bv-f32-set! dst:8 idx:8 src:8
2991 * bv-f64-set! dst:8 idx:8 src:8
2993 * Store SRC into the bytevector DST at byte offset IDX. Multibyte
2994 * values are written using native endianness.
2996 #define BV_FIXABLE_INT_SET(stem, fn_stem, type, min, max, size) \
2998 scm_t_uint8 dst, idx, src; \
2999 scm_t_signed_bits i, j = 0; \
3000 SCM bv, scm_idx, val; \
3001 scm_t_ ## type *int_ptr; \
3003 UNPACK_8_8_8 (op, dst, idx, src); \
3004 bv = LOCAL_REF (dst); \
3005 scm_idx = LOCAL_REF (idx); \
3006 val = LOCAL_REF (src); \
3007 VM_VALIDATE_BYTEVECTOR (bv, "bv-" #stem "-set!"); \
3008 i = SCM_I_INUM (scm_idx); \
3009 int_ptr = (scm_t_ ## type *) (SCM_BYTEVECTOR_CONTENTS (bv) + i); \
3011 if (SCM_LIKELY (SCM_I_INUMP (scm_idx) \
3013 && (i + size <= SCM_BYTEVECTOR_LENGTH (bv)) \
3014 && (ALIGNED_P (int_ptr, scm_t_ ## type)) \
3015 && (SCM_I_INUMP (val)) \
3016 && ((j = SCM_I_INUM (val)) >= min) \
3018 *int_ptr = (scm_t_ ## type) j; \
3022 scm_bytevector_ ## fn_stem ## _set_x (bv, scm_idx, val); \
3027 #define BV_INT_SET(stem, type, size) \
3029 scm_t_uint8 dst, idx, src; \
3030 scm_t_signed_bits i; \
3031 SCM bv, scm_idx, val; \
3032 scm_t_ ## type *int_ptr; \
3034 UNPACK_8_8_8 (op, dst, idx, src); \
3035 bv = LOCAL_REF (dst); \
3036 scm_idx = LOCAL_REF (idx); \
3037 val = LOCAL_REF (src); \
3038 VM_VALIDATE_BYTEVECTOR (bv, "bv-" #stem "-set!"); \
3039 i = SCM_I_INUM (scm_idx); \
3040 int_ptr = (scm_t_ ## type *) (SCM_BYTEVECTOR_CONTENTS (bv) + i); \
3042 if (SCM_LIKELY (SCM_I_INUMP (scm_idx) \
3044 && (i + size <= SCM_BYTEVECTOR_LENGTH (bv)) \
3045 && (ALIGNED_P (int_ptr, scm_t_ ## type)))) \
3046 *int_ptr = scm_to_ ## type (val); \
3050 scm_bytevector_ ## stem ## _native_set_x (bv, scm_idx, val); \
3055 #define BV_FLOAT_SET(stem, fn_stem, type, size) \
3057 scm_t_uint8 dst, idx, src; \
3058 scm_t_signed_bits i; \
3059 SCM bv, scm_idx, val; \
3062 UNPACK_8_8_8 (op, dst, idx, src); \
3063 bv = LOCAL_REF (dst); \
3064 scm_idx = LOCAL_REF (idx); \
3065 val = LOCAL_REF (src); \
3066 VM_VALIDATE_BYTEVECTOR (bv, "bv-" #stem "-set!"); \
3067 i = SCM_I_INUM (scm_idx); \
3068 float_ptr = (type *) (SCM_BYTEVECTOR_CONTENTS (bv) + i); \
3070 if (SCM_LIKELY (SCM_I_INUMP (scm_idx) \
3072 && (i + size <= SCM_BYTEVECTOR_LENGTH (bv)) \
3073 && (ALIGNED_P (float_ptr, type)))) \
3074 *float_ptr = scm_to_double (val); \
3078 scm_bytevector_ ## fn_stem ## _native_set_x (bv, scm_idx, val); \
3083 VM_DEFINE_OP (117, bv_u8_set
, "bv-u8-set!", OP1 (U8_U8_U8_U8
))
3084 BV_FIXABLE_INT_SET (u8
, u8
, uint8
, 0, SCM_T_UINT8_MAX
, 1);
3086 VM_DEFINE_OP (118, bv_s8_set
, "bv-s8-set!", OP1 (U8_U8_U8_U8
))
3087 BV_FIXABLE_INT_SET (s8
, s8
, int8
, SCM_T_INT8_MIN
, SCM_T_INT8_MAX
, 1);
3089 VM_DEFINE_OP (119, bv_u16_set
, "bv-u16-set!", OP1 (U8_U8_U8_U8
))
3090 BV_FIXABLE_INT_SET (u16
, u16_native
, uint16
, 0, SCM_T_UINT16_MAX
, 2);
3092 VM_DEFINE_OP (120, bv_s16_set
, "bv-s16-set!", OP1 (U8_U8_U8_U8
))
3093 BV_FIXABLE_INT_SET (s16
, s16_native
, int16
, SCM_T_INT16_MIN
, SCM_T_INT16_MAX
, 2);
3095 VM_DEFINE_OP (121, bv_u32_set
, "bv-u32-set!", OP1 (U8_U8_U8_U8
))
3096 #if SIZEOF_VOID_P > 4
3097 BV_FIXABLE_INT_SET (u32
, u32_native
, uint32
, 0, SCM_T_UINT32_MAX
, 4);
3099 BV_INT_SET (u32
, uint32
, 4);
3102 VM_DEFINE_OP (122, bv_s32_set
, "bv-s32-set!", OP1 (U8_U8_U8_U8
))
3103 #if SIZEOF_VOID_P > 4
3104 BV_FIXABLE_INT_SET (s32
, s32_native
, int32
, SCM_T_INT32_MIN
, SCM_T_INT32_MAX
, 4);
3106 BV_INT_SET (s32
, int32
, 4);
3109 VM_DEFINE_OP (123, bv_u64_set
, "bv-u64-set!", OP1 (U8_U8_U8_U8
))
3110 BV_INT_SET (u64
, uint64
, 8);
3112 VM_DEFINE_OP (124, bv_s64_set
, "bv-s64-set!", OP1 (U8_U8_U8_U8
))
3113 BV_INT_SET (s64
, int64
, 8);
3115 VM_DEFINE_OP (125, bv_f32_set
, "bv-f32-set!", OP1 (U8_U8_U8_U8
))
3116 BV_FLOAT_SET (f32
, ieee_single
, float, 4);
3118 VM_DEFINE_OP (126, bv_f64_set
, "bv-f64-set!", OP1 (U8_U8_U8_U8
))
3119 BV_FLOAT_SET (f64
, ieee_double
, double, 8);
3121 END_DISPATCH_SWITCH
;
3123 vm_error_bad_instruction
:
3124 vm_error_bad_instruction (op
);
3126 abort (); /* never reached */
3130 #undef ABORT_CONTINUATION_HOOK
3135 #undef BEGIN_DISPATCH_SWITCH
3136 #undef BINARY_INTEGER_OP
3137 #undef BR_ARITHMETIC
3141 #undef BV_FIXABLE_INT_REF
3142 #undef BV_FIXABLE_INT_SET
3147 #undef CACHE_REGISTER
3148 #undef CHECK_OVERFLOW
3149 #undef END_DISPATCH_SWITCH
3150 #undef FREE_VARIABLE_REF
3159 #undef POP_CONTINUATION_HOOK
3160 #undef PUSH_CONTINUATION_HOOK
3161 #undef RESTORE_CONTINUATION_HOOK
3163 #undef RETURN_ONE_VALUE
3164 #undef RETURN_VALUE_LIST
3168 #undef SYNC_BEFORE_GC
3170 #undef SYNC_REGISTER
3176 #undef VARIABLE_BOUNDP
3179 #undef VM_CHECK_FREE_VARIABLE
3180 #undef VM_CHECK_OBJECT
3181 #undef VM_CHECK_UNDERFLOW
3183 #undef VM_INSTRUCTION_TO_LABEL
3185 #undef VM_VALIDATE_BYTEVECTOR
3186 #undef VM_VALIDATE_PAIR
3187 #undef VM_VALIDATE_STRUCT
3190 (defun renumber-ops ()
3191 "start from top of buffer and renumber 'VM_DEFINE_FOO (\n' sequences"
3194 (let ((counter -1)) (goto-char (point-min))
3195 (while (re-search-forward "^ *VM_DEFINE_[^ ]+ (\\([^,]+\\)," (point-max) t)
3197 (number-to-string (setq counter (1+ counter)))