Virtual machine definition
Document formatted by vherva at Fri Apr 24 11:23:51 1998 on the host schemestation. This document is produced by the SchemeStation project during the Tik-76.115 course.
| |
1 Introduction | |
SCHEMESTATION virtual machine is supposed to be a multipurpose virtual machine with some specific support for the scheme language. The instruction set has been derived from SICP(*) and HUTScheme (**) virtual machine constructions with some appropriate modifications. The basic architecture of the SCHEMESTATION virtual machine is a register machine (12 general purpose registers) with a garbage collected and list-based (typed) memory (/heap).
| |
2 Registers | |
There are 12 general purpose registers available in the SCHEMESTATION
virtual machine. Registers are named R1-R16. Registers R13-R16 are
reserved for internal use by the message queue (R13), exception handler (R14),
stack (R15) and program counter (R16). Registers R13-R16 should not normally
be tampered with by user programs -- that is, use at your own risk.
Each register holds 64 bits of data and an 8bit type tag. The default
procedure calling convention consists of putting the number of arguments
to register R1, possible first three (3) arguments to registers R2 - R4,
a vector of all other arguments to register R5 and the return value to R6.
This calling convention is used for example in conjunction with the
exception handler. Registers R7 - R9 are callee-saved and registers R10 - R12
caller-saved. The called procedure can modify registers R1 - R6.
| |
3 Instructions | |
The actual instruction numbers are defined elsewhere (SchemeStation VM instruction numbers and argument types).
| |
3.1 Heap | |
| |
3.1.1 ALLOC-INTEGER Rdest | |
Allocate an integer from the heap and put the address of the
integer to Rdest.
| |
3.1.2 ALLOC-FLOAT Rdest | |
Allocate a float from the heap and put the address of the
float to Rdest.
| |
3.1.3 ALLOC-BOOLEAN Rdest | |
Allocate a boolean from the heap and put the address of the
boolean to Rdest.
| |
3.1.4 ALLOC-PAIR Rdest | |
Allocate a pair from the heap and put the address of the
pair to Rdest.
| |
3.1.5 ALLOC-PAIR-TAGGED Rdest, tag | |
Allocate a tagged pair from the heap with tag tag and
put the address of the pair to Rdest.
| |
3.1.6 ALLOC-VECTOR Rdest, Rsize | |
Allocate a vector of size Rsize from the heap and
put the address of the vector to Rdest.
| |
3.1.7 ALLOC-VECTOR-IMMEDIATE Rdest, size | |
Allocate a vector of size size from the heap and
put the address of the vector to Rdest.
| |
3.1.8 ALLOC-VECTOR-TAGGED Rdest, Rsize, tag | |
Allocate a tagged vector of size Rsize and tag
tag from the heap and put the address of the
vector to Rdest.
| |
3.1.9 ALLOC-SHARED-BIT-STRING Rdest, Rsize | |
Allocate a shared bit string of size Rsize from the heap and
put the address of the bit string to Rdest.
| |
3.1.10 ALLOC-SHARED-BIT-STRING-TAGGED Rdest, Rsize, tag | |
Allocate a tagged shared bit string of size Rsize and
tag tag from the heap and put the address of the
bit string to Rdest.
| |
3.1.11 ALLOC-PRIVATE-BIT-STRING Rdest, Rsize | |
Allocate a private bit string of size Rsize from the heap and
put the address of the bit string to Rdest.
| |
3.1.12 ALLOC-PRIVATE-BIT-STRING-TAGGED Rdest, Rsize, tag | |
Allocate a tagged private bit string of size Rsize and
tag tag from the heap and put the address of the
bit string to Rdest.
The difference between shared and private bit strings is the fact that an access to private bit strings generates a copy of the string, but an access to shared bit string references always the same bit string. This means that modifying a shared bit string can be seen from all references of that particular bit string, whereas modifying a private bit string can only be seen from that particular point of access.
| |
3.1.13 INTEGER-SET! Rdest, Rvalue | |
Set the value of Rdest to integer Rvalue.
| |
3.1.14 FLOAT-SET! Rdest, Rvalue | |
Set the value of Rdest to float Rvalue.
| |
3.1.15 BOOLEAN-SET! Rdest, Rvalue | |
Set the value of Rdest to boolean Rvalue.
| |
3.1.16 PAIR-SET-CAR! Rdest, Rsource | |
Set the first element of the pair Rdest to
Rsource.
| |
3.1.17 PAIR-SET-CDR! Rdest, Rsource | |
Set the second element of the pair Rdest to
Rsource.
| |
3.1.18 PAIR-GET-CAR Rdest, Rsource | |
Set the Rdest to the value of the first element of a pair
Rsource.
| |
3.1.19 PAIR-GET-CAR-OR-BLOCK Rdest, Rsource | |
Set the Rdest to the value of the first element of a pair
Rsource, however, if the value of the first element is
null, block execution until it changes value.
| |
3.1.20 PAIR-GET-CDR Rdest, Rsource | |
Set the Rdest to the value of the second element of a pair
Rsource.
| |
3.1.21 VECTOR-SET! Rdest, Rindex, Rvalue | |
Set the Rindexth value in vector Rdest
to Rvalue.
| |
3.1.22 VECTOR-GET Rdest, Rsource, Rindex | |
Put the Rindexth value in vector Rsource
to Rdest.
| |
3.1.23 VECTOR-LEN Rdest, Rsource | |
Set the Rdest to the length of the vector
Rsource.
| |
3.1.24 COPY-PAIR Rdest, Rsource | |
Make a copy of the pair in Rsource to Rdest.
| |
3.1.25 COPY-VECTOR Rdest, Rsource | |
Make a copy of the vector in Rsource to Rdest.
| |
3.1.26 COPY-BIT-STRING Rdest, Rsource | |
Make a copy of the bit string in Rsource to
Rdest.
| |
3.1.27 CONS Rdest, Rcar, Rcdr | |
Make a pair to Rdest with Rcar as
the first item and Rcdr as the second item.
| |
3.2 Register | |
| |
3.2.1 MOVE Rdest, Rsource | |
Move the contents of Rsource to Rdest.
| |
3.2.2 LOAD-IMMED Rdest, index | |
Load a constant value from index (64bit value and 8bit type)
to Rdest. The index is a 24-bit offset to a table of
constants within the binary file
| |
3.2.3 LOAD-NULL Rdest | |
Load a null to Rdest.
| |
3.3 Arithmetic | |
| |
3.3.1 INT-ADD Rdest, Rfirst, Rsecond | |
Integer addition of Rfirst, Rsecond to
Rdest
(Rdest=Rfirst+Rsecond).
| |
3.3.2 INT-SUB Rdest, Rfirst, Rsecond | |
Integer subtraction of Rfirst, Rsecond to
Rdest
(Rdest=Rfirst-Rsecond).
| |
3.3.3 INT-MUL Rdest, Rfirst, Rsecond | |
Integer multiplication of Rfirst, Rsecond to
Rdest
(Rdest=Rfirst*Rsecond).
| |
3.3.4 INT-DIV Rdest, Rfirst, Rsecond | |
Integer division of Rfirst, Rsecond to
Rdest
(Rdest=Rfirst/Rsecond).
| |
3.3.5 INT-MOD Rdest, Rfirst, Rsecond | |
Integer modulo of Rfirst, Rsecond to
Rdest
(Rdest=Rfirst%Rsecond).
Modulo has the sign of Rsecond.
| |
3.3.6 INT-REM Rdest, Rfirst, Rsecond | |
Integer remainder of Rfirst, Rsecond to
Rdest
(Rdest=Rfirst%Rsecond).
Remainder has the sign of Rfirst.
| |
3.3.7 FLOAT-ADD Rdest, Rfirst, Rsecond | |
Float addition of Rfirst, Rsecond to
Rdest
(Rdest=Rfirst+Rsecond).
| |
3.3.8 FLOAT-SUB Rdest, Rfirst, Rsecond | |
Float subtraction of Rfirst, Rsecond to
Rdest
(Rdest=Rfirst-Rsecond).
| |
3.3.9 FLOAT-MUL Rdest, Rfirst, Rsecond | |
Float multiplication of Rfirst, Rsecond to
Rdest
(Rdest=Rfirst*Rsecond).
| |
3.3.10 FLOAT-DIV Rdest, Rfirst, Rsecond | |
Float division of Rfirst, Rsecond to
Rdest
(Rdest=Rfirst/Rsecond).
| |
3.3.11 FLOAT-MOD Rdest, Rfirst, Rsecond | |
Float modulo of Rfirst, Rsecond to
Rdest
(Rdest=Rfirst%Rsecond).
Modulo has the sign of Rsecond.
| |
3.3.12 FLOAT-REM Rdest, Rfirst, Rsecond | |
Float remainder of Rfirst, Rsecond to
Rdest
(Rdest=Rfirst%Rsecond).
Remainder has the sign of Rfirst.
| |
3.3.13 FLOAT-LOG Rdest, Rsource | |
Computes the natural logarithm of Rsource to
Rdest.
| |
3.3.14 FLOAT-LOG10 Rdest, Rsource | |
Computes the base-10 logarithm of Rsource to
Rdest.
| |
3.3.15 FLOAT-EXP Rdest, Rsource | |
Computes the value of e (the base of natural logarithms) raised to the power
of Rsource to Rdest.
| |
3.3.16 FLOAT-SQRT Rdest, Rsource | |
Computes the square root of Rsource to Rdest.
How about LOG, EXP, (A)SIN, (A)COS, (A)TAN, (trigonometric functions in general)? What happens in case of overflow, underflow, etc?
| |
3.4 Bit level | |
Bit level operations are valid only for bit strings.
| |
3.4.1 SHR Rdest, Rtarget, Ramount | |
Shift to right Ramount of bits the value in
Rtarget, set the leftmost Ramount bits
to zero and put the result to Rdest.
| |
3.4.2 SHL Rdest, Rtarget, Ramount | |
Shift to left Ramount of bits the value in
Rtarget, set the rightmost Ramount bits
to zero and put the result to Rdest.
| |
3.4.3 AND Rdest, Rone, Rother | |
Bitwise AND for values of the same type in Rone and
Rother to Rdest.
| |
3.4.4 OR Rdest, Rone, Rother | |
Bitwise OR for values of the same type in Rone and
Rother to Rdest.
| |
3.4.5 XOR Rdest, Rone, Rother | |
Bitwise XOR for values of the same type in Rone and
Rother to Rdest.
| |
3.4.6 NEG Rdest, Rsource | |
Bitwise negation for the value in Rsource to
Rdest.
| |
3.4.7 ROR Rdest, Rtarget, Ramount | |
Rotate to right Ramount of bits the value in
Rtarget and put the result to Rdest.
| |
3.4.8 ROL Rdest, Rtarget, Ramount | |
Rotate to left Ramount of bits the value in
Rtarget and put the result to Rdest.
| |
3.5 Logical | |
Logical operations are valid only for boolean type.
| |
3.5.1 LAND Rdest, Rone, Rother | |
Set Rdest to the logical AND of Rone
and Rother.
| |
3.5.2 LOR Rdest, Rone, Rother | |
Set Rdest to the logical OR of Rone
and Rother.
| |
3.5.3 NOT Rdest, Rsource | |
Set Rdest to the logical NOT of Rsource.
| |
3.5.4 BOOLEAN-NOT Rdest, Rsource | |
Set Rdest to the boolean NOT of Rsource
(#f -> #t, #t -> #f, (non-boolean) -> undefined).
| |
3.6 Control | |
| |
3.6.1 HALT | |
Stop execution.
| |
3.6.2 JUMP Rtarget | |
Continue execution from address specified in Rtarget.
| |
3.6.3 JUMPI target | |
Continue execution from address specified in constant offset target.
| |
3.6.4 BRANCH Rtarget, Rcondition | |
Continue execution from address specified in Rtarget
if Rcondition contains value #f (boolean false).
| |
3.6.5 BRANCHI Rcondition, offset | |
Continue execution from address specified in offset
if Rcondition contains value #f (boolean false).
| |
3.6.6 NOP | |
Do nothing.
| |
3.7 Stack | |
The stack pointer is kept in R11. Note that the stack is defined to be a list made out of pairs. | |
3.7.1 PUSH Rstack, Rsource | |
Push the contents of Rsource to the stack in Rstack | |
3.7.2 POP Rstack, Rdest | |
Remove the topmost element from stack in Rstack
and place it to Rdest.
| |
3.7.3 SAVE Rstack, Rbitmask | |
Push the contents of registers specified in bit string Rbitmask
to the stack in Rstack as a vector containing the bit string
and the contents of the registers. The first element of the vector contains
the bitmap of the saved registers - the rest is implementation specific,
and should not be relied upon.
| |
3.7.4 RESTORE Rstack, Rbitmask | |
Replace the registers specified in bit string Rbitmask from
stack in Rstack (stack should contain a vector formed by
SAVE - if the bit string contains registers which have not been
saved to the vector, they are not replaced).
| |
3.8 Type conversion | |
3.8.1 INT-TO-FLOAT Rdest, Rsource | |
Convert the integer value Rsource into a float value in
Rdest. If Rsource is not an integer,
Rdest is undefined.
| |
3.8.2 FLOAT-TO-INT Rdest, Rsource | |
Convert the float value in Rsource into an integer value in
Rdest. If Rsource is not a float,
Rdest is undefined.
| |
3.8.3 INT-TO-BIT-STRING Rdest, Rsource, Rlen | |
Convert the integer value in Rsource into a bit string in
Rdest with length Rlen. If
Rsource is not an integer,
Rdest is undefined.
| |
3.8.4 BIT-STRING-TO-INT Rdest, Rsource, Rlen | |
Convert the bit string value in Rsource with length
Rlen into an integer value in Rdest.
If Rsource is not a bit string,
Rdest is undefined.
| |
3.9 Tests | |
3.9.1 EQ? Rdest, Rone, Rother | |
Test if the values Rone and Rother
are equal (pointer comparison), result to Rdest.
| |
3.9.2 IS-OF-BOOLEAN? Rdest, Rsource | |
Test if Rsource is of type boolean,
result to Rdest.
| |
3.9.3 IS-OF-INTEGER? Rdest, Rsource | |
Test if Rsource is of type integer,
result to Rdest.
| |
3.9.4 IS-OF-FLOAT? Rdest, Rsource | |
Test if Rsource is of type float,
result to Rdest.
| |
3.9.5 IS-OF-PAIR? Rdest, Rsource | |
Test if Rsource is of type pair,
result to Rdest.
| |
3.9.6 IS-OF-PAIR-TAGGED? Rdest, Rsource | |
Test if Rsource is of type tagged pair,
result to Rdest.
| |
3.9.7 IS-OF-VECTOR? Rdest, Rsource | |
Test if Rsource is of type vector,
result to Rdest.
| |
3.9.8 IS-OF-VECTOR-TAGGED? Rdest, Rsource | |
Test if Rsource is of type tagged vector,
result to Rdest.
| |
3.9.9 IS-OF-PRIVATE-BIT-STRING? Rdest, Rsource | |
Test if Rsource is of type private bit string,
result to Rdest.
| |
3.9.10 IS-OF-PRIVATE-BIT-STRING-TAGGED? Rdest, Rsource | |
Test if Rsource is of type tagged private bit string,
result to Rdest.
| |
3.9.11 IS-OF-SHARED-BIT-STRING? Rdest, Rsource | |
Test if Rsource is of type shared bit string,
result to Rdest.
| |
3.9.12 IS-OF-SHARED-BIT-STRING-TAGGED? Rdest, Rsource | |
Test if Rsource is of type tagged shared bit string,
result to Rdest.
| |
3.9.13 IS-OF-PROCEDURE? Rdest, Rsource | |
Test if Rsource is of type procedure,
result to Rdest.
| |
3.9.14 IS-OF-ACTOR-ADDRESS? Rdest, Rsource | |
Test if Rsource is of type actor address,
result to Rdest.
| |
3.9.15 IS-OF-BYTE-CODE? Rdest, Rsource | |
Test if Rsource is of type byte code,
result to Rdest.
| |
3.9.16 INT-CMP Rdest, Rfirst, Rsecond | |
Integer comparison of Rfirst, Rsecond to
Rdest
(Rdest=Rfirst == Rsecond).
| |
3.9.17 FLOAT-CMP Rdest, Rfirst, Rsecond | |
Float comparison of Rfirst, Rsecond to
Rdest
(Rdest=Rfirst == Rsecond).
| |
3.9.18 INT-GE Rdest, Rfirst, Rsecond | |
Integer greater-or-equal of Rfirst, Rsecond to
Rdest
(Rdest=Rfirst >= Rsecond).
| |
3.9.19 FLOAT-GE Rdest, Rfirst, Rsecond | |
Float greater-or-equal comparison of Rfirst,
Rsecond to Rdest
(Rdest=Rfirst >= Rsecond).
| |
3.9.20 TAG-CMP Rdest, Rtarget, tag | |
Test if Rtarget has a tag tag,
result to Rdest.
| |
3.10 Bit string | |
3.10.1 GET-SUBSTRING Rdest, Rsource, Roffset, Rlength | |
Get substring from Rsource starting from
Roffset of size Rlength and store it to
Rdest.
Rsource -> 1010101 Rdest -> Roffset -> 2 Rlength -> 3 ==> GET-SUBSTRING Rdest, Rsource, Roffset, Rlength ==> Rsource -> 1010101 Rdest -> 101 Roffset -> 2 Rlength -> 3
| |
3.10.2 SET-SUBSTRING Rdest, Rsource, Roffset | |
Set Rsource to be the substring of Rdest
starting from Roffset.
Rsource -> 1010101 Rdest -> 11001100110011 Roffset -> 4 ==> SET-SUBSTRING Rdest, Rsource, Roffset ==> Rsource -> 1010101 Rdest -> 11001010101 Roffset -> 4
| |
3.11 Special | |
| |
3.11.1 CREATE-PROCEDURE Rdest, Raddress, Renv | |
Create a procedure to Rdest with address
Raddress and environment Renv.
| |
3.11.2 CREATE-PROCEDURE-IMMEDIATE Rdest, Renv, address | |
Create a procedure to Rdest with address
address and environment Renv.
| |
3.11.3 GET-ADDRESS Rdest, Rprocedure | |
Put the address of Rprocedure to Rdest.
| |
3.11.4 GET-ENV Rdest, Rprocedure | |
Put the environment of Rprocedure to Rdest.
| |
3.11.5 SEND-MSG Raddr, Rmsg | |
Send message Rmsg to Raddr.
| |
3.11.6 SET-EXCEPTION-HANDLER Rsource | |
Set exception handler to Rsource.
| |
3.11.7 IMM-EXTEND offset | |
| |
4 Exceptions and messages | |
| |
4.1 Exception handling | |
In case of some "abnormal" or asynchronous event occurs, it is called an exception. Exceptions are handled in the exception handler, which can be set to any user defined procedure with SET-EXCEPTION-HANDLER instruction. This procedure should, however, contain the instruction RESTORE VM_REG_STACK, B1111111111111111(restores all registers from stack) as the last instruction of the procedure (Actually, if it is not the last already, it will become due to the fact that the VM_REG_PC is restored also). Parameters are passed to the exception handler with the default calling convention. The return value of the exception handler is not used. If the VM_REG_EXCEPTION -register contain NIL, then exceptions are disabled. Whenever there is an exception and the exceptions are disabled, the running agent is terminated (this is a notable fact for exception handler writers). Exceptions are by default disabled before entering the exception handler (the VM_REG_EXCEPTION is set to NIL).
| |
4.2 Exception types | |
There are several possible exception types and each exception type can have an argument attached. The type of the exception is represented as a bitstring in the exception handler argument. The first phase of the virtual machine handles only messages, exceptions cause the executable to be halted and removed from the system. Here are some of the possible future exceptions described, in addition to the message exception.
| |
4.2.1 MESSAGE | |
The arrival of a message is an asynchronous event. The natural way to handle these events are therefore exceptions. Exceptions and messages are alike, there is no strict distinction between them. There are some "reserved" names for the system's exceptions, but otherwise there is no noticeable difference.
| |
4.2.2 MATH-OVERFLOW | |
4.2.3 MATH-UNDERFLOW | |
4.2.4 MATH-DOMAIN | |
4.2.5 MATH-RANGE | |
4.2.6 MATH-DIVZERO | |
These exceptions are from the arithmetic instructions.
| |
4.2.7 INVALID-ADDRESS | |
The program counter was set to an invalid value.
| |
4.2.8 INVALID-REFERENCE | |
Reference to heap invalid; the attempted reference as a parameter.
| |
4.2.9 INVALID-INSTRUCTION | |
Invalid instruction detected. The bad instruction as a parameter.
| |
5 Types and type tags | |
Type tags:
| |
6 Binary representation of instructions | |
| |
6.1 A proposal | |
All instructions are 32-bit entities (in big-endian representation), where
the highest order byte (bits 24-31) represent the actual instruction number
and the following (preceding) bits the parameters for that particular instruction. Each
register parameter takes 6 bits and they are ordered just like in their
description. Parameters other than registers are defined separately for
each command using them. Exception to this scheme are the immediate type
instructions, which refer to a constant table in the binary file. 32-bit
entity does not provide sufficient amount of bits to address this constant
table, so the instruction IMM-EXTEND extends this address space for each
immediate type instruction with 24 additional bits, if it precedes it, eg.
IMM-EXTEND 1010 1010 1010 1001 1001 0011 LOADI r5, 1001 1010 1001 0101 10 Two consecutive IMM-EXTEND instructions can be provided to extend the indexing capability to full 64bits (first IMM-EXTEND instruction may have few leading obsolete bits depending on how many bits the "real" immediate instruction can provide).
| |
6.1.1 Basic instruction format | |
| |
6.1.2 Instruction with register operands | |
|
© SchemeStation project 1997-1998 | [Back to the document index] |