BLOCK and RETURN-FROMTAGBODY and GOCATCH and THROWUNWIND-PROTECTHANDLER-BIND| mnemonic | description | semantics |
|---|---|---|
( | Load NIL into values. | value1 := NIL, mv_count := 1 |
(PUSH-NIL | Push n NILs into the STACK. | n times do: *--STACK := NIL,
Invalidate values. |
( | Load T into values. | value1 := T, mv_count := 1 |
(CONST | Load the function's nth constant into values. | value1 := consts[n],
mv_count := 1 |
| mnemonic | description | semantics |
|---|---|---|
(LOAD | Load a directly accessible local variable into values. | value1 := *(STACK+n),
mv_count := 1 |
(LOADI | Load an indirectly accessible local variable into values. | k := k1 + jmpbufsize * k2,
value1 := *(*(SP+k)+ n),
mv_count := 1 |
(LOADC | 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 | Load a closed-up variable, defined in an outer function,
into values. | v := venv-const,
m times do: v := SVREF(v,0),
value1 := SVREF(v,m),
mv_count := 1 |
(LOADIC | 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 | Store values into a directly accessible local variable. | *(STACK+n) := value1,
mv_count := 1 |
(STOREI | Store values into an indirectly accessible local variable. | k := k1 + jmpbufsize * k2,
*(*(SP+k)+ n) := value1,
mv_count := 1 |
(STOREC | 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 | Store values into a closed-up variable, defined in an outer function. | v := venv-const,
m times do: v := SVREF(v,0),
SVREF(v,m) := value1,
mv_count := 1 |
(STOREIC | 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 | Load a symbol's value into values. | value1 := symbol-value(consts[n]),
mv_count := 1 |
(SETVALUE | Store values into a symbol's value. | symbol-value(consts[n]) := value1,
mv_count := 1 |
(BIND | Bind a symbol dynamically. | Bind the value of the symbol
consts[n] to value1,
implicitly STACK -= 3,
Invalidate values. |
(UNBIND1) | Dissolve one binding frame. | Unbind the binding frame STACK is pointing to,
implicitly STACK += 3 |
(UNBIND | Dissolve n binding frames. | n times do:
Unbind the binding frame STACK is pointing to, thereby
incrementing STACK
Thus, STACK += 1+2*n |
(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,
Invalidate values. |
| mnemonic | description | semantics |
|---|---|---|
(PUSH) | Push one object onto the STACK. | *--STACK := value1,
Invalidate values. |
(POP) | Pop one object from the STACK, into values. | value1 := *STACK++, mv_count := 1 |
(SKIP | Restore a previous STACK pointer.
Remove n objects from the STACK. | STACK := STACK + n |
(SKIPI | 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,
STACK := STACK + n |
(SKIPSP | Restore a previous SP pointer. | k := k1 + jmpbufsize * k2,
SP := SP+k |
| mnemonic | description | semantics |
|---|---|---|
(SKIP&RET | Clean up the STACK, and return from the function. | STACK := STACK+n,
return from the function, returning values. |
(SKIP&RETGF | 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 | Jump to label. | PC := label. |
(JMPIF | Jump to label, if value1 is true. | If value1 is not NIL, PC := label. |
(JMPIFNOT | Jump to label, if value1 is false. | If value1 is NIL, PC := label. |
(JMPIF1 | Jump to label and forget secondary values,
if value1 is true. | If value1 is not NIL,
mv_count := 1, PC := label. |
(JMPIFNOT1 | Jump to label and forget secondary values,
if value1 is false. | If value1 is NIL,
mv_count := 1, PC := label. |
(JMPIFATOM | Jump to label, if value1 is not a cons. | If value1 is not a cons, PC := label.
Invalidate values. |
(JMPIFCONSP | Jump to label, if value1 is a cons. | If value1 is a cons, PC := label.
Invalidate values. |
(JMPIFEQ | Jump to label, if value1 is EQ to the top-of-stack. | If eq(value1,*STACK++), PC := label.
Invalidate values. |
(JMPIFNOTEQ | Jump to label, if value1 is not EQ
to the top-of-stack. | If not eq(value1,*STACK++), PC := label.
Invalidate values. |
(JMPIFEQTO | Jump to label,
if the top-of-stack is EQ to a constant. | If eq(*STACK++,consts[n]), PC := label.
Invalidate values. |
(JMPIFNOTEQTO | Jump to label, if the top-of-stack is not EQ
to a constant. | If not eq(*STACK++,consts[n]), PC := label.
Invalidate values. |
(JMPHASH | 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.
Invalidate values. |
(JMPHASHV | 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.
Invalidate values. |
(JSR | 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 . |
(JMPTAIL | 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 | Create a SIMPLE-VECTOR used for closed-up variables. | v := new SIMPLE-VECTOR of size n+1.
SVREF(v,0) := value1.
*--STACK := v. Invalidate values. |
(COPY-CLOSURE | Create a closure by copying the prototype and filling in the lexical environment. | f := copy-function(consts[m]).
For i=0,..,n-1:
f_consts[i] := *(STACK+n-1-i).
STACK += n.
value1 := f, mv_count := 1 |
| mnemonic | description | semantics |
|---|---|---|
(CALL | 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 | Calls a constant function with 0 arguments. | The function consts[n] is called with 0 arguments.
The returned values go into values. |
(CALL1 | 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 | 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 | 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 | 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 | 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 &KEYs. | 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 &KEYs. | 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 | 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 | 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 | Push n #<UNBOUND>s into the STACK. | n times do: *--STACK := #<UNBOUND>.
Invalidate values. |
(UNLIST | 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.
Invalidate values. |
(UNLIST* | 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.
Invalidate values. |
(JMPIFBOUNDP | 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: Invalidate values.. |
(BOUNDP | Load T or NIL into values, depending on whether a local
variable is bound. | If *(STACK+n) is not #<UNBOUND>,
value1 := T, mv_count := 1.
Else: value1 := NIL, mv_count := 1. |
(UNBOUND->NIL | 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 |
( | Pop the first n objects from STACK into values. | Load values(*(STACK+n-1),...,*(STACK+0)) into
values. STACK += n. |
(MV-TO- | Save values on STACK. | Push the mv_count values onto the STACK
(in order: value1 comes first).
STACK -= mv_count. Invalidate values. |
(NV-TO- | Save n values on STACK. | Push the first n values onto the STACK
(in order: value1 comes first).
STACK -= n. Invalidate values. |
(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. |
BLOCK and RETURN-FROM| mnemonic | description | semantics |
|---|---|---|
(BLOCK-OPEN | 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) (its block-cons).
Upon a RETURN-FROM to this frame, execution will continue at label.
Invalidate values.. |
(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 | Leave a BLOCK whose block-cons is given. | block-cons := consts[n].
If CDR(block-cons) = #<DISABLED>, an ERROR is SIGNALed.
Else CDR(block-cons) is a frame-pointer.
Unwind the stack up to this frame, pass it values. |
(RETURN-FROM-I | Leave a BLOCK whose block-cons is indirectly accessible. | k := k1 + jmpbufsize * k2,
block-cons := *(*(SP+k)+n).
If CDR(block-cons) = #<DISABLED>, an ERROR is SIGNALed.
Else CDR(block-cons) is a frame-pointer.
Unwind the stack up to this frame, pass it values. |
| mnemonic | description | semantics |
|---|---|---|
(TAGBODY-OPEN | Create a TAGBODY frame. | Fetch consts[m], this is a SIMPLE-VECTOR with
n elements, then decode n label operands.
Create a TAGBODY frame, STACK -= 3+n, SP -= 1+jmpbufsize.
The third object in the TAGBODY frame is
CONS(consts[m],frame-pointer) (the tagbody-cons)
Upon a GO to tag label of this frame, execution
will continue at labell.
Invalidate values. |
(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 | Jump into a TAGBODY whose tagbody-cons is given. | tagbody-cons := consts[n].
If CDR(tagbody-cons) = #<DISABLED>, an ERROR is SIGNALed.
Else CDR(tagbody-cons) is a frame-pointer. Unwind the stack up
to this frame, pass it the number label. |
(GO-I | Jump into a TAGBODY whose tagbody-cons is indirectly
accessible. | k := k1 + jmpbufsize * k2,
tagbody-cons := *(*(SP+k)+n).
If CDR(tagbody-cons) = #<DISABLED>, an ERROR is SIGNALed.
Else CDR(tagbody-cons) is a frame-pointer. Unwind the stack up
to this frame, pass it the number label. |
| mnemonic | description | semantics |
|---|---|---|
(CATCH-OPEN | 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. |
UNWIND-PROTECT| mnemonic | description | semantics |
|---|---|---|
(UNWIND-PROTECT-OPEN
| 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. |
HANDLER-BIND| mnemonic | description | semantics |
|---|---|---|
(HANDLER-OPEN | 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 (. | arg1 := *(STACK+1),
arg2 := *(STACK+0), STACK += 2.
SVREF(arg2,value1) :=
arg1.
value1 := arg1,
mv_count := 1. |
(LIST | Inlined call to LIST. | value1 := LIST(*(STACK+n-1),...,*(STACK+0)),
mv_count := 1, STACK += n. |
(LIST* | Inlined call to LIST*. | value1 := LIST*(*(STACK+n-1),...,
*(STACK+0),value1),
mv_count := 1, STACK += n. |
The most frequent short sequences of instructions have an
equivalent combined instruction. They are only present for space and
speed optimization. The only exception is
FUNCALL&SKIP&RETGF, which is needed for
generic functions.
| mnemonic | equivalent |
|---|---|
(NIL&PUSH) | (NIL) (PUSH) |
(T&PUSH) | (T) (PUSH) |
(CONST&PUSH | (CONST |
(LOAD&PUSH | (LOAD |
(LOADI&PUSH | (LOADI |
(LOADC&PUSH | (LOADC |
(LOADV&PUSH | (LOADV |
(POP&STORE | (POP) (STORE |
(GETVALUE&PUSH | (GETVALUE |
(JSR&PUSH | (JSR |
(COPY-CLOSURE&PUSH | (COPY-CLOSURE |
(CALL&PUSH | (CALL |
(CALL1&PUSH | (CALL1 |
(CALL2&PUSH | (CALL2 |
(CALLS1&PUSH | (CALLS1 |
(CALLS2&PUSH | (CALLS2 |
(CALLSR&PUSH | (CALLSR |
(CALLC&PUSH) | (CALLC) (PUSH) |
(CALLCKEY&PUSH) | (CALLCKEY) (PUSH) |
(FUNCALL&PUSH | (FUNCALL |
(APPLY&PUSH | (APPLY |
(CAR&PUSH) | (CAR) (PUSH) |
(CDR&PUSH) | (CDR) (PUSH) |
(CONS&PUSH) | (CONS) (PUSH) |
(LIST&PUSH | (LIST |
(LIST*&PUSH | (LIST* |
(NIL&STORE | (NIL) (STORE |
(T&STORE | (T) (STORE |
(LOAD&STOREC | (LOAD |
(CALLS1&STORE | (CALLS1 |
(CALLS2&STORE | (CALLS2 |
(CALLSR&STORE | (CALLSR |
(LOAD&CDR&STORE | (LOAD |
(LOAD&CONS&STORE | (LOAD |
(LOAD&INC&STORE | (LOAD |
(LOAD&DEC&STORE | (LOAD |
(LOAD&CAR&STORE | (LOAD |
(CALL1&JMPIF | (CALL1 |
(CALL1&JMPIFNOT | (CALL1 |
(CALL2&JMPIF | (CALL2 |
(CALL2&JMPIFNOT | (CALL2 |
(CALLS1&JMPIF | (CALLS1 |
(CALLS1&JMPIFNOT | (CALLS1 |
(CALLS2&JMPIF | (CALLS2 |
(CALLS2&JMPIFNOT | (CALLS2 |
(CALLSR&JMPIF | (CALLSR |
(CALLSR&JMPIFNOT | (CALLSR |
(LOAD&JMPIF | (LOAD |
(LOAD&JMPIFNOT | (LOAD |
(LOAD&CAR&PUSH | (LOAD |
(LOAD&CDR&PUSH | (LOAD |
(LOAD&INC&PUSH | (LOAD |
(LOAD&DEC&PUSH | (LOAD |
(CONST&SYMBOL-FUNCTION | (CONST |
(CONST&SYMBOL-FUNCTION&PUSH | (CONST |
(CONST&SYMBOL-FUNCTION&STORE | (CONST |
(APPLY&SKIP&RET | (APPLY |
(FUNCALL&SKIP&RETGF | (FUNCALL |
| These notes document CLISP version 2.49 | Last modified: 2010-07-07 |