Sirius Virtual Machine Specification

Version 1.6

Last modification: 27-August-2009

Overview
         
The Sirius Virtual Machine (SVM) is a hypothetical CPU, implemented in software.  As such, it is portable between various hardware platforms.  It was originally developed to run DOS Sirius programs, but SVM is not tied to features of the Sirius programming language.  Some of the advanced features directly support high-level languages, but the base system is a general-purpose machine suitable as a target by any compiler.  Data types directly supported are strings (0 to 255 bytes each), integers (1 to 8 bytes each), and pointers.
         
SVM is a flexible architecture that provides a general-purpose scripting ability for use in other applications.  It can also serve as a stand-alone program executor.
         
SVM has built-in memory management features, such as paging, which allow programs much larger than physical memory to be executed.  Programs are paged in from disk as needed by the interpreter.  Each page is 256 bytes in length.  Code pages use a memory-resident cache to improve response time.  Data is non-paged and occupies segments no larger than 32K contiguous bytes each.  All data and stack memory is a linear byte-addressable address range. Separate code and data address spaces prevents code corruption due to user program bugs.
         
Debugging support may be built into the run-time system, but is implementation dependent.
         
Instructions for the virtual machine are all one-byte operation codes, some of which have one or more additional operand bytes.  Support for relative code addressing allows compact and position-independant code.  Besides general-purpose operations, the instruction set also provides array bounds checking and RTTI (Run Time Type Information) support.  The instruction set provides for a user-extended instruction set which allows further customization of SVM.
         
This specification is organized into seven sections: "Virtual Machine Architecture", "File Formats", "Instruction Set", "Virtual Functions", “API”, "Callable SDK", and "SVM Compiler Backend".  The first describes the features of the Virtual Machine that are significant for application programmers.  The second describes SVM file formats.  The third describes the Virtual Machine's set of instructions.  The fourth describes the standard callable library (implemented as functions with addresses but only requiring one byte of the code space).  The fifth describes the API of the classes used by SVM.  The sixth section describes the callable Software Development Kit.  The seventh section describes the Compiler-backend support for SVM.

Change history

V1.6 of the specification adds the callable SDK, the compiler back-end, clarifies some text, and includes symbol file information.

VIRTUAL MACHINE ARCHITECTURE
    
This section describes the SVM application-programming environment as seen by programmers writing compilers to target the architecture.

Memory Usage
    
There are three separate memory spaces in the SVM - one for code, one for stack, and one for data.  Each memory space can be viewed as a sequence of (8-bit) bytes with no word-boundary constraints.  Each byte is assigned a unique address ranging from 0 to the maximum.  Data and Stack can each be up to 1 Gb in size.  Since data is stored in non-paged memory, the 1 GB data space is largely theoretical.
    
Because of the paging of executable code, the program code can be up to 2^64 bytes in length and only what is needed at the time will be kept in memory.
    
All linked-in sharable libraries will occupy a portion of the application's data and code space.  Calls to them also use stack space.

Stack

Calls create a stack frame in the stack memory for each call.  This allows recursion and local variables.  The current stack frame is the area of the stack bounded by the Stack Frame and Stack Pointer registers.  Local data is stored within the current stack frame and referenced by relative offsets from the base of the stack frame, which is the address in the Stack Frame register.  The previous stack frame ends at the Stack Frame.  Thus, positive offsets from the Stack Frame access the current stack frame and negative offsets reference the previous stack frame.  Parameters passed are stored in the top of the previous stack frame.    Note that all previous stack frames have the previous Program Counter and Stack Frame register values at the end, so references to parameters must be 16 less than the offset otherwise expected.  See the CALL and EXIT instructions for details on how stack frames are automatically managed.

Data Types
    
Bytes, words, longwords, and quadwords are the fundamental units which the SVM uses to manipulate data.  A byte is 8 contiguous bits, numbered 0 to 7 (bit 7 being the most significant).  A word is defined as two contiguous bytes, with the least significant byte at the lower of the two-byte addresses.  A longword is defined as four contiguous bytes, with the least significant byte in the lowest byte address and the most significant byte in the highest byte address. A quadword is defined as eight contiguous bytes, with the least significant byte in the lowest byte address and the most significant byte in the highest byte address.  Note that there are no address alignment issues (i.e. the word, longword, or quadword can start on any odd or even byte address).  The relationship of word alignment and performance is entirely dependent upon the actual underlying hardware implementation.
    
Although Bytes, Words, Longwords, and Quadwords are the fundamental data types, the SVM also supports integers, strings, and pointers.  Note that pointers are simply longwords which are used as indirect references to data addresses.
    
Integers are binary numeric values contained in one to eight bytes.  All operations assume a 2's complement representation.  Integers may be signed or unsigned, except for 8-byte integers, which cannot be unsigned.
    
Strings are contiguous sequences of bytes containing a length byte and from 0 to 255 data bytes.  Data byte offset 0 is at the address immediately above the length byte.  Each data byte corresponds to an ASCII character.

Registers
    
The SVM is a stack-based architecture and supplies very few registers.  Those provided are not available to the application programmer.  However, they are described here since the programmer can observe their effects.
    
The Program Counter (PC) is the address of the next code byte to fetch.  At anytime, it may point to an op-code or operand.
    
The Stack Pointer (SP) is the address of the next stack address, relative to the base of the stack area.  Each PUSH or POP instruction implicitly uses and modifies the value in this register.
    
The Stack Frame (SF) is the base stack address for the current stack frame.  Each call instruction implicitly creates a stack frame on the stack, with the SF pointing to the base of the frame.
    
The Temp register is used for the creation and concatenation of strings.  It is the only register directly accessible via instructions, although its contents are not.

Input/Output
    
I/O in the SVM is accomplished solely through virtual functions or direct memory access.

Integration

Though SVM is a virtual machine, programs running on it can interface with the physical machine that SVM is running on.  The exact mechanism for this is implementation-dependant.  When this occurs, the program running on the physical machine is referred to as "native" code.  Calls to and from native code will translate between virtual and physical data automatically.

Note that when the stack grows (due to calls), its physical location in memory may shift as it is reallocated.  Thus, it is not recommended that a physical stack address be passed to any native routines if it is possible for the stack to grow between references to a given location.

SDK

SVM supports both the simple program model, where source code is turned directly into an SVM executable, and the traditional model, where multiple source files are converted into object modules, which are then linked into a final executable.  SVM provides an asembler, linker, and librarian to facilitate a flexible and powerful development environment.

SVM supports both static linking, using the linker, and dynamic (run-time) linking via Sharable Libraries.  

The SDK is described in greater detail in the section titled "Callable SDK".

Symbol Flags

Symbol information is used in various places, including RTTI and debug symbol files used by the SVM engine itself, and in symbol tables used by the linker, back-end, and the SVM.  Although the format of various symbol records can vary, when they have symbol flags, they have a consistent meaning, as follows(bolded values are essential to linker operation):

Bit value	Meaning
1	SMU routine or variable used
2	Literal
4	Global
8	External
16	Defined label
32	Referenced label
64	Constant
128	Predefined
256	Function
512	Pass By Reference
1024	Memory
2048	Left Unary Operator
4096	Right Unary Operator
8192	Pass RTTI
16384	Pass only LValue
32768	Dynamic
65536	Native
131072	Compile-Time

FILE FORMATS

This section describes the format of files used by the SVM.  Note that, unless otherwise indicated, numeric values are 2's-complement signed integers with little-endian layout.

Binary File Format
    
The default binary (program image) file extension is .BIN.  The default extension for sharable libraries is .SSL.  The header for a .BIN or .SSL file is the first 256 bytes of the file.

Header for .BIN and .SSL files:
    
Byte offset(s) 	Meaning	
0	Prefix.  Must be 255	
1	ID.	
2	OK flag (0=OK, anything else=bad file format).	
3	Version (15=1.5).	
4 	1 (indicates SVM).	
5	File format (0=.SOB,1=.BIN, 3=.SSL).	
6-13	Absolute code size in bytes, including header.	
14-21	Starting execution address.	
22-25	Flags.  See the discussion of Symbol Flags in the Virtual Machine Architecture section.	
26-33	Compile/Link time (not used)	
34-37	Data segment size	
38-41	Size of initialized data within data segment.	
42-45	Manifest size, in bytes.	
46-255	Reserved (should be 0).	
    
The file layout is as follows:

Executable	0-n bytes.  When a BIN file is bound into an executable, the executable image precedes the binary file.	
Header	256 bytes.  Described above.	
Code	0-N bytes (multiple of 256 bytes)	
Data	0-N bytes (multiple of 256 bytes)	
Symbols	0-N bytes (multiple of 256 bytes)	
Manifest	0-N bytes.  Described below.	
Internal file	0-n bytes.  Reserved for future use.	

The symbols area of the file is a symbol table containing external and global symbol definitions.  Each 256-byte block contains 8 32-byte records with the following layout:

Offset	Size	Description	
0	17	Symbol name.  The first byte is the length (max 16), the remaining n bytes are the name in ASCII form.	
17	4	Address of symbol.	
21	4	Flags.  See the discussion of Symbol Flags in the Virtual Machine Architecture section.	
25	2	Data type (the actual type is a sum of one or more of the following):

Value    Meaning
  0      Undefined
  1      Logical
  2      String
  3      Numeric
  4      Procedure
  5      User
  6      List
  3      Integer
  7      Ncm
 10      Fixed String
 11      Real
 12      Generic Pointer
 14      Stack
 15      New Module
 19      Rational
 20      Other Pointer
 23      Type
 27      Fixed
 30      Queue
 31      Void
 35      Imaginary
 38      Array
 43      IMRAT
 46      Sparse Array
 51      Complex
 54      Record (structure)
 59      Comrat
 62      External File
 70      Internal File
131      Packed	
27	1	0 = unsigned, 1 = signed.  Applies only to numeric types.	
28	2	Data size, in bytes.	
30	2	Filler	

The symbol table is of arbitrary length.  Its end is the first 32-byte record which is all 0s.  The symbol table always starts immediately after the Data area.

The manifest can be considered a secondary arbitrary-sized header.  It contains a stream of variable-length records which define additional information about the file.  Each record begins with a single byte record identifier, followed by some number of bytes of data.  Most records contain a data field which contains data specific to that record ID.  In the case of a length value, the length value is 1 or 2 bytes, interpreted as a 0-255 or 0-65535 byte length, respectively.  That many bytes of data then follow.

The following manifest records are defined:

Record ID	Data field	Description	
0	None	Null record.  Next record immediately follows.	
1	2-byte length	VM extension.  Following is a 2-byte length value indicating the length of the data field, and then a data field of that length.  This data field contains the filename of a virtual machine extension to load.  All VM extensions are loaded prior to execution of the code.	
2	1-byte length	User Attribute.  Following is a 1 byte length, followed by a string identifier of that length, followed by a 2-byte length, followed by data of that length.	
3-254		Reserved	
255	2-byte length	Reserved for user.  The SVM will ignore these records.	

Symbol File Format

The default symbol file extension for object files is .SYM.  The default symbol file extension for binary files is .DBG.  Symbol files contain information about mneumonic symbols used in the original source files.  Symbol files are optional - being used to provide debugging information to the virtual machine.  The linker combines zero, one, or more, symbols files into a single symbol file associated with the output binary file.

The SVM symbol file layout is a series of variable-length records.  Each record begins with a 1 byte record type indicator.  The size, content, and meaning of the following record depends upon the type.  The next record begins immediately after the end of the preceding record without any padding.  The first record is a header record, of which there should only be one.  The EOF record defines the logical end of the symbol file.

Many records contain a datatype specification, which has the following layout:

Item	Size	Description	
ID	2	Type of data:
0 = Real
1 = Fixed-point
2 = String
3 = Integer	
Signed	1	True if signed numeric value.	
Size	2	Size of data type, in bytes.	
Variant1	2	For Reals: this is the mantissa size, in bytes.
For Fixed: this is the whole part size, in bytes.
For Strings: this is the length of the string (0=dynamic)
unused for all other types.	
Variant2	2	For Reals: this is the exponent size, in bytes.
For Fixed: this is the fractional part size, in bytes.
unused for all other types.	

Symbol file record types:

Record type	Size	Description	
0	1	EOF	
1	27	Header	
2	2-256	File	
3	14	Line	
4	17-271	Symbol	
5	2-256	Type name	
6	12	Type	
7	3	Record	
8	12	Array	
9	5	Subscript	
10	10	Procedure	
11	10	Parameter	
12	10-234	Module	
13	2	Constant	
14+		reserved for future use.	

Any code that attempts to parse a symbol file should read a single byte to get the type, then read the minimal size for that record.  Then, for variable-sized records, read the remainder of the record.

The individual record types are now described:  Note that the EOF and Header records only occur once, each, in the file.  The header appears at the beginning of the file, and EOF at the logical end of the file.  Any number of File or Line records may occur and they may occur anywhere in the file.

EOF
This record contains nothing other than the record type byte of 0.

Header
This record defines basic information about the symbol file:

Item	Size	Description	
Version	1	The version of the specification with which this file complies, times 10.  For instance, a valud of 16 means Version 1.6.	
Date/Time	8	A Sirius timestamp.  This should match the timestamp in the header of the associated binary file.  Used to verify that the symbol file is valid for a given binary file.	
Validation	17	A byte of 13 followed by "Sirius Symbol".  Used to validate that this is a valid symbol file.	

File
This record contains the name of a file.  The first file record encountered is referenced as file index 0, the second as index 1, and so on.  The record contains a length byte, followed by that many bytes of text.  Note that up to 65536 total files can be referenced.

Line
This record maps source file line numbers to addresses in the binary.

Item	Size	Description	
Address	8	Beginning address in binary for this line.	
Line	4	Line number in file.	
File index	2	Index of file to which this applies.	

Module
This record only appears in symbol files generated by the linker and provides information at the module level.

Item	Size	Description	
Address	4	Beginning address in binary for this module.	
Name	2-256	A length byte followed by that many bytes of a module name.	

Symbol
This record provides information about a symbol.  Symbol records may be followed by one, or more, records that provide additional information about the symbol.  None of the following records will be found without an associated Symbol record.

Item	Size	Description	
Address	4	Data address for symbol.	
Datatype	9	Type information.	
Flags	2	Symbol flags.	
Name	2-256	A length byte followed by the symbol name.	

Typename
This record follows a Symbol record if the symbol indicated a type of Type_User.  It consists of a length byte, followed by that number of bytes of name.

Type
This record follows a Symbol record if the symbol indicated a type of Type_Type.

Item	Size	Description	
Index	2	Unique user-type index.  Defined by compiler.	
Datatype	9	Internal type of data.	

Record
This record follows a Symbol record if the symbol indicated a type of Type_Record.  It consists of a single 2-byte value indicating how many components are in the record.  The record will then be followed by that many Symbol records, one for each component in the record.

Array
This record follows a Symbol record if the symbol indicated a type of Type_Array.

Item	Size	Description	
Count	2	Number of subscripts in array.  This record will then be followed by this many Subscript records, one per subscript.	
Datatype	9	Data type of each element.	

Procedure
This record follows a Symbol record if the symbol indicated a function or procedure.

Item	Size	Description	
Address	8	Address of routine.	
Count	2	Number of parameters.  This record will then be followed by this many Parameter reords.	

Subscript
This record follows an Array record.

Item	Size	Description	
Low	2	Low bound of subscript.	
High	2	High bound of subscript.	

Parameter
This record follows a Procedure record.  It consists of a 9-byte Datatype.

Constant
This record follows a Symbol record with a symbol flag indicating a constant.  The record consists of a length byte followed by that many byte of text indicating the value of the constant.

INSTRUCTION SET
    
This section describes the SVM instruction set.  All possible operand types are described here.  Compiled code is a stream of one-byte operation codes (opcodes) and 0 or more operand bytes.  Execution begins when the SVM is told to execute starting at a specific code address.  Once an address is selected, the SVM reads a byte (assumed to be an op-code) and acts upon it.  There may or may not be operand data following the op-code.  SVM instructions move data, do arithmetic, convert data types, test and compare values, and transfer control. The following table defines the op-codes and their operands (if any).  The instructions are described in detail later in this section.
    
Op-codes
    
Number	Mnemonic	Meaning 	Operand	Comments	
 0	NULL	Null operation			
 1	EXIT	EXIT			
 2	STOP	STOP			
 3	END	END			
 4	ZERO	Zero Temp			
 5	CONT	Concatenate top of stack to Temp			
 6	CONL	Concatenate literal to Temp	Byte length, 0-255 bytes data		
 7	STOREDL	Store Temp direct	Longword address		
 8	CALLB	Call routine	Byte address	This reads a byte and calls a run-time routine as defined by that byte.  The possible routines are described in the "Virtual Functions" section.	
 9 	CALLW	Call routine 	Word address		
10	CALLL	CALL  	Longword address		
11	CALLQ	Call quadword	Quadword address		
12	RCALLB	Call Byte Relative			
13	RCALLW	Call Word Relative			
14	RCALLL	Call Long Relative			
15	RCALLQ	Call quadword relative.	Quadword address		
16	reserved				
17 	GOTOW	GOTO 	Word address		
18	GOTOL	GOTO 	Longword address		
19	GOTOQ	Go to quadword address	Quadword address		
20	RGOTOB	Go to Byte Relative			
21	RGOTOW	Go to Word Relative			
22	RGOTOL	Go to Long Relative			
23	RGOTOQ	Go to relative quadword address	Quadword address		
24-25	reserved				
26	IF	IF...THEN 	Longword address (false)		
27	IFQ	IF...THEN	Quadword address
(false)		
28-29	reserved				
30	RIF	If Relative	Longword address		
31	RIFQ	IF...THEN	Quadword address
(false)		
32 	PUSHIB	Push immediate 	Byte data		
33 	PUSHIW	Push immediate 	Word address		
34	PUSHIL	Push immediate	Longword constant		
35-48	Reserved				
49 	PUSHDW	Push direct 	Word address		
50	PUSHDL	Push direct 	Longword address		
51-56	Reserved				
57	SKIP1	Skip the next instruction byte.			
58	SKIP2	Skip the next 2 instruction bytes.			
59	SKIP3	Skip the next 3 instruction bytes.			
60	SKIP4	Skip the next 4 instruction bytes.			
61	SKIP5	Skip the next 5 instruction bytes.			
62	SKIP6	Skip the next 6 instruction bytes.			
63	Reserved				
64	ADDI	Add Integer			
65	ADDW	Integer (word) add			
66	ADDL	Add Long			
67-71	Reserved				
72	DIVI	Divide Integer			
73	DIVW	Integer (word) divide			
74	DIVL	Divide Long			
75-79	Reserved				
80	MULI	Multiply Integer			
81	MULW	Integer (word) multiply			
82	MULL	Multiply Long			
83-87	Reserved				
88	SUBI	Subtract Integer			
89	SUBW	Integer (word) subtract			
90	SUBL	Subtract Long			
91-95	Reserved				
96	DEREFI	Dereference Integer			
97	Reserved				
98	DEREF	Dereference (longword)			
99-103	Reserved				
104	NEGSI	Negate top of stack integer			
105 	NEGIS	Negate Stack (word)			
106-114	Reserved				
115	PROWL	Promote Word To Long			
116-127	Reserved				
128	CONVERT	Convert Number			
129	CREATE	Create string from Temp			
130	CONS	Concatenate strings on stack			
131	COPY	Copy strings from stack			
132	CALLV	Call Vector			
133	ZEROS	Zero String			
134	RANGE	Range Check			
135	RCOPY	Reverse Copy Strings			
136	CALLD	Call Dynamic	Longword	Calls a routine in a sharable library.	
137	CALLN	Call Native	Longword	Calls a native function on the runtime platform.	
138	NOTS	NOT top of stack			
139 	ANDS	AND top of stack			
140	NANDS	NAND top of stack			
141	ORS	OR top of stack			
142 	NORS	NOR top of stack			
143	XORS	XOR top of stack			
144	XNORS	XNOR top of stack			
145	PUSH0	Push Zeroes	Word count		
146	PUSHILA	Push immediate longword address	Longword address		
147	PUSHITA	Push immediate type address	Longword address		
148	POPS	Pop To Stack			
149	PUSHIN	Push n Immediate			
150	PUSHNL	Push n bytes 	byte size - Long address		
151	PUSHNW	Push n bytes	byte size - Word address		
152	POPNW	Pop n bytes	byte size - Word address		
153	POPNSIL	Pop n To Stack Indirect Long			
154	EXPI	Exponent Integer			
155	FACI	Factorial Integer			
156	COPYNI	Copy n bytes Indirect			
157	PERI	Percent Integer			
158	CALLIL	Call Long Indirect			
159	POPDL	Pop direct 	Longword address		
160	POPDW	Pop direct 	Word address		
161 	POPN	Pop n bytes			
162	POPNL	Pop n bytes 	byte size - Long address		
163	POP	Pop stack			
164-191	Reserved				
192	NEM	Memory Compare NE			
193	EQM	Memory Compare EQ			
194	LTM	Memory Compare LT			
195	GTM	Memory Compare GT			
196	LEM	Memory Compare LE			
197	GEM	Memory Compare GE			
198-199	Reserved				
200	NEI	Integer compare <>	Byte size		
201	EQI	Integer compare =	Byte size		
202 	LTI	Integer compare <	Byte size		
203	GTI	Integer compare >	Byte size		
204	LEI	Integer compare <= 	Byte size		
205	GEI	Integer compare >=	Byte size		
206-207	Reserved				
208	NES	String compare <>			
209	EQS	String compare =			
210	LTS	String compare <			
211 	GTS	String compare >			
212	LES	String compare <=			
213	GES	String compare >=			
254-253	Reserved				
254	EXT	Extension	Next byte is an extension op-code.	Reserved for future extensions to the SVM op-code set.	
255	UEXT	User Extension		Used to extend/customize the SVM op-code set.	

RTTI
    
SVM supports Run-Time Type Information in the form of read-only records in the program dataspace.  Certain Run Time routines use RTTI.  Given the base address of RTTI information for a specific parameter, the following data is stored:
    
Byte(s)	Description	
0-1	Type ID.  Currently ignored.  This field may be supported in future versions of the SVM.  Therefore, this should be set, as follows:

Type     Value
String   2
Integer  3
NCM      7
Pointer  12
File     62	
2	0 if unsigned, <> 0 if signed (integers only).	
3	Size in bytes (integers only)	

Parameter Passing Mechanism
    
Routines are called with parameters passed on the stack.  The parameter passing mechanism, from top of stack towards bottom, is as follows:
    
Last parameter
.
.
.
Second parameter
First parameter

For functions which take a variable number of parameters, the stack looks like this:
    
Parameter count (byte)
Last parameter (RTTI address)
Last parameter (data address)
.
.
.
Second parameter (RTTI address)
Second parameter (data address)
First parameter (RTTI address)
First parameter (data address)

Data Address Specifications

Each 32-bit SVM data address is split into an addressing mode and an offset, as described in the following table.  Note that the maximum data area is 2^30 bits, or just over 1 billion addresses.   This scheme also limits the range of addresses that can be accessed from the stack to 1 billion bytes around the stack frame.

Bits	Description	
31-30	Addressing mode for normal data:
bit 31    bit 30    Meaning
------    ------    -------
0         0         Normal data address.
0         1         Stack-frame relative address (SF+offset)
1         0         not used/not valid.
1         1         Stack-frame relative address (SF-offset)

Addressing mode for Data Type references:
bit 31    bit 30    Meaning
------    ------    -------
0         0         Normal data address.
0         1         reserved for future use.
1         0         Pass by reference.
1         1         Pass by reference.	
29-0	Offset in data area.	

Instructions
    
        The following sections define the SVM instructions.

Call
Mnemonic	Opcode	Description	
CALLL	10	Call to immediate absolute longword address. A call to an absolute address will result in execution continuing at that address.	
CALLW	9	Call to immediate absolute word address. 	
CALLB	8	Call to immediate absolute byte address	
RCALLL	14	Call to relative longword address	
CALLIL	158	Call to indirect longword address. Calls to the absolute longword address on the top of the stack.	
RCALLW	13	Call to relative word address. A call to a relative address is a call to a positive or negative offset from the address of the instruction immediately following the call instruction.	
RCALLB	12	Call to relative byte address. A call to a relative address is a call to a positive or negative offset from the address of the instruction immediately following the call instruction.	
CALLV	132	Call vector. A call to a vector takes a word value and calls to the specified vector. Note that this requires a customized interpreter which creates a vector table.	
CALLQ	11	Call to quadword address.	
RCALLQ
	15	Call to relative quadword address. A call to a relative address is a call to a positive or negative offset from the address of the instruction immediately following the call instruction.	
CALLD	136	Call dynamic. A call to a dynamic address is a call to a routine in a Sirius Sharable Library (SSL) file. Beyond that difference, the two operate the same way.  The destination address is determined at the time of the call since the actual absolute address may vary from run to run of the program.  The operand is a longword absolute address of a dynamic routine vector.  The dynamic routine vector specifies the name of the file and the absolute address once the file is loaded into the program's virtual code space. The first time the routine is called, the dynamic routine vector is loaded with the absolute address, which requires a lookup in the SSL or DLL file for the specified routine.  If the SSL or DLL file is not loaded, it is loaded first.  The dynamic routine vector is defined below.	
CALLN	137	Call native. A call to a native address.  On windows, this is a call to a routine in a Windows Dynamic Link Library (DLL) file.  Other than that, this functions exactly as Call Dynamic. Note that DLLs do not require SVM virtual code space.	

All Call instructions, except CALLD and CALLN, push the program counter and stack frame to the stack and then set the program counter to the appropriate address and continue execution there.  Upon encountering an Exit instruction, the program execution will continue with the instruction immediately following the Call instruction.  The operation of a call is as follows:
1.	Push Program Counter
2.	Push Stack Frame
3.	Set Stack Frame to current Stack Pointer
4.	Call to routine

A relative address is a positive or negative offset from the address which immediate follows the op-code and the offset.
    
Dynamic/native routine vector layout:

Byte(s) 	Description	
0-3	Absolute address of routine (0 until loaded)	
4	Length of routine name	
5-n 	ASCII value of routine name	
n+1	Length of library name	
n+2+	ASCII value of library name	

    
End
Mnemonic	Opcode	Description	
END	3	End (same as Stop).	

This instruction is exactly the same as the Stop instruction.  It is used to inform the linker as to the physical end of a module.

    
Exit
Mnemonic	Opcode	Description	
EXIT	1	Returns from a called routine.	

This pops the stack frame and program counter from the stack, which effectively continues execution after the previously executed Call instruction.  The operation of the exit is as follows:
1.	Set Stack Pointer to current value of Stack Frame.  This effectively clears the current stack frame.
2.	Pop Stack Frame from stack.  This makes the previous stack frame the current stack frame.
3.	Pop Program Counter from stack.
4.	Continue execution from new Program Counter.

    
Goto
Mnemonic	Opcode	Description	
GOTOL	18	Go to immediate absolute longword address	
GOTOW	17	Go to immediate absolute word address	
GOTOQ	19	Go to immediate absolute quadword address.	
RGOTOB	20	Go to immediate relative byte offset	
RGOTOL	22	Go to immediate relative longword offset	
RGOTOW	21	Go to immediate relative word offset	
RGOTOQ	23	Go to immediate relative quadword address.	

This transfers program control to another address.  If given an absolute address, the program counter is set to that address and the instruction at that address is the next one executed.  A relative address is a positive or negative offset from the address which immediate follows the op-code and the offset.

    
    
If
Mnemonic	Opcode	Description	
IF	26	If absolute (longword address)	
RIF	30	If relative (longword address)	
IFQ	27	If absolute (quadword address)	
RIFQ	31	If relative (quadword address)	
    
The If instruction is used to conditionally branch to another address. Following the opcode is a longword or quadword absolute address or relative offset.  The top byte of the stack is popped and if 0, execution continues at the opcode following the address/offset.  If the top byte of the stack is not 0, execution continues at the specified address.  The offset is from the address of the immediately following instruction.

Null
Mnemonic	Opcode	Description	
NULL	0	No operation	
    
Performs no operation.  Null is a one-byte filler instruction that takes up space but affects none of the SVM context, except PC.

    
Pop
Mnemonic	Opcode	Description	
POPDL	159	Pop word to immediate longword address	
POPDW	160	Pop word to immediate word address	
POP	163	Pop 1 byte from stack. This removes data from the stack but doesn't transfer it to memory.  This has the effect of simply adjusting the Stack Pointer.	
POPNW	152	Pop n bytes to immediate word address (n=byte)	
POPNL	162	Pop n bytes to immediate longword address (n=byte)	
POPN	161	Pop n bytes (n=word)	
POPS	148	Pop to stack   Pop top word on stack to next longword on stack address	
POPNSIL	153	Pop to stack   Pop n bytes to stack, indirect longword (n=byte)	
    
This instruction reads data from the stack.  Push is used to write data to the stack.  On a pop operation, the stack pointer is decremented and the data at the address pointed to by the stack pointer is read.  All Pop addresses are absolute;  there are no relative addresses.
    
All Pop instructions which operate on a variable number of bytes are followed by a length byte indicating the number of bytes to pop.  The exception is instruction 61, which is followed by a length word instead of a byte.
    
Pop To Stack uses the stack both for the data to pop and for the address to write the data to.  In this case, the top n bytes of the stack contain the data and immediately below that is a longword address.

    
Push
Mnemonic	Opcode	Description	
PUSHILA	146	Push Immediate Longword Address	
PUSHDL	50	Push Direct Longword Address	
PUSHIW	33	Push Immediate Word	
PUSHIN	149	Push n bytes Immediate	
PUSHDW	49	Push Direct Word	
PUSHIB	32	Push Immediate byte	
PUSHNW	151	Push n bytes from word address	
PUSHNL	150	Push n bytes from longword address	
PUSHIL	34	Push Immediate Longword	
PUSH0	145	Push n Zeroes	
PUSHITA	147	Push immediate Typedef longword address.	

This instruction places data on the stack.  Pop is used to retrieve data from the stack.  On a push operation, the address pointed to by the stack pointer is written to, and the stack pointer is then incremented.  Note that PUSHILA, PUSHITA, and PUSHIL are identical except in how addresses may be translated (dependant upon the implementation).
    
Push immediate instructions read data from the code immediately following the Push instruction and push that onto the stack.  Push direct instructions use the immediately following address of the specified size, read a longword from that address, and push that onto the stack.
    
Push n instructions are followed by a length byte, which indicates the number of bytes to push from the source.
    
Push Zeroes, pushes a series of bytes with value 0 onto the stack.  The number of bytes pushed is determined by the word value which follows the opcode.

    
Skip
Mnemonic	Opcode	Description	
SKIP1	57	Skips execution of the next byte.  In other words IP = IP + 1.	
SKIP2	58	Skips execution of the next 2 bytes.  In other words IP = IP + 2.	
SKIP3	59	Skips execution of the next 3 bytes.  In other words IP = IP + 3.	
SKIP4	60	Skips execution of the next 4 bytes.  In other words IP = IP + 4.	
SKIP5	61	Skips execution of the next 5 bytes.  In other words IP = IP + 5.	
SKIP6	62	Skips execution of the next 6 bytes.  In other words IP = IP + 6.	

The skip instructions are ultra-short and compact jumps.  They can only jump forward.

    
Stop
Mnemonic	Opcode	Description	
STOP	2	Terminates program.	

This terminates the executing program.  No further execution occurs.

    
Zero Temp
Mnemonic	Opcode	Description	
ZERO	4	Zero Temp register.	

        This resets the Temp register to null (a string of zero length).

    
Concatenate
Mnemonic	Opcode	Description	
CONT	5	Concatenate Indirect to Temp register	
CONL	6	Concatenate Immediate Literal To Temp Register.	
CONS	130	Concatenate Strings On Stack.	

Concatenate indirect takes the longword address on the stack and uses it to locate the string to append to the Temp register.
    
Concatenate immediate literal is followed by a length byte value (0 to 255). Following it are the specified number of bytes of ASCII data.  These are appended to the string in the Temp register.
    
Concatenate strings on stack uses three longword addresses on the stack.  The first address popped is the address of the result string.  The next address popped is the address of the first string to concatenate.  The next address popped is the address of the string to be concatenated to the first string. The result address is then pushed back onto the stack.

    
Store Temp
Mnemonic	Opcode	Description	
STOREDL	7	Store Temp register to immediate longword address	

This instruction writes the Temp register contents to the longword address following the instruction.

    
Negate
Mnemonic	Opcode	Description	
NEGSI	104	Negate word integer	
NEGIS	105	Negate integer	
        
The Negate word integer pops the top word of the stack, negates it, and pushes the negated value onto the stack.
    
The general Negate integer instruction is followed by an integer flag byte, which determines the type of integer to negate on the stack.

    
Add
Mnemonic	Opcode	Description	
ADDW	65	Add words	
ADDL	66	Add longwords	
ADDI	64	Add integer	

The Add instruction adds two integers of the same type (size and sign).  The two integers are popped from the stack, added, and the sum is pushed onto the stack.  The integer pushed onto the stack is the same type as those popped from it.  Overflow is not trapped or noted.
    
Add Integer is a general integer function which is followed by an integer flag byte, which determines the type of integers to add.
    
The Add Words and Add Longwords are special add instructions which add signed values of the appropriate size.

    
Subtract
Mnemonic	Opcode	Description	
SUBW	89	Subtract words	
SUBL	90	Subtract longwords	
SUBI	88	Subtract integer	

The Subtract instruction subtracts one integer from another integer of the same type (size and sign).  The two integers are popped from the stack, and the difference is pushed onto the stack. The integer pushed onto the stack is the same type as those popped from it.  The top integer is subtracted from the next-to-top integer. Underflow is not trapped or noted.
    
Subtract Integer is a general integer function which is followed by an integer flag byte, which determines the type of integers to subtract.
    
The Subtract Words and Subtract Longwords are special instructions which subtract signed values of the appropriate size.

    
Multiply
Mnemonic	Opcode	Description	
MULW	81	Multiply words	
MULL	82	Multiply longwords	
MULI	80	Multiply integer	
    
The Multiply instruction multiplies two integers of the same type (size and sign).  The two integers are popped from the stack, multiplied, and the product is pushed onto the stack.  The integer pushed onto the stack is the same type as those popped from it. Overflow is not trapped or noted.
    
Multiply Integer is a general integer function which is followed by an integer flag byte, which determines the type of integers to multiply.
    
The Multiply Words and Multiply Longwords are special add instructions which multiply signed values of the appropriate size.

    
Divide
Mnemonic	Opcode	Description	
DIVW	73	Divide words	
DIVL	74	Divide longwords	
DIVI	72	Divide integer	

The Divide instruction divides one integer into another integer of the same type (size and sign).  The two integers are popped from the stack, and the result is pushed onto the stack.  The integer pushed onto the stack is the same type as those popped from it.  The top integer is divided into the next-to-top integer (the next-to-top is divided by the top).  Underflow is not trapped or noted.
    
Divide Integer is a general integer function which is followed by an integer flag byte, which determines the type of integers to divide.
    
The Divide Words and Divide Longwords are special instructions which divide signed values of the appropriate size.

    
Compare NE
Mnemonic	Opcode	Description	
NEI	200	Compare not-equal integer	
NES	208	Compare not-equal string	
NEM	192	Compare not-equal memory	

The Compare NE instructions compare two values on the stack, pops them, and pushes a result word onto the stack.  The result is 0 if the two values are equal and 65535 if the two values are not equal.
    
The Compare NE integer instruction compares two integers of the same type (size and sign).  The byte following the instruction is an Integer Flag Byte.
    
The Compare NE string instruction compares two strings.  The addresses of the strings to compare are on the stack (longwords).  The addresses are popped before the result is pushed.
    
The Compare NE memory instruction compares 1 to 64K bytes of memory.  The starting addresses of the two memory areas to compare are on the stack (longwords).  Following the instruction is a word length value indicating the number of bytes to compare.  If any bytes at the same offset from the start of both addresses are not equal, the result is 65535 - otherwise the result is 0.  The result is pushed onto the stack after the two addresses are popped.

    
Compare EQ
Mnemonic	Opcode	Description	
EQI	201	Compare equal integer	
EQS	209	Compare equal string	
EQM	193	Compare equal memory	

        The Compare EQ instructions compare two values on the stack, pops them, and pushes a result word onto the stack.  The result is 0 if the two values are not equal and 65535 if the two values are equal.
    
The Compare EQ integer instruction compares two integers of the same type (size and sign).  The byte following the instruction is an Integer Flag Byte.
    
The Compare EQ string instruction compares two strings.  The addresses of the strings to compare are on the stack (longwords).  The addresses are popped before the result is pushed.
    
The Compare EQ memory instruction compares 1 to 64K bytes of memory.  The starting addresses of the two memory areas to compare are on the stack (longwords).  Following the instruction is a word length value indicating the number of bytes to compare.  If any bytes at the same offset from the start of both addresses are equal, the result is 65535 - otherwise the result is 0.  The result is pushed onto the stack after the two addresses are popped.

    
Compare LT
Mnemonic	Opcode	Description	
LTI	202	Compare less-than integer	
LTS	210	Compare less-than string	
LTM	194	Compare less-than memory	

The Compare LT instructions compare two values on the stack, pops them, and pushes a result word onto the stack.  The result is 0 if the top value is less than or equal the next-to-top, and 65535 otherwise.
    
The Compare LT integer instruction compares two integers of the same type (size and sign).  The byte following the instruction is an Integer Flag Byte.
    
The Compare LT string instruction compares two strings.  The addresses of the strings to compare are on the stack (longwords). The addresses are popped before the result is pushed.
    
The Compare LT memory instruction compares 1 to 64K bytes of memory.  The starting addresses of the two memory areas to compare are on the stack (longwords).  Following the instruction is a word length value indicating the number of bytes to compare.  If any bytes at the same offset from the start of the top address are greater than or equal to the bytes at the same offset from the start of the next-to-top address, the result is 65535 - otherwise the result is 0. The result is pushed onto the stack after the two addresses are popped.

    
Compare GT
Mnemonic	Opcode	Description	
GTI	203	Compare greater-than integer	
GTS	211	Compare greater-than string	
GTM	195	Compare greater-than memory	

The Compare GT instructions compare two values on the stack, pops them, and pushes a result word onto the stack.  The result is 0 if the top value is greater than or equal the next-to-top, and 65535 otherwise.
    
The Compare GT integer instruction compares two integers of the same type (size and sign).  The byte following the instruction is an Integer Flag Byte.
    
The Compare GT string instruction compares two strings.  The addresses of the strings to compare are on the stack (longwords).  The addresses are popped before the result is pushed.
    
The Compare GT memory instruction compares 1 to 64K bytes of memory.  The starting addresses of the two memory areas to compare are on the stack (longwords).  Following the instruction is a word length value indicating the number of bytes to compare.  If any bytes at the same offset from the start of the top address are less than or equal to the bytes at the same offset from the start of the next-to-top address, the result is 65535 - otherwise the result is 0.  The result is pushed onto the stack after the two addresses are popped.

    
Compare LE
Mnemonic	Opcode 	Description	
LEI	204	Compare less-than-or-equal integer	
LES	212	Compare less-than-or-equal string	
LEM	196	Compare less-than-or-equal memory	

The Compare LE instructions compare two values on the stack, pops them, and pushes a result word onto the stack.  The result is 0 if the top value is greater than the next-to-top, and 65535 otherwise.
    
The Compare LE integer instruction compares two integers of the same type (size and sign).  The byte following the instruction is an Integer Flag Byte.
    
The Compare LE string instruction compares two strings.  The addresses of the strings to compare are on the stack (longwords). The addresses are popped before the result is pushed.
    
The Compare LE memory instruction compares 1 to 64K bytes of memory.  The starting addresses of the two memory areas to compare are on the stack (longwords).  Following the instruction is a word length value indicating the number of bytes to compare.  If any bytes at the same offset from the start of the top address are greater than the bytes at the same offset from the start of the next-to-top address, the result is 65535 - otherwise the result is 0.  The result is pushed onto the stack after the two addresses are popped.

    
Compare GE
Mnemonic	Opcode	Description	
GEI	205	Compare greater-than-or-equal integer	
GES	213	Compare greater-than-or-equal string	
GEM	197	Compare greater-than-or-equal memory	

        The Compare GE instructions compare two values on the stack, pops them, and pushes a result word onto the stack.  The result is 0 if the top value is greater than the next-to-top, and 65535 otherwise.
    
        The Compare GE integer instruction compares two integers of the same type (size and sign).  The byte following the instruction is an Integer Flag Byte.
    
        The Compare GE string instruction compares two strings.  The addresses of the strings to compare are on the stack (longwords). The addresses are popped before the result is pushed.
    
        The Compare GE memory instruction compares 1 to 64K bytes of memory.  The starting addresses of the two memory areas to compare are on the stack (longwords).  Following the instruction is a word length value indicating the number of bytes to compare.  If any bytes at the same offset from the start of the top address are less than the bytes at the same offset from the start of the next-to-top address, the result is 65535 - otherwise the result is 0.  The result is pushed onto the stack after the two addresses are popped.

    
Convert Number
Mnemonic	Opcode	Description	
CONVERT	128	Promote/demote an integer	

The Convert Number instruction changes the precision of an integer.  If the integer is converted to higher precision, it is called promotion.  If the integer is converted to lower precision, it is called demotion.  The top of the stack is a longword address of the data type specifier indicating the desired integer precision, which is popped from the stack.  The next to top of the stack is a longword address of the data type specifier indicating the integer precision to convert from, which is also popped from the stack.  The next-to-the-next-to top of stack is the integer value to convert. Note that the size of this integer value must match the integer precision to convert from. The converted value is pushed onto the stack after the original value is popped from the stack.
    
Contents of Data Type specifier:
    
Byte(s)	Description	
0-1	Ignored.	
2	0 for unsigned, non-zero for signed.	
3-4	Size of integer, in bytes.  The only supported sizes are: 1 through 7, signed or unsigned, 8 signed.	

    
Create String
Mnemonic	Opcode	Description	
CREATE	129	Create string	

The Create String instruction pops the longword address of a string from the stack and writes the contents of the Temp register to that string.

    
Not
Mnemonic	Opcode	Description	
NOTS	138	Logically not top of stack	

The Not instruction pops the top word from the stack and logically negates it, pushing the new value onto the stack.  If the value on the stack is 0, 65535 is pushed.  If the value on the stack is anything other than 0, then 0 is pushed onto the stack.  The value pushed is a word.

    
And
Mnemonic	Opcode 	Description	
ANDS	139	Logically AND top of stack	

The And instruction does a logical And of the top two words on the stack.  Each stack value is assumed to be false if 0 and true otherwise.  The result of the And operation is a word 0 indicating false or 65535 representing true. The result word is pushed onto the stack after the two operands are popped from the stack.  The result table follows.
    
Top word	Next-to-top word	Result	
True	True	True	
False	True	False	
True	False	False	
False	False	False	

    
Nand
Mnemonic	Opcode	Description	
NANDS	140	Logically NAND top of stack	
    
The Nand instruction does a logical Nand (not And) of the top two words on the stack.  Each stack value is assumed to be false if 0 and true otherwise.  The result of the Nand operation is a word 0 indicating false or 65535 representing true.  The result word is pushed onto the stack after the two operands are popped from the stack.  The result table follows.
    
Top word	Next-to-top word	Result	
True	True	False	
False	True	True	
True	False	True	
False	False	True	

    
Or
Mnemonic	Opcode	Description	
ORS	141	Logically OR top of stack	

The Or instruction does a logical inclusive Or of the top two words on the stack.  Each stack value is assumed to be false if 0 and true otherwise.  The result of the Or operation is a word 0 indicating false or 65535 representing true.  The result word is pushed onto the stack after the two operands are popped from the stack.  The result table follows.
    
Top word	Next-to-top word	Result	
True	True	True	
False	True	True	
True	False	True	
False	False	False	

    
Nor
Mnemonic	Opcode	Description	
NORS	142	Logically NOR top of stack	

The Nor instruction does a logical Nor (not or) of the top two words on the stack.  Each stack value is assumed to be false if 0 and true otherwise.  The result of the Nor operation is a word 0 indicating false or 65535 representing true.  The result word is pushed onto the stack after the two operands are popped from the stack.  The result table follows.
    
Top word	Next-to-top word	Result	
True	True	False	
False	True	False	
True	False	False	
False	False	True	

    
Xor
Mnemonic	Opcode	Description	
XORS	143	Logically exclusive-or top of stack	

The Xor instruction does a logical exclusive or of the top two words on the stack.  Each stack value is assumed to be false if 0 and true otherwise.  The result of the Xor operation is a word 0 indicating false or 65535 representing true.  The result word is pushed onto the stack after the two operands are popped from the stack.  The result table follows.
    
Top word	Next-to-top word	Result	
True	True	False	
False	True	True	
True	False	True	
False	False	False	

    
XNor
Mnemonic	Opcode	Description	
XNORS	144	Logically exclusive-nor top of stack	

The XNor instruction does a logical exclusive nor (not xor) of the top two words on the stack.  Each stack value is assumed to be false if 0 and true otherwise. The result of the XNor operation is a word 0 indicating false or 65535 representing true.  The result word is pushed onto the stack after the two operands are popped from the stack.  The result table follows.
    
Top word	Next-to-top word	Result	
True	True	True	
False	True	False	
True	False	False	
False	False	True	

    
Copy String
Mnemonic	Opcode	Description	
COPY	131	Copy String	
RCOPY	135	Reverse Copy	

The Copy String instruction pops a longword destination address from the stack and then pops a longword source address from the stack.  The contents of the string at the source address are copied to the string at the destination address.
    
The Reverse Copy instruction performs the same operation as the Copy String instruction except that the order of the operands on the stack is reversed. In other words, the first address popped from the stack is the source and the second address popped is the destination.

Dereference
Mnemonic	Opcode	Description	
DEREF	98	Dereference	
DEREFI	96	Dereference integer	

The Dereference instruction pops a longword address from the stack, reads the longword at that address, and pushes it onto the stack.
    
The Dereference Integer instruction is a generic version of the Dereference instruction.  Immediately following the opcode is an Integer Type flag.  The instruction pops the longword address from the stack, reads the integer of the appropriate size and pushes it onto the stack.

    
Zero String
Mnemonic	Opcode	Description	
ZEROS	133	Zero String	

The Zero String instruction pops the longword address of a string from the stack, and sets the string to length 0.

    
Promote Word To Long
Mnemonic	Opcode	Description	
PROWL	115	Promote Word to Longword	

The Promote instruction pops a word integer from the stack and pushes a longword integer in its place.

    
Range Check
Mnemonic	Opcode	Description	
RANGE	134	Range Check	

The Range Check instruction is used to ensure that a signed array index is within the limits defined by two word values.  The instruction pops a word integer from the stack which defines the highest valid value to check against. Then another word integer is popped which defines the lowest valid value to check against.  Then the word integer on top of the stack is compared to the high and low range values.  If the value is not within the range (inclusive), the program ends with a "?Subscript out of range" error.  Otherwise, the execution continues with the value to compare still on the top of the stack.

Copy Indirect
Mnemonic	Opcode	Description	
COPYNI	156	Copy n bytes indirect	

The Copy Indirect instruction copies a block of data between two addresses. Following the instruction is a word value indicating the number of bytes to copy (1 to 65535).  The source address is popped from the stack and then the destination address is popped from the stack.  Both are longword addresses.

    
Percent Integer
Mnemonic	Opcode	Description	
PERI	157	Percent integer	

The Percent instruction divides an integer by 100.  The instruction is followed by an Integer Flag byte, indicating the size of the integer to perform the operation on.  An integer of the specified size is popped from the stack.  The result of the operation is then pushed onto the stack.  The result is the same size and sign as the value being operated on.

    
Exponent Integer
Mnemonic	Opcode	Description	
EXPI	154	Exponent integer	

The Exponent instruction raises an integer to the power of another integer. The instruction is followed by an Integer Flag Byte, indicating the size and type of the source operands and the result.  The first integer popped from the stack is the exponent value.  The second integer popped from the stack is the operand.  The result pushed onto the stack is the operand to the power of the exponent.  Various errors are possible, which will terminate the program.
    
    Possible errors:
    
    ?Integer _Result too large
    ?Illegal argument in LOG
    ?Argument too large in exponent

    
Factorial Integer
Mnemonic	Opcode	Description	
FACI	155	Factorial integer	

The Factorial instruction performs a factorial operation.  The instruction is followed by an Integer Flag byte, indicating the size of the integer to perform the operation on.  An integer of the specified size is popped from the stack.  The result of the operation is then pushed onto the stack.  The result is the same size and sign as the value being operated on.

    
Extension
Mnemonic	Opcode	Description	
EXT	254	Machine extension	

        This instruction is reserved for future use.

    
User Extension
Mnemonic	Opcode	Description	
UEXT	255	User-defined instruction	

This instruction precedes a user-defined (customized) instruction.  The standard SVM generates an error if this instruction is encountered.  A customized SVM can use this to extend the SVM instruction set.

    
Integer Flag Bytes
    
The Integer Flag Byte follows certain integer instructions and indicates the size of the integer (1 to 127 bytes - in the low 7 bits) and whether or not the integer is signed (high bit set means signed, clear means unsigned).  Note that the current implementation supports integers sized from 1 to 7 bytes, signed or unsigned, and 8-byte signed integers.  An Integer Flag Byte value of 0 is reserved for future use.  The operation of the SVM with a value of 0 is undefined.  Sizes outside the range 1 to 8 result in the source operand(s) being popped from the stack but no result being pushed.  This behavior is not supported, however, and invalid values may result in errors in future releases of the SVM.

    
Strings
    
Strings in SVM are collections of ASCII characters from 0 to 255 bytes in length.  All strings are referenced through a string header. A string header in the SVM is a longword pointer to the string data.  The string data begins with a length byte, followed by the appropriate number of ASCII bytes (0 through 255).  Note that a pointer value of 0 indicates a null string, as does a pointer to a byte of 0.

VIRTUAL FUNCTIONS

The standard Run Time Library for SVM consists of virtual functions.  A virtual function has an address within the virtual address space, but has no code there.  Instead, calls to these functions are handled specially by the SVM.  Thus, their addresses simply provide a mapping into SVM internal code. Note that only the address, parameter types, and name of the function are provided. Parameters are listed in stack order (topmost one is on the top of the stack).  "String" indicates a longword address of a string header.  Integer parameters are preceded by an indication of the integer size and type.  The number is the size, in bytes, and "s" indicates signed, "u" unsigned.  Thus, "s8 integer" indicates a signed 8-byte integer.  "RTTI" indicates a longword address of the Run-Time Type Information for a parameter.  "address" indicates a longword address of some data, as defined by the preceding RTTI specification.  "file" indicates a longword address of a file variable. "pointer" is a longword address of some data structure. "count" indicates a byte count indicating the number of parameters being passed to a routine which takes variable parameters.  The following items on the stack indicate what is required for each parameter.  Note that functions return values on the stack unless the location of the result is passed to the function.
    
Address	Parameters	Name	
0	s2 integer	RANDOM	
1	s2 integer	EDIT	
	string		
	result string		
2	s8 integer	COMPARE	
	s8 integer		
3	s8 integer	SET	
	RTTI		
	address		
4	s8 integer	CLEAR	
	RTTI		
	address		
5	count	OUTPUT	
	RTTI		
	address		
6	count	INPUT	
	RTTI		
	address		
7	string	OPEN	
	file		
8	file	CLOSE	
9	string	DELETE	
10	s8 integer	ABS	
11	string	BINARY	
12	string	INSTR	
	string		
	s2 integer		
13	string	LENGTH	
14	s2 integer	SIGN	
15	s2 integer	ASCII	
	result string		
16	string	CHAR	
17	s2 integer	LEFT	
	string		
	result string		
18	s2 integer	RIGHT	
	string		
	result string		
19	s2 integer	STRING	
	s2 integer		
	result string		
20	s8 integer	TEST	
	RTTI		
	address		
21	s2 integer	MID	
	s2 integer		
	string		
	result string		
22	s8 integer	MAX	
	s8 integer		
23	s8 integer	MIN	
	s8 integer		
24	file	TRANSFER	
	file		
25	s2 integer	CVT	
	s2 integer		
	string		
	result string		
26	s2 integer	EMPTY	
	string		
	string		
	result string		
27		TIME	
28	result string	COMMAND_LINE	
29	string	PARSE	
	string		
	result string		
99	string	HELP	
	string		
100	pointer	WINDOW_MAPPED	
103	s2 integer	CREATE_WINDOW	
	s2 integer		
	s2 integer		
	result pointer		
104	pointer	UNMAP_WINDOW	
105	s2 integer	MAP_WINDOW	
	s2 integer		
	s2 integer		
	s2 integer		
	s2 integer		
	s2 integer		
	s2 integer		
	pointer		
106	pointer	DELETE_WINDOW	
107	pointer	CLEAR_WINDOW	
108	pointer	UPDATE_WINDOW	
109		UPDATE_SCREEN	
110	pointer	REFRESH_WINDOW	
111		REFRESH_SCREEN	
112	s2 integer	INIT_SMU	
	s2 integer		
	s2 integer		
	s2 integer		
113	s2 integer	SET_SCREEN	
	s2 integer		
	s2 integer		
	s2 integer		
114	s2 integer	SET_CURSOR	
	s2 integer		
115	s2 integer	CLEAR_CURSOR	
	s2 integer		
116	s2 integer	SET_WINDOW	
	s2 integer		
	s2 integer		
	s2 integer		
	pointer		
117	pointer	SELECT_WINDOW	
118	pointer	ERASE_EOW	
119	pointer	ERASE_EOL	
120	s2 integer	INSERT_LINE	
	pointer		
121	s2 integer	DELETE_LINE	
	pointer		
122	s2 integer	GET_WINDOW_ATTRIBUTE	
	s2 integer		
123	s2 integer	GET_SCREEN	
	s2 integer		
124	string	LOAD_DRIVER	
125	s2 integer	GET_WINDOW_CHAR	
	s2 integer		
126	s2 integer	SET_VIEWPORT	
	s2 integer		
127	result pointer	CURRENT_WINDOW	

Function Descriptions

There are two sets of SVM functions: General and SMU.  SMU functions are described in their own section:

ABS

Y = Abs value

This function returns the absolute value of the passed numeric value.

ASCII 

Y = Ascii value

This returns a string of one character whose ASCII value is passed.

BINARY

Y = Binary string

This function converts a number in a string into an integer value.

CHAR

Y = Char string

This function returns the ASCII value of the first character in the passed string.

CLEAR

Clear Variable, Value 

This clears all bits in the integer variable specified, that are set in the specified value.

CLOSE

Close file

The file associated with the specified file variable is closed.  If the file is not opened, this has no effect.

COMMAND_LINE

X = Command_Line

Returns a string containing the command line used to invoke the program.

COMPARE

Y = Compare value1, value2

This function returns the bit mask result of a bit-by-bit ANDing of "value1" and "value2".

CVT

Y = Cvt string, base1, base2

This function converts a value between two bases between 2 and 36.  "string" is a string containing the number to convert.  "base1" is the base to convert from and "base2" is the base to convert to.  The result is a string containing the number in the target base.

DELETE

Delete name

The file named in the string "name" is deleted.  The file should not be currently opened.

EDIT

Y = Edit stringval, editval

This function returns a string that is equal to the string, "stringval", after performing some editing on the string.  Multiple functions can be performed at the same time, by adding the values of each function together. For example, to perform both function value 1 and 8, use a value of 9.

The value "editval" performs the following functions:

Value	Function	
1	Trim high order bit of each character.	
2	Discard ALL spaces and tabs.	
4	Discard CR, LF, FF, ESC, NUL, and DEL characters.	
8	Discard leading spaces and tabs.	
16	Reduce multiple contiguous spaces and tabs to a single space.	
32	Convert lowercase characters to uppercase.	
64	Convert "[" to "(" and "]" to ")".	
128	Discard trailing spaces and tabs.	
256	Don't alter any characters within quotes.	
512	Convert uppercase characters to lowercase.	
1024	Convert "[" to "{" and "]" to "}".	
2048	Convert "(" to "[" and ")" to "]".	
4096	Convert "(" to "{" and ")" to "}".	
8192	Convert "{" to "(" and "}" to ")".	
16384	Convert "{" to "[" and "}" to "]".	

Note that if multiple conflicting functions are specified, the lowest numbered function takes precedence over the higher number function(s).  Note that a value of -1 does ALL edits (except for contradictions).

Examples of how this works follows:

Function	Resulting value	
EDIT 'Hi there', 32	HI THERE	
EDIT 'Hi, "there", 288	HI, "there"	
EDIT '(Hi)', 2048	[Hi]	
EDIT 'Hi there, friend', 2	Hithere,friend	

EMPTY

X = Empty substring, string

This returns a string equal to "string", minus any occurrences of the string in "substring".

HELP

Help filename, topic

This displays help text.  The help file is defined by filename.  Topic is the help topic within that file (or null for top-level help).  Note that this help is not compatible with Windows help.  The Help file must be in C&C Help file format.

INPUT

Input variable {,variable...} {,ncm}

Anything typed at the keyboard during the execution of the Input is placed into the specified variable(s).  Normally, when a newline key is pressed, the cursor will go to the beginning of the next line. Using the ncm (No Cursor Motion) modifier, however, will leave the cursor in the same place.  When multiple variables are used, each variable is filled with a value until each variable has been assigned one.  The user must enter each value separated by a delimiter.  For numeric variables, the delimiter is either a space, a comma, or a newline.  For string variables, the only delimiter is a newline.  Newline characters are "RETURN", "ESCAPE", "LINEFEED", and "FORMFEED". Entering a non-number for a numeric variable will result in a "%Data format error" warning being displayed.  The numeric variable is left in an undefined state in this case.  Using ncm, except as the last item, is unsupported and will have unpredictable results.

INSTR

Y = Instr value, string1, string2

This function returns a value which is the position of string2 in string1.  The search begins at position "value".  0 is returned if string2 is not found.

LEFT

X = Left string, value

This function returns the left-most "value" characters of "string".

LENGTH

Y = Length string

This function returns the length of "string" in characters.  This will be a value from 0 to 255.

MAX

Y = Max Value1, Value2

This function returns the larger of the two passed values.

MIN

X = Min value1, value2

This function returns the smaller of the two passed values.

MID

X = Mid string, value1, value2

This function returns a portion of "string", beginning at position "value1", for a length of "value2".

OUTPUT

Output value {,value...} {,ncm}

This outputs data to the screen.  The values used may be strings or numbers. If the ncm (No Cursor Motion) is the last item listed, then Output will not move the cursor to the beginning of the next line. A maximum of eight parameters may be passed to Output.  Using ncm except as the last item is unsupported and will have unpredictable results.  Example:

A special case of Output is when no parameters are provided.  In this case it simply displays a blank line.

PARSE

X = Parse separator, string

  This function returns the next portion of "string" up to the specified separator string.  If the separator is not found, the entire value of "string" is returned.  The string passed for "string" is modified to contain that portion of the original string not returned by the function.

RANDOM

X = Random max

This function returns a random number between 0 and max-1, inclusive.  For example, Random 10 returns a random number that could be 0, 1, 2, 3, 4, 5, 6, 7, 8, or 9.

RIGHT

X = Right string, value

This function returns the right portion of "string" beginning at position "value".

SIGN

Y = Sign value

This function returns the sign of the passed value.  If value is zero, then 0 is returned.  If value is positive, then 1 is returned.  If value is negative, then -1 is returned.

SET

Set variable, value

This will set the bits specified by value in the specified variable.  It is equivalent to a bit-wise OR (variable = variable ored with value).

STRING

Y = String value1, value2

  This function returns a string of length "value2", filled with characters of ASCII value "value1".

TEST

Y = Test variable, value

This function sets "variable" to "value" if "variable" is zero (0).  If "variable" is not zero, it is not modified and 0 is returned.  Otherwise, -1 is returned.

TIME

X = Time

This returns an 8-byte signed integer value indicating the current date and time (in 100ns increments from year 0, projecting the Gregorian calendar backwards to year 0).

TRANSFER

Transfer File1, File2

This will transfer the contents of File1 into File2.  Both files must be open prior to this call.  The position in File1 remains unchanged.

SMU Function Descriptions

SMU (Screen Management Utility) is a windowing utility for text-based programs, and is integrated into SVM.  When used, all screen I/O goes through SMU.  SMU is a set of functions that create, delete, and manage text windows.  Each window has a viewport associated with it that allows some portion of the window to show on-screen.  An SMU window is referenced via a generic pointer.  CREATE_WINDOW creates a window and returns a pointer for it.  DELETE_WINDOW is used to delete a previously-created window.  INIT_SMU must be called to initialize the SMU system.  The following functions are provided to manage SMU windows.

CLEAR_CURSOR

Clear_Cursor Row, Column

This deletes the cursor from the location it was placed with Set_Cursor.  Generally there is no need to use it.

CLEAR_WINDOW

Clear_Window pointer

This clears the specified window.

CREATE_WINDOW

X = Create_Window Rows, Columns, Flags

This function creates a window and returns a pointer to it.  "rows" and "columns" indicate the number of rows and columns in the window.  "flags" are options for how the window is treated

Bit Value	Meaning	
1	No scroll - vertical wrap.	
2	reserved.	
4	No wrap at end of line.	
8	reserved.	
16	reserved.	
32	Cursor is disabled in this window	
64-32768	reserved.	

CURRENT_WINDOW

X = Current_Window

This function returns a pointer to the currently selected window.

DELETE_LINE

Delete_Line pointer, direction

This is used to delete a line in the specified window.  "direction" indicates where to gain a new blank line.  Since deleting a line in a window results in room for another line on the screen, you must specify where the new line is to appear.  If 0, then the new line appears at the top of the screen.  Otherwise it appears at the bottom of the screen.  The rest of the lines between the deleted line and the new line are shifted appropriately.

DELETE_WINDOW

Delete_Window pointer

This deletes the specified window, releasing all memory required by the window.

ERASE_EOL

Erase_EOL pointer

This erases all characters from the current position of the specified window to the end of the current line.

ERASE_EOW

Erase_EOW pointer

This erases all characters from the current position to the end of the specified window.

GET_SCREEN

X = Get_Screen row, column

  This function returns the character at the specified physical screen coordinates (row "row" and column "column").  The return value is the ASCII (numeric) representation of the character.  For example, a space is returned as 32.

GET_WINDOW_ATTRIBUTE

X = Get_Window_Attribute row, column

  This function returns the attribute of the character at the specified position of the current window.  If Row and Column are zero (0), the attribute from the current position is returned.  For a description of what attribute values are, see Set-Window.

GET_WINDOW_CHAR

X = Get_Window_Char row, column

  This function returns the character at the specified position on the current window.  The current position is used if the row and column are zero (0).  The return value is the ASCII (numeric) value of the character.  For example, a space is returned as 32.

INIT_SMU

Init_SMU model, printer, lines, mode

This initializes or resets the SMU characteristics.  All windows should be deleted before this is called or memory will be wasted.  The parameters passed are:

Parameter	Meaning	
model	model number of machine.  Generally, this should be zero (0) to indicate that the machine type be automatically determined.	
printer	printer type.  Generally, this should be zero (0) to indicate that the printer type be automatically determined.	
lines	SMU input saves previous lines of input which may be recalled with the arrow keys.  This indicates how many lines should be saved.  The larger this number, the more memory is used.  The default is 20 lines (if this is 0).	
mode	SMU input allows line editing with character insertion or replacement.  This indicates which is the default mode.  0 is over-write mode, and 1 is insert mode.	

INSERT_LINE

Insert_Line pointer, direction

This inserts a blank line at the current position of the current window.  "direction" indicates which line should be lost from the screen, since inserting a line requires that another be deleted.  If 0, the top line of the screen is lost, otherwise the bottom line of the screen is lost.  The lines between the current position on the lost line are scrolled appropriately.

LOAD_DRIVER

Load_Driver filename

This loads a screen driver specified by "filename".  This must be a position-independant binary image of an assembly routine which begins at offset 0 in the file.

MAP_WINDOW

Map_Window pointer, row, row_count, column, column_count, vrow, vcol, level

This maps a window to the screen.  If the window is already mapped, it is unmapped and remapped.  The parameters passed are:

Parameter	Meaning	
pointer	pointer to window to map.	
row	physical row on screen where window is to begin.	
row_count	number of rows to display on screen.	
column	physical column on screen where window is to begin.	
column_count	number of columns to display on screen.	
vrow	row of window to display as first row in viewport.	
vcol	column of window to display as first column in viewport.	
level	level for window (0 to 255).  For windows that occupy the same physical location on the screen, this determines which shows on the screen.  The lower the number, the lower the priority.  The window with the highest priority is shown in a conflict.	

REFRESH_SCREEN

Format: Refresh_Screen

This refreshes all windows mapped to the screen.  This is useful if a TSR writes information to the screen and you wish to restore the windows to their internal representations.

REFRESH_WINDOW

Refresh_Window pointer

This refreshes the specified window.  This is useful if a TSR writes information to the screen and you wish to restore the window to its internal representation.

SELECT_WINDOW

Select_Window pointer

This function selects the specified window.  All I/O will henceforth take place on this window until another window is selected.

SET_CURSOR

Set_Cursor row, column

This is used to place a cursor (a blinking box) at a specific location on the screen.  Generally this is not used.

SET_SCREEN

Set_Screen model, printer, lines, mode

This is used to change screen attributes.  The parameters passed are:

Parameter	Meaning	
model	Model number of machine.  Generally, this should be zero (0) to indicate that the machine type be automatically determined.	
printer	Printer type.  Generally, this should be zero (0) to indicate that the printer type be automatically determined.	
lines	SMU input saves previous lines of input which may be recalled with the arrow keys.  This indicates how many lines should be saved.  The larger this number, the more memory is used.  The default is 20 lines (if this is 0).	
mode	SMU input allows line editing with character insertion or replacement.  This indicates which is the default mode.  0 is over-write mode, and 1 is insert mode.	

SET_VIEWPORT

Set_Viewport row, column

This is used to change the portion of the current window that is to be displayed on the screen.  The row and column indicate the row and column of the window that are to show in the upper left-hand corner of the viewport.

SET_WINDOW

Set_Window pointer, row, column, flags, attributes

This is used to set window characteristics.  The parameters passed are:

Parameter	Meaning	
pointer	window to change.	
row	row to set current position to.  Ignored if less than 1.	
column	column to set current position to.  Ignored is less than 1.	
flags	If zero, this is ignored unless row and/or column are negative.  See Create_Window for a list of flags.	
attributes	attributes for window.  This must be negative or it is ignored.  This defines how characters written to the window are portrayed.	

Attribute meanings:

Bit Value	Meaning	
1	Reverse-video	
2	High-intensity	
4	Blink	
8	Low-intensity	
16	No blink	
32	Normal video	
64	Modify existing attributes (instead of changing attributes to this, modify them to also have these attributes).	
128-16384	reserved	

UNMAP_WINDOW

Unmap_Window pointer

This unmaps the specified window.

UPDATE_SCREEN

Update_Screen

This updates all windows that are visible on the screen.  There is generally no need to call this function.

UPDATE_WINDOW

Update_Window pointer

This forces an update of the specified window.  There is generally no need to call this function.

WINDOW_MAPPED

X = Window_Mapped pointer

This function returns -1 if the specified window is mapped to the screen, and 0 otherwise.  Note that a window may not be visible even if it is mapped.

    
API

All methods use the stdcall calling convention.  Note that the following type names are used:

Type	Description	
Integer	32-bit signed 2’s-complement integer.	
Int64	64-bit signed 2’s-complement integer.	
String	Pointer to a null-terminated ASCII string. (char* in C++, PChar in Delphi)	
Byte	A single-byte of data. (unsigned char in C++, Byte in Delphi)	

SVM API
This section describes the Application interface to an implementation of SVM.  SVM is contained in an executable callable unit (such as a Windows DLL) with the following functions (all of which use stdcall calling convention):

TSVM_Engine* Get_Engine()

Returns an instance of an SVM execution engine.

TSVM_Debugger_Client* Get_Debugger_Client()

Returns an instance of an SVM debugger client.  If the implementation doesn’t support this, the function returns NULL.

long Version()

Returns the version of the SVM API, times 10.  For instance 15 indicates Version 1.5.

Extension API
This section describes loadable VM extensions.  Such extensions are contained in an executable callable unit (such as a Windows DLL) with the following functions (all of which use stdcall calling convention):

TSVM_Extension* Get_Extension()

Returns an instance of an SVM extension..

long Version()

Returns the version of the Extension API, times 10.  For instance 15 indicates Version 1.5.

SVM classes

Execution_Types
This enumeration indicates the execution state.  It has the following values:

Name	Value	Meaning	
SVM_IT_Step	0	Single step execution.	
SVM_IT_Go	1	Execute until termination.	
SVM_IT_Prompt	2	Read for prompting (debugger).	
SVM_IT_End_Normal	3	Program terminated normally.	
SVM_IT_End_Abnormal	4	Program terminated due to error.	
SVM_IT_End_User_Abort	5	Program execution terminated due to user abort.	
SVM_IT_Not_Executable	6	Image is not a valid executable format.	

TWatchpoint_Type
This enumeration defines the type of a watchpoint.  Watchpoints are used to interrupt execution when data is accessed or code is executed.  Watchpoints are managed by the Watchpoint Manager.   An execution watchpoint is typically known as a “breakpoint”.  It has the following values.

Name	Value	Meaning	
SWT_None	0	No watchpoint.	
SWT_All	1	Data and execution watchpoint.	
SWT_Data	2	Data access watchpoint.	
SWT_Execution	3	Execution watchpoint (breakpoint).	

TFile_Operation
This enumeration defines file operations that are passed to the SVM observer object.

Name	Value	Meaning	
FO_Open	0	Opening a file.	
FO_Delete	1	Deleting a file.	

TData_Type
This structure defines a data type as used by SVM.

Field	Size in bytes	Description	
ID	2	ID of data type:
0 = Real
1 = Fixed-point
2 = String
3 = Integer	
Signed	1	True if signed.  Only applies to numeric types.	
Size	2	Size of data.  For real and fixed-point, this is the sum of the mantissa+exponent or whole+fractional.	
Data	4	Data-type-specific information:
For reals:
Mantissa   2   Size of mantissa in bytes
Exponent  2   Size of exponent in bytes
For fixed-point:
Whole        2  Size of whole part in bytes
Fractional  2  Size of fractional part in bytes
For strings:
Length       2  Length of static string.  0 = dynamic string.
Reserved   2  Undefined
For other types, this is undefined.	

TSVM_Watchpoint_Manager

This class manages watchpoints.  The watchpoint manager can be viewed as an array of watchpoints.  The implementation can put the indexes in any order, but once a watchpoint has an index, that index cannot move unless a watchpoint is removed.  The class has the following methods.

integer Add(TWatchpoint_Type Type, string Name, int64 Address, integer Line, integer DT, int64 SB, int64 SE )

Add a new watchpoint of type Type.  The watchpoint is at code or data address Address.  If Line is not –1, then it is the line number in the file named Name.  For code watchpoints, DT, SB, and SE are ignored.  Otherwise, DT indicates the data type of the data, SB indicates the code address that begins the valid scope for the data and SE indicates the code address that ends the valid scope for the data.

Int64 Address_At( TWatchpoint_Type Type, integer Index )

Returns the address of the Indexth watchpoint of the specified type.  All indexes start with 0.

integer Cancel(TWatchpoint_Type Type, int64 Address )

Deletes the watchpoint of the specified type and address.

void Cancel_All( TWatchpoint_Type Type )

Deletes all watchpoints of the specified type(s).

integer Cancel_By_Name( TWatchpoint_Type Type, string Name )

Deletes the watchpoint of the specified type and name.

integer Count( TWatchpoint_Type Type )

Returns the number of defined watchpoints of the specified type(s).

int64 Data_Type_At( TWatchpoint_Type Type, integer Index )

Returns the data type of the Indexth watchpoint of the specified type.  All indexes start with 0.

integer Index_Of_Address( TWatchpoint_Type Type, int64 Address )

Returns the index of the watchpoint with the specified type and address.

integer Index_Of_Address_With_Scope( TWatchpoint_Type Type, int64 Address, int64 Scope_Address )

Returns the index of the watchpoint with the specified type and address whose scope address range contains Scope_Address.

string Name_At( TWatchpoint_Type Type, integer Index )

Returns the name of the Indexth watchpoint of the specified type.  All indexes start with 0.

TSVM_Observer

SVM Observer objects are used to monitor, and optionally change, the operation of executing SVM code.  This can be used to customize behavior or to implement security by disallowing certain operations, or constraining operations to a sandbox.  The class has the following methods:

string DLL_Load( string Name )

Called when program attempts to load a DLL – usually upon the first call to a routine in the DLL.  The passed name is the filename of the DLL.  The return value is the actual DLL to load, which may be the passed name.  If NULL is returned, the DLL load operation fails.

string SSL_Load( string Name )

Called when program attempts to load an SSL – usually upon the first call to a routine in the SSL.  The passed name is the filename of the SSL.  The return value is the actual SSL file to load, which may be the passed name.  If NULL is returned, the SSL load operation fails.

void File_Operation( string& Name, string& Name1, TFile_Operation Operation )

Called when program attempts certain file operations.  Name is the filename for which the operation is taking place.  Name1 is reserved for future use. On return, Name is the actual file name to use, or NULL to abort.

TSVM_Environment

The TSVM_Environment class provides read/write access to the SVM data and access to special "standard" routines.  The class has the following methods:

void Init( TSVM_Engine : Engine )

Initializes the SVM Environment.  Engine is the running SVM engine for access to data.

void Terminate()

Destructs the SVM Environment object.

boolean Call( integer XX )

Calls pre-defiened routine XX.

boolean Valid_Memory( int64 Address )

Returns True if this environment handles access to memory address Address.

boolean Valid_Call( integer Address )

Returns True if this environment handles the specified Call.

Int64 Data_Read_Comp( int64 B, integer Size, integer& Result )

Reads and returns an 1nt64 value from data memory address B.  The size of the value read is Size bytes (1-8).

void Data_Read_n( int64 B, integer Size, integer& Result, string& Buffer )

Read Size (up to 256) bytes from data memory address B into passed buffer.  Result indicates the success of the operation: 0 = success, non-zero indicates an out-of-range address.

integer Data_Read_Val( int64 Address, integer Size, integer& Result )

Read an integer value, of size Size bytes from data address Address. Result indicates the success of the operation: 0 = success, non-zero indicates an out-of-range address.

string Data_Read_Str( int64 Address, integer& Result )

Read a string value from data address Address. Result indicates the success of the operation: 0 = success, non-zero indicates an out-of-range address.

integer Data_Read_Num( int64 Address, integer& Result ) 

Read a 16-bit signed integer value from data address Address. Result indicates the success of the operation: 0 = success, non-zero indicates an out-of-range address.

void Write_Data( string A, integer B, int64 Address, integer D )

Write data memory. A is data to write for strings.  B is data to write for integers.  Address is the address (if 0, then pop 32-bit memory address and write to that memory).  D indicates the data type.  If D<0 then the absolute value of D is the number of bytes to copy).

Void Set_Observer( TSVM_Observer Observer )

Sets the Observer object for the environment.

TSVM_Extension

Extensions are a means of extending the instruction set of SVM.  This class is a descendant of TSVM_Environment.  The class has the following methods:

boolean Valid_Instruction( byte X )

Returns True if the passed op-code is recognized by the extension.

void Execute_OpCode( int64 Address )

Execute the instruction at the passed address (address is immediately after the 255 op-code).

string Disassemble( int64& Address )

Disassembles the instruction at the specified address, returns a string containing the Mnemonic and updates Address to point to the next address.

TSVM_Engine

The SVM engine class is a descendant of TSVM_Environment.  The class has the following methods:

boolean Initialize( string Name, string Default, integer Language_Id, integer Low_Version, integer High_Version, Flags, boolean Allow_Control_C, TSVM_Debugger_Client* Debugger_Interface )

Initializes the engine.  Name is the filename of the program to execute.  If Name is NULL or empty, the command line is examined for a filename.  Default is the default file extension to use if one is not specified.  Low_Version and High_Version indicate the version range that the executable must contain.  If Allow_Control_C is true, then the user can abort the execution with a Control-C.  Debugger_Interface is the debugger to use (NULL if no debugger).  Flags indicate the following:

Flag	Meaning	
1	Use SMU for I/O.	
2-16384	reserved	

string Disassemble( int64& Address )

Disassembles the instruction at the specified address, returns a string containing the Mnemonic and updates Address to point to the next address.  If the disassembly contains both op-codes and operands, it MAY break the lines into multiple parts, delimited by CRLF.

Execution_Types Execute( int64 Pc, boolean Single_Step )

Execute the program starting at address PC.  If Single_Step is true, only one instruction is executed.

Execution_Types Run( int64 PC, boolean Single_Step )

Execute the program starting at address PC.  If Single_Step is true, only one instruction is executed.  No debugger interface is invoked with this method.

byte Fetch( int64 PC )

Fetches the Op-code from address PC.  If PC is 0, the current PC position is used, and incremented.

int64 Fetch_N( int64 PC, integer Size )

Fetches Size (1 minimum, 4 maximum) bytes from address PC.  If PC is 0, the current PC position is used, and incremented by Size.

void Push( string Buffer, integer Size )

Push Size (65535 maximum) bytes onto stack from Buffer.

void Pop( string& Buffer, integer Size )

Pop Size bytes from the stack to buffer Buffer.  The receiving buffer must be large enough to hold all the retrieved data.

int64 Read_Stack( int64 Stack_Pointer, integer Size )

	Reads Size bytes from the passed Stack address.  The stack pointer is not affected by this method.

int64 Get_IP()

Return's the current Instruction Pointer.

int64 Get_SP()

Return's the current Stack Pointer.

int64 Get_SF()

Return's the current Stack Frame pointer.

TSVM_Watchpoint_Manager Watchpoint_Manager()

Returns the watchpoint manager object.

integer Get_Temp_Length()

Returns the length of the Temp register, in bytes.

string Get_Temp()

Returns the contents of the Temp register.

procedure Set_Temp( string Value, integer Length )

Sets the Temp register from Value, with length Length bytes.

int64 Low_Code()

Returns the lowest valid code address.

int64 High_Code()

Returns the highest valid code address.

void Redirect_Input( string Source )

Indicate where to get user input from (NULL=default).  Source is the name of a file.

void Redirect_Output( string Source )

Indicate where to send user output to (NULL=default). Source is the name of a file.

Boolean Load_Extension( string Name )

Loads a VM extension named Name.  The name may be a fully-qualified or partially-qualified filename. Returns False if the load failed, which could be due to the extension already being loaded, the name being empty, not being able to find the file, or some failure to load the extension from the file.

Boolean Load_Extension( TSVM_Extension Extension )

Loads the passed VM extension.  Returns False if the load failed, which could be due to the passed object being NULL, or the extension has already been loaded.

Int64 Load_Image( string File_Name )

Loads an SVM image (BIN or SSL) into memory.  This is generally used for loading SSLs.  The result is the address of the first code in the loaded image.  If the result is 0 there was a load error, possibly because the file name is invalid or the file was not found.  If the image is already loaded, the function does nothing except return the address of the loaded image.

Int64 Get_Symbol( string File_Name, string Symbol )

Returns the address of the specific symbol within the loaded image (File_Name).  Returns 0 if the image is not loaded or does not contain the specified symbol.

Int64 Allocate_Data( integer Size )

Allocates Size bytes of data space.  This memory cannot be deallocated once allocated.  It can be accessed via the Data_Manager object.

TSVM_Data_Manager* Get_Data_Manager( int64 Address, integer Size )

	Creates and returns a Data Manager for data allocated via Allocate_Data.  It is the responsibility of the caller to terminate this object when he is finished with it.

TSVM_Debugger_Client

Debugger client objects are used to provide a debugger interface to the user.

void Trigger_Watchpoint( string A, int64 B, int64 Address, integer D, string Name, integer Type, boolean Data )

Called asynchronously when a watchpoint is triggered.  Parameters:

Parameter	Description	
A	string value being written.	
B	Integer value begin written.	
Address	Address being modified/executed.	
D	Datatype (if D<0 then the absolute value of D is the number of bytes).	
Name	Name of variable with watchpoint.	
Type	Data type of variable with watchpoint.	
Data	True if the watchpoint is on data.  False if execution watchpoint.	

void Execute()

Passes control to the debugger.

void Initialize( TSVM_Engine Engine, string Name )

Initializes the debugger client.  Engine is the SVM engine used to execute code.  Name is the name of the program to execute.

TSVM_Data_Manager

The SVM Data Manager is a heap manager used to manage data-space memory in the SVM engine.  An instance for a given area of data memory can be obtained from the engine via the Get_Data_Manager method.  TSVM_Data_Manager has the following methods:

void Terminate()

Call this to destruct the instance.  Note that this has no effect on the data memory.

Int64 Allocate( TData_Type DT )

Allocate data for the specified data type.  Returns the data address of the allocation or 0 if it could not be allocated.

void Deallocate( TData_Type DT, int64 Address )

Deallocates the specified type of data at the specified address.

int64 Allocate_Data_Type( TData_Type DT )

Allocates and initializes a data type definition.  Returns the address of the definition or 0 if it could not be allocated.

void Deallocate_Data_Type( int64 Address )

Deallocates a data type definition at the specified address.

void Set_Integer( int64 Address, int64 Value, TData_Type DT )

Sets the integer at the specified address, with the specified data type, to Value.

Int64 Get_Integer( Address : int64 ; DT : TData_Type )

Returns an integer value from the specified address, with the specified data type.

void Set_String( int64 Address, char* Value, int Size)

Sets the value of the string at the specified address to Value.  Size indicates the number of bytes in Value.

int Get_String_Length( int64 Address )

Returns the length of the string at the specified address.

char* Get_String( int64 Address )

Returns a pointer to the string at the specified address.  Note that this pointer is temporary and should only be used to copy the contents to a location for later use.

FILES

The SVM interpreter understands three types of file: binary, executable, and sharable.  All are executable by the SVM interpreter, but differ in some ways.

Binary files
    
The Binary file is a file with the standard header, described earlier. Immediately following the header is the program code, and then the initialized data segment.

Executable files
    
The executable file is a binary file with a normal executable file prefixed to the binary file image.  Thus, the general layout of the file is: executable image, binary header, binary code, binary data.

Sharable files
    
The sharable file is a binary file with symbol records appended to the end of the binary image, after the initialized data segment.

CALLABLE SDK

The callable SDK is a set of classes and APIs that can be used to access SDK utility functions from compilers, linkers, IDEs, and the like.

ASSEMBLER
The assembler can be called directly from a program.  The format of the call is:

TUEC SVM_Assembler( string Command, TCOM_Compiler_Interface* interface )

	This routine is used to assemble SVM source files.  Command is the assembly specification (described hereafter).   interface is an instance of a compiler interface class.  The interface may be null, but detailed errors cannot be reported in this case.  

The command specification has the basic format:
	{output {,list} = } input
	where "input" is the name of the file to assemble, "list" is an optional listing file, and "output" is an optional output filename.

The following errors can be returned by the SVM Librarian,. in addition to O/S errors related to the filesystem.

SVM Assembler facility = 118

SVM Assembler errors:

1	Unknown switch
2	No files specified

These errors reflect problems with the command specification.  Actual assembly errors are reported via the list file.

LINKER
Ths SVM linker can be called directly from a program.

TUEC SVM_Link( string Command, TCOM_Compiler_Interface* interface, integer Flags, inegert& CS, integer& DS )

This routine is used to link one or more SVM object files into an executable file.  Command is the link specification (described hereafter).  interface is an instance of a compiler interface class.  The interface may be null, but detailed errors cannot be reported in this case.  Flags are processing flags, and are reserved for future use.  CS and DS are ignored on call.  On return, they contain the sizes of the Code and Data areas, respectively.  The CS and DS values are in bytes.

The command specification has the basic format:
executable{/switch...} {,list} = object1{/switch} {,object2...}
where "executable" is the filename of the output executable file, "list" is the name of a listing file, "objectn" are the names of input object files, and "switch" indicates processing options.  The default output is a native executable for the target platform, but this can be changed with executable switches.

Valid executable switches include:
/BIN	output file is an SVM binary file.
/CREATE	output file is an SVM sharable library.
/DEBUG	Generate debug symbol file.
/EXT=x	Indicates a linker extension.
/VECTORS	Generate vector fixup file.  This may do nothing on some implementations.
/XREF	Generate a cross-reference listing.  This may do nothing on some implementations.

Valid object file swtiches include:
/L		Indicates an SVM object module library file.
/N		Indicates a native library file (such as a DLL on Windows).  This may not be supported on some implementations.
/S		Indicates an SVM sharable library.

Examples of valid command specifications:

myfile = file1, file2
myprog, mylist = file1, file2.dll/N, shared/S
myshare/CREATE = file1, file2, lib/L, shared/S

Errors reported through the compiler interface, Log_Message method:

?Missing input file

No object file was specified.  Error code returned is SVMLink_ErrMissing_Input_File.

?Parameters not allowed on /CREATE

Parameters were passed with /CREATE.  Error code returned is SVMLink_ErrParameters_On_Create.

?Parameters not allowed on /BIN

Parameters were passed with /BIN.  Error code returned is SVMLink_ErrParameters_On_Bin.

?Incompatible switches: /BIN and /CREATE

Both /BIN and /CREATE were supplied.  Error code returned is SVMLink_ErrIncompatible_Switches.

?Parameters not allowed on /DEBUG

Parameters were passed with /DEBUG.  Error code returned is SVMLink_ErrParameters_On_Debug.

?Parameters not allowed on /XREF

Parameters were passed with /XREF.  Error code returned is SVMLink_ErrParameters_On_XRef.

?Parameters not allowed on /VECTORS

Parameters were passed with /VECTORS.  Error code returned is SVMLink_ErrParameters_On_Vectors.

?Invalid switch: xxx

A switch was found that was not recognized, or was not valid in the position it was found.  Error returned is  SVMLink_ErrInvalid_Switch.

?Syntax error

The command contained invalid syntax.  Error code returned is SVMLink_ErrSyntax_Error.

'?Illegal file specification

An input switch was found without a corresponding filename.

?Incompatible switches: /S, /L, and /N must be used alone

One object file had more than one switch.

?Illegal object module format - xxx
?Corrupted symbol table in module xxx
?Illegal file format - xxx

These errors indicate that an object file had an invalid format.

?Multiply defined symbol: xxx in module yyy

When resolving an external symbol reference, an object module was found that defined the symbol more than once.

?Undefined symbol: xxx in module yyy

An external symbol reference was found but no matching symbol could be found in any of the object files.

xxxxx

Various errors from the operating system can also be reported during file I/O.

TCOM_Compiler_Interface

This class is used to asychronously communicate with the calling code.  The methods in the class are as follows:

TUEC Initialize()

Initializes the object.  Not called by SVM.  It is assumed that the object is already initialized before calling SVMLink.

TUEC Terminate()

Terminates the object.  SVM does not call this method.

void Attach()

Increments reference count.  SVM does not call this method.

void Detach ()

Decrements reference count and destroys the object if the reference count goes to 0.  SVM does not call this method.

int Interface_Version()

Returns the interface version of the object.

int Facility_ID()

Returns the facility ID of the object.

int Facility_Version()

Returns the version of the facility of the object.

TDebug_Interface* Debugger()

Returns a debug interface for the object.  SVM does not call this method.

void* Extension()

Reserved for future use.  SVMLink does not call this method.

void Log_Message( string Message, integer Level, boolean&  Abort )

Used to log errors.  Error text is in Message.  Abort can be set to true before returning to abort the process.  Level is one of the following.

0 Undefined.
1 Fatal error.
2 Serious error.
3 Warning
4 Hint
5 Notification

void Log_Nested_Message( string Mess, integer Level, boolean& Abort )

Used to log nested errors.  See Log_Message for parameter descriptions.  SVM does not call this method.

void Unnest_Message( int Level, boolean& Abort )

Used to unnest nested errors.  SVM does not call this method.

boolean Check_Terminate()

If the function returns True, the process will abort.

TFile* Get_File( string Nam )

Returns a file object for the specified filename.  SVMLink does not call this method.

void Release_File( TFile* F )

Indicates that the process is finished with the file.  SVMLink does not call this method.

LINKER EXTENSION
When extended instructions are used (UEXT prefix), an SVM engine is required to interpret them at runtime, and a linker extension is required to relocate addresses at link time.  The Linker Extension must have an API function:

TSVM_Linker_Extension* Load_Linker_Extension ()

This returns a linker extension object.

TSVM_Linker_Extension
This class is used by the linker to relocate extension instructions.  The linker calls the Register_Code method with the byte code that is part of the extension instruction (not including the UEXT opcode).  It repeats the call as long as the result indicates that the extension wants more bytes.  When the method returns 0, the extension has constructed the relocated instruction and the linker calls Get_Result to retrieve that instruction.  Note that the relocated instruction is always the same length as the number of bytes passed to Register_Code.  For extension instructions with no address operands, the returned function will be the same as what was passed.

void Terminate()

Destructs the object.

int Register_Code( char Code, int64 Data_Offset, int64 Address ) 

Return information on the passed opcode.  Data_Offset is the current data offset for the module.  Address is the current address for the instruction.

Result is:
    0 = Result is ready, via Get_Result.
    1 = Instruction not recognized
    2 = Request another byte

void* Get_Result()

Returns a pointer to the relocated instruction.

int Version()

Returns the specification version that this extension complies with, times 10.  For instance, if it complies with version 1.6 of the specification, it returns 16.

LIBRARIAN
There are two interfaces to the librarian - the high-level interface and the low-level interface.

High-Level Librarian Interface
The High-level Librarian interface is a function which takes a text command and operates based on the command text.  The API function is:

TUEC SVM_Librarian( string Command, TCOM_Compiler_Interface* Interface )

Command contains the command and Interface is an optional callback mechanism for the librarian to notify the caller of errors or other information.  If you wish no callbacks, NULL can be passed for Interface.  The format of the command text is as follows:

{<output filename> =} <library filename> /<switch> {<options>}

The output filename is only required for the extract operation.  Options are only required for deletion, extraction, insertion, and replacement operations.  By default, libraries have an file extension of ".OLB".  The valid switches are:

/CREATE
This switch is used to create a new library.  The library will be empty and ready for modules to be inserted.  Format:

<library name> /CREATE

Example:

MYLIB/CREATE

/DELETE
This switch is used to delete a module in a library.  Note that the module will no longer be available, but the space it occupied in the file is not released.  Format:

<library name> /DELETE <module name>

Example:

MYLIB/DELETE OLDMOD

/EXTRACT
This switch is used to extract a module from the library and create an object module file.  Format:

<output filename> = <library name> /EXTRACT <module name>

Example:

MOD.SOB=MYLIB/EXTRACT MOD

/FULL
This switch provides a directory of modules in the library similiar to the /LIST switch, but in more detail.  The insertion date of each module is listed.  The information is sent via the Compiler Interface Log_Message method (as notifications).  Format:

<library name> /FULL

Example:

MYLIB/FULL

/INSERT
This switch is used to insert a new module into the library.  The file specified must be an SVM Object file.  Format:

<library name> /INSERT <module filename>

Example:

MYLIB/INSERT NEWMOD.SOB

/LIST
This switch provides a list of modules in the library.  The information is sent via the Compiler Interface Log_Message method (as notifications).  Format:

<library name> /LIST

Example:

MYLIB/LIST

/REPLACE
This switch is used to replace an existing module with a new version.  It is equivalent to a deletion followed by an insertion.  Format:

<library name> /REPLACE <new module filename>

Example:

MYLIB/REPLACE NEWMOD.SOB

Low-Level Librarian Interface
The Low-level Librarian interface is through an instance of the Librarian class.  The API function to return an instance of the class is:

TCOM_Object_Librarian* Get_Library()

This function returns an instance of TCOM_Object_Librarian, which has the following methods.

TUEC Initialize()

Initializes the instance.  This is already done - the Get_Library function returns an initialized object.

TUEC Terminate()

Terminate the use of the object.  Returns result of termination.  This generally should not be used - instead, use the Detach method.

void Attach()

Increments the reference count for the object.

void Detach()

Decrements the reference count for the object.  When count reaches 0, the object is destroyed.

int Interface_Version()

Version of the COM interface for this object.

int Facility_ID()

Facility ID for the facility represented by this object.

int Facility_Version()

Facility version.

TDebug_Interface*  Debugger()

Returns a debugging interface for the object.  Returns nil if not supported.

void* Extension()

Reserved for future use.

int Creation_Hour()

Returns the creation hour (0-23) of the library.

int Creation_Minute()

Returns the creation minute (0-59) of the library.

int Creation_Day()

Returns the creation day (1-31) of the library.

int Creation_Month()

Returns the creation month (1-12) of the library.

int Creation_Year()

Returns the creation year of the library/

int Deleted_Space()

Returns the number of bytes of unrecovered deleted space in the library.

int Modified_Hour()

Returns the hour (0-23) that the library was last modified.

int Modified_Minute()

Returns the minue (0-59) that the library was last modified.

int Modified_Day()

Returns the day (1-31) that the library was last modified.

int Modified_Month()

Returns the month (1-12) that the library was last modified.

int Modified_Year()

Returns the year that the library was last modified.

string Version()

Returns the version of the librarian that created the library.

void Create_New( string Name, integer X, integer Y )

Creates a new library with the filename in Name.  For SVM compliance, X and Y are reserved for future use and should be 0.

void Error( tUEC& UEC )

UEC is ignored on call.  On return, it contains the last error (if any) encountered.

void Extract( string Module, string Filename )

Extracts the module whose name is in Module to the filename in Filename.

TUEC Open( string X )

Opens the library whose name is in X.  This must be done before calling any method which performs an action on the library.

void Delete( string Command )

Deletes the module whose name is in Command.

TUEC Insert( string Name, string Filename )

Inserts the module from the file named in Filename and inserts it into the library with the module name in Name.

boolean Get_Module_Info( string Name, TModule_Info& Info )

Retrieves information about the module whose name is in Name.  Info is ignored on call.  On return Info contains information about the module.  If the module was found, the method returns True, otherwise it returns False.  TModule_Info is a structure defined in the following text.

integer Size()

Returns the total size of the library, in bytes.

The TModule_Info structure contains the following fields:

char Name[ 128 ]

This contains the module name.  The first byte is the length of the following data.  Note that SVMLib truncates module names to 15 characters.

integer Size

The size of the module, in bytes.

integer Day

The day (1-31) that the module was inserted into the library.

integer Month

The month (1-12) that the module was inserted into the library.

integer Year

The year that the module was inserted into the library.

integer Hour

The hour (0-23) that the module was inserted into the library.

integer Minute

The minute (0-59) that the module was inserted into the library.

integer Flags

Flags for the module.  Reserved for future use.

The following errors can be returned by the SVM Librarian,. in addition to O/S errors related to the filesystem.

SVM Librarian facility = 119

SVM Library errors:

1	Output filename was required, but was missing.
2	Command syntax error.
3	A switch had a parameter that was not recognized.
4	An unrecognized switch was used.
5	Multiple conflicting switches were used.
6	A module name was required, but was missing.
7	The specified module was not found in the library.
8	The specified file has an invalid format.

Base Librarian facility = 14

Base Librarian errors:

1	The library file has an invalid format.
2	The specified module was not found.
3	The specified module already exists.
4	The module file has an invalid format.

SVM COMPILER BACKEND

The SVM Compiler Backend (or simply "Backend") is a set of routines that can be used in compilers which target SVM.  It provides management of symbols, abstraction away from the SVM instruction set, and various other utilties.

The back-end API consists of the following function:

TCompiler_Back_End* Get_Back_End()

This returns a compiler back-end object.

TCompiler_Back_End
This object is used by compilers to abstract away from some of the SVM details.  The back-end manages many different resources and provides services to speed compiler development.  Some of these are integral to any use of the back end and some are independant and can be used, or not, as desired by the compiler writer.

Concepts:
The back-end takes a series of calls to generate code and data, generating a single binary or object output file.  The file is viewed as a series of 256-byte Object blocks.  A number of these are cached in memory to speed compilation.  If external symbols are referenced, then an object file should be created so that the SVM Linker can resolve these references.  The back-end can also optionally generate a debug symbol file which is used by the SVM to support symbolic debugging.

The SVM uses 256-byte pages for accessing code, which allows it to execute programs much larger than physical memory.  These pages are called Code Blocks (or simply blocks).  Code Blocks are encapsulated by the TSVMBE_Code_Block  class.  A compiler only needs to use this object for expression handling, since the code block that is used by the back-end serves only as a place for the back-end to generate code to.  At execution time, code blocks are read-only.  The back-end keeps a code size pointer which indicates the next position in the code to generate.  This pointer indicates the size of the code thus far generated.

Data blocks are a maximum of 65,536 bytes in length.  The back-end will not allocate data across a 64 Kb boundary.  Code and Data are kept in separate areas - they are not interleaved.  The back-end can allocate up to 1 Mb of data, but fragmentation due to the 64 Kb data segments means that the back-end can indicate no room for data that should theoretically fit.

The various Generate* (and related) methods generate code to the code section.  There are both low-level and high-level generation methods.  The highest-level method that accomplished your purposes is the one that should be used.

The back-end manages all file I/O for the output object file.  Before any code or data is generated, the compiler must first call Prepare_For_Compile, which initializes the back-end for code generation.  It will also create and initialize the debug symbol file if Get_Debug is true.  Then the compiler must call Open_Object_Output_File with the output filename.  This creates the file and prepares it for futher use by the back-end.

When the compiler completes the code and data generation, it should call Report_Undefined_References() to get a list of unresolved internal references.  Then the compiler should call Flush_Object_Output_File to flush all remaining code and data to the output file.  After this call, Get_Data_Size will return the final data section size.  Finally, the compiler should call Finish_Object_Output_File to generate a cross-reference listing (if requested via Set_XRef), finalize the contents of the output file, and close it.

Use of the back-end symbol handling is optional, but it may be difficult to avoid using it if you wish to create symbol files.  The back-end Symbol Table is organized as a stack of symbol tables.  The top table on the stack is the "current" symbol table.  Each time a new symbol scope is opened (via Push_Nest) a new empty symbol table is pushed onto the symbol table stack.  Pop_Nest will destruct the current symbol table and make the next one on the stack the current symbol table.  See Symbol_Manager for details on the operations available on the symbol table, and the type of data that is stored for each symbol.  Some symbols, such as structures, have their own symbol table for their contents.

Use of scoping is optional.  It can be used to automatically set up/clean up scoped symbols, and track whether or not there are unterminated structures.

Use of the back-end expression handling is entirely optional.  The back-end does not parse expressions since the parsing rules vary for each language and compiler, but it can process expressions parsed into an expression tree..  The compiler must parse an expression into a binary expression tree which is encapsulated in the TSVMBE_Expression_Node class.  Expression trees are binary trees where each node represents a literal, an operator, or some code that will result in a value being placed on the stack when executed.  The structure of the tree will determine the order of operations.  A binary (2-operand) operation will consist of a node of the specific operator type, with a left and right node of the two parameters.  Monadal operations (consisting of an operator that operates on a single operand) would consist of the specific operator type and only a left node.

Example of a binary operation:

  +
 / \
1   2

Example of a monadal operation:

  !
 /
1

When code is generated for the expression, the back-end first generates code for the left-hand side of the root node, then the right-hand side, and then the operator.  So, in the first example, execution of the generated code would be: push 1 onto stack, push 2 onto stack, pop and add the two values on top of stack.  The result would then be the result of the expression (3) on the top of the stack.  Generation of code from an expression tree requires a recursive following of links so that only leaf nodes are processed, and that they are processed from left to right.  So only when a node's children are both leaf nodes (or NULL) will that node's code be generated.

Example of an expression tree for  the equation 1 + 2 * 3:

  +
 / \
1   *
   / \
  2   3
 
Example of an expression tree for the equation (1 + 2 ) * 3:

    *
   / \
  +   3
 / \
1   2

Methods:
The methods of the TCompiler_Back_End class are:

int Get_Code_Size()

Returns the current size of the code section, in bytes.

int Get_Data_Size()

Returns the size of data section, in bytes.

boolean Get_Debug()

Returns the Debug flag value.

void Set_Debug( boolean Value )

Sets the Debug flag.  This determines whether or not debug symbol information is written.

boolean Get_Object_File()

Returns true if output is object file, false if binary.

void Set_Object_File( boolean Value )

If Value is true then the output is an object file, otherwise it is a binary file.

TCOM_Logger* Get_Int()

Returns the current logger interface object.

Set_Int( TCOM_Logger* Value )

Sets the current logger interface object to Value.

byte Get_Last_OpCode()

Returns the last generated opcode.

void Set_Last_OpCode( byte Value )

Sets the last generated opcode value.

string Get_Literal( int Index, int& Length )

Returns Indexth string literal value.  Length is ignored on call.  On return Length is the length of the literal, in bytes.

int Get_Max_Object_Cache()

Returns the maximum number of object blocks that are cached in memory.

void Set_Max_Object_Cache( int Value )

Sets the maximum number of object blocks that are cached in memory.  The higher the value, the more memory is required.  The lower the value, the more I/O occurs which can slow down the compile.

int Get_Offset()

Current offset in the current code block.

int Get_This_File()

Returns the index of current source file.

void Set_This_File( int Value )

Sets the index of current source file to Value.

int Get_Token_Line()

Returns the line number of the current token.

void Set_Token_Line( int Value )

Sets the line number of the current token.

void Generate( int64 X, byte Y )

Generates Y bytes of the value X to the code section.  Y must be 1 to 8, inclusive.

void Generate_Byte( byte X )

Generates a single byte to the code section.

void Generate_Byte_Data( byte X )

Generates a single byte to the data section.

boolean Generate_Code_Buffer( TSVMBE_Code_Block X )

Generates the contents of Code Block X to the code section.  Returns true on success.  Failure indicates an error occurred during generation.

void Generate_Word( int X, byte Y ) 

Generates Y bytes of X to the code section.  Y must be 1 to 2, inclusive.

void Generate_Buffer( string X, int Y )

Generates Y bytes from X to the code section.

void Do_Exit_Scope()

Generates code to exit the current scope.

void Do_Exit()

Generates an EXIT instruction.

void Do_Stop()

Generates a STOP instruction.

void Generate_Jump( int64 Destination_Address )

Generates a jump from the current address to Destination_Address.  The back-end will use the smallest instruction possible to accomplish this.

void Jump_To_Undefined_Label( char* Identifier_Name )

Generates a jump instruction to a label which is not yet defined.  When compilation is complete, the jump will be back-patched appropriately.

void Generate_End()

Generates an END instruction.

void Add_Relative( int A )

Adds relative address A to the current code block.

void Call_Routine( int64 A )

Generates a call to the routine at address A.

void Call_Symbol( char* Identifier_Name, int Variable_Flags, int Procedure_Size, TData_Type Variable_Type )

Defines the symbol with the specified flags, size, and data type.  Then it generates an absolute call to the specified identifier.

void Call_Indirect()

Generates a call to the address on the stack.

void Push_Address( int X )

Generates code to push address X to the stack.

void Push_From_Address( int A, int S )

Generates code to push S bytes from address A onto the stack.

boolean Push_Long_Address( int Addr, int Flags, char* Identifier_Name, int Variable_Flags, int Procedure_Size, TData_Type Variable_Type )

Generates code to push the specified address.  If the flags indicate an external symbol, it is added to the list of external symbols for resolution at link time.  Returns True if success, or false if there was an error.

void Range_Check( int Subscript_Low, int Subscript_High )

Generates code to perform a range-check of the top of the stack.

void Normalize_Subscript( int Subscript_Base )

Generates code to normalize the subscript on the top of the stack with to the passed base.

void Dereference

Generates code to dereference the address on the top of the stack.

void Dereference_Integer( int Size )

Generates code to replace the address on the top of the stack with the integer at that address.  Size is the size of the integer, in bytes.

void Push_Long( int A )

Generates code to push immediate longword value A.

void Add_Long_To_TOS( int A )

Generates code to add A to the long on the top of the stack.

void Copy_String_Indirect()

Generates a Copy-string-indirect instruction.

void Copy_String_Indirect_Reversed()

Generates a copy-string-indirect-reversed instruction.

void Copy_TOS_String_To_Address( int Z )

Generates code to copy the string pointed to by the address on the top of the stack to address Z.

void Copy_Indirect( int Size )

Generates code for a copy-n-indirect instruction with Size bytes.

void Push_Byte( byte G )

Generates code to push byte G to the stack.

void Push_Word( word G )

Generates code to push word G to the stack.

void Pop_Bytes( int D )

Generates code to pop D bytes from the stack.

void Pop_To_Address( int64 Tmp, TData_Type DT )

Generates code to pop data from the stack to address Tmp.  The number of bytes popped is determined by the datatype size.

void Pop_To_Stack( int Size )

Generates code to pop Size bytes to stack indirect longword.

void Pop_Direct( int Size )

Generates code to pop Size bytes to the following direct address.

void Concatenate_To_Temp0( char* S, int Len )

Generates code to place Len bytes of S in the Temp0 register.

void Assign_String_From_Literal( char* Literal_Text, int Len, int Address )

Generates code to set the string at address Address with Len bytes of Literal_Text.

void Begin_Loop( int64 Address )

Marks the beginning of a loop.

void End_Loop()

Marks the end of a loop, backpatching the conditional exit-address at the top of the loop.

void Begin_Then()

Marks the beginning of a THEN block.

void Begin_Else()

Marks the beginning of an ELSE block.

void End_Then()

Marks the end of an IF...THEN block and backpatches previously marked THEN and ELSE blocks.

void Calculate_Array_Element_Address( int Size )

Generates code to calculate an offset by multiplying the normalized array index on the top of stack with Size, replacing the index on the top of the stack with the calculated byte offset.

void Zero_Expression_Tree( TSVMBE_Expression_Node* X )

Zero storage stored at tree with root X

void Optimize_Tree( TSVMBE_Expression_Node* X )

The back-end optimizes the passed expression tree.

void Expression( TData_Type& DT, TSVMBE_Expression_Node Result, TCompiler_Status* Status )

Generates code for expression Result.  DT is the minimum sized data type result requested on call and the actual result data type of expression on return (returns an ID of -1 if an error).

TSVMBE_Expression_Node* Negate_Operator( int Precedence, TSVMBE_Expression_Node* Node )

Returns an expression node which is a numeric negation operation.

TSVMBE_Expression_Node* String_Literal_Expression( string Literal, int Len )

Returns an expression node which is a string literal of Len bytes.

TSVMBE_Expression_Node* Numeric_Literal_Expression( string Literal_Text, int Len )

Returns an expression node which is a numeric literal, in text form.  Len is the length of the text, in bytes.

void Flush_Object_Output_File()

Writes out the remainder of the last block and calculates the total data space.

void Finish_Object_Output_File( boolean XRef, TCompiler_Status* Compiler_Status, boolean Errors )

This updates the output file header, writes out the data section, makes sure that the cache is flushed to the file, writes the debug file (if Get_Debug is true), outputs a cross-reference listing (if Get_XRef is true), and closes the files.

void Open_Object_Output_File( string Output_File )

Opens the specified output file.  This must be called before any code or data generation begins.

void Close_Object_Output_File()

Writes the symbols to the file and clears the symbol table.

boolean Copy_Header( string X )

Writes the executable header to the object file.

TSVMBE_Code_Block* New_Code_Block()

Returns an instance of the TSVMBE_Code_Block class.

void* Save_Procedure_Root()

Returns the current procedure root value.

void Restore_Procedure_Root( void* P )

Sets the current procedure root value to P.

void Add_User_Type( string Name )

Adds a user-type with name Name.  If already defined, this method does nothing.

int User_Types()

Returns the number of user types defined.

void Maximize_Type( TData_Type X, TData_Type& DT )

Determines the maximum data-type characteristics (such as signed/unsigned, size, type, etc) and sets DT equal to that maximized data-type.

void Convert_Literal_To_Data_Type( TData_Type& Data_Type, string* S, string& Packed, int& Packed_Length )

Determines the miminal numeric data type required to hold the value in S, and returns that data type via Data_Type.  Packed and Packed_Length are ignored on call.  On return, Packed is a pointer to a buffer containing the numeric value in binary form and Packed_Length is set to the number of bytes in that buffer.  For numeric types, S is assumed to be base 10.

void Convert_Numeric( TData_Type DT1, TData_Type DT2, string* S )

Convert the numeric value in S from DT1 to DT2.

string Get_Type_Name( int X )

Return name associated with a specific type

boolean Matched( TData_Type Type1, TData_Type Type2 )

Returns true if the two data types are compatible.  That is, if either are Type_Any, both are identical, or both are in the numeric family.

boolean Exactly_Matched( TData_Type DT1, TData_Type DT2 )

Returns true if the size,  type, and signedness is identical in the two passed data types,

void Zero_Data_Type( TData_Type& DT )

Zeroes out the passed data type.

void Free_Symbol( Symbol_Pointer Current )

Free memory for symbol.  After this call the symbol is no longer pointing to valid data.

void Write_Symbol_Table( Symbol_Pointer Current, boolean XRef, TCompiler_Status* Status )

Writes the symbol table to the debug file (if appropriate), the output file symbol table, and calls the Symbol method of the compiler interface for each symbol, in alphanumeric order.  When finished, the symbol table is deallocated.  Current indicates the root of the symbol table.

boolean Add_Symbol( string Identifier_Name, int Variable_Flags, int Procedure_Size, TData_Type Variable_Type )

Adds a symbol to the current symbol table with the specified Name, flags, size, and data type.  See the Symbol_Manager method for a description of flags.

void Symbol( string Sym, int& Addr, int& Pe, int& Flg, TData_Type& D_T, int& Cval, int& Subs, int&Siz, int& Result, TSymbol_Code Typ )

Performs a symbol table operation on the current symbol table.  See the Symbol_Manager method for a description of flags, symbol codes, and other parameters.

void Symbol_Manager( string Sym, int& Addr, int& Pe, int& Flg, TData_Type& D_T, int& Cval, int& Subs, int& Siz, int& Result, TSymbol_Code Typ, Symbol_Pointer Table )

Typ is used to define which symbol table operation is to be performed.  TSymbol_Code values:

Mnuemonic	Value	Meaning
Symbol_Add	0	Add symbol to table.  The parameters are only passed.
Symbol_Find	1	Lookup the symbol.  If found, Last_Symbol() will return the pointer to it.  The parameters are updated with the values of the symbol.
Symbol_Modify	2	Updates the symbol in the table.  The parameters are used to update the symbol.
Symbol_Link	3	Replace existing symbol with passed symbol, and create a link to a new symbol, which is a copy of the original.

Table indicates which symbol table to perform the operation on (this is the root node).

Result is always ignored when passed.  On return, it indicates the result of the operation:

Value	Meaning
0	Operation completed successfully.
1	reserved for future use
2	reserved for future use.
3	Symbol already defined.
4	Symbol not found.

The parameters used to pass to or from the method:

Parameter	Description
Addr		Symbol address.
PE		Parameter count (only for procedures/function - ignored otherwise).
Flg		Flags.  See the discussion of Symbol Flags in the Virtual Machine Architecture section.
D_T		Data type.
Cval		Value for numeric constant.
Subs		Number of subscripts for arrays.
Siz		Size of symbol, in bytes.

void Param_Type( string Sym, int Element, TData_Type& Subs, int& Flags, TSymbol_Code Typ )

Symbol_Pointer Last_Symbol()

Returns a pointer to the last referenced symbol.

void Set_Last_Symbol( Symbol_Pointer Current )

Sets the last referenced symbol pointer.

Symbol_Pointer  Detach_Top_Symbol_Table()

Removes the current symbol table from the symbol table stack and returns it.

void Report_Undefined_References()

Reports through the Compiler Interface, all non-global symbols that were referenced but not defined.

int Get_Temp( word Siz, int Typ )

Returns an address for a temporary variable of the given type and size.

void Reset_Temp()

Clear temp address pointer for reuse of allocated temp addresses.

int Data_Address( int X )

Returns the next available data address for a the specified number of bytes (X).  If the variable will not fit anywhere, it returns 0.  The back-end is currently limited to 1 Mb of data, total.  Since data must not cross 64 Kb boundaries, it is possible with fragmentation to run out of space prior to fully allocating 1 Mb.  To reduce the liklihood of this happening, the largest data should be allocated first when possible.

int Data_Type_Address( TData_Type Data_Type )

Returns a data address for the RTTI of the passed data type.

int Add_Literal( string N, int Len )

Adds the string literal in N to the list of literals and returns the data address for the literal.  Len is the length of the data.  If Len is -1, the data is considered to end at the first null character.

boolean Unterminated_Structures()

Returns true if there are unterminated structures within the current scope.

boolean Push_Nest( int Type ) 

Starts a new scope.  Type must be 0 in cases where symbols within the scope will be deleted when the scope is exited.  If Type is non-zero, no symbols go out of scope when the scope is exited.  Only positive non-zero values should be used.

void Pop_Nest()

Exits the last scope.

boolean In_Nest()

Returns true if there have been more Push_Nest calls than Pop_Nest calls.

void Unnest_To( int Type )

Performs repeated Pop_Nest operations until it reaches a scope with a type equal to Typ.

boolean Within_Procedure()

Returns true if the back-end scope is inside a procedure.  This procedure can be any number of scope levels outside the current scope.

int Stack_Index()

Indicates how many scopes are nested.

void Index_File( string X )

Adds the specified filename to the file list.  It is necessary for all source files to be registered just before they are processed so that the back-end can generate debug symbol files that will allow the debugger to map addresses to specific lines in files.

boolean Prepare_For_Compile( byte Language_ID, string Output_File )

Initializes the back-end for code generation.  Language_ID is the value that is placed into the output file's header for ID.  Output_File is the name of the output file.

void Begin_New_Statement()

Indicates to the back-end that a new source statement is beginning.  All code addresses between the code size of the last call to Begin_New_Statement and the code size of this call (minus 1) are associated with the last statement in the debug symbol file.  Thus, it is important that the compiler call this each time a new statement (or source line) begins.

void Clear_Tables( int C, string X, boolean XRef, TCompiler_Status* Status )

Called at the end of generating a procedure.  It clears structure memory, such as goto blocks, temp address points, and symbol tables.  It also back-patches EXITs to current address, and generates errors for undefined but referenced labels via the compiler interface.

void Deallocate_Space()

Deallocate all back-end-allocated space.

void Add_Label( string Identifier_Name, int64 X3 )

Adds a label with the specified name and address.

void Patch( string X )

Back-patches forward symbol references for symbol X to the current code offset.

void Patch_File( int X, int Y )

Patch address X with value Y (4 bytes).

int Version()

Returns the version of the specification that the back-end conforms to, times 10.  For instance a value of 16 means version 1.6.

void Terminate()

Destructs the back-end object.

TSVMBE_Code_Block* Get_Code_Buffer()

Returns the back-end's code buffer where code generation is directed.

void Set_Code_Buffer( TSVMBE_Code_Block* Value )

	Sets the back-end's code buffer to Value.

int Get_Object_Origin()

Returns the block origin of the object file (after executable header).  It is 0 if there is no executable header.

void Set_Object_Origin( int Value )

Sets the block origin of the object file.  The back-end properly sets this, so there should be no need for this to be called.

TSVMBE_Sym
The TSVMBE_Sym class contains a symbol pointer and an ofset.  Methods in the class are:

word Get_Offset()

Returns the symbol offset.

void Set_Offset( word Value )

Sets the symbol offset.

Symbol_Pointer Get_Symbol()

Returns the symbol pointer.

void Set_Symbol( Symbol_Pointer Value )

Sets the symbol pointer.

TSVMBE_Symbol_List
The TSVMBE_Symbol_List is a collection of TSVMBE_Sym objects.  Methods in the class are:

void Add( TSVMBE_Sym* Value )

Adds the specified symbol to the end of the list.

int Count()

Returns the number of symbols in the list.

void Clear()

Deletes all symbols in the list.  After this call, the count will be 0.

TSVMBE_Sym* Get_Item( int Index )

Returns the symbol at the given index.  The first symbol is always index 0.  If the index is invalid, the result is NULL.

void Set_item( int Index, TSVMBE_Sym* Value )

Sets the specified index to the specified symbol.  If index is invalid, this call has no effect.

TSVMBE_Relative
The TSVMBE_Relative class encapsulates an address/offset pair used for managing relative addresses.  Methods in the class are:

int Get_Offset()

Returns the offset value.

void Set_Offset( int Value )

Sets the offset value.

int Get_Address()

Returns the address value.

void Set_Address( int Value )

Sets the address value.

TSVMBE_Relatives_List
The TSVMBE_Relatives_List class is a collection of TSVMBE_Relative objects.  The methods in the class are:

void Add( TSVMBE_Relative* Value )

Adds the specified object to the end of the collection.

int Count()

Returns the number of objects in the collection.

void Clear()

Deletes all objects in the collection.  After this call, the Count method will return 0.

TSVMBE_Relative* Get_Item( int Index )

Returns the object at the given index.  The first object is always index 0.  If the index is invalid, the result is NULL.

void Set_item( int Index, TSVMBE_Relative* Value )

Sets the specified index to the specified object.  If index is invalid, this call has no effect.

TSVMBE_Code_Block
The TSVMBE_Code_Block class encapsulates the buffer which contains generated code.  The methods in the class are:

int Get_Size()

Returns the size of code block, in bytes.

void Set_Size( int Value )

Sets the size of the code block to Value bytes.

TByte_Array*  Get_Code()

Returns a pointer to a byte array containing the contents of the code block.

void Set_Code( TByte_Array* Value )

Sets the code buffer to the passed buffer.  Note that when the object is destructed, the back-end will attempt to deallocate its buffer, which can cause heap corruption if the buffer was allocated by the compiler.  Therefore, it is always best to reset the buffer to the original one or to NULL before the object is destructed.

TSVMBE_Symbol_List*  Get_Externals()

Returns the code block's external symbol list.

void Set_Externals( TSVMBE_Symbol_List* Value )

Sets the code block's external symbol list.

TSVMBE_Relatives_List* Get_Relatives()

Returns the code block's relative address list.

void Set_Relatives( TSVMBE_Relatives_List* Value )

Sets the code block's relative address list.

void Terminate()

Destructs the object.

Node Type values:

Value	Mnuemonic	Description
0	Node_Literal	The node is a string or numeric literal.
1	Node_Code	The node contains code.
2	Node_Operator	The node is an operator.

TSVMBE_Expression_Node
The TSVMBE_Expression_Node class represents a node in a binary expression tree.  Because expression nodes have links to other nodes, a given node is always the root of an expression sub-tree.  Methods in the class are:

TNode_Type Get_Node_Type()

Returns the type of the node.

void Set_Node_Type( tNode_Type Value )

Sets the type of the node.

TData_Type Get_Data_Type()

Returns the data type of the node.

void Set_Data_Type( TData_Type Value )

Sets the data type of the node.

TData_Type Get_Left_Type()

Returns the data type of the left child.

void Set_Left_Type( TData_Type Value )

Sets the data type of the left child.

TData_Type Get_Right_Type()

Returns the data type of the right child.

void Set_Right_Type( TData_Type Value )

Sets the data type of the right child.

int Get_Operator()

Returns the operator value.  The result is undefined if the node is not an operator.

void Set_Operator( int Value )

Sets the operator value for an operator node.  The operator values are as follows.  Note that the operation is data-type independant, unless otherwise specified.  For instance, Add applies to all numeric types and comparisons apply to all types, including strings.

Mnuemonic	Operation
Op_Add_Integer	Add numbers.
Op_Subtract_Integer	Subtract numbers.
Op_Multiply_Integer	Multiply numbers.
Op_Exponent_Integer	Left number to the power of right number.
Op_Divide_Integer	Left number divided by right number.
Op_Concat_Indirect	Concatenate strings.
Op_Integer_Compare_EQ	Both values have relational equality.
Op_Integer_Compare_NE	Values have relational inequality.
Op_Integer_Compare_LT	Left is relational less than right.
Op_Integer_Compare_GT	Left is relational greater than right.
Op_Integer_Compare_LE	Left is relational less than or equal to right.
Op_Integer_Compare_GE	Left is relational greater than or equal to right.
Op_AND	Logical and of two integers.
Op_NAND	Logical nand of two integers.
Op_OR	Logical inclusive or of two integers.
Op_NOR	Logical inclusive nor of integers.
Op_XOR	Logical exclusive or of integers.
Op_XNOR	Logical exclusive nor of integers.
Op_NOT	Logical not of integer.
Op_Factorial_Integer	Factorial of number.
Op_Percent_Integer	Percentage of number (number divided by 100).

int Get_Precedence()

Returns the node's precedence.  Result is meaningless if the node is not an operator.

void Set_Precedence( int Value )

Sets the operator node's precedence.  The back-end does not use this value, it is provided as a convenience to the compiler.

TSVMBE_Expression_Node* Get_Back()

Returns the parent node of the node.  Returns NULL if this node is the root of the expression tree.

void Set_Back( TSVMBE_Expression_Node* Value )

Sets the parent of the node.

TSVMBE_Expression_Node* Get_Left()

Returns the left child node.

void Set_Left( TSVMBE_Expression_Node* Value )

Sets the left child node.

TSVMBE_Expression_Node* Get_Right()

Returns the right child node.

void Set_Right( TSVMBE_Expression_Node* Value )

Sets the right child node.

TSVMBE_Code_Block* Get_Code()

Returns the code block for a code node.  It returns NULL for other node types.

void Set_Code( TSVMBE_Code_Block* Value )

Sets the code block for the node.

string Get_Literal()

Returns the literal for a literal node.

void Set_Literal( string Value )

Sets the literal for the node.

boolean Get_Signed()

Returns true if the node data type is signed.  Equivalent to calling Get_Data_Type().Signed

void Set_Signed( boolean Value )

Sets the node data type signedness.

int Get_Size()

Returns the data type size for the node.  Equivalent to calling Get_Data_Type().Size

void Set_Size( int Value )

Sets the node data type size.

void Terminate()

Destructs the object.

TCompiler_Status
The TCompiler_Status class is used to communicate errors and other information from the back-end during certain back-end method calls.

The Compiler Status Notice Types values are used to communicate status information via TCompiler_Status objects.  The values are:

Value	Mnuemonic	Meaning
0	CSNT_Undefined_Forward_Reference	A forward reference to an undefined symbol was found.

Methods are:

void Error( int Err )

Called when an error is encountered.  Err is the error value.

void Notice( string S, Symbol_Pointer P, int Notice_Type )

Called when the back-end is notifying the compiler of something.  The notification is in S, the symbol in question is P (which is null if the issue has nothing to do with a symbol), and Notice_Type is one of the compiler status notice types described above.

void Symbol( Symbol_Pointer S ) ;

Called to indicate the next cross-reference symbol.

Errors
UEH error codes for the back-end.

Facility ID = 121

Value	Mnuemonic	Description
0	SVM32BE_Err_Success	Operation was successful.
9	SMV32BE_Err_Type_Mismatch	Operation failed because of imcompatible data types.
32	SMV32BE_Err_Expression_Too_Complex	Operation failed because the expression tree was too large.

TLogger
TLogger is a generic logging interface.  Note that an integer Level is passed to most methods.  Level is used to indicate that type of message as follows:

		Value	Meaning
		0	Undefined
		1	Fatal error
		2	Serious error
		3	Warning
		4	Hint
		5	Notification

The class has the following methods:

void Log_Message( char* Mess, int Level, boolean& Abort )

This procedure is called to log informational messages to the code supplying the logger.  Mess is the message text, Level indicates the type of message, and Abort indicates whether or not to abort the process which created the message.  If Abort is True upon return the process should be terminated as gracefully and as quickly as possible.

void Log_Nested_Message( char* Mess, int Level,  boolean& Abort )

Same as Log_Message, but the message will be followed by a Unest_Message call when the condition causing the message goes out of scope.

void Unnest_Message( int Level, boolean& Abort )

This indicates the end of the condition under which the previous message with the specified level occurred.  If Abort is True upon return, the process should be gracefully terminated as quickly as possible.

bool Check_Terminate()

This function is called during a long process to allow for the user to abort it or for checking Windows messages, etc.  If the function returns True, the process should be gracefully terminated as quickly as possible.