car
/cdr
), programs run with all safety checks
enabled even when compiled.
disassemble
function. A rule of thumb
is that every elementary instruction costs 1 time unit, whereas a
function call costs 3 to 4 time units.
The virtual machine is a stack machine with two stacks:
The scope of STACK and SP is only valid for a given function invocation. Whereas the amount of STACK space needed for executing a function (excluding other function calls) is unlimited, the amount of SP space needed is known a priori, at compile time. When a function is called, no relation is specified between the caller's STACK and the callee's STACK, and between the caller's SP and the callee's SP. The bytecode is designed so that outgoing arguments on the caller's STACK can be shared by the caller's incoming arguments area (on the callee's STACK), but a virtual machine implementation may also copy outgoing arguments to incoming arguments instead of sharing them.
The virtual machine has a special data structure, values
,
containing the "top of stack", specially adapted to Common Lisp multiple values:
mv_count
, an unsigned integer.
value1
, the first value, a Lisp object.
If mv_count
= 0, this is nil
.
mv_space
, all values except the first one,
an array of Lisp objects.
values
is short-lived. It does not survive
a function call, not even a garbage collection.
The interpretation of some bytecode instructions depends on a constant,
jmpbufsize. This is a CPU dependent number, the value of
system::*jmpbuf-size*
. In C, it is defined as
ceiling(sizeof(jmp_buf),sizeof(void*))
.
Typically, the byte vector is about twice as large as the function vector. The separation thus helps the garbage collector (since the byte vector does not need to be scanned for pointers).
The function looks like this (cf. the C type Cclosure
):
(setf symbol)
. It is
used for printing the function and for error messages. This field
is immutable.
simple-bit-vector
(because
that's the simplest type in CLISP which contains immediate data -- note
that (simple-vector (unsigned-byte 8))
is more complex
than this). This field is immutable.
Some of the consts can play special roles. A function's looks like this, in more detail:
#(next value1 ... valuen)
where value1, ..., valuen
are the values of the closed-up variables, and next is
either nil
or a simple-vector having the same structure.
block
tags,
representing the block
tags of the lexical environment
in which this function was defined. Each is a cons containing in the
cdr part: either a frame pointer to the block frame, or
#<DISABLED>
if the block has already been left.
The car is the block's name, only for error message purposes.
tagbody
tags,
representing the tagbody
tags of the lexical environment
in which this function was defined. Each is a cons containing in the
cdr part: either a frame pointer to the tagbody frame, or
#<DISABLED>
if the tagbody has already been left.
The car is a simple-vector containing the names of the
tagbody
tags, only for error message purposes.
&key
, here come the symbols ("keywords"), in their
correct order. They are used by the interpreter during function call.
If venv-const, block-const, tagbody-const are all absent, the function is called autonomous. This is the case if the function does not refer to lexical variables, blocks or tags defined in compile code outside of the function. In particular, it is the case if the function is defined in a null lexical environment.
If some venv-const, block-const, or
tagbody-const are present, the function (a "closure")
is created at runtime. The compiler only generates a prototype, containing
nil
values instead of each venv-const,
block-const, tagbody-const. At runtime, a function
is created by copying this prototype and replacing the nil
values
by the definitive ones.
The list (keyword-const* other-const*)
normally doesn't contain duplicates, because the compiler removes duplicates
when possible. (Duplicates can occur nevertheless, through the use of
load-time-value
.)
The codevec looks like this (cf. C type Codevec
):
&rest
parameter&key
parameters&allow-other-keys
&key
)&key
parameters.&key
)
The conversion from a byte (in the range 0..255) to the opcode is performed
by lookup in the table contained in the file bytecode.d
.
There are the following types of operands, denoted by different letters:
mnemonic | description | semantics |
---|---|---|
(NIL)
| Load nil into values.
| value1 := nil , mv_count := 1
|
(PUSH-NIL n)
| Push n nil s into the STACK.
| n times do: *--STACK := nil ,values undefined |
(T)
| Load t into values.
| value1 := t , mv_count := 1
|
(CONST n)
| Load the function's nth constant into values. | value1 := consts[n], mv_count := 1 |
mnemonic | description | semantics |
---|---|---|
(LOAD n)
| Load a directly accessible local variable into values. | value1 := *(STACK+n), mv_count := 1 |
(LOADI k1 k2 n)
| Load an indirectly accessible local variable into values. | k := k1 + jmpbufsize * k2, value1 := *(*(SP+k)+n), mv_count := 1 |
(LOADC n m)
| Load a closed-up variable, defined in the same function and directly accessible, into values. | value1 := svref(*(STACK+n),1+m), mv_count := 1 |
(LOADV k m)
| Load a closed-up variable, defined in an outer function, into values. | vector := venv-const, m times do: vector := svref(vector,0), value1 := svref(vector,m), mv_count := 1 |
(LOADIC k1 k2 n m)
| Load a closed-up variable, defined in the same function and indirectly accessible, into values. | k := k1 + jmpbufsize * k2, value1 := svref(*(*(SP+k)+n),1+m), mv_count := 1 |
(STORE n)
| Store values into a directly accessible local variable. | *(STACK+n) := value1, mv_count := 1 |
(STOREI k1 k2 n)
| Store values into an indirectly accessible local variable. | k := k1 + jmpbufsize * k2, *(*(SP+k)+n) := value1, mv_count := 1 |
(STOREC n m)
| Store values into a closed-up variable, defined in the same function and directly accessible. | svref(*(STACK+n),1+m) := value1, mv_count := 1 |
(STOREV k m)
| Store values into a closed-up variable, defined in an outer function. | vector := venv-const, m times do: vector := svref(vector,0), svref(vector,m) := value1, mv_count := 1 |
(STOREIC k1 k2 n m)
| Store values into a closed-up variable, defined in the same function and indirectly accessible. | k := k1 + jmpbufsize * k2, svref(*(*(SP+k)+n),1+m) := value1, mv_count := 1 |
mnemonic | description | semantics |
---|---|---|
(GETVALUE n)
| Load a symbol's value into values. | value1 := symbol-value(consts[n]), mv_count := 1 |
(SETVALUE n)
| Store values into a symbol's value. | symbol-value(consts[n]) := value1, mv_count := 1 |
(BIND n)
| Bind a symbol dynamically. | Bind the value of the symbol consts[n] to value1, implicitly STACK -= 3, values undefined |
(UNBIND1)
| Dissolve one binding frame. | Unbind the binding frame STACK is pointing to, implicitly STACK += 1+2*x |
(UNBIND n)
| Dissolve n binding frames. | n times do: Unbind the binding frame STACK is pointing to, thereby incrementing STACK |
(PROGV)
| Bind a set of symbols dynamically to a set of values. | symbols := *STACK++, *--SP := STACK, build a single binding frame binding the symbols in symbols to the values in value1, values undefined |
mnemonic | description | semantics |
---|---|---|
(PUSH)
| Push one object onto the STACK. | *--STACK := value1, values undefined |
(POP)
| Pop one object from the STACK, into values. | value1 := *STACK++, mv_count := 1 |
(SKIP n)
| Restore a previous STACK pointer. Remove n objects from the STACK. | STACK := STACK + n |
(SKIPI k1 k2 n)
| Restore a previous STACK pointer. Remove an unknown number of objects from the STACK. | k := k1 + jmpbufsize * k2, STACK := *(SP+k), SP := SP+k+1 |
(SKIPSP k1 k2)
| Restore a previous SP pointer. | k := k1 + jmpbufsize * k2, SP := SP+k |
mnemonic | description | semantics |
---|---|---|
(SKIP&RET n)
| Clean up the STACK, and return from the function. | STACK := STACK+n, return from the function, returning values. |
(SKIP&RETGF n)
| Clean up the STACK, and return from the generic function. | If bit 3 is set in the function's flags,
then STACK := STACK+n, mv_count := 1, and
return from the function. Otherwise: if the current
function has no &rest argument, then
STACK := STACK+n-numreq, apply
value1 to the numreq arguments still on the
STACK, and return from the function. Else
STACK := STACK+n-numreq-1, apply
value1 to the numreq arguments and the
&rest argument, all still on the STACK,
and return from the function.
|
(JMP label)
| Jump to label. | PC := label. |
(JMPIF label)
| Jump to label, if value1 is true. | If value1 is not nil , PC := label.
|
(JMPIFNOT label)
| Jump to label, if value1 is false. | If value1 is nil , PC := label.
|
(JMPIF1 label)
| Jump to label and forget secondary values, if value1 is true. | If value1 is not nil , mv_count := 1, PC := label.
|
(JMPIFNOT1 label)
| Jump to label and forget secondary values, if value1 is false. | If value1 is nil , mv_count := 1, PC := label.
|
(JMPIFATOM label)
| Jump to label, if value1 is not a cons. | If value1 is not a cons, PC := label. values undefined |
(JMPIFCONSP label)
| Jump to label, if value1 is a cons. | If value1 is a cons, PC := label. values undefined |
(JMPIFEQ label)
| Jump to label, if value1 is eq
to the top-of-stack.
| If eq(value1,*STACK++), PC := label. values undefined |
(JMPIFNOTEQ label)
| Jump to label, if value1 is not eq
to the top-of-stack.
| If not eq(value1,*STACK++), PC := label. values undefined |
(JMPIFEQTO n label)
| Jump to label, if the top-of-stack is eq
to a constant.
| If eq(*STACK++,consts[n]),
PC := label. values undefined |
(JMPIFNOTEQTO n label)
| Jump to label, if the top-of-stack is not eq
to a constant.
| If not eq(*STACK++,consts[n]),
PC := label. values undefined |
(JMPHASH n label)
| Table-driven jump, depending on value1. | Lookup value1 in the hash table consts[n].
(The hash table's test is either EQ or EQL.)
If found, the hash table value is a signed fixnum, jump
to it: PC := PC + value. Else jump to label. values undefined |
(JMPHASHV n label)
| Table-driven jump, depending on value1, inside a generic function. | Lookup value1 in the hash table svref(consts[0],n).
(The hash table's test is either EQ or EQL.)
If found, the hash table value is a signed fixnum, jump
to it: PC := PC + value. Else jump to label. values undefined |
(JSR label)
| Subroutine call. | *--STACK := function. Then start interpreting the
bytecode at label, with values undefined.
When a (RET) is encountered, program
execution is resumed at the instruction after
(JSR label) .
|
(JMPTAIL m n label)
| Tail subroutine call. | n >= m. The STACK frame of size
n is reduced to size m:
{*(STACK+n-m), ..., *(STACK+n-1)} := {*STACK, ..., *(STACK+m-1)}. STACK += n-m. *--STACK := function. Then jump to label, with values undefined. |
mnemonic | description | semantics |
---|---|---|
(VENV)
| Load the venv-const into values. | value1 := consts[0], mv_count := 1. |
(MAKE-VECTOR1&PUSH n)
| Create a simple-vector used for closed-up variables. | vector := new simple-vector of size n+1. svref(vector,0) := value1. *--STACK := vector. values undefined |
(COPY-CLOSURE m n)
| Create a closure by copying the prototype and filling in the lexical environment. | func := copy-function(consts[m]). For i=0,..,n-1: func_consts[i] := *(STACK+n-1-i). STACK += n. value1 := func, mv_count := 1 |
mnemonic | description | semantics |
---|---|---|
(CALL k n)
| Calls a constant function with k arguments. | The function consts[n] is called
with the arguments *(STACK+k-1), ..., *(STACK+0). STACK += k. The returned values go into values. |
(CALL0 n)
| Calls a constant function with 0 arguments. | The function consts[n] is called
with 0 arguments. The returned values go into values. |
(CALL1 n)
| Calls a constant function with 1 argument. | The function consts[n] is called
with one argument *STACK. STACK += 1. The returned values go into values. |
(CALL2 n)
| Calls a constant function with 2 arguments. | The function consts[n] is called
with two arguments *(STACK+1) and *(STACK+0). STACK += 2. The returned values go into values. |
(CALLS1 b)
| Calls a system function with no &rest .
| Calls the system function FUNTAB[b]. The
right number of arguments is already on the STACK
(including #<UNBOUND> s in place
of absent &optional or
&key parameters). The arguments are
removed from the STACK. The returned values go into
values.
|
(CALLS2 b)
| Calls a system function with no &rest .
| Calls the system function FUNTAB[256+b]. The
right number of arguments is already on the STACK
(including #<UNBOUND> s in place
of absent &optional or
&key parameters). The arguments are
removed from the STACK. The returned values go into
values.
|
(CALLSR m b)
| Calls a system function with &rest .
| Calls the system function FUNTABR[b]. The minimum number of arguments is already on the STACK, and m additional arguments as well. The arguments are removed from the STACK. The returned values go into values. |
(CALLC)
| Calls a computed compiled function with no &key .
| Calls the compiled function value1. The right number of
arguments is already on the STACK (including
#<UNBOUND> s in place of absent
&optional parameters). The arguments are
removed from the STACK. The returned values go into
values.
|
(CALLCKEY)
| Calls a computed compiled function with &key .
| Calls the compiled function value1. The right number of
arguments is already on the STACK (including
#<UNBOUND> s in place of absent
&optional or &key
parameters). The arguments are removed from the STACK.
The returned values go into values.
|
(FUNCALL n)
| Calls a computed function. | Calls the function *(STACK+n)
with the arguments *(STACK+n-1), ..., *(STACK+0). STACK += n+1. The returned values go into values. |
(APPLY n)
| Calls a computed function with an unknown number of arguments. | Calls the function *(STACK+n)
with the arguments *(STACK+n-1), ..., *(STACK+0)
and a list of additional arguments value1. STACK += n+1. The returned values go into values. |
mnemonic | description | semantics |
---|---|---|
(PUSH-UNBOUND n)
| Push n #<UNBOUND> s into
the STACK.
| n times do: *--STACK := #<UNBOUND> .values undefined |
(UNLIST n m)
| Destructure a proper list. | 0 <= m <= n. n times do: *--STACK := car(value1), value1 := cdr(value1). During the last m iterations, the list value1 may already have reached its end; in this case, *--STACK := #<UNBOUND> .At the end, value1 must be nil .values undefined |
(UNLIST* n m)
| Destructure a proper or dotted list. | 0 <= m <= n, n > 0. n times do: *--STACK := car(value1), value1 := cdr(value1). During the last m iterations, the list value1 may already have reached its end; in this case, *--STACK := #<UNBOUND> .At the end, after n cdrs, *--STACK := value1. values undefined |
(JMPIFBOUNDP n label)
| Jump to label, if a local variable is not unbound. | If *(STACK+n) is not #<UNBOUND> ,
value1 := *(STACK+n), mv_count := 1, PC := label.
Else: values undefined.
|
(BOUNDP n)
| Load t or nil into values,
depending on whether a local variables is not unbound.
| If *(STACK+n) is not #<UNBOUND> ,
value1 := t , mv_count := 1.
Else: value1 := nil , mv_count := 1.
|
(UNBOUND->NIL n)
| If a local variable is unbound, assign a default value
nil to it.
| If *(STACK+n) is #<UNBOUND> ,
*(STACK+n) := nil .
|
mnemonic | description | semantics |
---|---|---|
(VALUES0)
| Load no values into values. | value1 := nil , mv_count := 0
|
(VALUES1)
| Forget secondary values. | mv_count := 1 |
(STACK-TO-MV n)
| Pop the first n objects from STACK into values. | Load values(*(STACK+n-1),...,*(STACK+0)) into values. STACK += n. |
(MV-TO-STACK)
| Save values on STACK. | Push the mv_count values onto the STACK
(in order: value1 comes first).
STACK -= mv_count. values undefined |
(NV-TO-STACK n)
| Save n values on STACK. | Push the first n values onto the STACK
(in order: value1 comes first).
STACK -= n. values undefined |
(MV-TO-LIST)
| Convert multiple values into a list. | value1 := list of values, mv_count := 1 |
(LIST-TO-MV)
| Convert a list into multiple values. | Call the function values-list with value1
as argument. The returned values go into values.
|
(MVCALLP)
| Start a multiple-value-call invocation. | *--SP := STACK. *--STACK := value1. |
(MVCALL)
| Finish a multiple-value-call invocation. | newSTACK := *SP++. Call the function *(newSTACK-1), passing it *(newSTACK-2), ..., *(STACK+0) as arguments. STACK := newSTACK. The returned values go into values. |
mnemonic | description | semantics |
---|---|---|
(BLOCK-OPEN n label)
| Create a block frame. | Create a block frame, STACK -= 3, SP -= 2+jmpbufsize. The topmost (third) object in the block frame is cons(consts[n],frame-pointer). Upon a return-from to this frame, execution will continue at label. |
(BLOCK-CLOSE)
| Dissolve a block frame. | Dissolve the block frame at STACK, STACK += 3, SP += 2+jmpbufsize. Mark the block-cons as invalid. |
(RETURN-FROM n)
| Leave a block whose block-cons is given. | block-cons := consts[n].
If cdr(block-cons) = #<DISABLED> ,
signal an error. Else cdr(block-cons) is a frame-pointer.
Unwind the stack up to this frame, pass it values.
|
(RETURN-FROM-I k1 k2 n)
| Leave a block whose block-cons is indirectly accessible. | k := k1 + jmpbufsize * k2, block-cons := *(*(SP+k)+n). If cdr(block-cons) = #<DISABLED> ,
signal an error. Else cdr(block-cons) is a frame-pointer.
Unwind the stack up to this frame, pass it values.
|
mnemonic | description | semantics |
---|---|---|
(TAGBODY-OPEN n label1 ... labelm)
| Create a tagbody frame. | Fetch consts[n], this is a
simple-vector with m elements, then decode
m label operands. Create a tagbody frame,
STACK -= 3+m, SP -= 1+jmpbufsize.
The third object in the tagbody frame is
cons(consts[n],frame-pointer).
Upon a go to tag l of this frame, execution
will continue at labell. values undefined |
(TAGBODY-CLOSE-NIL)
| Dissolve a tagbody frame,
and load nil into values.
| Dissolve the tagbody frame at STACK,
STACK += 3+m, SP += 1+jmpbufsize.
Mark the tagbody-cons as invalid. value1 := nil , mv_count := 1.
|
(TAGBODY-CLOSE)
| Dissolve a tagbody frame. | Dissolve the tagbody frame at STACK, STACK += 3+m, SP += 1+jmpbufsize. Mark the tagbody-cons as invalid. |
(GO n l)
| Jump into a tagbody whose tagbody-cons is given. | tagbody-cons := consts[n].
If cdr(tagbody-cons) = #<DISABLED> ,
signal an error. Else cdr(tagbody-cons) is a
frame-pointer. Unwind the stack up to this frame, pass it
the number l.
|
(GO-I k1 k2 n l)
| Jump into a tagbody whose tagbody-cons is indirectly accessible. | k := k1 + jmpbufsize * k2, tagbody-cons := *(*(SP+k)+n). If cdr(tagbody-cons) = #<DISABLED> ,
signal an error. Else cdr(tagbody-cons) is a
frame-pointer. Unwind the stack up to this frame, pass it
the number l.
|
mnemonic | description | semantics |
---|---|---|
(CATCH-OPEN label)
| Create a catch frame. | Create a catch frame, with value1 as tag. STACK -= 3, SP -= 2+jmpbufsize. Upon a throw to this tag execution continues at label. |
(CATCH-CLOSE)
| Dissolve a catch frame. | Dissolve the catch frame at STACK. STACK += 3, SP += 2+jmpbufsize. |
(THROW)
| Non-local exit to a catch frame. | tag := *STACK++. Search the innermost catch frame with tag tag on the STACK, unwind the stack up to it, pass it values. |
mnemonic | description | semantics |
---|---|---|
(UNWIND-PROTECT-OPEN label)
| Create an unwind-protect frame. | Create an unwind-protect frame. STACK -= 2, SP -= 2+jmpbufsize. When the stack will be unwound by a non-local exit, values will be saved on STACK, and execution will be transferred to label. |
(UNWIND-PROTECT-NORMAL-EXIT)
| Dissolve an unwind-protect frame, and start the cleanup code. | Dissolve the unwind-protect frame at STACK. STACK += 2, SP += 2+jmpbufsize. *--SP := 0, *--SP := 0, *--SP := STACK. Save the values on the STACK, STACK -= mv_count. |
(UNWIND-PROTECT-CLOSE)
| Terminate the cleanup code. | newSTACK := *SP++. Load values(*(newSTACK-1), ..., *(STACK+0)) into values. STACK := newSTACK. SPword1 := *SP++, SPword2 := *SP++. Continue depending on SPword1 and SPword2. If both are 0, simply continue execution. If SPword2 is 0 but SPword1 is nonzero, interpret it as a label and jump to it. |
(UNWIND-PROTECT-CLEANUP)
| Dissolve an unwind-protect frame, and execute the cleanup code like a subroutine call. | Dissolve the unwind-protect frame at STACK, get label out of the frame. STACK += 2, SP += 2+jmpbufsize. *--SP := 0, *--SP := PC, *--SP := STACK. Save the values on the STACK, STACK -= mv_count. PC := label. |
mnemonic | description | semantics |
---|---|---|
(HANDLER-OPEN n)
| Create a handler frame. | Create a handler frame, using consts[n] which contains the condition types, the corresponding labels and the current SP depth (= function entry SP - current SP). |
(HANDLER-BEGIN&PUSH)
| Start a handler. | Restore the same SP state as after the HANDLER-OPEN.
value1 := the condition that was passed to the handler,
mv_count := 1. *--STACK := value1. |
mnemonic | description | semantics |
---|---|---|
(NOT)
| Inlined call to NOT. | value1 := not(value1), mv_count := 1. |
(EQ)
| Inlined call to EQ. | value1 := eq(*STACK++,value1), mv_count := 1. |
(CAR)
| Inlined call to CAR. | value1 := car(value1), mv_count := 1. |
(CDR)
| Inlined call to CDR. | value1 := cdr(value1), mv_count := 1. |
(CONS)
| Inlined call to CONS. | value1 := cons(*STACK++,value1), mv_count := 1. |
(SYMBOL-FUNCTION)
| Inlined call to SYMBOL-FUNCTION. | value1 := symbol-function(value1), mv_count := 1. |
(SVREF)
| Inlined call to SVREF. | value1 := svref(*STACK++,value1), mv_count := 1. |
(SVSET)
| Inlined call to SYSTEM::SVSTORE. | arg1 := *(STACK+1), arg2 := *(STACK+0), STACK += 2. svref(arg2,value1) := arg1. value1 := arg1, mv_count := 1. |
(LIST n)
| Inlined call to LIST. | value1 := list(*(STACK+n-1),...,*(STACK+0)), mv_count := 1, STACK += n. |
(LIST* n)
| Inlined call to LIST*. | value1 := list*(*(STACK+n-1),...,*(STACK+0),value1), mv_count := 1, STACK += n. |
FUNCALL&SKIP&RETGF
, whose existence is needed
for generic functions.
mnemonic | equivalent |
---|---|
(NIL&PUSH)
| (NIL) (PUSH)
|
(T&PUSH)
| (T) (PUSH)
|
(CONST&PUSH n)
| (CONST n) (PUSH)
|
(LOAD&PUSH n)
| (LOAD n) (PUSH)
|
(LOADI&PUSH k1 k2 n)
| (LOADI k1 k2 n) (PUSH)
|
(LOADC&PUSH n m)
| (LOADC n m) (PUSH)
|
(LOADV&PUSH k m)
| (LOADV k m) (PUSH)
|
(POP&STORE n)
| (POP) (STORE n)
|
(GETVALUE&PUSH n)
| (GETVALUE n) (PUSH)
|
(JSR&PUSH label)
| (JSR label) (PUSH)
|
(COPY-CLOSURE&PUSH m n)
| (COPY-CLOSURE m n) (PUSH)
|
(CALL&PUSH k n)
| (CALL k n) (PUSH)
|
(CALL1&PUSH n)
| (CALL1 n) (PUSH)
|
(CALL2&PUSH n)
| (CALL2 n) (PUSH)
|
(CALLS1&PUSH b)
| (CALLS1 b) (PUSH)
|
(CALLS2&PUSH b)
| (CALLS2 b) (PUSH)
|
(CALLSR&PUSH m n)
| (CALLSR m n) (PUSH)
|
(CALLC&PUSH)
| (CALLC) (PUSH)
|
(CALLCKEY&PUSH)
| (CALLCKEY) (PUSH)
|
(FUNCALL&PUSH n)
| (FUNCALL n) (PUSH)
|
(APPLY&PUSH n)
| (APPLY n) (PUSH)
|
(CAR&PUSH)
| (CAR) (PUSH)
|
(CDR&PUSH)
| (CDR) (PUSH)
|
(CONS&PUSH)
| (CONS) (PUSH)
|
(LIST&PUSH n)
| (LIST n) (PUSH)
|
(LIST*&PUSH n)
| (LIST* n) (PUSH)
|
(NIL&STORE n)
| (NIL) (STORE n)
|
(T&STORE n)
| (T) (STORE n)
|
(LOAD&STOREC k n m)
| (LOAD k) (STOREC n m)
|
(CALLS1&STORE b k)
| (CALLS1 b) (STORE k)
|
(CALLS2&STORE b k)
| (CALLS2 b) (STORE k)
|
(CALLSR&STORE m n k)
| (CALLSR m n) (STORE k)
|
(LOAD&CDR&STORE n)
| (LOAD n) (CDR) (STORE n)
|
(LOAD&CONS&STORE n)
| (LOAD n+1) (CONS) (STORE n)
|
(LOAD&INC&STORE n)
| (LOAD n) (CALL1 #'1+) (STORE n)
|
(LOAD&DEC&STORE n)
| (LOAD n) (CALL1 #'1-) (STORE n)
|
(LOAD&CAR&STORE m n)
| (LOAD m) (CAR) (STORE n)
|
(CALL1&JMPIF n label)
| (CALL1 n) (JMPIF label)
|
(CALL1&JMPIFNOT n label)
| (CALL1 n) (JMPIFNOT label)
|
(CALL2&JMPIF n label)
| (CALL2 n) (JMPIF label)
|
(CALL2&JMPIFNOT n label)
| (CALL2 n) (JMPIFNOT label)
|
(CALLS1&JMPIF b label)
| (CALLS1 b) (JMPIF label)
|
(CALLS1&JMPIFNOT b label)
| (CALLS1 b) (JMPIFNOT label)
|
(CALLS2&JMPIF b label)
| (CALLS2 b) (JMPIF label)
|
(CALLS2&JMPIFNOT b label)
| (CALLS2 b) (JMPIFNOT label)
|
(CALLSR&JMPIF m n label)
| (CALLSR m n) (JMPIF label)
|
(CALLSR&JMPIFNOT m n label)
| (CALLSR m n) (JMPIFNOT label)
|
(LOAD&JMPIF n label)
| (LOAD n) (JMPIF label)
|
(LOAD&JMPIFNOT n label)
| (LOAD n) (JMPIFNOT label)
|
(LOAD&CAR&PUSH n)
| (LOAD n) (CAR) (PUSH)
|
(LOAD&CDR&PUSH n)
| (LOAD n) (CDR) (PUSH)
|
(LOAD&INC&PUSH n)
| (LOAD n) (CALL1 #'1+) (PUSH)
|
(LOAD&DEC&PUSH n)
| (LOAD n) (CALL1 #'1-) (PUSH)
|
(CONST&SYMBOL-FUNCTION n)
| (CONST n) (SYMBOL-FUNCTION)
|
(CONST&SYMBOL-FUNCTION&PUSH n)
| (CONST n) (SYMBOL-FUNCTION) (PUSH)
|
(CONST&SYMBOL-FUNCTION&STORE n k)
| (CONST n) (SYMBOL-FUNCTION) (STORE k)
|
(APPLY&SKIP&RET n k)
| (APPLY n) (SKIP&RET k)
|
(FUNCALL&SKIP&RETGF n k)
| (FUNCALL n) (SKIP&RETGF k)
|
mnemonic | operand range |
---|---|
(LOAD n)
| 0 <= n < 15 |
(LOAD&PUSH n)
| 0 <= n < 25 |
(CONST n)
| 0 <= n < 21 |
(CONST&PUSH n)
| 0 <= n < 30 |
(STORE n)
| 0 <= n < 8 |
Last modified: 19 September 1998.